Skip to content

Commit 135f2c2

Browse files
committed
[SILGen] InitAccessors: Start supporting assign_or_init for properties without a setter
Implement "init accessor" component emission which is paired with "init accessor" write strategy. Use `SILUndef` for a "setter" operand of an "assign_or_init" instruction in cases when property with init accessor doesn't have a setter. DI would detect re-initialization attempts to produce diagnostics.
1 parent 1e6c919 commit 135f2c2

File tree

3 files changed

+49
-15
lines changed

3 files changed

+49
-15
lines changed

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2737,6 +2737,9 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
27372737
checkAssigOrInitInstAccessorArgs(Src->getType(), initConv);
27382738
}
27392739

2740+
if (isa<SILUndef>(setterFn))
2741+
return;
2742+
27402743
// Check setter - it's a partially applied reference which takes
27412744
// `initialValue`.
27422745
CanSILFunctionType setterTy = setterFn->getType().castTo<SILFunctionType>();

lib/SILGen/SILGenLValue.cpp

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,7 +1560,7 @@ namespace {
15601560
ArgumentList *subscriptArgList,
15611561
PreparedArguments &&indices,
15621562
bool isOnSelfParameter,
1563-
Optional<ActorIsolation> actorIso)
1563+
llvm::Optional<ActorIsolation> actorIso)
15641564
: AccessorBasedComponent(
15651565
InitAccessorKind, decl, accessor, isSuper, isDirectAccessorUse,
15661566
substitutions, baseFormalType, typeData, subscriptArgList,
@@ -1587,9 +1587,14 @@ namespace {
15871587

15881588
SILValue setterFRef;
15891589
CanSILFunctionType setterTy;
1590-
std::tie(setterFRef, setterTy) = applySetterToBase(
1591-
SGF, loc, SILDeclRef(field->getOpaqueAccessor(AccessorKind::Set)),
1592-
base);
1590+
1591+
if (auto *setter = field->getOpaqueAccessor(AccessorKind::Set)) {
1592+
std::tie(setterFRef, setterTy) =
1593+
applySetterToBase(SGF, loc, SILDeclRef(setter), base);
1594+
} else {
1595+
setterFRef = SILUndef::get(initFRef->getType(), SGF.F);
1596+
setterTy = initFRef->getType().castTo<SILFunctionType>();
1597+
}
15931598

15941599
auto Mval =
15951600
emitValue(SGF, loc, field, fieldType, std::move(value), setterTy);
@@ -1618,7 +1623,7 @@ namespace {
16181623
/// the same dynamic PathComponent type as the receiver) to see if they are
16191624
/// identical. If so, there is a conflicting writeback happening, so emit a
16201625
/// diagnostic.
1621-
Optional<AccessStorage> getAccessStorage() const override {
1626+
llvm::Optional<AccessStorage> getAccessStorage() const override {
16221627
return AccessStorage{Storage, IsSuper,
16231628
Indices.isNull() ? nullptr : &Indices,
16241629
ArgListForDiagnostics};
@@ -3095,8 +3100,12 @@ namespace {
30953100
case AccessorKind::DidSet:
30963101
llvm_unreachable("cannot use accessor directly to perform an access");
30973102

3098-
case AccessorKind::Init:
3099-
llvm_unreachable("init accessor not yet implemented");
3103+
case AccessorKind::Init: {
3104+
auto typeData =
3105+
getLogicalStorageTypeData(SGF.getTypeExpansionContext(), SGF.SGM,
3106+
AccessKind, FormalRValueType);
3107+
return asImpl().emitUsingInitAccessor(accessor, isDirect, typeData);
3108+
}
31003109
}
31013110

31023111
llvm_unreachable("bad kind");
@@ -3257,6 +3266,11 @@ void LValue::addNonMemberVarComponent(
32573266
llvm_unreachable("cannot dispatch non-member var via distributed thunk");
32583267
}
32593268

3269+
void emitUsingInitAccessor(SILDeclRef accessor, bool isDirect,
3270+
LValueTypeData typeData) {
3271+
llvm_unreachable("cannot dispatch non-member var via init accessor");
3272+
}
3273+
32603274
} emitter(SGF, loc, var, subs, accessKind, formalRValueType, options,
32613275
actorIso, *this);
32623276

@@ -3789,6 +3803,13 @@ struct MemberStorageAccessEmitter : AccessEmitter<Impl, StorageType> {
37893803
BaseFormalType, typeData, ArgListForDiagnostics, std::move(Indices),
37903804
IsOnSelfParameter);
37913805
}
3806+
3807+
void emitUsingInitAccessor(SILDeclRef accessor, bool isDirect,
3808+
LValueTypeData typeData) {
3809+
LV.add<InitAccessorComponent>(
3810+
Storage, accessor, IsSuper, isDirect, Subs, BaseFormalType, typeData,
3811+
ArgListForDiagnostics, std::move(Indices), IsOnSelfParameter, ActorIso);
3812+
}
37923813
};
37933814
} // end anonymous namespace
37943815

lib/SILOptimizer/Mandatory/RawSILInstLowering.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -342,22 +342,32 @@ lowerAssignOrInitInstruction(SILBuilderWithScope &b,
342342
b.createEndAccess(loc, selfRef, /*aborted=*/false);
343343
}
344344

345-
auto *setterPA = dyn_cast<PartialApplyInst>(inst->getSetter());
346-
assert(setterPA);
347-
348345
// The unused partial_apply violates memory lifetime rules in case "self"
349346
// is an inout. Therefore we cannot keep it as a dead closure to be
350347
// cleaned up later. We have to delete it in this pass.
351-
toDelete.insert(setterPA);
348+
{
349+
auto setterRef = inst->getSetter();
350+
assert(isa<SILUndef>(setterRef) || isa<PartialApplyInst>(setterRef));
352351

353-
// Also the argument of the closure (which usually is a "load") has to be
354-
// deleted to avoid memory lifetime violations.
355-
if (setterPA->getNumArguments() == 1)
356-
toDelete.insert(setterPA->getArgument(0));
352+
toDelete.insert(setterRef);
353+
354+
if (auto *setterPA = dyn_cast<PartialApplyInst>(setterRef)) {
355+
// Also the argument of the closure (which usually is a "load") has to
356+
// be deleted to avoid memory lifetime violations.
357+
if (setterPA->getNumArguments() == 1)
358+
toDelete.insert(setterPA->getArgument(0));
359+
}
360+
}
357361
break;
358362
}
359363
case AssignOrInitInst::Set: {
360364
SILValue setterFn = inst->getSetter();
365+
366+
if (isa<SILUndef>(setterFn)) {
367+
toDelete.insert(inst->getInitializer());
368+
return;
369+
}
370+
361371
CanSILFunctionType fTy = setterFn->getType().castTo<SILFunctionType>();
362372
SILFunctionConventions convention(fTy, inst->getModule());
363373
assert(!convention.hasIndirectSILResults());

0 commit comments

Comments
 (0)