Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[silgenpattern] Fix pattern emission of tuples with address only and … #19959

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 31 additions & 5 deletions lib/SILGen/SILGenPattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1463,12 +1463,38 @@ emitTupleDispatch(ArrayRef<RowToSpecialize> rows, ConsumableManagedValue src,
auto &fieldTL = SGF.getTypeLowering(fieldTy);

SILValue member = SGF.B.createTupleElementAddr(loc, v, i, fieldTy);
if (!fieldTL.isAddressOnly()) {
member =
fieldTL.emitLoad(SGF.B, loc, member, LoadOwnershipQualifier::Take);
ConsumableManagedValue memberCMV;

// If we have a loadable sub-type of our tuple...
if (fieldTL.isLoadable()) {
switch (src.getFinalConsumption()) {
case CastConsumptionKind::TakeAlways: {
// and our consumption is take always, perform a load [take] and
// continue.
auto memberMV = ManagedValue::forUnmanaged(member);
memberCMV = {SGF.B.createLoadTake(loc, memberMV),
CastConsumptionKind::TakeAlways};
break;
}
case CastConsumptionKind::TakeOnSuccess:
case CastConsumptionKind::CopyOnSuccess: {
// otherwise we have take on success or copy on success perform a
// load_borrow.
auto memberMV = ManagedValue::forUnmanaged(member);
memberCMV = {SGF.B.createLoadBorrow(loc, memberMV),
CastConsumptionKind::BorrowAlways};
break;
}
case CastConsumptionKind::BorrowAlways:
llvm_unreachable("Borrow always can not be used on objects");
}
} else {
// Otherwise, if we have an address only type, just get the managed
// subobject.
memberCMV =
getManagedSubobject(SGF, member, fieldTL, src.getFinalConsumption());
}
auto memberCMV = getManagedSubobject(SGF, member, fieldTL,
src.getFinalConsumption());

destructured.push_back(memberCMV);
}

Expand Down
53 changes: 53 additions & 0 deletions test/SILGen/switch.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1148,3 +1148,56 @@ func testUninhabitedSwitchScrutinee() {
switch myFatalError() {}
}
}

// Make sure that we properly can handle address only tuples with loadable
// subtypes.
class Klass {}

enum TrivialSingleCaseEnum {
case a
}

enum NonTrivialSingleCaseEnum {
case a(Klass)
}

// CHECK-LABEL: sil hidden @$s6switch33address_only_with_trivial_subtypeyyAA21TrivialSingleCaseEnumO_yptF : $@convention(thin) (TrivialSingleCaseEnum, @in_guaranteed Any) -> () {
// CHECK: [[MEM:%.*]] = alloc_stack $(TrivialSingleCaseEnum, Any)
// CHECK: [[INIT_TUP_0:%.*]] = tuple_element_addr [[MEM]] : $*(TrivialSingleCaseEnum, Any), 0
// CHECK: [[INIT_TUP_1:%.*]] = tuple_element_addr [[MEM]] : $*(TrivialSingleCaseEnum, Any), 1
// CHECK: store {{%.*}} to [trivial] [[INIT_TUP_0]]
// CHECK: copy_addr [take] {{%.*}} to [initialization] [[INIT_TUP_1]]
// CHECK: [[TUP_0:%.*]] = tuple_element_addr [[MEM]] : $*(TrivialSingleCaseEnum, Any), 0
// CHECK: [[TUP_0_VAL:%.*]] = load [trivial] [[TUP_0]]
// CHECK: [[TUP_1:%.*]] = tuple_element_addr [[MEM]] : $*(TrivialSingleCaseEnum, Any), 1
// CHECK: switch_enum [[TUP_0_VAL]]
//
// CHECK: } // end sil function '$s6switch33address_only_with_trivial_subtypeyyAA21TrivialSingleCaseEnumO_yptF'
func address_only_with_trivial_subtype(_ a: TrivialSingleCaseEnum, _ value: Any) {
switch (a, value) {
case (.a, _):
break
default:
break
}
}

// CHECK-LABEL: sil hidden @$s6switch36address_only_with_nontrivial_subtypeyyAA24NonTrivialSingleCaseEnumO_yptF : $@convention(thin) (@guaranteed NonTrivialSingleCaseEnum, @in_guaranteed Any) -> () {
// CHECK: [[MEM:%.*]] = alloc_stack $(NonTrivialSingleCaseEnum, Any)
// CHECK: [[INIT_TUP_0:%.*]] = tuple_element_addr [[MEM]] : $*(NonTrivialSingleCaseEnum, Any), 0
// CHECK: [[INIT_TUP_1:%.*]] = tuple_element_addr [[MEM]] : $*(NonTrivialSingleCaseEnum, Any), 1
// CHECK: store {{%.*}} to [init] [[INIT_TUP_0]]
// CHECK: copy_addr [take] {{%.*}} to [initialization] [[INIT_TUP_1]]
// CHECK: [[TUP_0:%.*]] = tuple_element_addr [[MEM]] : $*(NonTrivialSingleCaseEnum, Any), 0
// CHECK: [[TUP_0_VAL:%.*]] = load_borrow [[TUP_0]]
// CHECK: [[TUP_1:%.*]] = tuple_element_addr [[MEM]] : $*(NonTrivialSingleCaseEnum, Any), 1
// CHECK: switch_enum [[TUP_0_VAL]]
// CHECK: } // end sil function '$s6switch36address_only_with_nontrivial_subtypeyyAA24NonTrivialSingleCaseEnumO_yptF'
func address_only_with_nontrivial_subtype(_ a: NonTrivialSingleCaseEnum, _ value: Any) {
switch (a, value) {
case (.a, _):
break
default:
break
}
}