Skip to content

Commit b6e9c4c

Browse files
committed
TempLValueElimination: don't propagate alloc_stack which have access scopes
If exclusivity is checked for the alloc_stack we must not replace it with the copy-destination. If the copy-destination is also in an access-scope this would result in an exclusivity violation which was not there before. Fixes a miscompile which results in a wrong exclusivity violation error at runtime. #83924 rdar://159220436
1 parent 86076e2 commit b6e9c4c

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/TempLValueElimination.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ private func tryEliminate(copy: CopyLikeInstruction, _ context: FunctionPassCont
113113
return
114114
}
115115

116+
// If exclusivity is checked for the alloc_stack we must not replace it with the copy-destination.
117+
// If the copy-destination is also in an access-scope this would result in an exclusivity violation
118+
// which was not there before.
119+
guard allocStack.uses.users(ofType: BeginAccessInst.self).isEmpty else {
120+
return
121+
}
122+
116123
var worklist = InstructionWorklist(context)
117124
defer { worklist.deinitialize() }
118125
worklist.pushIfNotVisited(firstUseOfAllocStack)
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// RUN: %target-build-swift %t/module.swift -parse-as-library -O -enable-library-evolution -module-name=Module -emit-module -emit-module-path %t/Module.swiftmodule
5+
// RUN: %target-build-swift %t/module.swift -parse-as-library -O -enable-library-evolution -module-name=Module -c -o %t/module.o
6+
// RUN: %target-build-swift -parse-as-library -O %t/main.swift -I%t %t/module.o -o %t/a.out
7+
// RUN: %target-codesign %t/a.out
8+
// RUN: %target-run %t/a.out | %FileCheck %s
9+
10+
// REQUIRES: executable_test
11+
12+
13+
// Check that TempLValueElimination does not cause an exclusivity violation at runtime.
14+
15+
//--- module.swift
16+
17+
public struct ResilientStruct {
18+
public init() {}
19+
}
20+
21+
//--- main.swift
22+
23+
import Module
24+
25+
struct MyState {
26+
var _prop: String
27+
var prop: String
28+
{
29+
@storageRestrictions(initializes: _prop)
30+
init(initialValue) {
31+
_prop = initialValue
32+
}
33+
get {
34+
return _prop
35+
}
36+
}
37+
38+
let resilient = ResilientStruct()
39+
40+
init(prop: String) {
41+
self.prop = prop
42+
}
43+
}
44+
45+
class Node {
46+
var state = MyState(prop: "initial value")
47+
48+
func update(_ body: (inout MyState) -> Void) {
49+
body(&state)
50+
}
51+
}
52+
53+
@inline(never)
54+
func test_exclusivity() {
55+
let node = Node()
56+
node.update { state in
57+
state = MyState(prop: "new value")
58+
}
59+
}
60+
61+
@main
62+
enum App {
63+
static func main() {
64+
test_exclusivity()
65+
// CHECK: success
66+
print("success")
67+
}
68+
}

test/SILOptimizer/templvalueopt_ossa.sil

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,3 +685,20 @@ bb2:
685685
%r = tuple ()
686686
return %r
687687
}
688+
689+
// CHECK-LABEL: sil [ossa] @dont_propagate_with_access_scope :
690+
// CHECK: alloc_stack
691+
// CHECK: copy_addr
692+
// CHECK-LABEL: } // end sil function 'dont_propagate_with_access_scope'
693+
sil [ossa] @dont_propagate_with_access_scope : $@convention(thin) (@inout Int, Int) -> () {
694+
bb0(%0 : $*Int, %1 : $Int):
695+
%2 = alloc_stack $Int
696+
%3 = begin_access [modify] [dynamic] %2
697+
store %1 to [trivial] %3
698+
end_access %3
699+
copy_addr %2 to %0
700+
dealloc_stack %2
701+
%8 = tuple ()
702+
return %8
703+
}
704+

0 commit comments

Comments
 (0)