Skip to content

Commit d191ef8

Browse files
committed
[SIL/Parse] InitAccessors: Implement printing and parsing of previously iniitalized properties
Properties that are marked as initialized are printed as `[assign=<index>]` where `<index>` point to the property position in `getInitializedProperties()` list.
1 parent 85a8a05 commit d191ef8

File tree

5 files changed

+118
-8
lines changed

5 files changed

+118
-8
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4989,6 +4989,7 @@ class AssignOrInitInst
49894989
/// Mark a property from `initializes(...)` list as initialized
49904990
/// before this instruction.
49914991
void markAsInitialized(VarDecl *property);
4992+
void markAsInitialized(unsigned propertyIdx);
49924993

49934994
/// Check whether a property from `initializes(...)` list with
49944995
/// the given index has already been initialized and requires

lib/SIL/IR/SILInstructions.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1270,12 +1270,17 @@ void AssignOrInitInst::markAsInitialized(VarDecl *property) {
12701270
auto toInitProperties = getInitializedProperties();
12711271
for (unsigned index : indices(toInitProperties)) {
12721272
if (toInitProperties[index] == property) {
1273-
Assignments.set(index);
1273+
markAsInitialized(index);
12741274
break;
12751275
}
12761276
}
12771277
}
12781278

1279+
void AssignOrInitInst::markAsInitialized(unsigned propertyIdx) {
1280+
assert(propertyIdx < getNumInitializedProperties());
1281+
Assignments.set(propertyIdx);
1282+
}
1283+
12791284
bool AssignOrInitInst::isPropertyAlreadyInitialized(unsigned propertyIdx) {
12801285
assert(propertyIdx < Assignments.size());
12811286
return Assignments.test(propertyIdx);

lib/SIL/IR/SILPrinter.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,6 +1771,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
17711771
*this << "[assign_wrapped_value] ";
17721772
break;
17731773
}
1774+
17741775
*this << getIDAndType(AI->getDest())
17751776
<< ", init " << getIDAndType(AI->getInitializer())
17761777
<< ", set " << getIDAndType(AI->getSetter());
@@ -1787,6 +1788,14 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
17871788
*this << "[set] ";
17881789
break;
17891790
}
1791+
1792+
// Print all of the properties that have been previously initialized.
1793+
for (unsigned i = 0, n = AI->getNumInitializedProperties(); i != n; ++i) {
1794+
if (AI->isPropertyAlreadyInitialized(i)) {
1795+
*this << "[assign=" << i << "] ";
1796+
}
1797+
}
1798+
17901799
*this << getIDAndType(AI->getSrc());
17911800
*this << ", init " << getIDAndType(AI->getInitializer())
17921801
<< ", set " << getIDAndType(AI->getSetter());

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2353,6 +2353,50 @@ static bool parseAssignOrInitMode(AssignOrInitInst::Mode &Result,
23532353
return false;
23542354
}
23552355

