Skip to content

Commit fab9e4b

Browse files
authored
Merge pull request #66987 from xedin/refactor-init-accessors-to-carry-more-info
[SIL] InitAccessors: Refactor `assign_or_init` instruction to carry "self"
2 parents 94e8ddc + 80a1e2c commit fab9e4b

File tree

12 files changed

+131
-98
lines changed

12 files changed

+131
-98
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -955,12 +955,14 @@ class SILBuilder {
955955
getSILDebugLocation(Loc), Src, Dest, Initializer, Setter, mode));
956956
}
957957

958-
AssignOrInitInst *createAssignOrInit(SILLocation Loc, SILValue Src,
958+
AssignOrInitInst *createAssignOrInit(SILLocation Loc,
959+
SILValue Self,
960+
SILValue Src,
959961
SILValue Initializer,
960962
SILValue Setter,
961963
AssignOrInitInst::Mode Mode) {
962964
return insert(new (getModule()) AssignOrInitInst(
963-
getSILDebugLocation(Loc), Src, Initializer, Setter, Mode));
965+
getSILDebugLocation(Loc), Self, Src, Initializer, Setter, Mode));
964966
}
965967

966968
StoreBorrowInst *createStoreBorrow(SILLocation Loc, SILValue Src,

include/swift/SIL/SILCloner.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,6 +1356,7 @@ void SILCloner<ImplClass>::visitAssignOrInitInst(AssignOrInitInst *Inst) {
13561356
recordClonedInstruction(
13571357
Inst, getBuilder().createAssignOrInit(
13581358
getOpLocation(Inst->getLoc()),
1359+
getOpValue(Inst->getSelf()),
13591360
getOpValue(Inst->getSrc()),
13601361
getOpValue(Inst->getInitializer()),
13611362
getOpValue(Inst->getSetter()), Inst->getMode()));

include/swift/SIL/SILInstruction.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4870,7 +4870,7 @@ class AssignOrInitInst
48704870
friend SILBuilder;
48714871
USE_SHARED_UINT8;
48724872

4873-
FixedOperandList<3> Operands;
4873+
FixedOperandList<4> Operands;
48744874

48754875
/// Marks all of the properties in `initializes(...)` list that
48764876
/// have been initialized before this intruction to help Raw SIL
@@ -4890,14 +4890,14 @@ class AssignOrInitInst
48904890
};
48914891

48924892
private:
4893-
AssignOrInitInst(SILDebugLocation DebugLoc,
4894-
SILValue Src, SILValue Initializer,
4895-
SILValue Setter, Mode mode);
4893+
AssignOrInitInst(SILDebugLocation DebugLoc, SILValue Self, SILValue Src,
4894+
SILValue Initializer, SILValue Setter, Mode mode);
48964895

48974896
public:
4898-
SILValue getSrc() const { return Operands[0].get(); }
4899-
SILValue getInitializer() const { return Operands[1].get(); }
4900-
SILValue getSetter() { return Operands[2].get(); }
4897+
SILValue getSelf() const { return Operands[0].get(); }
4898+
SILValue getSrc() const { return Operands[1].get(); }
4899+
SILValue getInitializer() const { return Operands[2].get(); }
4900+
SILValue getSetter() { return Operands[3].get(); }
49014901

49024902
Mode getMode() const {
49034903
return Mode(sharedUInt8().AssignOrInitInst.mode);

lib/SIL/IR/SILInstructions.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,11 +1259,12 @@ AssignByWrapperInst::AssignByWrapperInst(SILDebugLocation Loc,
12591259
sharedUInt8().AssignByWrapperInst.mode = uint8_t(mode);
12601260
}
12611261

1262-
AssignOrInitInst::AssignOrInitInst(SILDebugLocation Loc, SILValue Src,
1263-
SILValue Initializer, SILValue Setter,
1264-
AssignOrInitInst::Mode Mode)
1265-
: InstructionBase<SILInstructionKind::AssignOrInitInst, NonValueInstruction>(Loc),
1266-
Operands(this, Src, Initializer, Setter) {
1262+
AssignOrInitInst::AssignOrInitInst(SILDebugLocation Loc, SILValue Self,
1263+
SILValue Src, SILValue Initializer,
1264+
SILValue Setter, AssignOrInitInst::Mode Mode)
1265+
: InstructionBase<SILInstructionKind::AssignOrInitInst,
1266+
NonValueInstruction>(Loc),
1267+
Operands(this, Self, Src, Initializer, Setter) {
12671268
assert(Initializer->getType().is<SILFunctionType>());
12681269
sharedUInt8().AssignOrInitInst.mode = uint8_t(Mode);
12691270
Assignments.resize(getNumInitializedProperties());
@@ -1290,10 +1291,17 @@ bool AssignOrInitInst::isPropertyAlreadyInitialized(unsigned propertyIdx) {
12901291
}
12911292

12921293
AccessorDecl *AssignOrInitInst::getReferencedInitAccessor() const {
1293-
auto *initRef = cast<FunctionRefInst>(getInitializer());
1294-
auto *accessorRef = initRef->getReferencedFunctionOrNull();
1295-
assert(accessorRef);
1296-
return dyn_cast_or_null<AccessorDecl>(accessorRef->getDeclContext());
1294+
SILValue initRef = getInitializer();
1295+
SILFunction *accessorFn = nullptr;
1296+
1297+
if (auto *PAI = dyn_cast<PartialApplyInst>(initRef)) {
1298+
accessorFn = PAI->getReferencedFunctionOrNull();
1299+
} else {
1300+
accessorFn = cast<FunctionRefInst>(initRef)->getReferencedFunctionOrNull();
1301+
}
1302+
1303+
assert(accessorFn);
1304+
return dyn_cast_or_null<AccessorDecl>(accessorFn->getDeclContext());
12971305
}
12981306

12991307
unsigned AssignOrInitInst::getNumInitializedProperties() const {

lib/SIL/IR/SILPrinter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1806,7 +1806,8 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
18061806
}
18071807
}
18081808

1809-
*this << getIDAndType(AI->getSrc());
1809+
*this << "self " << getIDAndType(AI->getSelf());
1810+
*this << ", value " << getIDAndType(AI->getSrc());
18101811
*this << ", init " << getIDAndType(AI->getInitializer())
18111812
<< ", set " << getIDAndType(AI->getSetter());
18121813
}

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4745,21 +4745,23 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
47454745
}
47464746

47474747
case SILInstructionKind::AssignOrInitInst: {
4748-
SILValue Src, InitFn, SetFn;
4748+
SILValue Self, Src, InitFn, SetFn;
47494749
AssignOrInitInst::Mode Mode;
47504750
llvm::SmallVector<unsigned, 2> assignments;
47514751

47524752
if (parseAssignOrInitMode(Mode, *this) ||
47534753
parseAssignOrInitAssignments(assignments, *this) ||
4754-
parseTypedValueRef(Src, B) ||
4754+
parseVerbatim("self") || parseTypedValueRef(Self, B) ||
4755+
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
4756+
parseVerbatim("value") || parseTypedValueRef(Src, B) ||
47554757
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
47564758
parseVerbatim("init") || parseTypedValueRef(InitFn, B) ||
47574759
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
47584760
parseVerbatim("set") || parseTypedValueRef(SetFn, B) ||
47594761
parseSILDebugLocation(InstLoc, B))
47604762
return true;
47614763

4762-
auto *AI = B.createAssignOrInit(InstLoc, Src, InitFn, SetFn, Mode);
4764+
auto *AI = B.createAssignOrInit(InstLoc, Self, Src, InitFn, SetFn, Mode);
47634765

47644766
for (unsigned index : assignments)
47654767
AI->markAsInitialized(index);

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2725,17 +2725,12 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
27252725
SILValue initFn = AI->getInitializer();
27262726
SILValue setterFn = AI->getSetter();
27272727

2728-
CanSILFunctionType initTy = initFn->getType().castTo<SILFunctionType>();
27292728
// Check init - it's an unapplied reference that takes property addresses
27302729
// and `initialValue`.
27312730
{
2732-
// We need to map un-applied function reference into context before
2733-
// check `initialValue` argument.
2734-
auto subs = cast<PartialApplyInst>(setterFn)->getSubstitutionMap();
2735-
initTy = initTy->substGenericArgs(F.getModule(), subs,
2736-
F.getTypeExpansionContext());
2737-
2731+
CanSILFunctionType initTy = initFn->getType().castTo<SILFunctionType>();
27382732
SILFunctionConventions initConv(initTy, AI->getModule());
2733+
27392734
require(initConv.getNumIndirectSILResults() ==
27402735
AI->getInitializedProperties().size(),
27412736
"init function has invalid number of indirect results");

lib/SILGen/SILGenLValue.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,6 +1618,25 @@ namespace {
16181618
SGF.getTypeExpansionContext());
16191619
};
16201620

1621+
auto emitPartialInitAccessorApply =
1622+
[&](AccessorDecl *initAccessor) -> SILValue {
1623+
assert(initAccessor->isInitAccessor());
1624+
auto initConstant = SGF.getAccessorDeclRef(initAccessor);
1625+
SILValue initFRef = SGF.emitGlobalFunctionRef(loc, initConstant);
1626+
1627+
// If there are no substitutions there is no need to emit partial
1628+
// apply.
1629+
if (Substitutions.empty())
1630+
return initFRef;
1631+
1632+
// Emit partial apply without argument to produce a substituted
1633+
// init accessor reference.
1634+
PartialApplyInst *initPAI = SGF.B.createPartialApply(
1635+
loc, initFRef, Substitutions, ArrayRef<SILValue>(),
1636+
ParameterConvention::Direct_Guaranteed);
1637+
return SGF.emitManagedRValueWithCleanup(initPAI).getValue();
1638+
};
1639+
16211640
auto emitPartialSetterApply =
16221641
[&](SILValue setterFRef,
16231642
const SILFunctionConventions &setterConv) -> ManagedValue {
@@ -1707,9 +1726,8 @@ namespace {
17071726
}
17081727

17091728
// Emit the init accessor function partially applied to the base.
1710-
auto *initAccessor = field->getOpaqueAccessor(AccessorKind::Init);
1711-
auto initConstant = SGF.getAccessorDeclRef(initAccessor);
1712-
SILValue initFRef = SGF.emitGlobalFunctionRef(loc, initConstant);
1729+
auto initFn = emitPartialInitAccessorApply(
1730+
field->getOpaqueAccessor(AccessorKind::Init));
17131731

17141732
// Emit the set accessor function partially applied to the base.
17151733
auto setterFRef = getSetterFRef();
@@ -1719,8 +1737,8 @@ namespace {
17191737

17201738
// Create the assign_or_init with the initializer and setter.
17211739
auto value = emitValue(field, FieldType, setterTy, setterConv);
1722-
SGF.B.createAssignOrInit(loc, value.forward(SGF), initFRef,
1723-
setterFn.getValue(),
1740+
SGF.B.createAssignOrInit(loc, base.getValue(), value.forward(SGF),
1741+
initFn, setterFn.getValue(),
17241742
AssignOrInitInst::Unknown);
17251743
return;
17261744
}

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp

Lines changed: 43 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -655,8 +655,7 @@ class ElementUseCollector {
655655
private:
656656
void collectUses(SILValue Pointer, unsigned BaseEltNo);
657657
bool addClosureElementUses(PartialApplyInst *pai, Operand *argUse);
658-
void collectAssignOrInitUses(PartialApplyInst *pai, Operand *argUse,
659-
unsigned BaseEltNo = 0);
658+
void collectAssignOrInitUses(AssignOrInitInst *pai, unsigned BaseEltNo = 0);
660659

661660
void collectClassSelfUses(SILValue ClassPointer);
662661
void collectClassSelfUses(SILValue ClassPointer, SILType MemorySILType,
@@ -1088,14 +1087,17 @@ void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
10881087
if (User->isDebugInstruction())
10891088
continue;
10901089

1090+
if (auto *AI = dyn_cast<AssignOrInitInst>(User)) {
1091+
collectAssignOrInitUses(AI, BaseEltNo);
1092+
continue;
1093+
}
1094+
10911095
if (auto *PAI = dyn_cast<PartialApplyInst>(User)) {
10921096
if (onlyUsedByAssignByWrapper(PAI))
10931097
continue;
10941098

1095-
if (onlyUsedByAssignOrInit(PAI)) {
1096-
collectAssignOrInitUses(PAI, Op, BaseEltNo);
1099+
if (onlyUsedByAssignOrInit(PAI))
10971100
continue;
1098-
}
10991101

11001102
if (BaseEltNo == 0 && addClosureElementUses(PAI, Op))
11011103
continue;
@@ -1188,47 +1190,38 @@ bool ElementUseCollector::addClosureElementUses(PartialApplyInst *pai,
11881190
}
11891191

11901192
void
1191-
ElementUseCollector::collectAssignOrInitUses(PartialApplyInst *pai,
1192-
Operand *argUse,
1193+
ElementUseCollector::collectAssignOrInitUses(AssignOrInitInst *Inst,
11931194
unsigned BaseEltNo) {
1194-
for (Operand *Op : pai->getUses()) {
1195-
SILInstruction *User = Op->getUser();
1196-
if (!isa<AssignOrInitInst>(User) || Op->getOperandNumber() != 2) {
1197-
continue;
1198-
}
1199-
1200-
/// AssignOrInit doesn't operate on `self` so we need to make sure
1201-
/// that the flag is dropped before calling \c addElementUses.
1202-
llvm::SaveAndRestore<bool> X(IsSelfOfNonDelegatingInitializer, false);
1203-
1204-
auto *inst = cast<AssignOrInitInst>(User);
1205-
auto *typeDC = inst->getReferencedInitAccessor()
1206-
->getDeclContext()
1207-
->getSelfNominalTypeDecl();
1208-
1209-
auto selfTy = pai->getOperand(1)->getType();
1210-
1211-
auto addUse = [&](VarDecl *property, DIUseKind useKind) {
1212-
auto expansionContext = TypeExpansionContext(*pai->getFunction());
1213-
auto type = selfTy.getFieldType(property, Module, expansionContext);
1214-
addElementUses(Module.getFieldIndex(typeDC, property), type, User,
1215-
useKind, property);
1216-
};
1217-
1218-
auto initializedElts = inst->getInitializedProperties();
1219-
if (initializedElts.empty()) {
1220-
// Add a placeholder use that doesn't touch elements to make sure that
1221-
// the `assign_or_init` instruction gets the kind set when `initializes`
1222-
// list is empty.
1223-
trackUse(DIMemoryUse(User, DIUseKind::InitOrAssign, BaseEltNo, 0));
1224-
} else {
1225-
for (auto *property : initializedElts)
1226-
addUse(property, DIUseKind::InitOrAssign);
1227-
}
1195+
/// AssignOrInit doesn't operate on `self` so we need to make sure
1196+
/// that the flag is dropped before calling \c addElementUses.
1197+
llvm::SaveAndRestore<bool> X(IsSelfOfNonDelegatingInitializer, false);
12281198

1229-
for (auto *property : inst->getAccessedProperties())
1230-
addUse(property, DIUseKind::Load);
1199+
auto *typeDC = Inst->getReferencedInitAccessor()
1200+
->getDeclContext()
1201+
->getSelfNominalTypeDecl();
1202+
1203+
auto selfTy = Inst->getSelf()->getType();
1204+
1205+
auto addUse = [&](VarDecl *property, DIUseKind useKind) {
1206+
auto expansionContext = TypeExpansionContext(*Inst->getFunction());
1207+
auto type = selfTy.getFieldType(property, Module, expansionContext);
1208+
addElementUses(Module.getFieldIndex(typeDC, property), type, Inst, useKind,
1209+
property);
1210+
};
1211+
1212+
auto initializedElts = Inst->getInitializedProperties();
1213+
if (initializedElts.empty()) {
1214+
// Add a placeholder use that doesn't touch elements to make sure that
1215+
// the `assign_or_init` instruction gets the kind set when `initializes`
1216+
// list is empty.
1217+
trackUse(DIMemoryUse(Inst, DIUseKind::InitOrAssign, BaseEltNo, 0));
1218+
} else {
1219+
for (auto *property : initializedElts)
1220+
addUse(property, DIUseKind::InitOrAssign);
12311221
}
1222+
1223+
for (auto *property : Inst->getAccessedProperties())
1224+
addUse(property, DIUseKind::Load);
12321225
}
12331226

12341227
/// collectClassSelfUses - Collect all the uses of a 'self' pointer in a class
@@ -1626,17 +1619,20 @@ void ElementUseCollector::collectClassSelfUses(
16261619

16271620
if (User->isDebugInstruction())
16281621
continue;
1629-
1622+
1623+
if (auto *AI = dyn_cast<AssignOrInitInst>(User)) {
1624+
collectAssignOrInitUses(AI);
1625+
continue;
1626+
}
1627+
16301628
// If this is a partial application of self, then this is an escape point
16311629
// for it.
16321630
if (auto *PAI = dyn_cast<PartialApplyInst>(User)) {
16331631
if (onlyUsedByAssignByWrapper(PAI))
16341632
continue;
16351633

1636-
if (onlyUsedByAssignOrInit(PAI)) {
1637-
collectAssignOrInitUses(PAI, Op);
1634+
if (onlyUsedByAssignOrInit(PAI))
16381635
continue;
1639-
}
16401636

16411637
if (addClosureElementUses(PAI, Op))
16421638
continue;

lib/SILOptimizer/Mandatory/RawSILInstLowering.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,7 @@ lowerAssignOrInitInstruction(SILBuilderWithScope &b,
284284
CanSILFunctionType fTy = initFn->getType().castTo<SILFunctionType>();
285285
SILFunctionConventions convention(fTy, inst->getModule());
286286

287-
auto *setterPA = dyn_cast<PartialApplyInst>(inst->getSetter());
288-
assert(setterPA);
289-
290-
auto selfValue = setterPA->getOperand(1);
287+
auto selfValue = inst->getSelf();
291288
auto isRefSelf = selfValue->getType().getASTType()->mayHaveSuperclass();
292289

293290
SILValue selfRef;
@@ -337,18 +334,21 @@ lowerAssignOrInitInstruction(SILBuilderWithScope &b,
337334
for (auto *property : inst->getAccessedProperties())
338335
arguments.push_back(emitFieldReference(property));
339336

340-
b.createApply(loc, initFn, setterPA->getSubstitutionMap(), arguments);
337+
b.createApply(loc, initFn, SubstitutionMap(), arguments);
341338

342339
if (isRefSelf) {
343340
b.emitEndBorrowOperation(loc, selfRef);
344341
} else {
345342
b.createEndAccess(loc, selfRef, /*aborted=*/false);
346343
}
347344

345+
auto *setterPA = dyn_cast<PartialApplyInst>(inst->getSetter());
346+
assert(setterPA);
347+
348348
// The unused partial_apply violates memory lifetime rules in case "self"
349349
// is an inout. Therefore we cannot keep it as a dead closure to be
350350
// cleaned up later. We have to delete it in this pass.
351-
toDelete.insert(inst->getSetter());
351+
toDelete.insert(setterPA);
352352

353353
// Also the argument of the closure (which usually is a "load") has to be
354354
// deleted to avoid memory lifetime violations.

0 commit comments

Comments
 (0)