Skip to content

Commit 627c906

Browse files
committed
SILGen: Emit alloc_global when initializing global variables
It is still not clear to me when we access global variables from other modules directly, versus using accessors; it seems to be controlled by the -sil-serialize-all flag, rather than any language feature. Until/if we add a @_fixed_layout equivalent for globals, I can't really test direct access of globals from other modules; when we figure out the story here I'll be able to add more tests and also tighten up some isResilient() checks in the global code, but what's in there now seems to work.
1 parent 85a3e5c commit 627c906

File tree

9 files changed

+140
-7
lines changed

9 files changed

+140
-7
lines changed

lib/IRGen/GenInit.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@ Address IRGenModule::emitSILGlobalVariable(SILGlobalVariable *var) {
3636
auto &ti = getTypeInfo(var->getLoweredType());
3737

3838
// If the variable is empty, don't actually emit it; just return undef.
39-
if (ti.isKnownEmpty()) {
39+
if (ti.isFixedSize(ResilienceExpansion::Minimal) && ti.isKnownEmpty())
4040
return ti.getUndefAddress();
41-
}
42-
41+
4342
/// Get the global variable.
4443
Address addr = getAddrOfSILGlobalVariable(var, ti,
4544
var->isDefinition() ? ForDefinition : NotForDefinition);

lib/IRGen/IRGenSIL.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,8 +1633,9 @@ void IRGenSILFunction::visitGlobalAddrInst(GlobalAddrInst *i) {
16331633
assert(loweredTy == i->getType().getObjectType());
16341634
auto &ti = getTypeInfo(loweredTy);
16351635

1636-
// If the variable is empty, don't actually emit it; just return undef.
1637-
if (ti.isKnownEmpty()) {
1636+
// If the variable is universally fixed-size and known to be empty, don't
1637+
// actually emit a symbol for the global at all, just return undef.
1638+
if (ti.isFixedSize(ResilienceExpansion::Minimal) && ti.isKnownEmpty()) {
16381639
setLoweredAddress(SILValue(i, 0), ti.getUndefAddress());
16391640
return;
16401641
}

lib/SILGen/SILGenDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,7 @@ InitializationPtr SILGenFunction::emitInitializationForVarDecl(VarDecl *vd) {
918918
InitializationPtr Result;
919919
if (!vd->getDeclContext()->isLocalContext()) {
920920
auto *silG = SGM.getSILGlobalVariable(vd, NotForDefinition);
921+
B.createAllocGlobal(vd, silG);
921922
SILValue addr = B.createGlobalAddr(vd, silG);
922923
if (isUninitialized)
923924
addr = B.createMarkUninitializedVar(vd, addr);

test/Inputs/resilient_global.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
public struct EmptyResilientStruct {
2+
public init() {}
3+
4+
public var computed: Int {
5+
return 1337
6+
}
7+
}
8+
9+
public var emptyGlobal = EmptyResilientStruct()
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// RUN: rm -rf %t && mkdir %t
2+
// RUN: %target-build-swift -emit-library -I %t -Xfrontend -enable-resilience -c %S/../Inputs/resilient_global.swift -o %t/resilient_global.o
3+
// RUN: %target-build-swift -emit-module -I %t -Xfrontend -enable-resilience -c %S/../Inputs/resilient_global.swift -o %t/resilient_global.o
4+
// RUN: %target-build-swift -emit-library -I %t -Xfrontend -enable-resilience -c %S/../Inputs/resilient_struct.swift -o %t/resilient_struct.o
5+
// RUN: %target-build-swift -emit-module -I %t -Xfrontend -enable-resilience -c %S/../Inputs/resilient_struct.swift -o %t/resilient_struct.o
6+
// RUN: %target-build-swift %s -Xlinker %t/resilient_global.o -Xlinker %t/resilient_struct.o -I %t -L %t -o %t/main
7+
// RUN: %target-run %t/main
8+
9+
import StdlibUnittest
10+
import resilient_global
11+
import resilient_struct
12+
13+
var ResilientGlobalTestSuite = TestSuite("ResilientGlobal")
14+
15+
//
16+
// Fits inside a buffer's inline storage.
17+
//
18+
19+
public struct MySmallResilientStruct {
20+
let x: Int32
21+
}
22+
23+
let mySmallGlobal = MySmallResilientStruct(x: 1)
24+
25+
ResilientGlobalTestSuite.test("MySmallGlobal") {
26+
expectEqual(1, mySmallGlobal.x)
27+
}
28+
29+
//
30+
// Requires out-of-line allocation.
31+
//
32+
33+
public struct MyLargeResilientStruct {
34+
let w: Int64
35+
let x: Int64
36+
let y: Int64
37+
let z: Int64
38+
}
39+
40+
var myLargeGlobal = MyLargeResilientStruct(w: 1, x: 2, y: 3, z: 4)
41+
42+
ResilientGlobalTestSuite.test("MyLargeGlobal") {
43+
expectEqual(1, myLargeGlobal.w)
44+
expectEqual(2, myLargeGlobal.x)
45+
expectEqual(3, myLargeGlobal.y)
46+
expectEqual(4, myLargeGlobal.z)
47+
48+
myLargeGlobal = MyLargeResilientStruct(w: 5, x: 6, y: 7, z: 8)
49+
expectEqual(5, myLargeGlobal.w)
50+
expectEqual(6, myLargeGlobal.x)
51+
expectEqual(7, myLargeGlobal.y)
52+
expectEqual(8, myLargeGlobal.z)
53+
}
54+
55+
let myLargeGlobalUninitialized: MyLargeResilientStruct
56+
57+
myLargeGlobalUninitialized = MyLargeResilientStruct(w: 9, x: 10, y: 11, z: 12)
58+
59+
ResilientGlobalTestSuite.test("MyLargeGlobal") {
60+
expectEqual(9, myLargeGlobalUninitialized.w)
61+
expectEqual(10, myLargeGlobalUninitialized.x)
62+
expectEqual(11, myLargeGlobalUninitialized.y)
63+
expectEqual(12, myLargeGlobalUninitialized.z)
64+
}
65+
66+
//
67+
// Unknown size -- must call value witness functions for buffer
68+
// management.
69+
//
70+
71+
let myOtherGlobal = Size(w: 10, h: 15)
72+
73+
ResilientGlobalTestSuite.test("MyOtherGlobal") {
74+
expectEqual(10, myOtherGlobal.w)
75+
expectEqual(15, myOtherGlobal.h)
76+
}
77+
78+
//
79+
// Global variable is itself defined in a different module.
80+
//
81+
82+
ResilientGlobalTestSuite.test("OtherGlobal") {
83+
expectEqual(1337, emptyGlobal.computed)
84+
}
85+
86+
runAllTests()

test/SILGen/lazy_globals.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// RUN: %target-swift-frontend -parse-as-library -emit-silgen %s | FileCheck %s
22

33
// CHECK: sil private @globalinit_[[T:.*]]_func0 : $@convention(thin) () -> () {
4+
// CHECK: alloc_global @_Tv12lazy_globals1xSi
45
// CHECK: [[XADDR:%.*]] = global_addr @_Tv12lazy_globals1xSi : $*Int
56
// CHECK: store {{%.*}} to [[XADDR]] : $*Int
7+
68
// CHECK: sil hidden [global_init] @_TF12lazy_globalsau1xSi : $@convention(thin) () -> Builtin.RawPointer {
79
// CHECK: [[TOKEN_ADDR:%.*]] = global_addr @globalinit_[[T]]_token0 : $*Builtin.Word
810
// CHECK: [[TOKEN_PTR:%.*]] = address_to_pointer [[TOKEN_ADDR]] : $*Builtin.Word to $Builtin.RawPointer
@@ -14,8 +16,21 @@
1416
// CHECK: }
1517
var x: Int = 0
1618

19+
// CHECK: sil private @globalinit_[[T:.*]]_func1 : $@convention(thin) () -> () {
20+
// CHECK: alloc_global @_TZvV12lazy_globals3Foo3fooSi
21+
// CHECK: [[XADDR:%.*]] = global_addr @_TZvV12lazy_globals3Foo3fooSi : $*Int
22+
// CHECK: store {{.*}} to [[XADDR]] : $*Int
23+
// CHECK: return
24+
1725
struct Foo {
1826
// CHECK: sil hidden [global_init] @_TFV12lazy_globals3Fooau3fooSi : $@convention(thin) () -> Builtin.RawPointer {
27+
// CHECK: [[TOKEN_ADDR:%.*]] = global_addr @globalinit_[[T]]_token1 : $*Builtin.Word
28+
// CHECK: [[TOKEN_PTR:%.*]] = address_to_pointer [[TOKEN_ADDR]] : $*Builtin.Word to $Builtin.RawPointer
29+
// CHECK: [[INIT_FUNC:%.*]] = function_ref @globalinit_[[T]]_func1 : $@convention(thin) () -> ()
30+
// CHECK: builtin "once"([[TOKEN_PTR]] : $Builtin.RawPointer, [[INIT_FUNC]] : $@convention(thin) () -> ()) : $()
31+
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @_TZvV12lazy_globals3Foo3fooSi : $*Int
32+
// CHECK: [[GLOBAL_PTR:%.*]] = address_to_pointer [[GLOBAL_ADDR]] : $*Int to $Builtin.RawPointer
33+
// CHECK: return [[GLOBAL_PTR]] : $Builtin.RawPointer
1934
static var foo: Int = 22
2035

2136
static var computed: Int {
@@ -25,8 +40,21 @@ struct Foo {
2540
static var initialized: Int = 57
2641
}
2742

43+
// CHECK: sil private @globalinit_[[T:.*]]_func3 : $@convention(thin) () -> () {
44+
// CHECK: alloc_global @_TZvO12lazy_globals3Bar3barSi
45+
// CHECK: [[XADDR:%.*]] = global_addr @_TZvO12lazy_globals3Bar3barSi : $*Int
46+
// CHECK: store {{.*}} to [[XADDR]] : $*Int
47+
// CHECK: return
48+
2849
enum Bar {
2950
// CHECK: sil hidden [global_init] @_TFO12lazy_globals3Barau3barSi : $@convention(thin) () -> Builtin.RawPointer {
51+
// CHECK: [[TOKEN_ADDR:%.*]] = global_addr @globalinit_[[T]]_token3 : $*Builtin.Word
52+
// CHECK: [[TOKEN_PTR:%.*]] = address_to_pointer [[TOKEN_ADDR]] : $*Builtin.Word to $Builtin.RawPointer
53+
// CHECK: [[INIT_FUNC:%.*]] = function_ref @globalinit_[[T]]_func3 : $@convention(thin) () -> ()
54+
// CHECK: builtin "once"([[TOKEN_PTR]] : $Builtin.RawPointer, [[INIT_FUNC]] : $@convention(thin) () -> ()) : $()
55+
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @_TZvO12lazy_globals3Bar3barSi : $*Int
56+
// CHECK: [[GLOBAL_PTR:%.*]] = address_to_pointer [[GLOBAL_ADDR]] : $*Int to $Builtin.RawPointer
57+
// CHECK: return [[GLOBAL_PTR]] : $Builtin.RawPointer
3058
static var bar: Int = 33
3159
}
3260

test/SILGen/lazy_globals_multiple_vars.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// RUN: %target-swift-frontend -parse-as-library -emit-silgen %s | FileCheck %s
22

33
// CHECK: sil private [[INIT_A_B:@globalinit_.*]] :
4+
// CHECK: alloc_global @_Tv26lazy_globals_multiple_vars1aSi
45
// CHECK: global_addr @_Tv26lazy_globals_multiple_vars1aSi
6+
// CHECK: alloc_global @_Tv26lazy_globals_multiple_vars1bSi
57
// CHECK: global_addr @_Tv26lazy_globals_multiple_vars1bSi
68
// CHECK: sil hidden [global_init] @_TF26lazy_globals_multiple_varsau1aSi
79
// CHECK: global_addr [[TOKEN_A_B:@globalinit_.*]] :
@@ -13,13 +15,15 @@ var (a, b) = (1, 2)
1315

1416
// CHECK: sil private [[INIT_C:@globalinit_.*]] :
1517
// CHECK-NOT: global_addr @_Tv26lazy_globals_multiple_vars1dSi
18+
// CHECK: alloc_global @_Tv26lazy_globals_multiple_vars1cSi
1619
// CHECK: global_addr @_Tv26lazy_globals_multiple_vars1cSi
1720
// CHECK-NOT: global_addr @_Tv26lazy_globals_multiple_vars1dSi
1821
// CHECK: sil hidden [global_init] @_TF26lazy_globals_multiple_varsau1cSi
1922
// CHECK: global_addr [[TOKEN_C:@globalinit_.*]] :
2023
// CHECK: function_ref [[INIT_C]]
2124
// CHECK: sil private [[INIT_D:@globalinit_.*]] :
2225
// CHECK-NOT: global_addr @_Tv26lazy_globals_multiple_vars1cSi
26+
// CHECK: alloc_global @_Tv26lazy_globals_multiple_vars1dSi
2327
// CHECK: global_addr @_Tv26lazy_globals_multiple_vars1dSi
2428
// CHECK-NOT: global_addr @_Tv26lazy_globals_multiple_vars1cSi
2529
// CHECK: sil hidden [global_init] @_TF26lazy_globals_multiple_varsau1dSi

test/SILGen/properties.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,8 @@ func force_global_observing_property_setter() {
566566
// The property is initialized with "zero".
567567
// CHECK-LABEL: sil private @globalinit_{{.*}}_func1 : $@convention(thin) () -> () {
568568
// CHECK: bb0:
569-
// CHECK-NEXT: %0 = global_addr @_Tv10properties25global_observing_propertySi : $*Int
569+
// CHECK-NEXT: alloc_global @_Tv10properties25global_observing_propertySi
570+
// CHECK-NEXT: %1 = global_addr @_Tv10properties25global_observing_propertySi : $*Int
570571
// CHECK: properties.zero.unsafeMutableAddressor
571572
// CHECK: return
572573

test/SILGen/toplevel.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ func markUsed<T>(t: T) {}
1111
// CHECK: bb0({{%.*}} : $Int32, {{%.*}} : $UnsafeMutablePointer<UnsafeMutablePointer<Int8>>):
1212

1313
// -- initialize x
14+
// CHECK: alloc_global @_Tv8toplevel1xSi
1415
// CHECK: [[X:%[0-9]+]] = global_addr @_Tv8toplevel1xSi : $*Int
1516
// CHECK: integer_literal $Builtin.Int2048, 999
1617
// CHECK: store {{.*}} to [[X]]
@@ -32,6 +33,7 @@ x = 0
3233
print_x()
3334

3435
// <rdar://problem/19770775> Deferred initialization of let bindings rejected at top level in playground
36+
// CHECK: alloc_global @_Tv8toplevel5countSi
3537
// CHECK: [[COUNTADDR:%[0-9]+]] = global_addr @_Tv8toplevel5countSi : $*Int
3638
// CHECK-NEXT: [[COUNTMUI:%[0-9]+]] = mark_uninitialized [var] [[COUNTADDR]] : $*Int
3739
let count: Int
@@ -60,6 +62,7 @@ func print_y() {
6062

6163

6264
// -- assign y
65+
// CHECK: alloc_global @_Tv8toplevel1ySi
6366
// CHECK: [[Y1:%[0-9]+]] = global_addr @_Tv8toplevel1ySi : $*Int
6467
// CHECK: [[Y:%[0-9]+]] = mark_uninitialized [var] [[Y1]]
6568
// CHECK: assign {{.*}} to [[Y]]
@@ -81,7 +84,8 @@ guard let a = Optional(A()) else { trap() }
8184
markUsed(a)
8285

8386

84-
// CHECK: [[VARADDR:%[0-9]+]] = global_addr @_Tv8toplevel21NotInitializedIntegerSi
87+
// CHECK: alloc_global @_Tv8toplevel21NotInitializedIntegerSi
88+
// CHECK-NEXT: [[VARADDR:%[0-9]+]] = global_addr @_Tv8toplevel21NotInitializedIntegerSi
8589
// CHECK-NEXT: [[VARMUI:%[0-9]+]] = mark_uninitialized [var] [[VARADDR]] : $*Int
8690
// CHECK-NEXT: mark_function_escape [[VARMUI]] : $*Int
8791

0 commit comments

Comments
 (0)