2356+
static bool
2357+
parseAssignOrInitAssignments(llvm::SmallVectorImpl<unsigned> &assignments,
2358+
SILParser &SP) {
2359+
// Could be more than one [assign=<index>] attributes.
2360+
for (;;) {
2361+
SourceLoc loc;
2362+
2363+
// Consume '['
2364+
if (!SP.P.consumeIf(tok::l_square))
2365+
return false;
2366+
2367+
// Consume the identifier which should be "assign"
2368+
{
2369+
Identifier Id;
2370+
if (SP.parseSILIdentifier(Id, loc, diag::expected_in_attribute_list))
2371+
return true;
2372+
2373+
if (!Id.is("assign")) {
2374+
SP.P.diagnose(loc, diag::sil_invalid_attribute_for_expected, Id.str(),
2375+
"assign");
2376+
return true;
2377+
}
2378+
}
2379+
2380+
uint64_t index;
2381+
2382+
// Consume '='
2383+
if (!SP.P.consumeIf(tok::equal)) {
2384+
SP.P.diagnose(loc, diag::expected_equal_in_sil_instr);
2385+
return true;
2386+
}
2387+
2388+
// Consume the property index.
2389+
if (SP.parseInteger(index, diag::expected_in_attribute_list))
2390+
return true;
2391+
2392+
// Consume ']'
2393+
if (SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list))
2394+
return true;
2395+
2396+
assignments.push_back(index);
2397+
}
2398+
}
2399+
23562400
// Parse a list of integer indices, prefaced with the given string label.
23572401
// Returns true on error.
23582402
static bool parseIndexList(Parser &P, StringRef label,
@@ -4700,16 +4744,24 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
47004744
case SILInstructionKind::AssignOrInitInst: {
47014745
SILValue Src, InitFn, SetFn;
47024746
AssignOrInitInst::Mode Mode;
4747+
llvm::SmallVector<unsigned, 2> assignments;
47034748

4704-
if (parseAssignOrInitMode(Mode, *this) || parseTypedValueRef(Src, B) ||
4749+
if (parseAssignOrInitMode(Mode, *this) ||
4750+
parseAssignOrInitAssignments(assignments, *this) ||
4751+
parseTypedValueRef(Src, B) ||
47054752
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
47064753
parseVerbatim("init") || parseTypedValueRef(InitFn, B) ||
47074754
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
47084755
parseVerbatim("set") || parseTypedValueRef(SetFn, B) ||
47094756
parseSILDebugLocation(InstLoc, B))
47104757
return true;
47114758

4712-
ResultVal = B.createAssignOrInit(InstLoc, Src, InitFn, SetFn, Mode);
4759+
auto *AI = B.createAssignOrInit(InstLoc, Src, InitFn, SetFn, Mode);
4760+
4761+
for (unsigned index : assignments)
4762+
AI->markAsInitialized(index);
4763+
4764+
ResultVal = AI;
47134765
break;
47144766
}
47154767

test/SILOptimizer/init_accessor_raw_sil_lowering.swift

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -enable-experimental-feature InitAccessors -Xllvm -sil-print-after=definite-init -emit-sil %s -o /dev/null 2>&1 | %FileCheck %s
1+
// RUN: %target-swift-frontend -enable-experimental-feature InitAccessors -Xllvm -sil-print-after=definite-init -emit-sil -module-name assign_or_init_lowering %s -o /dev/null 2>&1 | %FileCheck %s
22

33
struct Test1 {
44
var _a: Int
@@ -23,14 +23,57 @@ struct Test1 {
2323
set { }
2424
}
2525

26-
// CHECK-LABEL: sil hidden [ossa] @$s4null5Test1V1aACSi_tcfC : $@convention(method) (Int, @thin Test1.Type) -> @owned Test1
27-
// CHECK: assign_or_init [init] {{.*}} : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> ()
28-
// CHECK: assign_or_init [init] {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String) -> (@out Int, @out String), set {{.*}} : $@callee_guaranteed (@owned String) -> ()
29-
// CHECK: assign_or_init [set] {{.*}} : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> ()
26+
// CHECK-LABEL: sil hidden [ossa] @$s23assign_or_init_lowering5Test1V1aACSi_tcfC : $@convention(method) (Int, @thin Test1.Type) -> @owned Test1
3027
init(a: Int) {
28+
// CHECK: assign_or_init [init] [[VALUE:%.*]] : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> ()
3129
self.a = a
30+
// CHECK: assign_or_init [init] [assign=0] [[VALUE:%.*]] : $String, init {{.*}} : $@convention(thin) (@owned String) -> (@out Int, @out String), set {{.*}} : $@callee_guaranteed (@owned String) -> ()
3231
self.a = -1
3332
self.b = ""
33+
// CHECK: assign_or_init [set] [[VALUE:%.*]] : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> ()
3434
self.a = a
3535
}
3636
}
37+
38+
struct Test2<T> {
39+
var _a: Int
40+
var _b: T
41+
var _c: String
42+
43+
var pair: (Int, T) {
44+
init(initialValue) initializes(_a, _b) {
45+
_a = initialValue.0
46+
_b = initialValue.1
47+
}
48+
49+
get { (_a, _b) }
50+
set { }
51+
}
52+
53+
// CHECK-LABEL: sil hidden [ossa] @$s23assign_or_init_lowering5Test2V1a1bACyxGSi_xtcfC : $@convention(method) <T> (Int, @in T, @thin Test2<T>.Type) -> @out Test2<T>
54+
init(a: Int, b: T) {
55+
// CHECK: assign_or_init [init] [[VALUE:%.*]] : $*(Int, T), init {{.*}} : $@convention(thin) <τ_0_0> (Int, @in τ_0_0) -> (@out Int, @out τ_0_0), set {{.*}} : $@callee_guaranteed (Int, @in T) -> ()
56+
self.pair = (a, b)
57+
// CHECK: assign_or_init [init] [assign=0] [assign=1] [[VALUE:%.*]] : $*(Int, T), init {{.*}} : $@convention(thin) <τ_0_0> (Int, @in τ_0_0) -> (@out Int, @out τ_0_0), set {{.*}} : $@callee_guaranteed (Int, @in T) -> ()
58+
self.pair = (0, b)
59+
self._c = ""
60+
// CHECK: assign_or_init [set] [[VALUE:%.*]] : $*(Int, T), init {{.*}} : $@convention(thin) <τ_0_0> (Int, @in τ_0_0) -> (@out Int, @out τ_0_0), set {{.*}} : $@callee_guaranteed (Int, @in T) -> ()
61+
self.pair = (1, b)
62+
}
63+
}
64+
65+
struct Test {
66+
var test: Int {
67+
init {
68+
}
69+
70+
get { 42 }
71+
set { }
72+
}
73+
74+
// CHECK-LABEL: sil hidden [ossa] @$s23assign_or_init_lowering4TestV1vACSi_tcfC : $@convention(method) (Int, @thin Test.Type) -> Test
75+
init(v: Int) {
76+
// CHECK: assign_or_init [set] %0 : $Int, init {{.*}} : $@convention(thin) (Int) -> (), set {{.*}} : $@callee_guaranteed (Int) -> ()
77+
self.test = v
78+
}
79+
}

0 commit comments

Comments
 (0)