Skip to content

Commit

Permalink
Add support for _hasAtomicBitWidth to evaluation
Browse files Browse the repository at this point in the history
  • Loading branch information
DougGregor committed Jul 7, 2024
1 parent aa97fbd commit 8779074
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 10 deletions.
17 changes: 15 additions & 2 deletions Sources/SwiftIfConfig/BuildConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -213,17 +213,30 @@ public protocol BuildConfiguration {

/// The bit width of a data pointer for the target architecture.
///
/// The target's pointer bit with (which also corresponds to the number of
/// The target's pointer bit width (which also corresponds to the number of
/// bits in `Int`/`UInt`) can only be queried with the experimental syntax
/// `_pointerBitWidth(_<bitwidth>)`, e.g.,
///
/// ```swift
/// #if _pointerBitWidth(32)
/// #if _pointerBitWidth(_32)
/// // 32-bit system
/// #endif
/// ```
var targetPointerBitWidth: Int { get }

/// The atomic bit widths that are natively supported by the target
/// architecture.
///
/// This lists all of the bit widths for which the target provides support
/// for atomic operations. It can be queried with
/// `_hasAtomicBitWidth(_<bitwidth>)`, e.g.
///
/// ```swift
/// #if _hasAtomicBitWidth(_64)
/// // 64-bit atomics are available
/// #endif
var targetAtomicBitWidths: [Int] { get }

/// The endianness of the target architecture.
///
/// The target's endianness can onyl be queried with the experimental syntax
Expand Down
20 changes: 13 additions & 7 deletions Sources/SwiftIfConfig/IfConfigEvaluation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -269,28 +269,34 @@ func evaluateIfConfig(
versioned: fn.isVersioned
)

case ._pointerBitWidth:
case ._pointerBitWidth, ._hasAtomicBitWidth:
// Ensure that we have a single argument that is a simple identifier, which
// is an underscore followed by an integer.
guard let argExpr = call.arguments.singleUnlabeledExpression,
let arg = argExpr.simpleIdentifierExpr,
let argFirst = arg.first,
argFirst == "_",
let expectedPointerBitWidth = Int(arg.dropFirst())
let expectedBitWidth = Int(arg.dropFirst())
else {
throw recordedError(
.requiresUnlabeledArgument(
name: fnName,
role: "pointer bit with ('_' followed by an integer)",
role: "bit width ('_' followed by an integer)",
syntax: ExprSyntax(call)
)
)
}

return (
active: configuration.targetPointerBitWidth == expectedPointerBitWidth,
versioned: fn.isVersioned
)
let active: Bool
if fn == ._pointerBitWidth {
active = configuration.targetPointerBitWidth == expectedBitWidth
} else if fn == ._hasAtomicBitWidth {
active = configuration.targetAtomicBitWidths.contains(expectedBitWidth)
} else {
fatalError("extraneous case above not handled")
}

return (active: active, versioned: fn.isVersioned)

case .swift:
return try doVersionComparisonCheck(configuration.languageVersion)
Expand Down
6 changes: 5 additions & 1 deletion Sources/SwiftIfConfig/IfConfigFunctions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ enum IfConfigFunctions: String {
/// A check for the target environment (e.g., simulator) via `targetEnvironment(<environment>)`.
case targetEnvironment

/// A check to determine whether the platform supports atomic operations
/// with the given bitwidth, e.g., `_hasAtomicBitWidth(_64)`.
case _hasAtomicBitWidth

/// A historical check against a specific compiler build version via `_compiler_version("<version>")`.
case _compiler_version

Expand All @@ -61,7 +65,7 @@ enum IfConfigFunctions: String {
return true

case .hasAttribute, .hasFeature, .canImport, .os, .arch, .targetEnvironment,
._endian, ._pointerBitWidth, ._runtime, ._ptrauth:
._hasAtomicBitWidth, ._endian, ._pointerBitWidth, ._runtime, ._ptrauth:
return false
}
}
Expand Down
2 changes: 2 additions & 0 deletions Tests/SwiftIfConfigTest/EvaluateTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ public class EvaluateTests: XCTestCase {
assertIfConfig("_ptrauth(none)", .inactive)
assertIfConfig("_pointerBitWidth(_64)", .active)
assertIfConfig("_pointerBitWidth(_32)", .inactive)
assertIfConfig("_hasAtomicBitWidth(_64)", .active)
assertIfConfig("_hasAtomicBitWidth(_128)", .inactive)
}

func testVersions() throws {
Expand Down
2 changes: 2 additions & 0 deletions Tests/SwiftIfConfigTest/TestingBuildConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ struct TestingBuildConfiguration: BuildConfiguration {

var targetPointerBitWidth: Int { 64 }

var targetAtomicBitWidths: [Int] { [32, 64] }

var endianness: SwiftIfConfig.Endianness { .little }

var languageVersion: VersionTuple { VersionTuple(5, 5) }
Expand Down

0 comments on commit 8779074

Please sign in to comment.