Skip to content

Commit b22e8e6

Browse files
committed
[SIL] InitAccessors: Add tracking of properties that require assign instead of initialization
Some properties from `initializes(...)` list could be already initialized, which means that Raw SIL lowering has to emit `destroy_addr` for them before calling init accessor.
1 parent 0e61a75 commit b22e8e6

File tree

3 files changed

+52
-10
lines changed

3 files changed

+52
-10
lines changed

include/swift/AST/Attr.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,6 +1568,8 @@ class InitializesAttr final
15681568
return numProperties;
15691569
}
15701570

1571+
unsigned getNumProperties() const { return numProperties; }
1572+
15711573
ArrayRef<Identifier> getProperties() const {
15721574
return {getTrailingObjects<Identifier>(), numProperties};
15731575
}

include/swift/SIL/SILInstruction.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4951,6 +4951,11 @@ class AssignOrInitInst
49514951

49524952
FixedOperandList<3> Operands;
49534953

4954+
/// Marks all of the properties in `initializes(...)` list that
4955+
/// have been initialized before this intruction to help Raw SIL
4956+
/// lowering to emit destroys.
4957+
llvm::BitVector Assignments;
4958+
49544959
public:
49554960
enum Mode {
49564961
/// The mode is not decided yet (by DefiniteInitialization).
@@ -4981,6 +4986,17 @@ class AssignOrInitInst
49814986
sharedUInt8().AssignOrInitInst.mode = uint8_t(mode);
49824987
}
49834988

4989+
/// Mark a property from `initializes(...)` list as initialized
4990+
/// before this instruction.
4991+
void markAsInitialized(VarDecl *property);
4992+
4993+
/// Check whether a property from `initializes(...)` list with
4994+
/// the given index has already been initialized and requires
4995+
/// destroy before it could be re-initialized.
4996+
bool isPropertyAlreadyInitialized(unsigned propertyIdx);
4997+
4998+
unsigned getNumInitializedProperties() const;
4999+
49845000
ArrayRef<VarDecl *> getInitializedProperties() const;
49855001
ArrayRef<VarDecl *> getAccessedProperties() const;
49865002

lib/SIL/IR/SILInstructions.cpp

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,27 +1263,51 @@ AssignOrInitInst::AssignOrInitInst(SILDebugLocation Loc, SILValue Src,
12631263
Operands(this, Src, Initializer, Setter) {
12641264
assert(Initializer->getType().is<SILFunctionType>());
12651265
sharedUInt8().AssignOrInitInst.mode = uint8_t(Mode);
1266+
Assignments.resize(getNumInitializedProperties());
1267+
}
1268+
1269+
void AssignOrInitInst::markAsInitialized(VarDecl *property) {
1270+
auto toInitProperties = getInitializedProperties();
1271+
for (unsigned index : indices(toInitProperties)) {
1272+
if (toInitProperties[index] == property) {
1273+
Assignments.set(index);
1274+
break;
1275+
}
1276+
}
1277+
}
1278+
1279+
bool AssignOrInitInst::isPropertyAlreadyInitialized(unsigned propertyIdx) {
1280+
assert(propertyIdx < Assignments.size());
1281+
return Assignments.test(propertyIdx);
12661282
}
12671283

12681284
AccessorDecl *AssignOrInitInst::getReferencedInitAccessor() const {
1269-
auto *initRef =
1270-
cast<FunctionRefInst>(getInitializer()->getDefiningInstruction());
1271-
auto *accessorRef = initRef->getReferencedFunction();
1272-
return cast<AccessorDecl>(accessorRef->getDeclContext());
1285+
auto *initRef = cast<FunctionRefInst>(getInitializer());
1286+
auto *accessorRef = initRef->getReferencedFunctionOrNull();
1287+
assert(accessorRef);
1288+
return dyn_cast_or_null<AccessorDecl>(accessorRef->getDeclContext());
1289+
}
1290+
1291+
unsigned AssignOrInitInst::getNumInitializedProperties() const {
1292+
if (auto *accessor = getReferencedInitAccessor()) {
1293+
auto *initAttr = accessor->getAttrs().getAttribute<InitializesAttr>();
1294+
return initAttr ? initAttr->getNumProperties() : 0;
1295+
}
1296+
return 0;
12731297
}
12741298

12751299
ArrayRef<VarDecl *> AssignOrInitInst::getInitializedProperties() const {
1276-
auto *accessor = getReferencedInitAccessor();
1277-
if (auto *initAttr = accessor->getAttrs().getAttribute<InitializesAttr>()) {
1278-
return initAttr->getPropertyDecls(accessor);
1300+
if (auto *accessor = getReferencedInitAccessor()) {
1301+
if (auto *initAttr = accessor->getAttrs().getAttribute<InitializesAttr>())
1302+
return initAttr->getPropertyDecls(accessor);
12791303
}
12801304
return {};
12811305
}
12821306

12831307
ArrayRef<VarDecl *> AssignOrInitInst::getAccessedProperties() const {
1284-
auto *accessor = getReferencedInitAccessor();
1285-
if (auto *accessAttr = accessor->getAttrs().getAttribute<AccessesAttr>()) {
1286-
return accessAttr->getPropertyDecls(accessor);
1308+
if (auto *accessor = getReferencedInitAccessor()) {
1309+
if (auto *accessAttr = accessor->getAttrs().getAttribute<AccessesAttr>())
1310+
return accessAttr->getPropertyDecls(accessor);
12871311
}
12881312
return {};
12891313
}

0 commit comments

Comments
 (0)