Skip to content

Commit 2abfa25

Browse files
authored
Merge pull request #67354 from gottesmm/pr-45bdcac91308a0aa164064d4356f91a367ea00fa
[move-only] Fix lazily initialized global initializers.
2 parents 82f1ea2 + 1f22f92 commit 2abfa25

File tree

4 files changed

+118
-5
lines changed

4 files changed

+118
-5
lines changed

lib/SILGen/SILGenLValue.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,13 +1085,17 @@ namespace {
10851085
ManagedValue Value;
10861086
llvm::Optional<SILAccessEnforcement> Enforcement;
10871087
bool IsRValue;
1088+
bool IsLazyInitializedGlobal;
1089+
10881090
public:
10891091
ValueComponent(ManagedValue value,
10901092
llvm::Optional<SILAccessEnforcement> enforcement,
10911093
LValueTypeData typeData, bool isRValue = false,
1092-
llvm::Optional<ActorIsolation> actorIso = llvm::None)
1094+
llvm::Optional<ActorIsolation> actorIso = llvm::None,
1095+
bool isLazyInitializedGlobal = false)
10931096
: PhysicalPathComponent(typeData, ValueKind, actorIso), Value(value),
1094-
Enforcement(enforcement), IsRValue(isRValue) {
1097+
Enforcement(enforcement), IsRValue(isRValue),
1098+
IsLazyInitializedGlobal(isLazyInitializedGlobal) {
10951099
assert(IsRValue || value.getType().isAddress() ||
10961100
value.getType().isBoxedNonCopyableType(value.getFunction()));
10971101
}
@@ -1106,7 +1110,7 @@ namespace {
11061110
if (Value.getType().isAddress() && Value.getType().isMoveOnly()) {
11071111
SILValue addr = Value.getValue();
11081112
auto box = dyn_cast<ProjectBoxInst>(addr);
1109-
if (box || isa<GlobalAddrInst>(addr)) {
1113+
if (box || isa<GlobalAddrInst>(addr) || IsLazyInitializedGlobal) {
11101114
if (Enforcement)
11111115
addr = enterAccessScope(SGF, loc, base, addr, getTypeData(),
11121116
getAccessKind(), *Enforcement,
@@ -3229,9 +3233,12 @@ void LValue::addNonMemberVarComponent(
32293233
auto astAccessKind = mapAccessKind(this->AccessKind);
32303234
auto address = SGF.maybeEmitValueOfLocalVarDecl(Storage, astAccessKind);
32313235

3236+
bool isLazyInitializedGlobal = false;
3237+
32323238
// The only other case that should get here is a global variable.
32333239
if (!address) {
3234-
address = SGF.emitGlobalVariableRef(Loc, Storage, ActorIso);
3240+
address = SGF.emitGlobalVariableRef(Loc, Storage, ActorIso);
3241+
isLazyInitializedGlobal = Storage->isLazilyInitializedGlobal();
32353242
} else {
32363243
assert((!ActorIso || Storage->isTopLevelGlobal()) &&
32373244
"local var should not be actor isolated!");
@@ -3257,7 +3264,8 @@ void LValue::addNonMemberVarComponent(
32573264
}
32583265

32593266
LV.add<ValueComponent>(address, enforcement, typeData,
3260-
/*isRValue=*/false, ActorIso);
3267+
/*isRValue=*/false, ActorIso,
3268+
isLazyInitializedGlobal);
32613269

32623270
if (address.getType().is<ReferenceStorageType>())
32633271
LV.add<OwnershipComponent>(typeData);

lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,15 @@ void UseState::initializeLiveness(
10281028
liveness.initializeDef(address, liveness.getTopLevelSpan());
10291029
}
10301030

1031+
if (auto *ptai = dyn_cast<PointerToAddressInst>(
1032+
stripAccessMarkers(address->getOperand()))) {
1033+
assert(ptai->isStrict());
1034+
LLVM_DEBUG(llvm::dbgs() << "Found pointer to address use... "
1035+
"adding mark_must_check as init!\n");
1036+
recordInitUse(address, address, liveness.getTopLevelSpan());
1037+
liveness.initializeDef(address, liveness.getTopLevelSpan());
1038+
}
1039+
10311040
// Now that we have finished initialization of defs, change our multi-maps
10321041
// from their array form to their map form.
10331042
liveness.finishedInitializationOfDefs();
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// RUN: %target-swift-emit-silgen -sil-verify-all -parse-as-library %s | %FileCheck %s
2+
3+
struct S: ~Copyable {
4+
let s: String
5+
init(_ s: String) { self.s = s }
6+
deinit { print("deiniting \(s)") }
7+
}
8+
9+
struct M4 : ~Copyable {
10+
var s1: S
11+
var s2: S
12+
init(_ s: String) {
13+
fatalError()
14+
}
15+
}
16+
17+
func rewriteTwo(_ one: inout S, _ two: inout S) {
18+
one = S("new1")
19+
two = S("new2")
20+
}
21+
22+
var m = M4("1")
23+
var m2 = M4("1")
24+
25+
struct Doit {
26+
static var m3 = M4("1")
27+
static var m4 = M4("1")
28+
29+
// CHECK-LABEL: sil hidden [ossa] @$s33moveonly_lazy_initialized_globals4DoitV3runyyFZ : $@convention(method) (@thin Doit.Type) -> () {
30+
// CHECK: [[F1:%.*]] = function_ref @$s33moveonly_lazy_initialized_globals1mAA2M4Vvau : $@convention(thin) () -> Builtin.RawPointer
31+
// CHECK: [[PTR1:%.*]] = apply [[F1]]()
32+
// CHECK: [[ADDR1:%.*]] = pointer_to_address [[PTR1]]
33+
// CHECK: [[F2:%.*]] = function_ref @$s33moveonly_lazy_initialized_globals2m2AA2M4Vvau : $@convention(thin) () -> Builtin.RawPointer
34+
// CHECK: [[PTR2:%.*]] = apply [[F2]]()
35+
// CHECK: [[ADDR2:%.*]] = pointer_to_address [[PTR2]]
36+
// CHECK: [[ACCESS1:%.*]] = begin_access [modify] [dynamic] [[ADDR1]]
37+
// CHECK: [[MARK1:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS1]]
38+
// CHECK: [[GEP1:%.*]] = struct_element_addr [[MARK1]]
39+
// CHECK: [[ACCESS2:%.*]] = begin_access [modify] [dynamic] [[ADDR2]]
40+
// CHECK: [[MARK2:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS2]]
41+
// CHECK: [[GEP2:%.*]] = struct_element_addr [[MARK2]]
42+
// CHECK: apply {{%.*}}([[GEP1]], [[GEP2]])
43+
//
44+
// CHECK: [[F3:%.*]] = function_ref @$s33moveonly_lazy_initialized_globals4DoitV2m3AA2M4Vvau : $@convention(thin) () -> Builtin.RawPointer
45+
// CHECK: [[PTR3:%.*]] = apply [[F3]]()
46+
// CHECK: [[ADDR3:%.*]] = pointer_to_address [[PTR3]]
47+
// CHECK: [[F4:%.*]] = function_ref @$s33moveonly_lazy_initialized_globals4DoitV2m4AA2M4Vvau : $@convention(thin) () -> Builtin.RawPointer
48+
// CHECK: [[PTR4:%.*]] = apply [[F4]]()
49+
// CHECK: [[ADDR4:%.*]] = pointer_to_address [[PTR4]]
50+
// CHECK: [[ACCESS3:%.*]] = begin_access [modify] [dynamic] [[ADDR3]]
51+
// CHECK: [[MARK3:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS3]]
52+
// CHECK: [[GEP3:%.*]] = struct_element_addr [[MARK3]]
53+
// CHECK: [[ACCESS4:%.*]] = begin_access [modify] [dynamic] [[ADDR4]]
54+
// CHECK: [[MARK4:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS4]]
55+
// CHECK: [[GEP4:%.*]] = struct_element_addr [[MARK4]]
56+
// CHECK: apply {{%.*}}([[GEP3]], [[GEP4]])
57+
// CHECK: } // end sil function '$s33moveonly_lazy_initialized_globals4DoitV3runyyFZ'
58+
static func run() {
59+
rewriteTwo(&m.s1, &m2.s2)
60+
rewriteTwo(&m3.s1, &m4.s2)
61+
}
62+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-swift-emit-sil -sil-verify-all -parse-as-library -verify %s
2+
3+
struct S: ~Copyable {
4+
let s: String
5+
init(_ s: String) { self.s = s }
6+
deinit { print("deiniting \(s)") }
7+
}
8+
9+
struct M4 : ~Copyable {
10+
var s1: S
11+
var s2: S
12+
init(_ s: String) {
13+
fatalError()
14+
}
15+
}
16+
17+
func rewriteTwo(_ one: inout S, _ two: inout S) {
18+
one = S("new1")
19+
two = S("new2")
20+
}
21+
22+
var m = M4("1")
23+
var m2 = M4("1")
24+
25+
struct Doit {
26+
static var m3 = M4("1")
27+
static var m4 = M4("1")
28+
29+
// We should get no diagnostics.
30+
static func run() {
31+
rewriteTwo(&m.s1, &m2.s2)
32+
rewriteTwo(&m3.s1, &m4.s2)
33+
}
34+
}

0 commit comments

Comments
 (0)