Skip to content

Commit 3e6b75a

Browse files
Merge pull request #14234 from aschwaighofer/swift-4.1-branch-sil_fix_indirect_enum_box_types
[4.1] SIL : Use the enum 's generic signature and the payloads type f…
2 parents 3cdeb5e + cce873d commit 3e6b75a

File tree

9 files changed

+95
-24
lines changed

9 files changed

+95
-24
lines changed

include/swift/SIL/TypeLowering.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,9 @@ class TypeConverter {
863863
GenericEnvironment *env,
864864
bool isMutable);
865865

866+
CanSILBoxType getBoxTypeForEnumElement(SILType enumType,
867+
EnumElementDecl *elt);
868+
866869
private:
867870
CanType getLoweredRValueType(AbstractionPattern origType, CanType substType);
868871

lib/SIL/SILType.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -328,17 +328,19 @@ SILType SILType::getEnumElementType(EnumElementDecl *elt, SILModule &M) const {
328328
return SILType(objectType, getCategory());
329329
}
330330

331+
// If the case is indirect, then the payload is boxed.
332+
if (elt->isIndirect() || elt->getParentEnum()->isIndirect()) {
333+
auto box = M.Types.getBoxTypeForEnumElement(*this, elt);
334+
return SILType(SILType::getPrimitiveObjectType(box).getSwiftRValueType(),
335+
getCategory());
336+
}
337+
331338
auto substEltTy =
332339
getSwiftRValueType()->getTypeOfMember(M.getSwiftModule(), elt,
333340
elt->getArgumentInterfaceType());
334341
auto loweredTy =
335342
M.Types.getLoweredType(M.Types.getAbstractionPattern(elt), substEltTy);
336343

337-
// If the case is indirect, then the payload is boxed.
338-
if (elt->isIndirect() || elt->getParentEnum()->isIndirect())
339-
loweredTy = SILType::getPrimitiveObjectType(
340-
SILBoxType::get(loweredTy.getSwiftRValueType()));
341-
342344
return SILType(loweredTy.getSwiftRValueType(), getCategory());
343345
}
344346

lib/SIL/TypeLowering.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,6 +2527,45 @@ TypeConverter::getContextBoxTypeForCapture(ValueDecl *captured,
25272527
return boxType;
25282528
}
25292529

