adding the @_compilerInitialized attribute

This attribute is designed for let-bound variables whose initializing
assignment is synthesized by the compiler. This assignment is
expected to happen at some point before DefiniteInitialization has
run, which is the pass that verifies whether the compiler truly
initialized the variable.

I generally expect that this will never be a user-facing feature, and
that the synthesized assignment happens in SILGen.
This commit is contained in:
Kavon Farvardin
2022-03-11 10:13:02 -07:00
parent 6c0cfac69a
commit 13cbe0dd15
11 changed files with 170 additions and 3 deletions

View File

@@ -524,6 +524,10 @@ private:
/// of this.
bool InEnumSubElement = false;
/// If true, then encountered uses correspond to a VarDecl marked
/// as \p @_compilerInitialized
bool InCompilerInitializedField = false;
public:
ElementUseCollector(const DIMemoryObjectInfo &TheMemory,
DIElementUseInfo &UseInfo,
@@ -665,6 +669,16 @@ static SILValue getAccessedPointer(SILValue Pointer) {
return Pointer;
}
static DIUseKind verifyCompilerInitialized(SILValue pointer,
SILInstruction *write,
DIUseKind origKind) {
// if the write is _not_ auto-generated, it's a bad store.
if (!write->getLoc().isAutoGenerated())
return DIUseKind::BadExplicitStore;
return origKind;
}
void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
assert(Pointer->getType().isAddress() &&
"Walked through the pointer to the value?");
@@ -733,6 +747,11 @@ void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
else
Kind = DIUseKind::Initialization;
// If it's a non-synthesized write to a @_compilerInitialized field,
// indicate that in the Kind.
if (LLVM_UNLIKELY(InCompilerInitializedField))
Kind = verifyCompilerInitialized(Pointer, User, Kind);
addElementUses(BaseEltNo, PointeeType, User, Kind);
continue;
}
@@ -1403,9 +1422,15 @@ void ElementUseCollector::collectClassSelfUses(
if (EltNumbering.count(REAI->getField()) != 0) {
assert(EltNumbering.count(REAI->getField()) &&
"ref_element_addr not a local field?");
// Remember whether the field is marked '@_compilerInitialized'
const bool hasCompInit =
REAI->getField()->getAttrs().hasAttribute<CompilerInitializedAttr>();
llvm::SaveAndRestore<bool> X1(InCompilerInitializedField, hasCompInit);
// Recursively collect uses of the fields. Note that fields of the class
// could be tuples, so they may be tracked as independent elements.
llvm::SaveAndRestore<bool> X(IsSelfOfNonDelegatingInitializer, false);
llvm::SaveAndRestore<bool> X2(IsSelfOfNonDelegatingInitializer, false);
collectUses(REAI, EltNumbering[REAI->getField()]);
continue;
}