Skip to content

Commit eaac735

Browse files
authored
Merge pull request #69301 from eeckstein/fix-static-init-globals
[5.10] Optimizer: fix compiler crashes caused by certain types of statically initialized global variables
2 parents 8184d27 + 32f3a1d commit eaac735

File tree

7 files changed

+79
-11
lines changed

7 files changed

+79
-11
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/InitializeStaticGlobals.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ private extension Function {
156156
private func mergeStores(in function: Function, _ context: FunctionPassContext) {
157157
for inst in function.instructions {
158158
if let store = inst as? StoreInst {
159-
if let elementStores = getSequenceOfElementStores(firstStore: store) {
160-
merge(elementStores: elementStores, context)
159+
if let (elementStores, lastStore) = getSequenceOfElementStores(firstStore: store) {
160+
merge(elementStores: elementStores, lastStore: lastStore, context)
161161
}
162162
}
163163
}
@@ -171,7 +171,7 @@ private func mergeStores(in function: Function, _ context: FunctionPassContext)
171171
/// %addr_n = struct_element_addr %structAddr, #field_n
172172
/// store %element_n to %addr_n
173173
///
174-
private func getSequenceOfElementStores(firstStore: StoreInst) -> [StoreInst]? {
174+
private func getSequenceOfElementStores(firstStore: StoreInst) -> ([StoreInst], lastStore: StoreInst)? {
175175
guard let elementAddr = firstStore.destination as? StructElementAddrInst else {
176176
return nil
177177
}
@@ -195,7 +195,7 @@ private func getSequenceOfElementStores(firstStore: StoreInst) -> [StoreInst]? {
195195
numStoresFound += 1
196196
if numStoresFound == numElements {
197197
// If we saw `numElements` distinct stores, it implies that all elements in `elementStores` are not nil.
198-
return elementStores.map { $0! }
198+
return (elementStores.map { $0! }, lastStore: store)
199199
}
200200
default:
201201
if inst.mayReadOrWriteMemory {
@@ -206,8 +206,7 @@ private func getSequenceOfElementStores(firstStore: StoreInst) -> [StoreInst]? {
206206
return nil
207207
}
208208

209-
private func merge(elementStores: [StoreInst], _ context: FunctionPassContext) {
210-
let lastStore = elementStores.last!
209+
private func merge(elementStores: [StoreInst], lastStore: StoreInst, _ context: FunctionPassContext) {
211210
let builder = Builder(after: lastStore, context)
212211

213212
let structAddr = (lastStore.destination as! StructElementAddrInst).struct

lib/IRGen/GenDecl.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2700,11 +2700,6 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
27002700
if (gvar) {
27012701
if (forDefinition) {
27022702
updateLinkageForDefinition(*this, gvar, entity);
2703-
2704-
if (var->getStaticInitializerValue()) {
2705-
assert(gvar->hasInitializer() &&
2706-
"global variable referenced before created");
2707-
}
27082703
}
27092704
if (forDefinition && !gvar->hasInitializer())
27102705
initVal = getGlobalInitValue(var, storageType, fixedAlignment);

lib/SILOptimizer/IPO/DeadFunctionElimination.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ class DeadFunctionAndGlobalElimination {
212212
for (const SILInstruction &initInst : *global) {
213213
if (auto *fRef = dyn_cast<FunctionRefInst>(&initInst))
214214
ensureAlive(fRef->getReferencedFunction());
215+
if (auto *gRef = dyn_cast<GlobalAddrInst>(&initInst))
216+
ensureAlive(gRef->getReferencedGlobal());
215217
}
216218
}
217219

test/IRGen/referenced_global.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-swift-frontend -parse-as-library -primary-file %s -O -emit-ir -o - | %FileCheck %s
2+
3+
// REQUIRES: swift_in_compiler
4+
5+
// Check that IRGen doesn't crash when a global variable reference another private global.
6+
7+
// CHECK-LABEL: @"$s17referenced_global1bSPySiGvp" ={{.*}} global {{.*}} ptr @"$s17referenced_global1x{{.*}}"
8+
public var b = UnsafePointer(&x)
9+
private var x = 1

test/SILOptimizer/dead_function_elimination.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
// RUN: %target-swift-frontend %s -O -emit-sil | %FileCheck %s
22
// RUN: %target-swift-frontend %s -O -emit-sil -enable-testing | %FileCheck -check-prefix=CHECK-TESTING %s
33

4+
// Check if a private global is kept alive if it's only reference from another global variable.
5+
6+
private var g1 = 27
7+
let g2 = UnsafePointer(&g1)
8+
49
// Check if cycles are removed.
510

611
@inline(never)
@@ -184,6 +189,8 @@ public func keepPtrAlive() {
184189
GFStr.aliveFuncPtr()
185190
}
186191

192+
// CHECK-LABEL: sil_global private @$s25dead_function_elimination2g1{{.*}}
193+
187194
// CHECK-NOT: sil {{.*}}inCycleA
188195
// CHECK-NOT: sil {{.*}}inCycleB
189196
// CHECK-NOT: sil {{.*}}DeadMethod

test/SILOptimizer/init_static_globals.sil

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ sil_global [let] @g7 : $TwoFields
9898
// CHECK-NEXT: }
9999
sil_global [let] @g8 : $UnsafePointer<Int32>
100100

101+
sil_global [let] @g9 : $TwoFields
102+
103+
sil @unknownfunc : $@convention(thin) () -> ()
104+
101105
// CHECK-LABEL: sil [global_init_once_fn] [ossa] @globalinit_trivialglobal_func :
102106
// CHECK-NOT: alloc_global
103107
// CHECK-NOT: store
@@ -233,6 +237,34 @@ bb0:
233237
return %10 : $()
234238
}
235239

240+
// CHECK-LABEL: sil [global_init_once_fn] [ossa] @merge_stores_but_no_global_init :
241+
// CHECK: [[GA:%.*]] = global_addr @g9 : $*TwoFields
242+
// CHECK: [[L10:%.*]] = integer_literal $Builtin.Int32, 10
243+
// CHECK: [[I10:%.*]] = struct $Int32 ([[L10]] : $Builtin.Int32)
244+
// CHECK: [[L11:%.*]] = integer_literal $Builtin.Int32, 11
245+
// CHECK: [[I11:%.*]] = struct $Int32 ([[L11]] : $Builtin.Int32)
246+
// CHECK: [[TF:%.*]] = struct $TwoFields ([[I11]] : $Int32, [[I10]] : $Int32)
247+
// CHECK: store [[TF]] to [trivial] [[GA]]
248+
// CHECK: function_ref
249+
// CHECK: } // end sil function 'merge_stores_but_no_global_init'
250+
sil [global_init_once_fn] [ossa] @merge_stores_but_no_global_init : $@convention(c) () -> () {
251+
bb0:
252+
alloc_global @g9
253+
%1 = global_addr @g9 : $*TwoFields
254+
%2 = integer_literal $Builtin.Int32, 10
255+
%3 = struct $Int32 (%2 : $Builtin.Int32)
256+
%4 = struct_element_addr %1 : $*TwoFields, #TwoFields.b
257+
store %3 to [trivial] %4 : $*Int32
258+
%6 = integer_literal $Builtin.Int32, 11
259+
%7 = struct $Int32 (%6 : $Builtin.Int32)
260+
%8 = struct_element_addr %1 : $*TwoFields, #TwoFields.a
261+
store %7 to [trivial] %8 : $*Int32
262+
%f = function_ref @unknownfunc : $@convention(thin) () -> ()
263+
%a = apply %f() : $@convention(thin) () -> ()
264+
%10 = tuple ()
265+
return %10 : $()
266+
}
267+
236268
// CHECK-LABEL: sil [global_init_once_fn] [ossa] @globalinit_wrong_separate_stores :
237269
// CHECK: alloc_global
238270
// CHECK: store

test/SILOptimizer/remove_unused_func.sil

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,30 @@ sil_global @globalFunctionPointer : $@callee_guaranteed () -> () = {
2525
%initval = thin_to_thick_function %0 : $@convention(thin) () -> () to $@callee_guaranteed () -> ()
2626
}
2727

28+
// CHECK-LABEL: sil_global private @self_referencing_private_global
29+
sil_global private @self_referencing_private_global : $Builtin.RawPointer = {
30+
%0 = global_addr @self_referencing_private_global : $*Builtin.RawPointer
31+
%initval = address_to_pointer %0 : $*Builtin.RawPointer to $Builtin.RawPointer
32+
}
33+
34+
// CHECK-LABEL: sil_global private @referencing_other_private_global
35+
sil_global private @referencing_other_private_global : $Builtin.RawPointer = {
36+
%0 = global_addr @self_referencing_private_global : $*Builtin.RawPointer
37+
%initval = address_to_pointer %0 : $*Builtin.RawPointer to $Builtin.RawPointer
38+
}
39+
40+
// CHECK-LABEL: sil_global @referencing_private_globals
41+
sil_global @referencing_private_globals : $Builtin.RawPointer = {
42+
%0 = global_addr @referencing_other_private_global : $*Builtin.RawPointer
43+
%initval = address_to_pointer %0 : $*Builtin.RawPointer to $Builtin.RawPointer
44+
}
45+
46+
// KEEP-NOT: @dead_self_referencing_private_global
47+
sil_global private @dead_self_referencing_private_global : $Builtin.RawPointer = {
48+
%0 = global_addr @dead_self_referencing_private_global : $*Builtin.RawPointer
49+
%initval = address_to_pointer %0 : $*Builtin.RawPointer to $Builtin.RawPointer
50+
}
51+
2852
// CHECK-LABEL: sil private @alivePrivateFunc
2953
sil private @alivePrivateFunc : $@convention(thin) () -> () {
3054
bb0:

0 commit comments

Comments
 (0)