2530+
CanSILBoxType TypeConverter::getBoxTypeForEnumElement(SILType enumType,
2531+
EnumElementDecl *elt) {
2532+
2533+
auto *enumDecl = enumType.getEnumOrBoundGenericEnum();
2534+
2535+
assert(elt->getDeclContext() == enumDecl);
2536+
assert(elt->isIndirect() || elt->getParentEnum()->isIndirect());
2537+
2538+
auto &C = M.getASTContext();
2539+
2540+
auto boxSignature = getEffectiveGenericSignature(enumDecl);
2541+
2542+
if (boxSignature == CanGenericSignature()) {
2543+
auto eltIntfTy = elt->getArgumentInterfaceType();
2544+
auto boxVarTy = getLoweredType(eltIntfTy).getSwiftRValueType();
2545+
auto layout = SILLayout::get(C, nullptr, SILField(boxVarTy, true));
2546+
return SILBoxType::get(C, layout, {});
2547+
}
2548+
2549+
// Use the enum's signature for the box type.
2550+
auto boundEnum = enumType.getSwiftRValueType();
2551+
2552+
// Lower the enum element's argument in the box's context.
2553+
auto eltIntfTy = elt->getArgumentInterfaceType();
2554+
GenericContextScope scope(*this, boxSignature);
2555+
auto boxVarTy = getLoweredType(getAbstractionPattern(elt), eltIntfTy)
2556+
.getSwiftRValueType();
2557+
auto layout = SILLayout::get(C, boxSignature, SILField(boxVarTy, true));
2558+
2559+
// Instantiate the layout with enum's substitution list.
2560+
auto subMap = boundEnum->getContextSubstitutionMap(
2561+
M.getSwiftModule(), enumDecl, enumDecl->getGenericEnvironment());
2562+
SmallVector<Substitution, 4> genericArgs;
2563+
boxSignature->getSubstitutions(subMap, genericArgs);
2564+
2565+
auto boxTy = SILBoxType::get(C, layout, genericArgs);
2566+
return boxTy;
2567+
}
2568+
25302569
static void countNumberOfInnerFields(unsigned &fieldsCount, SILModule &Module,
25312570
SILType Ty) {
25322571
if (auto *structDecl = Ty.getStructOrBoundGenericStruct()) {

lib/SILGen/SILGenApply.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3532,7 +3532,7 @@ ManagedValue SILGenFunction::emitInjectEnum(SILLocation loc,
35323532
// throws, we know to deallocate the uninitialized box.
35333533
if (element->isIndirect() ||
35343534
element->getParentEnum()->isIndirect()) {
3535-
auto boxTy = SILBoxType::get(payloadTL.getLoweredType().getSwiftRValueType());
3535+
auto boxTy = SGM.M.Types.getBoxTypeForEnumElement(enumTy, element);
35363536
auto *box = B.createAllocBox(loc, boxTy);
35373537
auto *addr = B.createProjectBox(loc, box, 0);
35383538

test/Interpreter/enum.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,3 +651,19 @@ func run() {
651651
}
652652

653653
run()
654+
655+
public enum Indirect<T> {
656+
indirect case payload((T, other: T))
657+
case none
658+
}
659+
660+
public func testIndirectEnum<T>(_ payload: T) -> Indirect<T> {
661+
return Indirect.payload((payload, other: payload))
662+
}
663+
664+
public func testCase(_ closure: @escaping (Int) -> ()) -> Indirect<(Int) -> ()> {
665+
return testIndirectEnum(closure)
666+
}
667+
668+
// CHECK: payload((Function), other: (Function))
669+
print(testCase({ _ in }))

test/SIL/Parser/indirect_enum.sil

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ entry(%e : $TreeA<T>):
2727
%b = project_box %a : $<τ_0_0> { var τ_0_0 } <T>, 0
2828

2929
%c = unchecked_enum_data %e : $TreeA<T>, #TreeA.Branch!enumelt.1
30-
%d = project_box %c : $<τ_0_0> { var τ_0_0 } <(left: TreeA<T>, right: TreeA<T>)>, 0
30+
%d = project_box %c : $<τ_0_0> { var (left: TreeA<τ_0_0>, right: TreeA<τ_0_0>) } <T>, 0
3131

3232
return undef : $()
3333
}
@@ -38,7 +38,7 @@ entry(%e : $*TreeB<T>):
3838
destroy_addr %a : $*T
3939

4040
%c = unchecked_take_enum_data_addr %e : $*TreeB<T>, #TreeB.Branch!enumelt.1
41-
%d = load [take] %c : $*<τ_0_0> { var τ_0_0 } <(left: TreeB<T>, right: TreeB<T>)>
41+
%d = load [take] %c : $*<τ_0_0> { var (left: TreeB<τ_0_0>, right: TreeB<τ_0_0>) } <T>
4242

4343
return undef : $()
4444
}
@@ -49,7 +49,7 @@ entry(%e : $TreeInt):
4949
store %a to [trivial] undef : $*Int
5050

5151
%c = unchecked_enum_data %e : $TreeInt, #TreeInt.Branch!enumelt.1
52-
%d = project_box %c : $<τ_0_0> { var τ_0_0 } <(left: TreeInt, right: TreeInt)>, 0
52+
%d = project_box %c : ${ var (left: TreeInt, right: TreeInt) }, 0
5353

5454
return undef : $()
5555
}

test/SILGen/enum.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,14 @@ enum Foo { case A(P, String) }
190190
func Foo_cases() {
191191
_ = Foo.A
192192
}
193+
194+
enum Indirect<T> {
195+
indirect case payload((T, other: T))
196+
case none
197+
}
198+
// CHECK-LABEL: sil{{.*}} @{{.*}}makeIndirectEnum{{.*}} : $@convention(thin) <T> (@in T) -> @owned Indirect<T>
199+
// CHECK: [[BOX:%.*]] = alloc_box $<τ_0_0> { var (τ_0_0, other: τ_0_0) } <T>
200+
// CHECK: enum $Indirect<T>, #Indirect.payload!enumelt.1, [[BOX]] : $<τ_0_0> { var (τ_0_0, other: τ_0_0) } <T>
201+
func makeIndirectEnum<T>(_ payload: T) -> Indirect<T> {
202+
return Indirect.payload((payload, other: payload))
203+
}

test/SILGen/indirect_enum.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func TreeA_cases<T>(_ t: T, l: TreeA<T>, r: TreeA<T>) {
2323
let _ = TreeA<T>.Leaf(t)
2424

2525
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeA<T>.Type
26-
// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <(left: TreeA<T>, right: TreeA<T>)>
26+
// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var (left: TreeA<τ_0_0>, right: TreeA<τ_0_0>) } <T>
2727
// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
2828
// CHECK-NEXT: [[LEFT:%.*]] = tuple_element_addr [[PB]] : $*(left: TreeA<T>, right: TreeA<T>), 0
2929
// CHECK-NEXT: [[RIGHT:%.*]] = tuple_element_addr [[PB]] : $*(left: TreeA<T>, right: TreeA<T>), 1
@@ -50,7 +50,7 @@ func TreeA_cases<T>(_ t: T, l: TreeA<T>, r: TreeA<T>) {
5050
func TreeA_reabstract(_ f: @escaping (Int) -> Int) {
5151
// CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed (Int) -> Int):
5252
// CHECK: [[METATYPE:%.*]] = metatype $@thin TreeA<(Int) -> Int>.Type
53-
// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <@callee_guaranteed (@in Int) -> @out Int>
53+
// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <(Int) -> Int>
5454
// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
5555
// CHECK-NEXT: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
5656
// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
@@ -92,7 +92,7 @@ func TreeB_cases<T>(_ t: T, l: TreeB<T>, r: TreeB<T>) {
9292
let _ = TreeB<T>.Leaf(t)
9393

9494
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeB<T>.Type
95-
// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <(left: TreeB<T>, right: TreeB<T>)>
95+
// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var (left: TreeB<τ_0_0>, right: TreeB<τ_0_0>) } <T>
9696
// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
9797
// CHECK-NEXT: [[LEFT:%.*]] = tuple_element_addr [[PB]]
9898
// CHECK-NEXT: [[RIGHT:%.*]] = tuple_element_addr [[PB]]
@@ -127,7 +127,7 @@ func TreeInt_cases(_ t: Int, l: TreeInt, r: TreeInt) {
127127
let _ = TreeInt.Leaf(t)
128128

129129
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeInt.Type
130-
// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <(left: TreeInt, right: TreeInt)>
130+
// CHECK-NEXT: [[BOX:%.*]] = alloc_box ${ var (left: TreeInt, right: TreeInt) }
131131
// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
132132
// CHECK-NEXT: [[LEFT:%.*]] = tuple_element_addr [[PB]]
133133
// CHECK-NEXT: [[RIGHT:%.*]] = tuple_element_addr [[PB]]
@@ -194,7 +194,7 @@ func switchTreeA<T>(_ x: TreeA<T>) {
194194
case .Leaf(let x):
195195
b(x)
196196

197-
// CHECK: [[BRANCH_CASE]]([[NODE_BOX:%.*]] : $<τ_0_0> { var τ_0_0 } <(left: TreeA<T>, right: TreeA<T>)>):
197+
// CHECK: [[BRANCH_CASE]]([[NODE_BOX:%.*]] : $<τ_0_0> { var (left: TreeA<τ_0_0>, right: TreeA<τ_0_0>) } <T>):
198198
// CHECK: [[TUPLE_ADDR:%.*]] = project_box [[NODE_BOX]]
199199
// CHECK: [[TUPLE:%.*]] = load_borrow [[TUPLE_ADDR]]
200200
// CHECK: [[LEFT:%.*]] = tuple_extract [[TUPLE]] {{.*}}, 0
@@ -370,7 +370,7 @@ func guardTreeA<T>(_ tree: TreeA<T>) {
370370
// CHECK: [[NO]]([[ORIGINAL_VALUE:%.*]] : $TreeA<T>):
371371
// CHECK: destroy_value [[ORIGINAL_VALUE]]
372372
// CHECK: end_borrow [[BORROWED_ARG_3]] from [[ARG]]
373-
// CHECK: [[YES]]([[BOX:%.*]] : $<τ_0_0> { var τ_0_0 } <(left: TreeA<T>, right: TreeA<T>)>):
373+
// CHECK: [[YES]]([[BOX:%.*]] : $<τ_0_0> { var (left: TreeA<τ_0_0>, right: TreeA<τ_0_0>) } <T>):
374374
// CHECK: [[VALUE_ADDR:%.*]] = project_box [[BOX]]
375375
// CHECK: [[TUPLE:%.*]] = load [take] [[VALUE_ADDR]]
376376
// CHECK: [[TUPLE_COPY:%.*]] = copy_value [[TUPLE]]
@@ -425,7 +425,7 @@ func guardTreeA<T>(_ tree: TreeA<T>) {
425425
// CHECK: [[NO]]([[ORIGINAL_VALUE:%.*]] : $TreeA<T>):
426426
// CHECK: destroy_value [[ORIGINAL_VALUE]]
427427
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
428-
// CHECK: [[YES]]([[BOX:%.*]] : $<τ_0_0> { var τ_0_0 } <(left: TreeA<T>, right: TreeA<T>)>):
428+
// CHECK: [[YES]]([[BOX:%.*]] : $<τ_0_0> { var (left: TreeA<τ_0_0>, right: TreeA<τ_0_0>) } <T>):
429429
// CHECK: [[VALUE_ADDR:%.*]] = project_box [[BOX]]
430430
// CHECK: [[TUPLE:%.*]] = load [take] [[VALUE_ADDR]]
431431
// CHECK: [[TUPLE_COPY:%.*]] = copy_value [[TUPLE]]
@@ -540,7 +540,7 @@ func dontDisableCleanupOfIndirectPayload(_ x: TrivialButIndirect) {
540540
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
541541
// CHECK: switch_enum [[ARG_COPY]] : $TrivialButIndirect, case #TrivialButIndirect.Direct!enumelt.1: [[YES:bb[0-9]+]], case #TrivialButIndirect.Indirect!enumelt.1: [[NO:bb[0-9]+]]
542542
//
543-
// CHECK: [[NO]]([[PAYLOAD:%.*]] : $<τ_0_0> { var τ_0_0 } <Int>):
543+
// CHECK: [[NO]]([[PAYLOAD:%.*]] : ${ var Int }):
544544
// CHECK: destroy_value [[PAYLOAD]]
545545
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
546546
guard case .Direct(let foo) = x else { return }
@@ -555,7 +555,7 @@ func dontDisableCleanupOfIndirectPayload(_ x: TrivialButIndirect) {
555555
// CHECK-NOT: destroy_value
556556
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
557557

558-
// CHECK: [[YES]]([[BOX:%.*]] : $<τ_0_0> { var τ_0_0 } <Int>):
558+
// CHECK: [[YES]]([[BOX:%.*]] : ${ var Int }):
559559
// CHECK: destroy_value [[BOX]]
560560

561561
guard case .Indirect(let bar) = x else { return }

test/SILOptimizer/predictable_memopt.sil

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -436,14 +436,14 @@ enum IndirectCase {
436436
sil @indirect_enum_box : $@convention(thin) (Int) -> IndirectCase {
437437
// CHECK: bb0([[X:%.*]] : $Int):
438438
entry(%x : $Int):
439-
// CHECK: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
440-
%b = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
439+
// CHECK: [[BOX:%.*]] = alloc_box ${ var Int }
440+
%b = alloc_box ${ var Int }
441441
// CHECK: [[PB:%.*]] = project_box [[BOX]]
442-
%ba = project_box %b : $<τ_0_0> { var τ_0_0 } <Int>, 0
442+
%ba = project_box %b : ${ var Int }, 0
443443
// CHECK: store [[X]] to [[PB]]
444444
store %x to %ba : $*Int
445-
// CHECK: [[E:%.*]] = enum $IndirectCase, #IndirectCase.X!enumelt.1, [[BOX]] : $<τ_0_0> { var τ_0_0 } <Int>
446-
%e = enum $IndirectCase, #IndirectCase.X!enumelt.1, %b : $<τ_0_0> { var τ_0_0 } <Int>
445+
// CHECK: [[E:%.*]] = enum $IndirectCase, #IndirectCase.X!enumelt.1, [[BOX]] : ${ var Int }
446+
%e = enum $IndirectCase, #IndirectCase.X!enumelt.1, %b : ${ var Int }
447447
// CHECK: return [[E]]
448448
return %e : $IndirectCase
449449
}
@@ -837,4 +837,4 @@ bb1:
837837
bb2:
838838
destroy_addr %1 : $*Builtin.NativeObject
839839
unreachable
840-
}
840+
}

0 commit comments

Comments
 (0)