diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h index 8ebd4f240cf94..40d0b1783d032 100644 --- a/include/swift/SIL/SILBuilder.h +++ b/include/swift/SIL/SILBuilder.h @@ -956,13 +956,15 @@ class SILBuilder { } AssignOrInitInst *createAssignOrInit(SILLocation Loc, + VarDecl *Property, SILValue Self, SILValue Src, SILValue Initializer, SILValue Setter, AssignOrInitInst::Mode Mode) { - return insert(new (getModule()) AssignOrInitInst( - getSILDebugLocation(Loc), Self, Src, Initializer, Setter, Mode)); + return insert(new (getModule()) + AssignOrInitInst(getSILDebugLocation(Loc), Property, Self, + Src, Initializer, Setter, Mode)); } StoreBorrowInst *createStoreBorrow(SILLocation Loc, SILValue Src, diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index 81f0b42e30388..05ac3044ee277 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -1356,6 +1356,7 @@ void SILCloner::visitAssignOrInitInst(AssignOrInitInst *Inst) { recordClonedInstruction( Inst, getBuilder().createAssignOrInit( getOpLocation(Inst->getLoc()), + Inst->getProperty(), getOpValue(Inst->getSelf()), getOpValue(Inst->getSrc()), getOpValue(Inst->getInitializer()), diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h index 9a7eb8c8dd49d..aa8762ba22767 100644 --- a/include/swift/SIL/SILInstruction.h +++ b/include/swift/SIL/SILInstruction.h @@ -4820,6 +4820,9 @@ class AssignOrInitInst FixedOperandList<4> Operands; + /// Property the init accessor is associated with. + VarDecl *Property; + /// Marks all of the properties in `initializes(...)` list that /// have been initialized before this intruction to help Raw SIL /// lowering to emit destroys. @@ -4838,10 +4841,12 @@ class AssignOrInitInst }; private: - AssignOrInitInst(SILDebugLocation DebugLoc, SILValue Self, SILValue Src, - SILValue Initializer, SILValue Setter, Mode mode); + AssignOrInitInst(SILDebugLocation DebugLoc, VarDecl *P, SILValue Self, + SILValue Src, SILValue Initializer, SILValue Setter, + Mode mode); public: + VarDecl *getProperty() const { return Property; } SILValue getSelf() const { return Operands[0].get(); } SILValue getSrc() const { return Operands[1].get(); } SILValue getInitializer() const { return Operands[2].get(); } diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 7fe4c9e3be1c7..60f6ab556d9ee 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -309,6 +309,11 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(ModuleDecl *ModuleToPrint, } } + if (auto *accessor = dyn_cast(D)) { + if (accessor->isInitAccessor() && !options.PrintForSIL) + return false; + } + return ShouldPrintChecker::shouldPrint(D, options); } }; @@ -2259,8 +2264,12 @@ void PrintAST::printAccessors(const AbstractStorageDecl *ASD) { accessorsToPrint.push_back(Accessor); }; + if (ASD->hasInitAccessor()) + AddAccessorToPrint(AccessorKind::Init); + if (PrintAbstract) { AddAccessorToPrint(AccessorKind::Get); + if (ASD->supportsMutation()) AddAccessorToPrint(AccessorKind::Set); } else { diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index 661f4a4d03407..f899b685131e2 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -1485,6 +1485,32 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options, break; } + case DAK_StorageRestrictions: { + auto *attr = cast(this); + Printer.printAttrName("@storageRestrictions"); + Printer << "("; + + auto initializes = attr->getInitializesNames(); + auto accesses = attr->getAccessesNames(); + + bool needsComma = !initializes.empty() && !accesses.empty(); + + if (!initializes.empty()) { + Printer << "initializes: "; + interleave(initializes, Printer, ", "); + } + + if (needsComma) + Printer << ", "; + + if (!accesses.empty()) { + Printer << "accesses: "; + interleave(accesses, Printer, ", "); + } + Printer << ")"; + break; + } + case DAK_Count: llvm_unreachable("exceed declaration attribute kinds"); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 51cb0c7ab2e79..764181353ed1d 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -7281,7 +7281,7 @@ static void diagnoseRedundantAccessors(Parser &P, SourceLoc loc, /*already*/ true); } -static bool isAllowedInProtocolRequirement(AccessorKind kind) { +static bool isAllowedWhenParsingLimitedSyntax(AccessorKind kind, bool forSIL) { switch (kind) { case AccessorKind::Get: case AccessorKind::Set: @@ -7293,8 +7293,10 @@ static bool isAllowedInProtocolRequirement(AccessorKind kind) { case AccessorKind::DidSet: case AccessorKind::Read: case AccessorKind::Modify: - case AccessorKind::Init: return false; + + case AccessorKind::Init: + return forSIL; } llvm_unreachable("bad accessor kind"); } @@ -7688,7 +7690,8 @@ ParserStatus Parser::parseGetSet(ParseDeclOptions Flags, ParameterList *Indices, // For now, immediately reject illegal accessors in protocols just to // avoid having to deal with them everywhere. - if (parsingLimitedSyntax && !isAllowedInProtocolRequirement(Kind)) { + if (parsingLimitedSyntax && !isAllowedWhenParsingLimitedSyntax( + Kind, SF.Kind == SourceFileKind::SIL)) { diagnose(Loc, diag::expected_getset_in_protocol); continue; } diff --git a/lib/SIL/IR/SILInstructions.cpp b/lib/SIL/IR/SILInstructions.cpp index 8e7a19753d256..6d99d2137c499 100644 --- a/lib/SIL/IR/SILInstructions.cpp +++ b/lib/SIL/IR/SILInstructions.cpp @@ -1259,12 +1259,13 @@ AssignByWrapperInst::AssignByWrapperInst(SILDebugLocation Loc, sharedUInt8().AssignByWrapperInst.mode = uint8_t(mode); } -AssignOrInitInst::AssignOrInitInst(SILDebugLocation Loc, SILValue Self, - SILValue Src, SILValue Initializer, - SILValue Setter, AssignOrInitInst::Mode Mode) +AssignOrInitInst::AssignOrInitInst(SILDebugLocation Loc, VarDecl *P, + SILValue Self, SILValue Src, + SILValue Initializer, SILValue Setter, + AssignOrInitInst::Mode Mode) : InstructionBase(Loc), - Operands(this, Self, Src, Initializer, Setter) { + Operands(this, Self, Src, Initializer, Setter), Property(P) { assert(Initializer->getType().is()); sharedUInt8().AssignOrInitInst.mode = uint8_t(Mode); Assignments.resize(getNumInitializedProperties()); @@ -1291,23 +1292,11 @@ bool AssignOrInitInst::isPropertyAlreadyInitialized(unsigned propertyIdx) { } StringRef AssignOrInitInst::getPropertyName() const { - auto *accessor = getReferencedInitAccessor(); - assert(accessor); - return cast(accessor->getStorage())->getNameStr(); + return Property->getNameStr(); } AccessorDecl *AssignOrInitInst::getReferencedInitAccessor() const { - SILValue initRef = getInitializer(); - SILFunction *accessorFn = nullptr; - - if (auto *PAI = dyn_cast(initRef)) { - accessorFn = PAI->getReferencedFunctionOrNull(); - } else { - accessorFn = cast(initRef)->getReferencedFunctionOrNull(); - } - - assert(accessorFn); - return dyn_cast_or_null(accessorFn->getDeclContext()); + return Property->getOpaqueAccessor(AccessorKind::Init); } unsigned AssignOrInitInst::getNumInitializedProperties() const { diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index e9dceabb76e8a..b1caaa0ce80ef 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -1806,7 +1806,11 @@ class SILPrinter : public SILInstructionVisitor { } } - *this << "self " << getIDAndType(AI->getSelf()); + *this << "#"; + printFullContext(AI->getProperty()->getDeclContext(), PrintState.OS); + *this << AI->getPropertyName(); + + *this << ", self " << getIDAndType(AI->getSelf()); *this << ", value " << getIDAndType(AI->getSrc()); *this << ", init " << getIDAndType(AI->getInitializer()) << ", set " << getIDAndType(AI->getSetter()); diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index 68c777b39a085..1387625908d59 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -4749,12 +4749,15 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B, } case SILInstructionKind::AssignOrInitInst: { + ValueDecl *Prop; SILValue Self, Src, InitFn, SetFn; AssignOrInitInst::Mode Mode; llvm::SmallVector assignments; if (parseAssignOrInitMode(Mode, *this) || parseAssignOrInitAssignments(assignments, *this) || + parseSILDottedPath(Prop) || + P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") || parseVerbatim("self") || parseTypedValueRef(Self, B) || P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") || parseVerbatim("value") || parseTypedValueRef(Src, B) || @@ -4765,7 +4768,8 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B, parseSILDebugLocation(InstLoc, B)) return true; - auto *AI = B.createAssignOrInit(InstLoc, Self, Src, InitFn, SetFn, Mode); + auto *AI = B.createAssignOrInit(InstLoc, cast(Prop), Self, Src, + InitFn, SetFn, Mode); for (unsigned index : assignments) AI->markAsInitialized(index); diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 820b47576cf59..66ee58e9914c2 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -2736,7 +2736,7 @@ class SILVerifier : public SILVerifierBase { SILFunctionConventions initConv(initTy, AI->getModule()); require(initConv.getNumIndirectSILResults() == - AI->getInitializedProperties().size(), + AI->getNumInitializedProperties(), "init function has invalid number of indirect results"); checkAssigOrInitInstAccessorArgs(Src->getType(), initConv); } diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index da22c25ed934c..14a3d71d7b5e5 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -1859,6 +1859,7 @@ void SILGenFunction::emitAssignOrInit(SILLocation loc, ManagedValue selfValue, setterFRef = SILUndef::get(initFRef->getType(), F); } - B.createAssignOrInit(loc, selfValue.getValue(), newValue.forward(*this), - initFRef, setterFRef, AssignOrInitInst::Unknown); + B.createAssignOrInit(loc, field, selfValue.getValue(), + newValue.forward(*this), initFRef, setterFRef, + AssignOrInitInst::Unknown); } diff --git a/test/SILOptimizer/init_accessor_raw_sil_lowering.swift b/test/SILOptimizer/init_accessor_raw_sil_lowering.swift index a894f71f0d9e2..640cd044b0a4c 100644 --- a/test/SILOptimizer/init_accessor_raw_sil_lowering.swift +++ b/test/SILOptimizer/init_accessor_raw_sil_lowering.swift @@ -48,11 +48,11 @@ final class TestIndirectionThroughStorage { // CHECK: [[STORAGE_INIT:%.*]] = function_ref @$s23assign_or_init_lowering29TestIndirectionThroughStorageC8_storage33_DE106275C2F16FB3D05881E72FBD87C8LLAA0H0_pAC1TAaFPRts_XPvpfi : $@convention(thin) () -> @out any Storage // CHECK-NEXT: {{.*}} = apply [[STORAGE_INIT]]([[STORAGE_REF]]) : $@convention(thin) () -> @out any Storage // Initialization: - // CHECK: assign_or_init [set] self %2 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> () - // CHECK: assign_or_init [set] self %2 : $TestIndirectionThroughStorage, value {{.*}} : $Optional, init {{.*}} : $@convention(thin) (Optional, @inout any Storage) -> (), set {{.*}} : $@callee_guaranteed (Optional) -> ( + // CHECK: assign_or_init [set] #TestIndirectionThroughStorage.name, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> () + // CHECK: assign_or_init [set] #TestIndirectionThroughStorage.age, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $Optional, init {{.*}} : $@convention(thin) (Optional, @inout any Storage) -> (), set {{.*}} : $@callee_guaranteed (Optional) -> ( // Explicit set: - // CHECK: assign_or_init [set] self %2 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> () - // CHECK: assign_or_init [set] self %2 : $TestIndirectionThroughStorage, value {{.*}} : $Optional, init {{.*}} : $@convention(thin) (Optional, @inout any Storage) -> (), set {{.*}} : $@callee_guaranteed (Optional) -> ( + // CHECK: assign_or_init [set] #TestIndirectionThroughStorage.name, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> () + // CHECK: assign_or_init [set] #TestIndirectionThroughStorage.age, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $Optional, init {{.*}} : $@convention(thin) (Optional, @inout any Storage) -> (), set {{.*}} : $@callee_guaranteed (Optional) -> ( init(name: String, age: Int) { self.name = name self.age = age @@ -63,8 +63,8 @@ final class TestIndirectionThroughStorage { // CHECK: [[STORAGE_INIT:%.*]] = function_ref @$s23assign_or_init_lowering29TestIndirectionThroughStorageC8_storage33_DE106275C2F16FB3D05881E72FBD87C8LLAA0H0_pAC1TAaFPRts_XPvpfi : $@convention(thin) () -> @out any Storage // CHECK-NEXT: {{.*}} = apply [[STORAGE_INIT]]([[STORAGE_REF]]) : $@convention(thin) () -> @out any Storage // Initialization: - // CHECK: assign_or_init [set] self %1 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> () - // CHECK: assign_or_init [set] self %1 : $TestIndirectionThroughStorage, value {{.*}} : $Optional, init {{.*}} : $@convention(thin) (Optional, @inout any Storage) -> (), set {{.*}} : $@callee_guaranteed (Optional) -> () + // CHECK: assign_or_init [set] #TestIndirectionThroughStorage.name, self %1 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> () + // CHECK: assign_or_init [set] #TestIndirectionThroughStorage.age, self %1 : $TestIndirectionThroughStorage, value {{.*}} : $Optional, init {{.*}} : $@convention(thin) (Optional, @inout any Storage) -> (), set {{.*}} : $@callee_guaranteed (Optional) -> () // Explicit set: // CHECK: [[STORAGE_SETTER:%.*]] = function_ref @$s23assign_or_init_lowering29TestIndirectionThroughStorageC7storageAA0H0_pAC1TAaEPRts_XPvs : $@convention(method) (@in any Storage, @guaranteed TestIndirectionThroughStorage) -> () // CHECK-NEXT: {{.*}} = apply [[STORAGE_SETTER]]({{.*}}, %1) : $@convention(method) (@in any Storage, @guaranteed TestIndirectionThroughStorage) -> () @@ -104,8 +104,8 @@ struct TestAccessOfOnePatternVars { // CHECK-NEXT: {{.*}} = apply [[Y_INIT]]() : $@convention(thin) () -> @owned String // CHECK-NOT: [[X_REF:%.*]] = struct_element_addr %3 : $*TestAccessOfOnePatternVars, #TestAccessOfOnePatternVars.x // CHECK-NOT: [[Y_REF:%.*]] = struct_element_addr {{.*}} : $*TestAccessOfOnePatternVars, #TestAccessOfOnePatternVars.y - // CHECK: assign_or_init [set] self {{.*}} : $*TestAccessOfOnePatternVars, value {{.*}} : $(Int, String), init {{.*}} : $@convention(thin) (Int, @owned String, @inout Int, @inout String) -> (), set {{.*}} : $@callee_guaranteed (Int, @owned String) -> () - // CHECK: assign_or_init [set] self {{.*}} : $*TestAccessOfOnePatternVars, value {{.*}} : $Bool, init {{.*}} : $@convention(thin) (Bool, @inout Int) -> (), set {{.*}} : $@callee_guaranteed (Bool) -> () + // CHECK: assign_or_init [set] #TestAccessOfOnePatternVars.data, self {{.*}} : $*TestAccessOfOnePatternVars, value {{.*}} : $(Int, String), init {{.*}} : $@convention(thin) (Int, @owned String, @inout Int, @inout String) -> (), set {{.*}} : $@callee_guaranteed (Int, @owned String) -> () + // CHECK: assign_or_init [set] #TestAccessOfOnePatternVars.other, self {{.*}} : $*TestAccessOfOnePatternVars, value {{.*}} : $Bool, init {{.*}} : $@convention(thin) (Bool, @inout Int) -> (), set {{.*}} : $@callee_guaranteed (Bool) -> () init(x: Int, y: String) { self.x = x self.y = y @@ -140,14 +140,14 @@ struct Test1 { // CHECK-LABEL: sil hidden [ossa] @$s23assign_or_init_lowering5Test1V1aACSi_tcfC : $@convention(method) (Int, @thin Test1.Type) -> @owned Test1 init(a: Int) { // CHECK: [[INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering5Test1V1aSivi : $@convention(thin) (Int) -> @out Int - // CHECK: assign_or_init [init] self {{.*}}, value [[VALUE:%.*]] : $Int, init [[INIT_REF]] : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> () + // CHECK: assign_or_init [init] #Test1.a, self {{.*}}, value [[VALUE:%.*]] : $Int, init [[INIT_REF]] : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> () self.a = a // CHECK: [[INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering5Test1V1bSSvi : $@convention(thin) (@owned String) -> (@out Int, @out String) - // CHECK: assign_or_init [init] [assign=0] self {{.*}}, value [[VALUE:%.*]] : $String, init [[INIT_REF]] : $@convention(thin) (@owned String) -> (@out Int, @out String), set {{.*}} : $@callee_guaranteed (@owned String) -> () + // CHECK: assign_or_init [init] [assign=0] #Test1.b, self {{.*}}, value [[VALUE:%.*]] : $String, init [[INIT_REF]] : $@convention(thin) (@owned String) -> (@out Int, @out String), set {{.*}} : $@callee_guaranteed (@owned String) -> () self.a = -1 self.b = "" // CHECK: [[INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering5Test1V1aSivi : $@convention(thin) (Int) -> @out Int - // CHECK: assign_or_init [set] self {{.*}}, value [[VALUE:%.*]] : $Int, init [[INIT_REF]] : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> () + // CHECK: assign_or_init [set] #Test1.a, self {{.*}}, value [[VALUE:%.*]] : $Int, init [[INIT_REF]] : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> () self.a = a } } @@ -172,16 +172,16 @@ struct Test2 { init(a: Int, b: T) { // CHECK: [[INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering5Test2V4pairSi_xtvi : $@convention(thin) <τ_0_0> (Int, @in τ_0_0) -> (@out Int, @out τ_0_0) // CHECK-NEXT: [[SUBST_INIT_REF:%.*]] = partial_apply [callee_guaranteed] [[INIT_REF]]() : $@convention(thin) <τ_0_0> (Int, @in τ_0_0) -> (@out Int, @out τ_0_0) - // CHECK: assign_or_init [init] self {{.*}}, value [[VALUE:%.*]] : $*(Int, T), init [[SUBST_INIT_REF]] : $@callee_guaranteed (Int, @in T) -> (@out Int, @out T), set {{.*}} : $@callee_guaranteed (Int, @in T) -> () + // CHECK: assign_or_init [init] #Test2.pair, self {{.*}}, value [[VALUE:%.*]] : $*(Int, T), init [[SUBST_INIT_REF]] : $@callee_guaranteed (Int, @in T) -> (@out Int, @out T), set {{.*}} : $@callee_guaranteed (Int, @in T) -> () self.pair = (a, b) // CHECK: [[INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering5Test2V4pairSi_xtvi : $@convention(thin) <τ_0_0> (Int, @in τ_0_0) -> (@out Int, @out τ_0_0) // CHECK-NEXT: [[SUBST_INIT_REF:%.*]] = partial_apply [callee_guaranteed] [[INIT_REF]]() : $@convention(thin) <τ_0_0> (Int, @in τ_0_0) -> (@out Int, @out τ_0_0) - // CHECK: assign_or_init [init] [assign=0] [assign=1] self {{.*}}, value [[VALUE:%.*]] : $*(Int, T), init [[SUBST_INIT_REF]] : $@callee_guaranteed (Int, @in T) -> (@out Int, @out T), set {{.*}} : $@callee_guaranteed (Int, @in T) -> () + // CHECK: assign_or_init [init] [assign=0] [assign=1] #Test2.pair, self {{.*}}, value [[VALUE:%.*]] : $*(Int, T), init [[SUBST_INIT_REF]] : $@callee_guaranteed (Int, @in T) -> (@out Int, @out T), set {{.*}} : $@callee_guaranteed (Int, @in T) -> () self.pair = (0, b) self._c = "" // CHECK: [[INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering5Test2V4pairSi_xtvi : $@convention(thin) <τ_0_0> (Int, @in τ_0_0) -> (@out Int, @out τ_0_0) // CHECK-NEXT: [[SUBST_INIT_REF:%.*]] = partial_apply [callee_guaranteed] [[INIT_REF]]() : $@convention(thin) <τ_0_0> (Int, @in τ_0_0) -> (@out Int, @out τ_0_0) - // CHECK: assign_or_init [set] self {{.*}}, value [[VALUE:%.*]] : $*(Int, T), init [[SUBST_INIT_REF]] : $@callee_guaranteed (Int, @in T) -> (@out Int, @out T), set {{.*}} : $@callee_guaranteed (Int, @in T) -> () + // CHECK: assign_or_init [set] #Test2.pair, self {{.*}}, value [[VALUE:%.*]] : $*(Int, T), init [[SUBST_INIT_REF]] : $@callee_guaranteed (Int, @in T) -> (@out Int, @out T), set {{.*}} : $@callee_guaranteed (Int, @in T) -> () self.pair = (1, b) } } @@ -198,7 +198,7 @@ struct Test { // CHECK-LABEL: sil hidden [ossa] @$s23assign_or_init_lowering4TestV1vACSi_tcfC : $@convention(method) (Int, @thin Test.Type) -> Test init(v: Int) { // CHECK: [[INIT_REF:%.*]] = function_ref @$s23assign_or_init_lowering4TestV4testSivi : $@convention(thin) (Int) -> () - // CHECK: assign_or_init [set] self {{.*}}, value %0 : $Int, init [[INIT_REF]] : $@convention(thin) (Int) -> (), set {{.*}} : $@callee_guaranteed (Int) -> () + // CHECK: assign_or_init [set] #Test.test, self {{.*}}, value %0 : $Int, init [[INIT_REF]] : $@convention(thin) (Int) -> (), set {{.*}} : $@callee_guaranteed (Int) -> () self.test = v } } @@ -227,7 +227,7 @@ func test_default_inits() { // CHECK: [[INIT_ACCESSOR:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test1L_V1xSivi : $@convention(thin) (Int) -> @out Int // CHECK: [[SETTER_REF:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test1L_V1xSivs : $@convention(method) (Int, @inout Test1) -> () // CHECK-NEXT: [[SETTER:%.*]] = partial_apply [callee_guaranteed] [[SETTER_REF]]([[SELF_REF]]) : $@convention(method) (Int, @inout Test1) -> () - // CHECK-NEXT: assign_or_init [init] self [[SELF_REF]] : $*Test1, value [[INIT_VAL]] : $Int, init [[INIT_ACCESSOR]] : $@convention(thin) (Int) -> @out Int, set [[SETTER]] : $@callee_guaranteed (Int) -> () + // CHECK-NEXT: assign_or_init [init] #Test1.x, self [[SELF_REF]] : $*Test1, value [[INIT_VAL]] : $Int, init [[INIT_ACCESSOR]] : $@convention(thin) (Int) -> @out Int, set [[SETTER]] : $@callee_guaranteed (Int) -> () // CHECK-NEXT: end_access [[SELF_REF]] : $*Test1 // CHECK-NEXT: destroy_value [[SETTER]] : $@callee_guaranteed (Int) -> () init() { @@ -240,11 +240,11 @@ func test_default_inits() { // CHECK: [[INIT_ACCESSOR:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test1L_V1xSivi : $@convention(thin) (Int) -> @out Int // CHECK: [[SETTER_REF:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test1L_V1xSivs : $@convention(method) (Int, @inout Test1) -> () // CHECK-NEXT: [[SETTER:%.*]] = partial_apply [callee_guaranteed] [[SETTER_REF]]([[SELF_REF]]) : $@convention(method) (Int, @inout Test1) -> () - // CHECK-NEXT: assign_or_init [init] self [[SELF_REF]] : $*Test1, value [[INIT_VAL]] : $Int, init [[INIT_ACCESSOR]] : $@convention(thin) (Int) -> @out Int, set [[SETTER]] : $@callee_guaranteed (Int) -> () + // CHECK-NEXT: assign_or_init [init] #Test1.x, self [[SELF_REF]] : $*Test1, value [[INIT_VAL]] : $Int, init [[INIT_ACCESSOR]] : $@convention(thin) (Int) -> @out Int, set [[SETTER]] : $@callee_guaranteed (Int) -> () // CHECK-NEXT: end_access [[SELF_REF]] : $*Test1 // CHECK-NEXT: destroy_value [[SETTER]] : $@callee_guaranteed (Int) -> () // - // CHECK: assign_or_init [set] self {{.*}} : $*Test1, value %0 : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> () + // CHECK: assign_or_init [set] #Test1.x, self {{.*}} : $*Test1, value %0 : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> () init(x: Int) { self.x = x } @@ -278,7 +278,7 @@ func test_default_inits() { // CHECK: [[SETTER_REF:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test2L_C1xx_SStvs : $@convention(method) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @owned String, @guaranteed Test2<τ_0_0>) -> () // CHECK-NEXT: [[SELF:%.*]] = copy_value %0 : $Test2 // CHECK-NEXT: [[SETTER:%.*]] = partial_apply [callee_guaranteed] [[SETTER_REF]]([[SELF]]) : $@convention(method) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @owned String, @guaranteed Test2<τ_0_0>) -> () - // CHECK-NEXT: assign_or_init [init] self %0 : $Test2, value [[NEW_VALUE]] : $*(T, String), init [[INIT_ACCESSOR]] : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set [[SETTER]] : $@callee_guaranteed (@in T, @owned String) -> () + // CHECK-NEXT: assign_or_init [init] #Test2.x, self %0 : $Test2, value [[NEW_VALUE]] : $*(T, String), init [[INIT_ACCESSOR]] : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set [[SETTER]] : $@callee_guaranteed (@in T, @owned String) -> () // CHECK-NEXT: destroy_value [[SETTER]] : $@callee_guaranteed (@in T, @owned String) -> () // CHECK-NEXT: destroy_value [[INIT_ACCESSOR]] : $@callee_guaranteed (@in T, @owned String) -> @out (T, String) // CHECK-NEXT: dealloc_stack [[NEW_VALUE]] : $*(T, String) @@ -301,15 +301,15 @@ func test_default_inits() { // CHECK: [[SETTER_REF:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test2L_C1xx_SStvs : $@convention(method) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @owned String, @guaranteed Test2<τ_0_0>) -> () // CHECK-NEXT: [[SELF:%.*]] = copy_value %3 : $Test2 // CHECK-NEXT: [[SETTER:%.*]] = partial_apply [callee_guaranteed] [[SETTER_REF]]([[SELF]]) : $@convention(method) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @owned String, @guaranteed Test2<τ_0_0>) -> () - // CHECK-NEXT: assign_or_init [init] self %3 : $Test2, value [[NEW_VALUE]] : $*(T, String), init [[INIT_ACCESSOR]] : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set [[SETTER]] : $@callee_guaranteed (@in T, @owned String) -> () + // CHECK-NEXT: assign_or_init [init] #Test2.x, self %3 : $Test2, value [[NEW_VALUE]] : $*(T, String), init [[INIT_ACCESSOR]] : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set [[SETTER]] : $@callee_guaranteed (@in T, @owned String) -> () // CHECK-NEXT: destroy_value [[SETTER]] : $@callee_guaranteed (@in T, @owned String) -> () // CHECK-NEXT: destroy_value [[INIT_ACCESSOR]] : $@callee_guaranteed (@in T, @owned String) -> @out (T, String) // CHECK-NEXT: dealloc_stack [[NEW_VALUE]] : $*(T, String) // CHECK-NEXT: dealloc_stack [[T]] : $*T // - // CHECK: assign_or_init [init] [assign=0] self %3 : $Test2, value {{.*}} : $*(T, String), init {{.*}} : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set {{.*}} : $@callee_guaranteed (@in T, @owned String) -> () + // CHECK: assign_or_init [init] [assign=0] #Test2.x, self %3 : $Test2, value {{.*}} : $*(T, String), init {{.*}} : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set {{.*}} : $@callee_guaranteed (@in T, @owned String) -> () // CHECK: assign %2 to [init] [[Y_REF:%.*]] : $*Int - // CHECK: assign_or_init [set] self %3 : $Test2, value {{.*}} : $*(T, String), init {{.*}} : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set {{.*}} : $@callee_guaranteed (@in T, @owned String) -> () + // CHECK: assign_or_init [set] #Test2.x, self %3 : $Test2, value {{.*}} : $*(T, String), init {{.*}} : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set {{.*}} : $@callee_guaranteed (@in T, @owned String) -> () init(x: (T, String), y: Int) { self.x = x self.y = y @@ -368,10 +368,10 @@ func test_default_inits() { // CHECK-LABEL: sil private [ossa] @$s23assign_or_init_lowering18test_default_initsyyF5Test4L_CADycfc : $@convention(method) (@owned Test4) -> @owned Test4 // CHECK: [[X_DEFAULT:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test4L_C1xSivpfi : $@convention(thin) () -> Int // CHECK-NEXT: [[X_VALUE:%.*]] = apply [[X_DEFAULT]]() : $@convention(thin) () -> Int - // CHECK: assign_or_init [init] self %0 : $Test4, value [[X_VALUE]] : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set undef : $@convention(thin) (Int) -> @out Int + // CHECK: assign_or_init [init] #Test4.x, self %0 : $Test4, value [[X_VALUE]] : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set undef : $@convention(thin) (Int) -> @out Int // CHECK: [[Y_DEFAULT:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test4L_C1ySSvpfi : $@convention(thin) () -> @owned String // CHECK-NEXT: [[Y_VALUE:%.*]] = apply [[Y_DEFAULT]]() : $@convention(thin) () -> @owned String - // CHECK: assign_or_init [init] self %0 : $Test4, value [[Y_VALUE]] : $String, init {{.*}} : $@convention(thin) (@owned String) -> @out String, set undef : $@convention(thin) (@owned String) -> @out String + // CHECK: assign_or_init [init] #Test4.y, self %0 : $Test4, value [[Y_VALUE]] : $String, init {{.*}} : $@convention(thin) (@owned String) -> @out String, set undef : $@convention(thin) (@owned String) -> @out String } } diff --git a/test/SILOptimizer/init_accessors.sil b/test/SILOptimizer/init_accessors.sil new file mode 100644 index 0000000000000..2f24abea8d150 --- /dev/null +++ b/test/SILOptimizer/init_accessors.sil @@ -0,0 +1,97 @@ +// RUN: %target-sil-opt -enable-sil-verify-all -definite-init -raw-sil-inst-lowering -enable-experimental-feature InitAccessors %s | %FileCheck %s + +// REQUIRES: asserts + +import Builtin +import Swift +import SwiftShims + +struct Test { + @_hasStorage var _x: Int { get set } + var x: Int { + @storageRestrictions(initializes: _x) init + get + set + } + init(v: Int) + init(v: Int, other: Int) +} + +sil private [ossa] @$s14init_accessors4TestV1xSivi : $@convention(thin) (Int) -> @out Int { +bb0(%0 : $*Int, %1 : $Int): + %2 = mark_uninitialized [out] %0 : $*Int + debug_value %1 : $Int, let, name "newValue", argno 1, implicit + %4 = begin_access [modify] [unknown] %2 : $*Int + assign %1 to %4 : $*Int + end_access %4 : $*Int + %7 = tuple () + return %7 : $() +} + +sil hidden [ossa] @$s14init_accessors4TestV1xSivs : $@convention(method) (Int, @inout Test) -> () { +bb0(%0 : $Int, %1 : $*Test): + debug_value %0 : $Int, let, name "newValue", argno 1, implicit + debug_value %1 : $*Test, var, name "self", argno 2, implicit, expr op_deref + %4 = begin_access [modify] [unknown] %1 : $*Test + %5 = struct_element_addr %4 : $*Test, #Test._x + assign %0 to %5 : $*Int + end_access %4 : $*Test + %8 = tuple () + return %8 : $() +} + +// CHECK-LABEL: sil hidden [ossa] @$s14init_accessors4TestV1vACSi_tcfC : $@convention(method) (Int, @thin Test.Type) -> Test +// CHECK: [[INIT_REF:%.*]] = function_ref @$s14init_accessors4TestV1xSivi : $@convention(thin) (Int) -> @out Int +// CHECK: [[SELF_REF:%.*]] = begin_access [modify] [dynamic] [[SELF:%.*]] : $*Test +// CHECK-NEXT: [[FIELD_REF:%.*]] = struct_element_addr [[SELF_REF]] : $*Test, #Test._x +// CHECK-NEXT: {{.*}} = apply [[INIT_REF]]([[FIELD_REF]], %0) : $@convention(thin) (Int) -> @out Int +sil hidden [ossa] @$s14init_accessors4TestV1vACSi_tcfC : $@convention(method) (Int, @thin Test.Type) -> Test { +bb0(%0 : $Int, %1 : $@thin Test.Type): + %2 = alloc_box ${ var Test }, var, name "self" + %3 = mark_uninitialized [rootself] %2 : ${ var Test } + %4 = project_box %3 : ${ var Test }, 0 + debug_value %0 : $Int, let, name "v", argno 1 + %6 = begin_access [modify] [unknown] %4 : $*Test + %7 = function_ref @$s14init_accessors4TestV1xSivi : $@convention(thin) (Int) -> @out Int + %8 = function_ref @$s14init_accessors4TestV1xSivs : $@convention(method) (Int, @inout Test) -> () + %9 = partial_apply [callee_guaranteed] %8(%6) : $@convention(method) (Int, @inout Test) -> () + assign_or_init #Test.x, self %6 : $*Test, value %0 : $Int, init %7 : $@convention(thin) (Int) -> @out Int, set %9 : $@callee_guaranteed (Int) -> () + end_access %6 : $*Test + destroy_value %9 : $@callee_guaranteed (Int) -> () + %13 = load [trivial] %4 : $*Test + destroy_value %3 : ${ var Test } + return %13 : $Test +} + +// CHECK-LABEL: sil hidden [ossa] @$s14init_accessors4TestV1v5otherACSi_SitcfC : $@convention(method) (Int, Int, @thin Test.Type) -> Test +// CHECK: [[INIT_REF:%.*]] = function_ref @$s14init_accessors4TestV1xSivi : $@convention(thin) (Int) -> @out Int +// CHECK: [[FIELD_REF:%.*]] = struct_element_addr {{.*}} : $*Test, #Test._x +// CHECK-NEXT: {{.*}} = apply [[INIT_REF]]([[FIELD_REF]], %0) : $@convention(thin) (Int) -> @out Int +// CHECK: [[SETTER_REF:%.*]] = function_ref @$s14init_accessors4TestV1xSivs : $@convention(method) (Int, @inout Test) -> () +// CHECK-NEXT: [[SETTER_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[SETTER_REF]]([[SELF_REF:%.*]]) : $@convention(method) (Int, @inout Test) -> () +// CHECK-NEXT: {{.*}} = apply [[SETTER_CLOSURE]](%1) : $@callee_guaranteed (Int) -> () +sil hidden [ossa] @$s14init_accessors4TestV1v5otherACSi_SitcfC : $@convention(method) (Int, Int, @thin Test.Type) -> Test { +bb0(%0 : $Int, %1 : $Int, %2 : $@thin Test.Type): + %3 = alloc_box ${ var Test }, var, name "self" + %4 = mark_uninitialized [rootself] %3 : ${ var Test } + %5 = project_box %4 : ${ var Test }, 0 + debug_value %0 : $Int, let, name "v", argno 1 + debug_value %1 : $Int, let, name "other", argno 2 + %8 = begin_access [modify] [unknown] %5 : $*Test + %9 = function_ref @$s14init_accessors4TestV1xSivi : $@convention(thin) (Int) -> @out Int + %10 = function_ref @$s14init_accessors4TestV1xSivs : $@convention(method) (Int, @inout Test) -> () + %11 = partial_apply [callee_guaranteed] %10(%8) : $@convention(method) (Int, @inout Test) -> () + assign_or_init #Test.x, self %8 : $*Test, value %0 : $Int, init %9 : $@convention(thin) (Int) -> @out Int, set %11 : $@callee_guaranteed (Int) -> () + end_access %8 : $*Test + destroy_value %11 : $@callee_guaranteed (Int) -> () + %15 = begin_access [modify] [unknown] %5 : $*Test + %16 = function_ref @$s14init_accessors4TestV1xSivi : $@convention(thin) (Int) -> @out Int + %17 = function_ref @$s14init_accessors4TestV1xSivs : $@convention(method) (Int, @inout Test) -> () + %18 = partial_apply [callee_guaranteed] %17(%15) : $@convention(method) (Int, @inout Test) -> () + assign_or_init #Test.x, self %15 : $*Test, value %1 : $Int, init %16 : $@convention(thin) (Int) -> @out Int, set %18 : $@callee_guaranteed (Int) -> () + end_access %15 : $*Test + destroy_value %18 : $@callee_guaranteed (Int) -> () + %22 = load [trivial] %5 : $*Test + destroy_value %4 : ${ var Test } + return %22 : $Test +} \ No newline at end of file