File: custom_rr_abi.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (86 lines) | stat: -rw-r--r-- 2,891 bytes parent folder | download
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.
class RetainReleaseChecker {
  var pointerValue: UnsafeMutableRawPointer

  private class Helper {}

  private weak var weakRef: Helper?

  private let originalRetainCount: UInt

  init() {
    do {
      // Make a helper object, retain it so it stays alive, and put it into
      // pointerValue and weakRef.
      let helper = 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.
  var retained: 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.
  var released: Bool {
    weakRef == nil
  }
}

var CustomRRABITestSuite = TestSuite("CustomRRABI")

CustomRRABITestSuite.test("retain") {
  foreachRRFunction { function, cname, register, isRetain in
    let name = String(cString: cname!)
    let fullname = "\(name)_x\(register)"

    // Create a set of RR checker objects.
    var checkers = (0..<NUM_REGS).map{ _ in RetainReleaseChecker() }

    // Fill out a registers array with the pointers from the RR checkers.
    var regs: [UnsafeMutableRawPointer?] = checkers.map{ $0.pointerValue }

    // Call the RR function.
    function!(&regs)

    // 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()