Skip to content

Commit c8dd802

Browse files
authored
Merge pull request #19959 from gottesmm/pr-b6f7d0f66251897bb96ee6da079f165aa7aa144f
[silgenpattern] Fix pattern emission of tuples with address only and …
2 parents 7ca0f46 + b7a7b1e commit c8dd802

File tree

2 files changed

+84
-5
lines changed

2 files changed

+84
-5
lines changed

lib/SILGen/SILGenPattern.cpp

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,12 +1463,38 @@ emitTupleDispatch(ArrayRef<RowToSpecialize> rows, ConsumableManagedValue src,
14631463
auto &fieldTL = SGF.getTypeLowering(fieldTy);
14641464

14651465
SILValue member = SGF.B.createTupleElementAddr(loc, v, i, fieldTy);
1466-
if (!fieldTL.isAddressOnly()) {
1467-
member =
1468-
fieldTL.emitLoad(SGF.B, loc, member, LoadOwnershipQualifier::Take);
1466+
ConsumableManagedValue memberCMV;
1467+
1468+
// If we have a loadable sub-type of our tuple...
1469+
if (fieldTL.isLoadable()) {
1470+
switch (src.getFinalConsumption()) {
1471+
case CastConsumptionKind::TakeAlways: {
1472+
// and our consumption is take always, perform a load [take] and
1473+
// continue.
1474+
auto memberMV = ManagedValue::forUnmanaged(member);
1475+
memberCMV = {SGF.B.createLoadTake(loc, memberMV),
1476+
CastConsumptionKind::TakeAlways};
1477+
break;
1478+
}
1479+
case CastConsumptionKind::TakeOnSuccess:
1480+
case CastConsumptionKind::CopyOnSuccess: {
1481+
// otherwise we have take on success or copy on success perform a
1482+
// load_borrow.
1483+
auto memberMV = ManagedValue::forUnmanaged(member);
1484+
memberCMV = {SGF.B.createLoadBorrow(loc, memberMV),
1485+
CastConsumptionKind::BorrowAlways};
1486+
break;
1487+
}
1488+
case CastConsumptionKind::BorrowAlways:
1489+
llvm_unreachable("Borrow always can not be used on objects");
1490+
}
1491+
} else {
1492+
// Otherwise, if we have an address only type, just get the managed
1493+
// subobject.
1494+
memberCMV =
1495+
getManagedSubobject(SGF, member, fieldTL, src.getFinalConsumption());
14691496
}
1470-
auto memberCMV = getManagedSubobject(SGF, member, fieldTL,
1471-
src.getFinalConsumption());
1497+
14721498
destructured.push_back(memberCMV);
14731499
}
14741500

test/SILGen/switch.swift

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,3 +1148,56 @@ func testUninhabitedSwitchScrutinee() {
11481148
switch myFatalError() {}
11491149
}
11501150
}
1151+
1152+
// Make sure that we properly can handle address only tuples with loadable
1153+
// subtypes.
1154+
class Klass {}
1155+
1156+
enum TrivialSingleCaseEnum {
1157+
case a
1158+
}
1159+
1160+
enum NonTrivialSingleCaseEnum {
1161+
case a(Klass)
1162+
}
1163+
1164+
// CHECK-LABEL: sil hidden @$s6switch33address_only_with_trivial_subtypeyyAA21TrivialSingleCaseEnumO_yptF : $@convention(thin) (TrivialSingleCaseEnum, @in_guaranteed Any) -> () {
1165+
// CHECK: [[MEM:%.*]] = alloc_stack $(TrivialSingleCaseEnum, Any)
1166+
// CHECK: [[INIT_TUP_0:%.*]] = tuple_element_addr [[MEM]] : $*(TrivialSingleCaseEnum, Any), 0
1167+
// CHECK: [[INIT_TUP_1:%.*]] = tuple_element_addr [[MEM]] : $*(TrivialSingleCaseEnum, Any), 1
1168+
// CHECK: store {{%.*}} to [trivial] [[INIT_TUP_0]]
1169+
// CHECK: copy_addr [take] {{%.*}} to [initialization] [[INIT_TUP_1]]
1170+
// CHECK: [[TUP_0:%.*]] = tuple_element_addr [[MEM]] : $*(TrivialSingleCaseEnum, Any), 0
1171+
// CHECK: [[TUP_0_VAL:%.*]] = load [trivial] [[TUP_0]]
1172+
// CHECK: [[TUP_1:%.*]] = tuple_element_addr [[MEM]] : $*(TrivialSingleCaseEnum, Any), 1
1173+
// CHECK: switch_enum [[TUP_0_VAL]]
1174+
//
1175+
// CHECK: } // end sil function '$s6switch33address_only_with_trivial_subtypeyyAA21TrivialSingleCaseEnumO_yptF'
1176+
func address_only_with_trivial_subtype(_ a: TrivialSingleCaseEnum, _ value: Any) {
1177+
switch (a, value) {
1178+
case (.a, _):
1179+
break
1180+
default:
1181+
break
1182+
}
1183+
}
1184+
1185+
// CHECK-LABEL: sil hidden @$s6switch36address_only_with_nontrivial_subtypeyyAA24NonTrivialSingleCaseEnumO_yptF : $@convention(thin) (@guaranteed NonTrivialSingleCaseEnum, @in_guaranteed Any) -> () {
1186+
// CHECK: [[MEM:%.*]] = alloc_stack $(NonTrivialSingleCaseEnum, Any)
1187+
// CHECK: [[INIT_TUP_0:%.*]] = tuple_element_addr [[MEM]] : $*(NonTrivialSingleCaseEnum, Any), 0
1188+
// CHECK: [[INIT_TUP_1:%.*]] = tuple_element_addr [[MEM]] : $*(NonTrivialSingleCaseEnum, Any), 1
1189+
// CHECK: store {{%.*}} to [init] [[INIT_TUP_0]]
1190+
// CHECK: copy_addr [take] {{%.*}} to [initialization] [[INIT_TUP_1]]
1191+
// CHECK: [[TUP_0:%.*]] = tuple_element_addr [[MEM]] : $*(NonTrivialSingleCaseEnum, Any), 0
1192+
// CHECK: [[TUP_0_VAL:%.*]] = load_borrow [[TUP_0]]
1193+
// CHECK: [[TUP_1:%.*]] = tuple_element_addr [[MEM]] : $*(NonTrivialSingleCaseEnum, Any), 1
1194+
// CHECK: switch_enum [[TUP_0_VAL]]
1195+
// CHECK: } // end sil function '$s6switch36address_only_with_nontrivial_subtypeyyAA24NonTrivialSingleCaseEnumO_yptF'
1196+
func address_only_with_nontrivial_subtype(_ a: NonTrivialSingleCaseEnum, _ value: Any) {
1197+
switch (a, value) {
1198+
case (.a, _):
1199+
break
1200+
default:
1201+
break
1202+
}
1203+
}

0 commit comments

Comments
 (0)