forked from swiftlang/swift
- Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcustom_rr_abi.swift
86 lines (69 loc) · 2.82 KB
/
custom_rr_abi.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// RUN: %target-run-simple-swift(-import-objc-header %S/Inputs/custom_rr_abi_utilities.h)
// REQUIRES: CPU=arm64 || CPU=arm64e
// REQUIRES: executable_test
// UNSUPPORTED: use_os_stdlib
// UNSUPPORTED: back_deployment_runtime
import StdlibUnittest
// A class that can provider a retainable pointer and determine whether it's
// been retained or released. This creates a helper object that will be retained
// or released. We don't attempt to clean up the helper so it leaks if not released,
// but this is only used for this one test so that's OK.
classRetainReleaseChecker{
varpointerValue:UnsafeMutableRawPointer
privateclassHelper{}
private weak varweakRef:Helper?
privateletoriginalRetainCount:UInt
init(){
do{
// Make a helper object, retain it so it stays alive, and put it into
// pointerValue and weakRef.
lethelper=Helper()
pointerValue =Unmanaged.passRetained(helper).toOpaque()
weakRef = helper
}
// Record the original retain count before anything happens. Then we can
// detect changes without needing to know exactly what the count is supposed
// to be.
originalRetainCount =_getRetainCount(weakRef!)
}
// If helper was retained, then weakRef will still point to it, and the retain
// count will have increased.
varretained:Bool{
weakRef !=nil && _getRetainCount(weakRef!)> originalRetainCount
}
// weakRef is the only reference we had to the helper, aside from the retain we put
// on it to create pointerValue. If helper was released, then it will be destroyed
// and weakRef will be nil.
varreleased:Bool{
weakRef ==nil
}
}
varCustomRRABITestSuite=TestSuite("CustomRRABI")
CustomRRABITestSuite.test("retain"){
foreachRRFunction{ function, cname, register, isRetain in
letname=String(cString: cname!)
letfullname="\(name)_x\(register)"
// Create a set of RR checker objects.
varcheckers=(0..<NUM_REGS).map{ _ inRetainReleaseChecker()}
// Fill out a registers array with the pointers from the RR checkers.
varregs:[UnsafeMutableRawPointer?]= checkers.map{ $0.pointerValue }
// Call the RR function.
function!(®s)
// Make sure all the checkers report what they're supposed to. All registers
// aside from `register` should be untouched, and `register` should have been
// either retained or released.
for(i, checker)in checkers.enumerated(){
if i == register {
if isRetain !=0{
expectTrue(checker.retained,"\(fullname) must retain x\(i)")
}else{
expectTrue(checker.released,"\(fullname) must release x\(i)")
}
}else{
expectFalse(checker.retained,"\(fullname) must not retain x\(i)")
expectFalse(checker.released,"\(fullname) must not retain x\(i)")
}
}
}
}
runAllTests()