Skip to content

Commit b5d9ff4

Browse files
Merge pull request #73626 from aschwaighofer/large_types_reg2mem_unchecked_trivial_bitcast_fix
IRGen: Large types reg2mem - Fix visitUncheckedTrivialBitCastInst
2 parents ff6cdeb + cb68a9b commit b5d9ff4

File tree

4 files changed

+75
-5
lines changed

4 files changed

+75
-5
lines changed

lib/IRGen/LoadableByAddress.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3800,17 +3800,23 @@ class AssignAddressToDef : SILInstructionVisitor<AssignAddressToDef> {
38003800

38013801
void visitUncheckedTrivialBitCastInst(UncheckedTrivialBitCastInst *bc) {
38023802
auto builder = assignment.getBuilder(bc->getIterator());
3803+
38033804
if (assignment.isLargeLoadableType(bc->getType()) &&
38043805
!assignment.isLargeLoadableType(bc->getOperand()->getType())) {
38053806
// Curious case of an imported C union.
38063807
// The union is imported as a struct that has no fields.
38073808
// When we access union members we instead bitcast to the union member
38083809
// type.
3809-
auto addr = assignment.createAllocStack(bc->getType());
3810-
auto opdAddr = builder.createUncheckedAddrCast(
3811-
bc->getLoc(), addr, bc->getOperand()->getType().getAddressType());
3810+
3811+
// We expect the "in" type to be larger or equal in size to the "out"
3812+
// type. See IRGenSILFunction::visitUncheckedTrivialBitCastInst.
3813+
// We therefore must use the bigger type, i.e the operand type, to create
3814+
// a stack allocation.
3815+
auto opdAddr = assignment.createAllocStack(bc->getOperand()->getType());
38123816
builder.createStore(bc->getLoc(), bc->getOperand(), opdAddr,
38133817
StoreOwnershipQualifier::Unqualified);
3818+
auto addr = builder.createUncheckedAddrCast(
3819+
bc->getLoc(), opdAddr, bc->getType().getAddressType());
38143820
assignment.mapValueToAddress(origValue, addr);
38153821
assignment.markForDeletion(bc);
38163822
return;

test/IRGen/Inputs/large_c.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,40 @@ typedef struct _ContainerType {
4040
char x1;
4141
ContainedType l[10];
4242
} __attribute__((packed)) ContainerType;
43+
44+
typedef unsigned char arr_t[32];
45+
46+
typedef enum : unsigned int {
47+
entry_0 = 0,
48+
entry_1 = 1,
49+
entry_2 = 2,
50+
entry_3 = 3,
51+
entry_4 = 4,
52+
entry_5 = 5,
53+
entry_6 = 6,
54+
entry_7 = 7,
55+
entry_8 = 8,
56+
entry_9 = 9,
57+
entry_10 = 10,
58+
entry_11 = 11,
59+
entry_12 = 12,
60+
entry_13 = 13,
61+
entry_14 = 14,
62+
entry_15 = 15,
63+
entry_16 = 16,
64+
entry_17 = 17,
65+
entry_18 = 18,
66+
entry_invalid = 255,
67+
} enum_t;
68+
69+
typedef union {
70+
struct {
71+
enum_t slot;
72+
arr_t buf;
73+
} in;
74+
struct {
75+
int result;
76+
arr_t buff;
77+
unsigned char cnt;
78+
} out;
79+
} union_t;

test/IRGen/large_union.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ public func test1(_ s: some_struct) -> some_struct {
77
}
88
// CHECK: sil @$s1t5test1ySo11some_structaADF : $@convention(thin) (@in_guaranteed some_struct) -> @out some_struct {
99
// CHECK-NOT: unchecked_trivial_bitcast
10-
// CHECK: unchecked_addr_cast {{.*}} : $*some_struct.__Unnamed_struct_out to $*some_struct
10+
// CHECK: unchecked_addr_cast {{.*}} : $*some_struct to $*some_struct.__Unnamed_struct_out
1111
// CHECK-NOT: unchecked_trivial_bitcast
1212
// CHECK: } // end sil function '$s1t5test1ySo11some_structaADF'
1313

1414
// CHECK: sil @$s1t5test2yySo11some_structazF : $@convention(thin) (@inout some_struct) -> () {
1515
// CHECK-NOT: unchecked_trivial_bitcast
16-
// CHECK: unchecked_addr_cast {{.*}} : $*some_struct.__Unnamed_struct_out to $*some_struct
16+
// CHECK: unchecked_addr_cast {{.*}} : $*some_struct to $*some_struct.__Unnamed_struct_out
1717
// CHECK-NOT: unchecked_trivial_bitcast
1818
// CHECK: } // end sil function '$s1t5test2yySo11some_structazF'
1919

test/IRGen/loadable_by_address_reg2mem.sil

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,30 @@ bb0(%0 : $*C1, %1 : $*Small):
269269
%t = tuple ()
270270
return %t : $()
271271
}
272+
273+
sil @use : $@convention(thin) (UInt32) -> ()
274+
275+
// We need to make sure we use the bigger alloc_stack for the address of
276+
// unchecked_trivial_bit_cast. A bitcast can go from bigger to smaller type.
277+
278+
// CHECK: sil @test11 : $@convention(thin) (@in union_t) -> () {
279+
// CHECK-NOT: unchecked_addr_cast %1 : $*union_t.__Unnamed_struct_in to $*union_t
280+
// CHECK: unchecked_addr_cast {{.*}} : $*union_t to $*union_t.__Unnamed_struct_in
281+
// CHECK: } // end sil function 'test11'
282+
283+
sil @test11 : $@convention(thin) (@in union_t) -> () {
284+
bb0(%0 : $*union_t):
285+
%1 = alloc_stack $union_t
286+
%2 = alloc_stack $union_t
287+
copy_addr [take] %0 to [init] %2 : $*union_t
288+
%4 = load %2 : $*union_t
289+
%7 = unchecked_trivial_bit_cast %4 : $union_t to $union_t.__Unnamed_struct_in
290+
%8 = struct_extract %7 : $union_t.__Unnamed_struct_in, #union_t.__Unnamed_struct_in.slot
291+
%10 = struct_extract %8 : $enum_t, #enum_t.rawValue
292+
%11 = function_ref @use : $@convention(thin) (UInt32) -> ()
293+
%12 = apply %11(%10) : $@convention(thin) (UInt32) -> ()
294+
%13 = tuple ()
295+
dealloc_stack %2 : $*union_t
296+
dealloc_stack %1 : $*union_t
297+
return %13 : $()
298+
}

0 commit comments

Comments
 (0)