Skip to content

Commit 18c24a1

Browse files
committed
Fix silcombine of inject_enum_addr when we have an empty struct with unreferenceable storage
1 parent 3d4457b commit 18c24a1

File tree

3 files changed

+43
-8
lines changed

3 files changed

+43
-8
lines changed

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,16 @@ SILCombiner::visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI) {
12401240
return nullptr;
12411241
}
12421242

1243+
SILType elemType = IEAI->getOperand()->getType().getEnumElementType(
1244+
IEAI->getElement(), IEAI->getFunction());
1245+
auto *structDecl = elemType.getStructOrBoundGenericStruct();
1246+
1247+
// We cannot create a struct when it has unreferenceable storage.
1248+
if (elemType.isEmpty(*IEAI->getFunction()) && structDecl &&
1249+
structDecl->hasUnreferenceableStorage()) {
1250+
return nullptr;
1251+
}
1252+
12431253
// Localize the address access.
12441254
Builder.setInsertionPoint(AI);
12451255
auto *AllocStack = Builder.createAllocStack(DataAddrInst->getLoc(),
@@ -1250,8 +1260,6 @@ SILCombiner::visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI) {
12501260

12511261
// If it is an empty type, apply may not initialize it.
12521262
// Create an empty value of the empty type and store it to a new local.
1253-
SILType elemType = IEAI->getOperand()->getType().getEnumElementType(
1254-
IEAI->getElement(), IEAI->getFunction());
12551263
if (elemType.isEmpty(*IEAI->getFunction())) {
12561264
enumValue = createEmptyAndUndefValue(
12571265
elemType.getObjectType(), &*Builder.getInsertionPoint(),

test/Inputs/clang-importer-sdk/usr/include/ctypes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ struct StructWithBitfields {
295295
unsigned : 11;
296296
};
297297

298+
union EmptyCUnion {};
299+
298300
typedef struct ModRM {
299301
unsigned rm: 3;
300302
unsigned reg: 3;

test/SILOptimizer/sil_combine_enum_addr.sil

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
// RUN: -emit-module-path=%t/resilient_struct.swiftmodule \
44
// RUN: -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
55

6-
// RUN: %target-sil-opt -enable-sil-verify-all %s -sil-combine -jumpthread-simplify-cfg -I %t | %FileCheck %s
6+
// RUN: %target-sil-opt -sdk %clang-importer-sdk-path -enable-sil-verify-all %s -sil-combine -jumpthread-simplify-cfg -I %t | %FileCheck %s
77

88
sil_stage canonical
99

1010
import Builtin
1111
import Swift
1212

1313
import resilient_struct
14+
import ctypes
1415

1516
// CHECK-LABEL: sil @convert_inject_enum_addr_select_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> ()
1617
// CHECK-NOT: init_existential_addr
@@ -47,7 +48,6 @@ bb2:
4748
br bb1
4849
}
4950

50-
5151
// CHECK-LABEL: sil @convert_inject_enum_addr_switch_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> ()
5252
// CHECK-NOT: init_existential_addr
5353
// CHECK-NOT: inject_enum_addr
@@ -122,7 +122,6 @@ bb22:
122122
br bb2
123123
}
124124

125-
126125
class A {
127126

128127
}
@@ -314,10 +313,10 @@ bb3:
314313

315314
sil @no_init_struct : $@convention(thin) () -> (@out ResilientEmptyStruct)
316315

317-
// CHECK-LABEL: sil @test_empty_struct_uninintialized : $@convention(thin) () -> () {
316+
// CHECK-LABEL: sil @test_empty_struct_uninitialized : $@convention(thin) () -> () {
318317
// CHECK-NOT: switch_enum_addr
319-
// CHECK-LABEL: } // end sil function 'test_empty_struct_uninintialized'
320-
sil @test_empty_struct_uninintialized : $@convention(thin) () -> () {
318+
// CHECK-LABEL: } // end sil function 'test_empty_struct_uninitialized'
319+
sil @test_empty_struct_uninitialized : $@convention(thin) () -> () {
321320
bb0:
322321
%0 = alloc_stack $Optional<ResilientEmptyStruct>
323322
%1 = init_enum_data_addr %0 : $*Optional<ResilientEmptyStruct>, #Optional.some!enumelt
@@ -337,3 +336,29 @@ bb3:
337336
%8 = tuple ()
338337
return %8 : $()
339338
}
339+
340+
sil @no_init_c_union : $@convention(thin) () -> (@out EmptyCUnion)
341+
342+
// CHECK-LABEL: sil @test_empty_c_union : $@convention(thin) () -> () {
343+
// CHECK: inject_enum_addr
344+
// CHECK-LABEL: } // end sil function 'test_empty_c_union'
345+
sil @test_empty_c_union : $@convention(thin) () -> () {
346+
bb0:
347+
%0 = alloc_stack $Optional<EmptyCUnion>
348+
%1 = init_enum_data_addr %0 : $*Optional<EmptyCUnion>, #Optional.some!enumelt
349+
%f = function_ref @no_init_c_union : $@convention(thin) () -> (@out EmptyCUnion)
350+
apply %f(%1) : $@convention(thin) () -> (@out EmptyCUnion)
351+
inject_enum_addr %0 : $*Optional<EmptyCUnion>, #Optional.some!enumelt
352+
switch_enum_addr %0 : $*Optional<EmptyCUnion>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
353+
354+
bb1:
355+
br bb3
356+
357+
bb2:
358+
br bb3
359+
360+
bb3:
361+
dealloc_stack %0 : $*Optional<EmptyCUnion>
362+
%8 = tuple ()
363+
return %8 : $()
364+
}

0 commit comments

Comments
 (0)