Skip to content

Commit c643c7b

Browse files
committed
[silgen] Fix tuple initialization for semantic sil.
rdar://29791263
1 parent 8aab9f7 commit c643c7b

File tree

3 files changed

+62
-34
lines changed

3 files changed

+62
-34
lines changed

lib/SILGen/SILGenDecl.cpp

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -76,36 +76,53 @@ namespace {
7676
};
7777
} // end anonymous namespace
7878

79-
void TupleInitialization::copyOrInitValueInto(SILGenFunction &SGF,
80-
SILLocation loc,
81-
ManagedValue valueMV,
82-
bool isInit) {
83-
// A scalar value is being copied into the tuple, break it into elements
84-
// and assign/init each element in turn.
85-
SILValue value = valueMV.forward(SGF);
86-
auto sourceType = valueMV.getType().castTo<TupleType>();
87-
auto sourceSILType = value->getType();
79+
static void copyOrInitValueIntoHelper(
80+
SILGenFunction &SGF, SILLocation loc, ManagedValue value, bool isInit,
81+
ArrayRef<InitializationPtr> subInitializations,
82+
llvm::function_ref<ManagedValue(ManagedValue, unsigned, SILType)> func) {
83+
auto sourceType = value.getType().castTo<TupleType>();
84+
auto sourceSILType = value.getType();
8885
for (unsigned i = 0, e = sourceType->getNumElements(); i != e; ++i) {
8986
SILType fieldTy = sourceSILType.getTupleElementType(i);
90-
auto &fieldTL = SGF.getTypeLowering(fieldTy);
91-
92-
SILValue member;
93-
if (value->getType().isAddress()) {
94-
member = SGF.B.createTupleElementAddr(loc, value, i, fieldTy);
95-
if (!fieldTL.isAddressOnly())
96-
member =
97-
fieldTL.emitLoad(SGF.B, loc, member, LoadOwnershipQualifier::Take);
98-
} else {
99-
member = SGF.B.createTupleExtract(loc, value, i, fieldTy);
100-
}
101-
102-
auto elt = SGF.emitManagedRValueWithCleanup(member, fieldTL);
103-
104-
SubInitializations[i]->copyOrInitValueInto(SGF, loc, elt, isInit);
105-
SubInitializations[i]->finishInitialization(SGF);
87+
ManagedValue elt = func(value, i, fieldTy);
88+
subInitializations[i]->copyOrInitValueInto(SGF, loc, elt, isInit);
89+
subInitializations[i]->finishInitialization(SGF);
10690
}
10791
}
10892

93+
void TupleInitialization::copyOrInitValueInto(SILGenFunction &SGF,
94+
SILLocation loc,
95+
ManagedValue value, bool isInit) {
96+
// In the object case, we perform a borrow + extract + copy sequence. This is
97+
// because we do not have a destructure operation.
98+
if (value.getType().isObject()) {
99+
value = value.borrow(SGF, loc);
100+
return copyOrInitValueIntoHelper(
101+
SGF, loc, value, isInit, SubInitializations,
102+
[&](ManagedValue aggregate, unsigned i,
103+
SILType fieldType) -> ManagedValue {
104+
auto elt = SGF.B.createTupleExtract(loc, aggregate, i, fieldType);
105+
return SGF.B.createCopyValue(loc, elt);
106+
});
107+
}
108+
109+
// In the address case, we can support takes directly, so forward the cleanup
110+
// of the aggregate and create takes of the underlying addresses.
111+
value = ManagedValue::forUnmanaged(value.forward(SGF));
112+
return copyOrInitValueIntoHelper(
113+
SGF, loc, value, isInit, SubInitializations,
114+
[&](ManagedValue aggregate, unsigned i,
115+
SILType fieldType) -> ManagedValue {
116+
ManagedValue elt =
117+
SGF.B.createTupleElementAddr(loc, value, i, fieldType);
118+
if (!fieldType.isAddressOnly(SGF.F.getModule())) {
119+
return SGF.B.createLoadTake(loc, elt);
120+
}
121+
122+
return SGF.emitManagedRValueWithCleanup(elt.getValue());
123+
});
124+
}
125+
109126
void TupleInitialization::finishUninitialized(SILGenFunction &gen) {
110127
for (auto &subInit : SubInitializations) {
111128
subInit->finishUninitialized(gen);

lib/SILGen/SILGenExpr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,8 @@ ManagedValue SILGenFunction::emitManagedRValueWithCleanup(SILValue v) {
290290

291291
ManagedValue SILGenFunction::emitManagedRValueWithCleanup(SILValue v,
292292
const TypeLowering &lowering) {
293-
assert(lowering.getLoweredType() == v->getType());
293+
assert(lowering.getLoweredType().getObjectType() ==
294+
v->getType().getObjectType());
294295
if (lowering.isTrivial())
295296
return ManagedValue::forUnmanaged(v);
296297
if (v->getType().isObject() &&

test/SILGen/indirect_enum.swift

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -375,14 +375,19 @@ func guardTreeA<T>(_ tree: TreeA<T>) {
375375
// CHECK: [[VALUE_ADDR:%.*]] = project_box [[BOX]]
376376
// CHECK: [[TUPLE:%.*]] = load [take] [[VALUE_ADDR]]
377377
// CHECK: [[TUPLE_COPY:%.*]] = copy_value [[TUPLE]]
378-
// CHECK: [[L:%.*]] = tuple_extract [[TUPLE_COPY]]
379-
// CHECK: [[R:%.*]] = tuple_extract [[TUPLE_COPY]]
378+
// CHECK: [[BORROWED_TUPLE_COPY:%.*]] = begin_borrow [[TUPLE_COPY]]
379+
// CHECK: [[L:%.*]] = tuple_extract [[BORROWED_TUPLE_COPY]]
380+
// CHECK: [[COPY_L:%.*]] = copy_value [[L]]
381+
// CHECK: [[R:%.*]] = tuple_extract [[BORROWED_TUPLE_COPY]]
382+
// CHECK: [[COPY_R:%.*]] = copy_value [[R]]
383+
// CHECK: end_borrow [[BORROWED_TUPLE_COPY]] from [[TUPLE_COPY]]
384+
// CHECK: destroy_value [[TUPLE_COPY]]
380385
// CHECK: destroy_value [[BOX]]
381386
// CHECK: end_borrow [[BORROWED_ARG_3]] from [[ARG]]
382387
guard case .Branch(left: let l, right: let r) = tree else { return }
383388

384-
// CHECK: destroy_value [[R]]
385-
// CHECK: destroy_value [[L]]
389+
// CHECK: destroy_value [[COPY_R]]
390+
// CHECK: destroy_value [[COPY_L]]
386391
// CHECK: destroy_addr [[X]]
387392
}
388393

@@ -426,12 +431,17 @@ func guardTreeA<T>(_ tree: TreeA<T>) {
426431
// CHECK: [[VALUE_ADDR:%.*]] = project_box [[BOX]]
427432
// CHECK: [[TUPLE:%.*]] = load [take] [[VALUE_ADDR]]
428433
// CHECK: [[TUPLE_COPY:%.*]] = copy_value [[TUPLE]]
429-
// CHECK: [[L:%.*]] = tuple_extract [[TUPLE_COPY]]
430-
// CHECK: [[R:%.*]] = tuple_extract [[TUPLE_COPY]]
434+
// CHECK: [[BORROWED_TUPLE_COPY:%.*]] = begin_borrow [[TUPLE_COPY]]
435+
// CHECK: [[L:%.*]] = tuple_extract [[BORROWED_TUPLE_COPY]]
436+
// CHECK: [[COPY_L:%.*]] = copy_value [[L]]
437+
// CHECK: [[R:%.*]] = tuple_extract [[BORROWED_TUPLE_COPY]]
438+
// CHECK: [[COPY_R:%.*]] = copy_value [[R]]
439+
// CHECK: end_borrow [[BORROWED_TUPLE_COPY]] from [[TUPLE_COPY]]
440+
// CHECK: destroy_value [[TUPLE_COPY]]
431441
// CHECK: destroy_value [[BOX]]
432442
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
433-
// CHECK: destroy_value [[R]]
434-
// CHECK: destroy_value [[L]]
443+
// CHECK: destroy_value [[COPY_R]]
444+
// CHECK: destroy_value [[COPY_L]]
435445
if case .Branch(left: let l, right: let r) = tree { }
436446
}
437447
}

0 commit comments

Comments
 (0)