Skip to content

Commit 5655b35

Browse files
authored
Merge pull request #20213 from rjmccall/resilient-global-modify
Synthesize modify accessors for resilient global variables
2 parents 679fc7d + 1d764fd commit 5655b35

File tree

5 files changed

+65
-25
lines changed

5 files changed

+65
-25
lines changed

lib/AST/Decl.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,13 +1699,8 @@ bool AbstractStorageDecl::requiresOpaqueModifyCoroutine() const {
16991699
if (isDynamic())
17001700
return false;
17011701

1702-
// We only need the modify coroutine in type contexts.
1703-
// TODO: resilient global variables?
1704-
auto *dc = getDeclContext();
1705-
if (!dc->isTypeContext())
1706-
return false;
1707-
17081702
// Requirements of ObjC protocols don't support the modify coroutine.
1703+
auto *dc = getDeclContext();
17091704
if (auto protoDecl = dyn_cast<ProtocolDecl>(dc))
17101705
if (protoDecl->isObjC())
17111706
return false;

lib/SILGen/SILGen.cpp

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,15 +1205,40 @@ void SILGenModule::visitVarDecl(VarDecl *vd) {
12051205
if (vd->hasStorage())
12061206
addGlobalVariable(vd);
12071207

1208-
if (vd->getImplInfo().isSimpleStored()) {
1209-
// If the global variable has storage, it might also have synthesized
1210-
// accessors. Emit them here, since they won't appear anywhere else.
1211-
vd->visitExpectedOpaqueAccessors([&](AccessorKind kind) {
1212-
auto accessor = vd->getAccessor(kind);
1213-
if (accessor)
1214-
emitFunction(accessor);
1215-
});
1216-
}
1208+
// Emit the variable's opaque accessors.
1209+
vd->visitExpectedOpaqueAccessors([&](AccessorKind kind) {
1210+
auto accessor = vd->getAccessor(kind);
1211+
if (!accessor) return;
1212+
1213+
// Only eit the accessor if it wasn't added to the surrounding decl
1214+
// list by the parser. We can test that easily by looking at the impl
1215+
// info, since all of these accessors have a corresponding access kind
1216+
// whose impl should definitely point at the accessor if it was parsed.
1217+
//
1218+
// This is an unfortunate formation rule, but it's easier than messing
1219+
// with the invariants for now.
1220+
bool shouldEmit = [&] {
1221+
auto impl = vd->getImplInfo();
1222+
switch (kind) {
1223+
case AccessorKind::Get:
1224+
return impl.getReadImpl() != ReadImplKind::Get;
1225+
case AccessorKind::Read:
1226+
return impl.getReadImpl() != ReadImplKind::Read;
1227+
case AccessorKind::Set:
1228+
return impl.getWriteImpl() != WriteImplKind::Set;
1229+
case AccessorKind::Modify:
1230+
return impl.getReadWriteImpl() != ReadWriteImplKind::Modify;
1231+
#define ACCESSOR(ID) \
1232+
case AccessorKind::ID:
1233+
#define OPAQUE_ACCESSOR(ID, KEYWORD)
1234+
#include "swift/AST/AccessorKinds.def"
1235+
llvm_unreachable("not an opaque accessor");
1236+
}
1237+
}();
1238+
if (!shouldEmit) return;
1239+
1240+
emitFunction(accessor);
1241+
});
12171242

12181243
tryEmitPropertyDescriptor(vd);
12191244
}

test/Inputs/resilient_global.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ public struct EmptyResilientStruct {
44
public var computed: Int {
55
return 1337
66
}
7+
8+
public mutating func mutate() {}
79
}
810

911
public var emptyGlobal = EmptyResilientStruct()

test/SILGen/global_resilience.swift

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public var myEmptyGlobal = MyEmptyStruct()
2121
// CHECK: global_addr @$s17global_resilience13myEmptyGlobalAA02MyD6StructVv
2222
// CHECK: return
2323

24-
// Synthesized getter and setter for our resilient global variable
24+
// Synthesized accessors for our resilient global variable
2525

2626
// CHECK-LABEL: sil @$s17global_resilience13myEmptyGlobalAA02MyD6StructVvg
2727
// CHECK: function_ref @$s17global_resilience13myEmptyGlobalAA02MyD6StructVvau
@@ -31,6 +31,12 @@ public var myEmptyGlobal = MyEmptyStruct()
3131
// CHECK: function_ref @$s17global_resilience13myEmptyGlobalAA02MyD6StructVvau
3232
// CHECK: return
3333

34+
// CHECK-LABEL: sil @$s17global_resilience13myEmptyGlobalAA02MyD6StructVvM
35+
// CHECK: function_ref @$s17global_resilience13myEmptyGlobalAA02MyD6StructVvau
36+
// CHECK: begin_access [modify] [dynamic]
37+
// CHECK: yield
38+
// CHECK: end_access
39+
3440
// Mutable addressor for fixed-layout global
3541

3642
// CHECK-LABEL: sil [global_init] @$s17global_resilience19myFixedLayoutGlobalAA13MyEmptyStructVvau
@@ -66,6 +72,19 @@ public func getEmptyGlobal() -> EmptyResilientStruct {
6672
return emptyGlobal
6773
}
6874

75+
// CHECK-LABEL: sil @$s17global_resilience17modifyEmptyGlobalyyF
76+
// CHECK: [[MODIFY:%.*]] = function_ref @$s16resilient_global11emptyGlobalAA20EmptyResilientStructVvM
77+
// CHECK-NEXT: ([[ADDR:%.*]], [[TOKEN:%.*]]) = begin_apply [[MODIFY]]()
78+
// CHECK-NEXT: // function_ref
79+
// CHECK-NEXT: [[FN:%.*]] = function_ref @$s16resilient_global20EmptyResilientStructV6mutateyyF
80+
// CHECK-NEXT: apply [[FN]]([[ADDR]])
81+
// CHECK-NEXT: end_apply [[TOKEN]]
82+
// CHECK-NEXT: tuple
83+
// CHECK-NEXT: return
84+
public func modifyEmptyGlobal() {
85+
emptyGlobal.mutate()
86+
}
87+
6988
// Accessing fixed-layout global from a different resilience domain --
7089
// call the addressor directly
7190

test/SILGen/properties.swift

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,14 @@ var global_observing_property : Int = zero {
648648
// CHECK: properties.zero.unsafeMutableAddressor
649649
// CHECK: return
650650

651+
// global_observing_property's setter needs to call didSet.
652+
653+
// CHECK-LABEL: sil hidden @$s10properties25global_observing_property{{[_0-9a-zA-Z]*}}vs
654+
// CHECK: function_ref properties.global_observing_property.unsafeMutableAddressor
655+
// CHECK-NEXT: function_ref @$s10properties25global_observing_property{{[_0-9a-zA-Z]*}}vau
656+
// CHECK: function_ref properties.global_observing_property.didset
657+
// CHECK-NEXT: function_ref @$s10properties25global_observing_property{{[_0-9a-zA-Z]*}}vW
658+
651659
// CHECK-LABEL: sil private @$s10properties25global_observing_property{{[_0-9a-zA-Z]*}}vW
652660
didSet {
653661
// The didSet implementation needs to call takeInt.
@@ -683,15 +691,6 @@ func force_global_observing_property_setter() {
683691
global_observing_property = x
684692
}
685693

686-
// global_observing_property's setter needs to call didSet.
687-
688-
// CHECK-LABEL: sil hidden @$s10properties25global_observing_property{{[_0-9a-zA-Z]*}}vs
689-
// CHECK: function_ref properties.global_observing_property.unsafeMutableAddressor
690-
// CHECK-NEXT: function_ref @$s10properties25global_observing_property{{[_0-9a-zA-Z]*}}vau
691-
// CHECK: function_ref properties.global_observing_property.didset
692-
// CHECK-NEXT: function_ref @$s10properties25global_observing_property{{[_0-9a-zA-Z]*}}vW
693-
694-
695694
// Test local observing properties.
696695

697696
// CHECK-LABEL: sil hidden @$s10properties24local_observing_property{{[_0-9a-zA-Z]*}}SiF

0 commit comments

Comments
 (0)