From 6834ce5a5555088ce0d1ced10d1c9c31c35cc19f Mon Sep 17 00:00:00 2001 From: Lucian Radu Teodorescu Date: Sun, 8 Dec 2024 17:49:50 +0200 Subject: [PATCH] Add extra atomic operations, beside load and store. --- Sources/CodeGen/LLVM/Transpilation.swift | 371 +++++++++++++ Sources/FrontEnd/BuiltinFunction.swift | 270 +++++++++- Sources/FrontEnd/NativeInstruction.swift | 594 ++++++++++++++++++++- Tests/HyloTests/BuiltinFunctionTests.swift | 104 ++++ 4 files changed, 1312 insertions(+), 27 deletions(-) diff --git a/Sources/CodeGen/LLVM/Transpilation.swift b/Sources/CodeGen/LLVM/Transpilation.swift index 91167c932..19b594d1d 100644 --- a/Sources/CodeGen/LLVM/Transpilation.swift +++ b/Sources/CodeGen/LLVM/Transpilation.swift @@ -1165,11 +1165,382 @@ extension SwiftyLLVM.Module { setOrdering(.sequentiallyConsistent, for: s) register[.register(i)] = target + case .atomic_swap_relaxed: + insert(atomicRMW: .xchg, ordering: .monotonic, for: i) + + case .atomic_swap_acquire: + insert(atomicRMW: .xchg, ordering: .acquire, for: i) + + case .atomic_swap_release: + insert(atomicRMW: .xchg, ordering: .release, for: i) + + case .atomic_swap_acqrel: + insert(atomicRMW: .xchg, ordering: .acquireRelease, for: i) + + case .atomic_swap_seqcst: + insert(atomicRMW: .xchg, ordering: .sequentiallyConsistent, for: i) + + case .atomic_add_relaxed: + insert(atomicRMW: .add, ordering: .monotonic, for: i) + + case .atomic_add_acquire: + insert(atomicRMW: .add, ordering: .acquire, for: i) + + case .atomic_add_release: + insert(atomicRMW: .add, ordering: .release, for: i) + + case .atomic_add_acqrel: + insert(atomicRMW: .add, ordering: .acquireRelease, for: i) + + case .atomic_add_seqcst: + insert(atomicRMW: .add, ordering: .sequentiallyConsistent, for: i) + + case .atomic_fadd_relaxed: + insert(atomicRMW: .fAdd, ordering: .monotonic, for: i) + + case .atomic_fadd_acquire: + insert(atomicRMW: .fAdd, ordering: .acquire, for: i) + + case .atomic_fadd_release: + insert(atomicRMW: .fAdd, ordering: .release, for: i) + + case .atomic_fadd_acqrel: + insert(atomicRMW: .fAdd, ordering: .acquireRelease, for: i) + + case .atomic_fadd_seqcst: + insert(atomicRMW: .fAdd, ordering: .sequentiallyConsistent, for: i) + + case .atomic_sub_relaxed: + insert(atomicRMW: .sub, ordering: .monotonic, for: i) + + case .atomic_sub_acquire: + insert(atomicRMW: .sub, ordering: .acquire, for: i) + + case .atomic_sub_release: + insert(atomicRMW: .sub, ordering: .release, for: i) + + case .atomic_sub_acqrel: + insert(atomicRMW: .sub, ordering: .acquireRelease, for: i) + + case .atomic_sub_seqcst: + insert(atomicRMW: .sub, ordering: .sequentiallyConsistent, for: i) + + case .atomic_fsub_relaxed: + insert(atomicRMW: .fSub, ordering: .monotonic, for: i) + + case .atomic_fsub_acquire: + insert(atomicRMW: .fSub, ordering: .acquire, for: i) + + case .atomic_fsub_release: + insert(atomicRMW: .fSub, ordering: .release, for: i) + + case .atomic_fsub_acqrel: + insert(atomicRMW: .fSub, ordering: .acquireRelease, for: i) + + case .atomic_fsub_seqcst: + insert(atomicRMW: .fSub, ordering: .sequentiallyConsistent, for: i) + + case .atomic_max_relaxed: + insert(atomicRMW: .max, ordering: .monotonic, for: i) + + case .atomic_max_acquire: + insert(atomicRMW: .max, ordering: .acquire, for: i) + + case .atomic_max_release: + insert(atomicRMW: .max, ordering: .release, for: i) + + case .atomic_max_acqrel: + insert(atomicRMW: .max, ordering: .acquireRelease, for: i) + + case .atomic_max_seqcst: + insert(atomicRMW: .max, ordering: .sequentiallyConsistent, for: i) + + case .atomic_umax_relaxed: + insert(atomicRMW: .uMax, ordering: .monotonic, for: i) + + case .atomic_umax_acquire: + insert(atomicRMW: .uMax, ordering: .acquire, for: i) + + case .atomic_umax_release: + insert(atomicRMW: .uMax, ordering: .release, for: i) + + case .atomic_umax_acqrel: + insert(atomicRMW: .uMax, ordering: .acquireRelease, for: i) + + case .atomic_umax_seqcst: + insert(atomicRMW: .uMax, ordering: .sequentiallyConsistent, for: i) + + case .atomic_fmax_relaxed: + insert(atomicRMW: .fMax, ordering: .monotonic, for: i) + + case .atomic_fmax_acquire: + insert(atomicRMW: .fMax, ordering: .acquire, for: i) + + case .atomic_fmax_release: + insert(atomicRMW: .fMax, ordering: .release, for: i) + + case .atomic_fmax_acqrel: + insert(atomicRMW: .fMax, ordering: .acquireRelease, for: i) + + case .atomic_fmax_seqcst: + insert(atomicRMW: .fMax, ordering: .sequentiallyConsistent, for: i) + + case .atomic_min_relaxed: + insert(atomicRMW: .min, ordering: .monotonic, for: i) + + case .atomic_min_acquire: + insert(atomicRMW: .min, ordering: .acquire, for: i) + + case .atomic_min_release: + insert(atomicRMW: .min, ordering: .release, for: i) + + case .atomic_min_acqrel: + insert(atomicRMW: .min, ordering: .acquireRelease, for: i) + + case .atomic_min_seqcst: + insert(atomicRMW: .min, ordering: .sequentiallyConsistent, for: i) + + case .atomic_umin_relaxed: + insert(atomicRMW: .uMin, ordering: .monotonic, for: i) + + case .atomic_umin_acquire: + insert(atomicRMW: .uMin, ordering: .acquire, for: i) + + case .atomic_umin_release: + insert(atomicRMW: .uMin, ordering: .release, for: i) + + case .atomic_umin_acqrel: + insert(atomicRMW: .uMin, ordering: .acquireRelease, for: i) + + case .atomic_umin_seqcst: + insert(atomicRMW: .uMin, ordering: .sequentiallyConsistent, for: i) + + case .atomic_fmin_relaxed: + insert(atomicRMW: .fMin, ordering: .monotonic, for: i) + + case .atomic_fmin_acquire: + insert(atomicRMW: .fMin, ordering: .acquire, for: i) + + case .atomic_fmin_release: + insert(atomicRMW: .fMin, ordering: .release, for: i) + + case .atomic_fmin_acqrel: + insert(atomicRMW: .fMin, ordering: .acquireRelease, for: i) + + case .atomic_fmin_seqcst: + insert(atomicRMW: .fMin, ordering: .sequentiallyConsistent, for: i) + + case .atomic_and_relaxed: + insert(atomicRMW: .and, ordering: .monotonic, for: i) + + case .atomic_and_acquire: + insert(atomicRMW: .and, ordering: .acquire, for: i) + + case .atomic_and_release: + insert(atomicRMW: .and, ordering: .release, for: i) + + case .atomic_and_acqrel: + insert(atomicRMW: .and, ordering: .acquireRelease, for: i) + + case .atomic_and_seqcst: + insert(atomicRMW: .and, ordering: .sequentiallyConsistent, for: i) + + case .atomic_nand_relaxed: + insert(atomicRMW: .nand, ordering: .monotonic, for: i) + + case .atomic_nand_acquire: + insert(atomicRMW: .nand, ordering: .acquire, for: i) + + case .atomic_nand_release: + insert(atomicRMW: .nand, ordering: .release, for: i) + + case .atomic_nand_acqrel: + insert(atomicRMW: .nand, ordering: .acquireRelease, for: i) + + case .atomic_nand_seqcst: + insert(atomicRMW: .nand, ordering: .sequentiallyConsistent, for: i) + + case .atomic_or_relaxed: + insert(atomicRMW: .or, ordering: .monotonic, for: i) + + case .atomic_or_acquire: + insert(atomicRMW: .or, ordering: .acquire, for: i) + + case .atomic_or_release: + insert(atomicRMW: .or, ordering: .release, for: i) + + case .atomic_or_acqrel: + insert(atomicRMW: .or, ordering: .acquireRelease, for: i) + + case .atomic_or_seqcst: + insert(atomicRMW: .or, ordering: .sequentiallyConsistent, for: i) + + case .atomic_xor_relaxed: + insert(atomicRMW: .xor, ordering: .monotonic, for: i) + + case .atomic_xor_acquire: + insert(atomicRMW: .xor, ordering: .acquire, for: i) + + case .atomic_xor_release: + insert(atomicRMW: .xor, ordering: .release, for: i) + + case .atomic_xor_acqrel: + insert(atomicRMW: .xor, ordering: .acquireRelease, for: i) + + case .atomic_xor_seqcst: + insert(atomicRMW: .xor, ordering: .sequentiallyConsistent, for: i) + + case .atomic_cmpxchg_relaxed_relaxed: + insertAtomicCompareExchange(successOrdering: .monotonic, failureOrdering: .monotonic, weak: false, for: i) + + case .atomic_cmpxchg_relaxed_acquire: + insertAtomicCompareExchange(successOrdering: .monotonic, failureOrdering: .acquire, weak: false, for: i) + + case .atomic_cmpxchg_relaxed_seqcst: + insertAtomicCompareExchange(successOrdering: .monotonic, failureOrdering: .sequentiallyConsistent, weak: false, for: i) + + case .atomic_cmpxchg_acquire_relaxed: + insertAtomicCompareExchange(successOrdering: .acquire, failureOrdering: .monotonic, weak: false, for: i) + + case .atomic_cmpxchg_acquire_acquire: + insertAtomicCompareExchange(successOrdering: .acquire, failureOrdering: .acquire, weak: false, for: i) + + case .atomic_cmpxchg_acquire_seqcst: + insertAtomicCompareExchange(successOrdering: .acquire, failureOrdering: .sequentiallyConsistent, weak: false, for: i) + + case .atomic_cmpxchg_release_relaxed: + insertAtomicCompareExchange(successOrdering: .release, failureOrdering: .monotonic, weak: false, for: i) + + case .atomic_cmpxchg_release_acquire: + insertAtomicCompareExchange(successOrdering: .release, failureOrdering: .acquire, weak: false, for: i) + + case .atomic_cmpxchg_release_seqcst: + insertAtomicCompareExchange(successOrdering: .release, failureOrdering: .sequentiallyConsistent, weak: false, for: i) + + case .atomic_cmpxchg_acqrel_relaxed: + insertAtomicCompareExchange(successOrdering: .acquireRelease, failureOrdering: .monotonic, weak: false, for: i) + + case .atomic_cmpxchg_acqrel_acquire: + insertAtomicCompareExchange(successOrdering: .acquireRelease, failureOrdering: .acquire, weak: false, for: i) + + case .atomic_cmpxchg_acqrel_seqcst: + insertAtomicCompareExchange(successOrdering: .acquireRelease, failureOrdering: .sequentiallyConsistent, weak: false, for: i) + + case .atomic_cmpxchg_seqcst_relaxed: + insertAtomicCompareExchange(successOrdering: .sequentiallyConsistent, failureOrdering: .monotonic, weak: false, for: i) + + case .atomic_cmpxchg_seqcst_acquire: + insertAtomicCompareExchange(successOrdering: .sequentiallyConsistent, failureOrdering: .acquire, weak: false, for: i) + + case .atomic_cmpxchg_seqcst_seqcst: + insertAtomicCompareExchange(successOrdering: .sequentiallyConsistent, failureOrdering: .sequentiallyConsistent, weak: false, for: i) + + case .atomic_cmpxchgweak_relaxed_relaxed: + insertAtomicCompareExchange(successOrdering: .monotonic, failureOrdering: .monotonic, weak: true, for: i) + + case .atomic_cmpxchgweak_relaxed_acquire: + insertAtomicCompareExchange(successOrdering: .monotonic, failureOrdering: .acquire, weak: true, for: i) + + case .atomic_cmpxchgweak_relaxed_seqcst: + insertAtomicCompareExchange(successOrdering: .monotonic, failureOrdering: .sequentiallyConsistent, weak: true, for: i) + + case .atomic_cmpxchgweak_acquire_relaxed: + insertAtomicCompareExchange(successOrdering: .acquire, failureOrdering: .monotonic, weak: true, for: i) + + case .atomic_cmpxchgweak_acquire_acquire: + insertAtomicCompareExchange(successOrdering: .acquire, failureOrdering: .acquire, weak: true, for: i) + + case .atomic_cmpxchgweak_acquire_seqcst: + insertAtomicCompareExchange(successOrdering: .acquire, failureOrdering: .sequentiallyConsistent, weak: true, for: i) + + case .atomic_cmpxchgweak_release_relaxed: + insertAtomicCompareExchange(successOrdering: .release, failureOrdering: .monotonic, weak: true, for: i) + + case .atomic_cmpxchgweak_release_acquire: + insertAtomicCompareExchange(successOrdering: .release, failureOrdering: .acquire, weak: true, for: i) + + case .atomic_cmpxchgweak_release_seqcst: + insertAtomicCompareExchange(successOrdering: .release, failureOrdering: .sequentiallyConsistent, weak: true, for: i) + + case .atomic_cmpxchgweak_acqrel_relaxed: + insertAtomicCompareExchange(successOrdering: .acquireRelease, failureOrdering: .monotonic, weak: true, for: i) + + case .atomic_cmpxchgweak_acqrel_acquire: + insertAtomicCompareExchange(successOrdering: .acquireRelease, failureOrdering: .acquire, weak: true, for: i) + + case .atomic_cmpxchgweak_acqrel_seqcst: + insertAtomicCompareExchange(successOrdering: .acquireRelease, failureOrdering: .sequentiallyConsistent, weak: true, for: i) + + case .atomic_cmpxchgweak_seqcst_relaxed: + insertAtomicCompareExchange(successOrdering: .sequentiallyConsistent, failureOrdering: .monotonic, weak: true, for: i) + + case .atomic_cmpxchgweak_seqcst_acquire: + insertAtomicCompareExchange(successOrdering: .sequentiallyConsistent, failureOrdering: .acquire, weak: true, for: i) + + case .atomic_cmpxchgweak_seqcst_seqcst: + insertAtomicCompareExchange(successOrdering: .sequentiallyConsistent, failureOrdering: .sequentiallyConsistent, weak: true, for: i) + + case .atomic_fence_acquire: + insertAtomicFence(.acquire, singleThread: false, for: i) + + case .atomic_fence_release: + insertAtomicFence(.release, singleThread: false, for: i) + case .atomic_fence_acqrel: + + insertAtomicFence(.acquireRelease, singleThread: false, for: i) + case .atomic_fence_seqcst: + insertAtomicFence(.sequentiallyConsistent, singleThread: false, for: i) + + case .atomic_singlethreadfence_acquire: + insertAtomicFence(.acquire, singleThread: true, for: i) + + case .atomic_singlethreadfence_release: + insertAtomicFence(.release, singleThread: true, for: i) + + case .atomic_singlethreadfence_acqrel: + insertAtomicFence(.acquireRelease, singleThread: true, for: i) + + case .atomic_singlethreadfence_seqcst: + insertAtomicFence(.sequentiallyConsistent, singleThread: true, for: i) + default: unreachable("unexpected LLVM instruction '\(s.instruction)'") } } + /// Inserts the transpilation of `i`, which is an `oper`, using `ordering` at `insertionPoint`. + func insert(atomicRMW oper: AtomicRMWBinOp, ordering: AtomicOrdering, for i: IR.InstructionID) { + let s = context.source[i] as! IR.LLVMInstruction + let target = llvm(s.operands[0]) + let value = llvm(s.operands[1]) + let o = insertAtomicRMW(target, operation: oper, value: value, ordering: ordering, singleThread: false, at: insertionPoint) + register[.register(i)] = o + } + + /// Inserts the transpilation of `i` at `insertionPoint`. + func insertAtomicCompareExchange(successOrdering: AtomicOrdering, failureOrdering: AtomicOrdering, weak: Bool, for i: IR.InstructionID) { + let s = context.source[i] as! IR.LLVMInstruction + let target = llvm(s.operands[0]) + let old = llvm(s.operands[1]) + let new = llvm(s.operands[2]) + let o = insertAtomicCmpXchg( + target, + old: old, + new: new, + successOrdering: successOrdering, + failureOrdering: failureOrdering, + weak: weak, + singleThread: false, + at: insertionPoint) + register[.register(i)] = o + } + + /// Inserts the transpilation of `i` at `insertionPoint`. + func insertAtomicFence(_ ordering: AtomicOrdering, singleThread: Bool, for i: IR.InstructionID) { + insertFence(ordering, singleThread: singleThread, at: insertionPoint) + register[.register(i)] = ptr.null + } + /// Inserts the transpilation of `i` at `insertionPoint`. func insert(load i: IR.InstructionID) { let s = context.source[i] as! Load diff --git a/Sources/FrontEnd/BuiltinFunction.swift b/Sources/FrontEnd/BuiltinFunction.swift index 41635bf9f..b5d7aa5d9 100644 --- a/Sources/FrontEnd/BuiltinFunction.swift +++ b/Sources/FrontEnd/BuiltinFunction.swift @@ -268,23 +268,259 @@ extension BuiltinFunction { /// Creates an atomic built-in function named `n` or returns `nil` if `n` isn't a valid atomic builtin name. private init?(atomic n: String) { - guard let (fs, ts) = splitLastUnderscore(n) else { return nil } - guard let t = BuiltinType.init(ts) else { return nil } - switch fs { - case "atomic_store_relaxed": - self = .init(name: .llvm(.atomic_store_relaxed(t))) - case "atomic_store_release": - self = .init(name: .llvm(.atomic_store_release(t))) - case "atomic_store_seqcst": - self = .init(name: .llvm(.atomic_store_seqcst(t))) - case "atomic_load_relaxed": - self = .init(name: .llvm(.atomic_load_relaxed(t))) - case "atomic_load_acquire": - self = .init(name: .llvm(.atomic_load_acquire(t))) - case "atomic_load_seqcst": - self = .init(name: .llvm(.atomic_load_seqcst(t))) - default: - return nil + // Special case for fence instructions; we don't have a type for them. + if n.contains("fence") { + switch n { + case "atomic_fence_acquire": + self = .init(name: .llvm(.atomic_fence_acquire)) + case "atomic_fence_release": + self = .init(name: .llvm(.atomic_fence_release)) + case "atomic_fence_acqrel": + self = .init(name: .llvm(.atomic_fence_acqrel)) + case "atomic_fence_seqcst": + self = .init(name: .llvm(.atomic_fence_seqcst)) + case "atomic_singlethreadfence_acquire": + self = .init(name: .llvm(.atomic_singlethreadfence_acquire)) + case "atomic_singlethreadfence_release": + self = .init(name: .llvm(.atomic_singlethreadfence_release)) + case "atomic_singlethreadfence_acqrel": + self = .init(name: .llvm(.atomic_singlethreadfence_acqrel)) + case "atomic_singlethreadfence_seqcst": + self = .init(name: .llvm(.atomic_singlethreadfence_seqcst)) + default: + return nil + } + } + else { + // For the rest of the atomics we have a type at the end. + guard let (fs, ts) = splitLastUnderscore(n) else { return nil } + guard let t = BuiltinType.init(ts) else { return nil } + switch fs { + case "atomic_store_relaxed": + self = .init(name: .llvm(.atomic_store_relaxed(t))) + case "atomic_store_release": + self = .init(name: .llvm(.atomic_store_release(t))) + case "atomic_store_seqcst": + self = .init(name: .llvm(.atomic_store_seqcst(t))) + case "atomic_load_relaxed": + self = .init(name: .llvm(.atomic_load_relaxed(t))) + case "atomic_load_acquire": + self = .init(name: .llvm(.atomic_load_acquire(t))) + case "atomic_load_seqcst": + self = .init(name: .llvm(.atomic_load_seqcst(t))) + case "atomic_swap_relaxed": + self = .init(name: .llvm(.atomic_swap_relaxed(t))) + case "atomic_swap_acquire": + self = .init(name: .llvm(.atomic_swap_acquire(t))) + case "atomic_swap_release": + self = .init(name: .llvm(.atomic_swap_release(t))) + case "atomic_swap_acqrel": + self = .init(name: .llvm(.atomic_swap_acqrel(t))) + case "atomic_swap_seqcst": + self = .init(name: .llvm(.atomic_swap_seqcst(t))) + case "atomic_add_relaxed": + self = .init(name: .llvm(.atomic_add_relaxed(t))) + case "atomic_add_acquire": + self = .init(name: .llvm(.atomic_add_acquire(t))) + case "atomic_add_release": + self = .init(name: .llvm(.atomic_add_release(t))) + case "atomic_add_acqrel": + self = .init(name: .llvm(.atomic_add_acqrel(t))) + case "atomic_add_seqcst": + self = .init(name: .llvm(.atomic_add_seqcst(t))) + case "atomic_fadd_relaxed": + self = .init(name: .llvm(.atomic_fadd_relaxed(t))) + case "atomic_fadd_acquire": + self = .init(name: .llvm(.atomic_fadd_acquire(t))) + case "atomic_fadd_release": + self = .init(name: .llvm(.atomic_fadd_release(t))) + case "atomic_fadd_acqrel": + self = .init(name: .llvm(.atomic_fadd_acqrel(t))) + case "atomic_fadd_seqcst": + self = .init(name: .llvm(.atomic_fadd_seqcst(t))) + case "atomic_sub_relaxed": + self = .init(name: .llvm(.atomic_sub_relaxed(t))) + case "atomic_sub_acquire": + self = .init(name: .llvm(.atomic_sub_acquire(t))) + case "atomic_sub_release": + self = .init(name: .llvm(.atomic_sub_release(t))) + case "atomic_sub_acqrel": + self = .init(name: .llvm(.atomic_sub_acqrel(t))) + case "atomic_sub_seqcst": + self = .init(name: .llvm(.atomic_sub_seqcst(t))) + case "atomic_fsub_relaxed": + self = .init(name: .llvm(.atomic_fsub_relaxed(t))) + case "atomic_fsub_acquire": + self = .init(name: .llvm(.atomic_fsub_acquire(t))) + case "atomic_fsub_release": + self = .init(name: .llvm(.atomic_fsub_release(t))) + case "atomic_fsub_acqrel": + self = .init(name: .llvm(.atomic_fsub_acqrel(t))) + case "atomic_fsub_seqcst": + self = .init(name: .llvm(.atomic_fsub_seqcst(t))) + case "atomic_max_relaxed": + self = .init(name: .llvm(.atomic_max_relaxed(t))) + case "atomic_max_acquire": + self = .init(name: .llvm(.atomic_max_acquire(t))) + case "atomic_max_release": + self = .init(name: .llvm(.atomic_max_release(t))) + case "atomic_max_acqrel": + self = .init(name: .llvm(.atomic_max_acqrel(t))) + case "atomic_max_seqcst": + self = .init(name: .llvm(.atomic_max_seqcst(t))) + case "atomic_umax_relaxed": + self = .init(name: .llvm(.atomic_umax_relaxed(t))) + case "atomic_umax_acquire": + self = .init(name: .llvm(.atomic_umax_acquire(t))) + case "atomic_umax_release": + self = .init(name: .llvm(.atomic_umax_release(t))) + case "atomic_umax_acqrel": + self = .init(name: .llvm(.atomic_umax_acqrel(t))) + case "atomic_umax_seqcst": + self = .init(name: .llvm(.atomic_umax_seqcst(t))) + case "atomic_fmax_relaxed": + self = .init(name: .llvm(.atomic_fmax_relaxed(t))) + case "atomic_fmax_acquire": + self = .init(name: .llvm(.atomic_fmax_acquire(t))) + case "atomic_fmax_release": + self = .init(name: .llvm(.atomic_fmax_release(t))) + case "atomic_fmax_acqrel": + self = .init(name: .llvm(.atomic_fmax_acqrel(t))) + case "atomic_fmax_seqcst": + self = .init(name: .llvm(.atomic_fmax_seqcst(t))) + case "atomic_min_relaxed": + self = .init(name: .llvm(.atomic_min_relaxed(t))) + case "atomic_min_acquire": + self = .init(name: .llvm(.atomic_min_acquire(t))) + case "atomic_min_release": + self = .init(name: .llvm(.atomic_min_release(t))) + case "atomic_min_acqrel": + self = .init(name: .llvm(.atomic_min_acqrel(t))) + case "atomic_min_seqcst": + self = .init(name: .llvm(.atomic_min_seqcst(t))) + case "atomic_umin_relaxed": + self = .init(name: .llvm(.atomic_umin_relaxed(t))) + case "atomic_umin_acquire": + self = .init(name: .llvm(.atomic_umin_acquire(t))) + case "atomic_umin_release": + self = .init(name: .llvm(.atomic_umin_release(t))) + case "atomic_umin_acqrel": + self = .init(name: .llvm(.atomic_umin_acqrel(t))) + case "atomic_umin_seqcst": + self = .init(name: .llvm(.atomic_umin_seqcst(t))) + case "atomic_fmin_relaxed": + self = .init(name: .llvm(.atomic_fmin_relaxed(t))) + case "atomic_fmin_acquire": + self = .init(name: .llvm(.atomic_fmin_acquire(t))) + case "atomic_fmin_release": + self = .init(name: .llvm(.atomic_fmin_release(t))) + case "atomic_fmin_acqrel": + self = .init(name: .llvm(.atomic_fmin_acqrel(t))) + case "atomic_fmin_seqcst": + self = .init(name: .llvm(.atomic_fmin_seqcst(t))) + case "atomic_and_relaxed": + self = .init(name: .llvm(.atomic_and_relaxed(t))) + case "atomic_and_acquire": + self = .init(name: .llvm(.atomic_and_acquire(t))) + case "atomic_and_release": + self = .init(name: .llvm(.atomic_and_release(t))) + case "atomic_and_acqrel": + self = .init(name: .llvm(.atomic_and_acqrel(t))) + case "atomic_and_seqcst": + self = .init(name: .llvm(.atomic_and_seqcst(t))) + case "atomic_nand_relaxed": + self = .init(name: .llvm(.atomic_nand_relaxed(t))) + case "atomic_nand_acquire": + self = .init(name: .llvm(.atomic_nand_acquire(t))) + case "atomic_nand_release": + self = .init(name: .llvm(.atomic_nand_release(t))) + case "atomic_nand_acqrel": + self = .init(name: .llvm(.atomic_nand_acqrel(t))) + case "atomic_nand_seqcst": + self = .init(name: .llvm(.atomic_nand_seqcst(t))) + case "atomic_or_relaxed": + self = .init(name: .llvm(.atomic_or_relaxed(t))) + case "atomic_or_acquire": + self = .init(name: .llvm(.atomic_or_acquire(t))) + case "atomic_or_release": + self = .init(name: .llvm(.atomic_or_release(t))) + case "atomic_or_acqrel": + self = .init(name: .llvm(.atomic_or_acqrel(t))) + case "atomic_or_seqcst": + self = .init(name: .llvm(.atomic_or_seqcst(t))) + case "atomic_xor_relaxed": + self = .init(name: .llvm(.atomic_xor_relaxed(t))) + case "atomic_xor_acquire": + self = .init(name: .llvm(.atomic_xor_acquire(t))) + case "atomic_xor_release": + self = .init(name: .llvm(.atomic_xor_release(t))) + case "atomic_xor_acqrel": + self = .init(name: .llvm(.atomic_xor_acqrel(t))) + case "atomic_xor_seqcst": + self = .init(name: .llvm(.atomic_xor_seqcst(t))) + case "atomic_cmpxchg_relaxed_relaxed": + self = .init(name: .llvm(.atomic_cmpxchg_relaxed_relaxed(t))) + case "atomic_cmpxchg_relaxed_acquire": + self = .init(name: .llvm(.atomic_cmpxchg_relaxed_acquire(t))) + case "atomic_cmpxchg_relaxed_seqcst": + self = .init(name: .llvm(.atomic_cmpxchg_relaxed_seqcst(t))) + case "atomic_cmpxchg_acquire_relaxed": + self = .init(name: .llvm(.atomic_cmpxchg_acquire_relaxed(t))) + case "atomic_cmpxchg_acquire_acquire": + self = .init(name: .llvm(.atomic_cmpxchg_acquire_acquire(t))) + case "atomic_cmpxchg_acquire_seqcst": + self = .init(name: .llvm(.atomic_cmpxchg_acquire_seqcst(t))) + case "atomic_cmpxchg_release_relaxed": + self = .init(name: .llvm(.atomic_cmpxchg_release_relaxed(t))) + case "atomic_cmpxchg_release_acquire": + self = .init(name: .llvm(.atomic_cmpxchg_release_acquire(t))) + case "atomic_cmpxchg_release_seqcst": + self = .init(name: .llvm(.atomic_cmpxchg_release_seqcst(t))) + case "atomic_cmpxchg_acqrel_relaxed": + self = .init(name: .llvm(.atomic_cmpxchg_acqrel_relaxed(t))) + case "atomic_cmpxchg_acqrel_acquire": + self = .init(name: .llvm(.atomic_cmpxchg_acqrel_acquire(t))) + case "atomic_cmpxchg_acqrel_seqcst": + self = .init(name: .llvm(.atomic_cmpxchg_acqrel_seqcst(t))) + case "atomic_cmpxchg_seqcst_relaxed": + self = .init(name: .llvm(.atomic_cmpxchg_seqcst_relaxed(t))) + case "atomic_cmpxchg_seqcst_acquire": + self = .init(name: .llvm(.atomic_cmpxchg_seqcst_acquire(t))) + case "atomic_cmpxchg_seqcst_seqcst": + self = .init(name: .llvm(.atomic_cmpxchg_seqcst_seqcst(t))) + case "atomic_cmpxchgweak_relaxed_relaxed": + self = .init(name: .llvm(.atomic_cmpxchgweak_relaxed_relaxed(t))) + case "atomic_cmpxchgweak_relaxed_acquire": + self = .init(name: .llvm(.atomic_cmpxchgweak_relaxed_acquire(t))) + case "atomic_cmpxchgweak_relaxed_seqcst": + self = .init(name: .llvm(.atomic_cmpxchgweak_relaxed_seqcst(t))) + case "atomic_cmpxchgweak_acquire_relaxed": + self = .init(name: .llvm(.atomic_cmpxchgweak_acquire_relaxed(t))) + case "atomic_cmpxchgweak_acquire_acquire": + self = .init(name: .llvm(.atomic_cmpxchgweak_acquire_acquire(t))) + case "atomic_cmpxchgweak_acquire_seqcst": + self = .init(name: .llvm(.atomic_cmpxchgweak_acquire_seqcst(t))) + case "atomic_cmpxchgweak_release_relaxed": + self = .init(name: .llvm(.atomic_cmpxchgweak_release_relaxed(t))) + case "atomic_cmpxchgweak_release_acquire": + self = .init(name: .llvm(.atomic_cmpxchgweak_release_acquire(t))) + case "atomic_cmpxchgweak_release_seqcst": + self = .init(name: .llvm(.atomic_cmpxchgweak_release_seqcst(t))) + case "atomic_cmpxchgweak_acqrel_relaxed": + self = .init(name: .llvm(.atomic_cmpxchgweak_acqrel_relaxed(t))) + case "atomic_cmpxchgweak_acqrel_acquire": + self = .init(name: .llvm(.atomic_cmpxchgweak_acqrel_acquire(t))) + case "atomic_cmpxchgweak_acqrel_seqcst": + self = .init(name: .llvm(.atomic_cmpxchgweak_acqrel_seqcst(t))) + case "atomic_cmpxchgweak_seqcst_relaxed": + self = .init(name: .llvm(.atomic_cmpxchgweak_seqcst_relaxed(t))) + case "atomic_cmpxchgweak_seqcst_acquire": + self = .init(name: .llvm(.atomic_cmpxchgweak_seqcst_acquire(t))) + case "atomic_cmpxchgweak_seqcst_seqcst": + self = .init(name: .llvm(.atomic_cmpxchgweak_seqcst_seqcst(t))) + default: + return nil + } } } diff --git a/Sources/FrontEnd/NativeInstruction.swift b/Sources/FrontEnd/NativeInstruction.swift index b269163f6..a2ef5acbf 100644 --- a/Sources/FrontEnd/NativeInstruction.swift +++ b/Sources/FrontEnd/NativeInstruction.swift @@ -130,6 +130,233 @@ public enum NativeInstruction: Hashable { case atomic_load_seqcst(BuiltinType) + case atomic_swap_relaxed(BuiltinType) + + case atomic_swap_acquire(BuiltinType) + + case atomic_swap_release(BuiltinType) + + case atomic_swap_acqrel(BuiltinType) + + case atomic_swap_seqcst(BuiltinType) + + case atomic_add_relaxed(BuiltinType) + + case atomic_add_acquire(BuiltinType) + + case atomic_add_release(BuiltinType) + + case atomic_add_acqrel(BuiltinType) + + case atomic_add_seqcst(BuiltinType) + + case atomic_fadd_relaxed(BuiltinType) + + case atomic_fadd_acquire(BuiltinType) + + case atomic_fadd_release(BuiltinType) + + case atomic_fadd_acqrel(BuiltinType) + + case atomic_fadd_seqcst(BuiltinType) + + case atomic_sub_relaxed(BuiltinType) + + case atomic_sub_acquire(BuiltinType) + + case atomic_sub_release(BuiltinType) + + case atomic_sub_acqrel(BuiltinType) + + case atomic_sub_seqcst(BuiltinType) + + case atomic_fsub_relaxed(BuiltinType) + + case atomic_fsub_acquire(BuiltinType) + + case atomic_fsub_release(BuiltinType) + + case atomic_fsub_acqrel(BuiltinType) + + case atomic_fsub_seqcst(BuiltinType) + + case atomic_max_relaxed(BuiltinType) + + case atomic_max_acquire(BuiltinType) + + case atomic_max_release(BuiltinType) + + case atomic_max_acqrel(BuiltinType) + + case atomic_max_seqcst(BuiltinType) + + case atomic_umax_relaxed(BuiltinType) + + case atomic_umax_acquire(BuiltinType) + + case atomic_umax_release(BuiltinType) + + case atomic_umax_acqrel(BuiltinType) + + case atomic_umax_seqcst(BuiltinType) + + case atomic_fmax_relaxed(BuiltinType) + + case atomic_fmax_acquire(BuiltinType) + + case atomic_fmax_release(BuiltinType) + + case atomic_fmax_acqrel(BuiltinType) + + case atomic_fmax_seqcst(BuiltinType) + + case atomic_min_relaxed(BuiltinType) + + case atomic_min_acquire(BuiltinType) + + case atomic_min_release(BuiltinType) + + case atomic_min_acqrel(BuiltinType) + + case atomic_min_seqcst(BuiltinType) + + case atomic_umin_relaxed(BuiltinType) + + case atomic_umin_acquire(BuiltinType) + + case atomic_umin_release(BuiltinType) + + case atomic_umin_acqrel(BuiltinType) + + case atomic_umin_seqcst(BuiltinType) + + case atomic_fmin_relaxed(BuiltinType) + + case atomic_fmin_acquire(BuiltinType) + + case atomic_fmin_release(BuiltinType) + + case atomic_fmin_acqrel(BuiltinType) + + case atomic_fmin_seqcst(BuiltinType) + + case atomic_and_relaxed(BuiltinType) + + case atomic_and_acquire(BuiltinType) + + case atomic_and_release(BuiltinType) + + case atomic_and_acqrel(BuiltinType) + + case atomic_and_seqcst(BuiltinType) + + case atomic_nand_relaxed(BuiltinType) + + case atomic_nand_acquire(BuiltinType) + + case atomic_nand_release(BuiltinType) + + case atomic_nand_acqrel(BuiltinType) + + case atomic_nand_seqcst(BuiltinType) + + case atomic_or_relaxed(BuiltinType) + + case atomic_or_acquire(BuiltinType) + + case atomic_or_release(BuiltinType) + + case atomic_or_acqrel(BuiltinType) + + case atomic_or_seqcst(BuiltinType) + + case atomic_xor_relaxed(BuiltinType) + + case atomic_xor_acquire(BuiltinType) + + case atomic_xor_release(BuiltinType) + + case atomic_xor_acqrel(BuiltinType) + + case atomic_xor_seqcst(BuiltinType) + + case atomic_cmpxchg_relaxed_relaxed(BuiltinType) + + case atomic_cmpxchg_relaxed_acquire(BuiltinType) + + case atomic_cmpxchg_relaxed_seqcst(BuiltinType) + + case atomic_cmpxchg_acquire_relaxed(BuiltinType) + + case atomic_cmpxchg_acquire_acquire(BuiltinType) + + case atomic_cmpxchg_acquire_seqcst(BuiltinType) + + case atomic_cmpxchg_release_relaxed(BuiltinType) + + case atomic_cmpxchg_release_acquire(BuiltinType) + + case atomic_cmpxchg_release_seqcst(BuiltinType) + + case atomic_cmpxchg_acqrel_relaxed(BuiltinType) + + case atomic_cmpxchg_acqrel_acquire(BuiltinType) + + case atomic_cmpxchg_acqrel_seqcst(BuiltinType) + + case atomic_cmpxchg_seqcst_relaxed(BuiltinType) + + case atomic_cmpxchg_seqcst_acquire(BuiltinType) + + case atomic_cmpxchg_seqcst_seqcst(BuiltinType) + + case atomic_cmpxchgweak_relaxed_relaxed(BuiltinType) + + case atomic_cmpxchgweak_relaxed_acquire(BuiltinType) + + case atomic_cmpxchgweak_relaxed_seqcst(BuiltinType) + + case atomic_cmpxchgweak_acquire_relaxed(BuiltinType) + + case atomic_cmpxchgweak_acquire_acquire(BuiltinType) + + case atomic_cmpxchgweak_acquire_seqcst(BuiltinType) + + case atomic_cmpxchgweak_release_relaxed(BuiltinType) + + case atomic_cmpxchgweak_release_acquire(BuiltinType) + + case atomic_cmpxchgweak_release_seqcst(BuiltinType) + + case atomic_cmpxchgweak_acqrel_relaxed(BuiltinType) + + case atomic_cmpxchgweak_acqrel_acquire(BuiltinType) + + case atomic_cmpxchgweak_acqrel_seqcst(BuiltinType) + + case atomic_cmpxchgweak_seqcst_relaxed(BuiltinType) + + case atomic_cmpxchgweak_seqcst_acquire(BuiltinType) + + case atomic_cmpxchgweak_seqcst_seqcst(BuiltinType) + + case atomic_fence_acquire + + case atomic_fence_release + + case atomic_fence_acqrel + + case atomic_fence_seqcst + + case atomic_singlethreadfence_acquire + + case atomic_singlethreadfence_release + + case atomic_singlethreadfence_acqrel + + case atomic_singlethreadfence_seqcst + + /// The parameters of a floating-point LLVM instruction. public struct MathFlags: OptionSet, Hashable { @@ -250,18 +477,139 @@ extension NativeInstruction { return .init(to: ^t) case .advancedByBytes(let byteOffset): return .init(.builtin(.ptr), ^byteOffset, to: .builtin(.ptr)) - case .atomic_store_relaxed(let t): - return .init(.builtin(.ptr), ^t, to: .builtin(.ptr)) - case .atomic_store_release(let t): + case .atomic_store_relaxed(let t), + .atomic_store_release(let t), + .atomic_store_seqcst(let t): return .init(.builtin(.ptr), ^t, to: .builtin(.ptr)) - case .atomic_store_seqcst(let t): - return .init(.builtin(.ptr), ^t, to: .builtin(.ptr)) - case .atomic_load_relaxed(let t): - return .init(.builtin(.ptr), to: ^t) - case .atomic_load_acquire(let t): - return .init(.builtin(.ptr), to: ^t) - case .atomic_load_seqcst(let t): + case .atomic_load_relaxed(let t), + .atomic_load_acquire(let t), + .atomic_load_seqcst(let t): return .init(.builtin(.ptr), to: ^t) + case .atomic_swap_relaxed(let t), + .atomic_swap_acquire(let t), + .atomic_swap_release(let t), + .atomic_swap_acqrel(let t), + .atomic_swap_seqcst(let t): + return .init(.builtin(.ptr), ^t, to: ^t) + case .atomic_add_relaxed(let t), + .atomic_add_acquire(let t), + .atomic_add_release(let t), + .atomic_add_acqrel(let t), + .atomic_add_seqcst(let t), + .atomic_fadd_relaxed(let t), + .atomic_fadd_acquire(let t), + .atomic_fadd_release(let t), + .atomic_fadd_acqrel(let t), + .atomic_fadd_seqcst(let t): + return .init(.builtin(.ptr), ^t, to: ^t) + case .atomic_sub_relaxed(let t), + .atomic_sub_acquire(let t), + .atomic_sub_release(let t), + .atomic_sub_acqrel(let t), + .atomic_sub_seqcst(let t), + .atomic_fsub_relaxed(let t), + .atomic_fsub_acquire(let t), + .atomic_fsub_release(let t), + .atomic_fsub_acqrel(let t), + .atomic_fsub_seqcst(let t): + return .init(.builtin(.ptr), ^t, to: ^t) + case .atomic_max_relaxed(let t), + .atomic_max_acquire(let t), + .atomic_max_release(let t), + .atomic_max_acqrel(let t), + .atomic_max_seqcst(let t), + .atomic_umax_relaxed(let t), + .atomic_umax_acquire(let t), + .atomic_umax_release(let t), + .atomic_umax_acqrel(let t), + .atomic_umax_seqcst(let t), + .atomic_fmax_relaxed(let t), + .atomic_fmax_acquire(let t), + .atomic_fmax_release(let t), + .atomic_fmax_acqrel(let t), + .atomic_fmax_seqcst(let t): + return .init(.builtin(.ptr), ^t, to: ^t) + case .atomic_min_relaxed(let t), + .atomic_min_acquire(let t), + .atomic_min_release(let t), + .atomic_min_acqrel(let t), + .atomic_min_seqcst(let t), + .atomic_umin_relaxed(let t), + .atomic_umin_acquire(let t), + .atomic_umin_release(let t), + .atomic_umin_acqrel(let t), + .atomic_umin_seqcst(let t), + .atomic_fmin_relaxed(let t), + .atomic_fmin_acquire(let t), + .atomic_fmin_release(let t), + .atomic_fmin_acqrel(let t), + .atomic_fmin_seqcst(let t): + return .init(.builtin(.ptr), ^t, to: ^t) + case .atomic_and_relaxed(let t), + .atomic_and_acquire(let t), + .atomic_and_release(let t), + .atomic_and_acqrel(let t), + .atomic_and_seqcst(let t): + return .init(.builtin(.ptr), ^t, to: ^t) + case .atomic_nand_relaxed(let t), + .atomic_nand_acquire(let t), + .atomic_nand_release(let t), + .atomic_nand_acqrel(let t), + .atomic_nand_seqcst(let t): + return .init(.builtin(.ptr), ^t, to: ^t) + case .atomic_or_relaxed(let t), + .atomic_or_acquire(let t), + .atomic_or_release(let t), + .atomic_or_acqrel(let t), + .atomic_or_seqcst(let t): + return .init(.builtin(.ptr), ^t, to: ^t) + case .atomic_xor_relaxed(let t), + .atomic_xor_acquire(let t), + .atomic_xor_release(let t), + .atomic_xor_acqrel(let t), + .atomic_xor_seqcst(let t): + return .init(.builtin(.ptr), ^t, to: ^t) + case .atomic_cmpxchg_relaxed_relaxed(let t), + .atomic_cmpxchg_relaxed_acquire(let t), + .atomic_cmpxchg_relaxed_seqcst(let t), + .atomic_cmpxchg_acquire_relaxed(let t), + .atomic_cmpxchg_acquire_acquire(let t), + .atomic_cmpxchg_acquire_seqcst(let t), + .atomic_cmpxchg_release_relaxed(let t), + .atomic_cmpxchg_release_acquire(let t), + .atomic_cmpxchg_release_seqcst(let t), + .atomic_cmpxchg_acqrel_relaxed(let t), + .atomic_cmpxchg_acqrel_acquire(let t), + .atomic_cmpxchg_acqrel_seqcst(let t), + .atomic_cmpxchg_seqcst_relaxed(let t), + .atomic_cmpxchg_seqcst_acquire(let t), + .atomic_cmpxchg_seqcst_seqcst(let t): + return .init(.builtin(.ptr), ^t, ^t, to: ^TupleType(types: [^t, .builtin(.i(1))])) + case .atomic_cmpxchgweak_relaxed_relaxed(let t), + .atomic_cmpxchgweak_relaxed_acquire(let t), + .atomic_cmpxchgweak_relaxed_seqcst(let t), + .atomic_cmpxchgweak_acquire_relaxed(let t), + .atomic_cmpxchgweak_acquire_acquire(let t), + .atomic_cmpxchgweak_acquire_seqcst(let t), + .atomic_cmpxchgweak_release_relaxed(let t), + .atomic_cmpxchgweak_release_acquire(let t), + .atomic_cmpxchgweak_release_seqcst(let t), + .atomic_cmpxchgweak_acqrel_relaxed(let t), + .atomic_cmpxchgweak_acqrel_acquire(let t), + .atomic_cmpxchgweak_acqrel_seqcst(let t), + .atomic_cmpxchgweak_seqcst_relaxed(let t), + .atomic_cmpxchgweak_seqcst_acquire(let t), + .atomic_cmpxchgweak_seqcst_seqcst(let t): + return .init(.builtin(.ptr), ^t, ^t, to: ^TupleType(types: [^t, .builtin(.i(1))])) + case .atomic_fence_acquire, + .atomic_fence_release, + .atomic_fence_acqrel, + .atomic_fence_seqcst, + .atomic_singlethreadfence_acquire, + .atomic_singlethreadfence_release, + .atomic_singlethreadfence_acqrel, + .atomic_singlethreadfence_seqcst: + return .init(to: .void) } } @@ -367,6 +715,232 @@ extension NativeInstruction: CustomStringConvertible { return "atomic_load_acquire_\(t)" case .atomic_load_seqcst(let t): return "atomic_load_seqcst_\(t)" + case .atomic_swap_relaxed(let t): + return "atomic_swap_relaxed_\(t)" + case .atomic_swap_acquire(let t): + return "atomic_swap_acquire_\(t)" + case .atomic_swap_release(let t): + return "atomic_swap_release_\(t)" + case .atomic_swap_acqrel(let t): + return "atomic_swap_acqrel_\(t)" + case .atomic_swap_seqcst(let t): + return "atomic_swap_seqcst_\(t)" + case .atomic_add_relaxed(let t): + return "atomic_add_relaxed_\(t)" + case .atomic_add_acquire(let t): + return "atomic_add_acquire_\(t)" + case .atomic_add_release(let t): + return "atomic_add_release_\(t)" + case .atomic_add_acqrel(let t): + return "atomic_add_acqrel_\(t)" + case .atomic_add_seqcst(let t): + return "atomic_add_seqcst_\(t)" + case .atomic_fadd_relaxed(let t): + return "atomic_fadd_relaxed_\(t)" + case .atomic_fadd_acquire(let t): + return "atomic_fadd_acquire_\(t)" + case .atomic_fadd_release(let t): + return "atomic_fadd_release_\(t)" + case .atomic_fadd_acqrel(let t): + return "atomic_fadd_acqrel_\(t)" + case .atomic_fadd_seqcst(let t): + return "atomic_fadd_seqcst_\(t)" + case .atomic_sub_relaxed(let t): + return "atomic_sub_relaxed_\(t)" + case .atomic_sub_acquire(let t): + return "atomic_sub_acquire_\(t)" + case .atomic_sub_release(let t): + return "atomic_sub_release_\(t)" + case .atomic_sub_acqrel(let t): + return "atomic_sub_acqrel_\(t)" + case .atomic_sub_seqcst(let t): + return "atomic_sub_seqcst_\(t)" + case .atomic_fsub_relaxed(let t): + return "atomic_fsub_relaxed_\(t)" + case .atomic_fsub_acquire(let t): + return "atomic_fsub_acquire_\(t)" + case .atomic_fsub_release(let t): + return "atomic_fsub_release_\(t)" + case .atomic_fsub_acqrel(let t): + return "atomic_fsub_acqrel_\(t)" + case .atomic_fsub_seqcst(let t): + return "atomic_fsub_seqcst_\(t)" + case .atomic_max_relaxed(let t): + return "atomic_max_relaxed_\(t)" + case .atomic_max_acquire(let t): + return "atomic_max_acquire_\(t)" + case .atomic_max_release(let t): + return "atomic_max_release_\(t)" + case .atomic_max_acqrel(let t): + return "atomic_max_acqrel_\(t)" + case .atomic_max_seqcst(let t): + return "atomic_max_seqcst_\(t)" + case .atomic_umax_relaxed(let t): + return "atomic_umax_relaxed_\(t)" + case .atomic_umax_acquire(let t): + return "atomic_umax_acquire_\(t)" + case .atomic_umax_release(let t): + return "atomic_umax_release_\(t)" + case .atomic_umax_acqrel(let t): + return "atomic_umax_acqrel_\(t)" + case .atomic_umax_seqcst(let t): + return "atomic_umax_seqcst_\(t)" + case .atomic_fmax_relaxed(let t): + return "atomic_fmax_relaxed_\(t)" + case .atomic_fmax_acquire(let t): + return "atomic_fmax_acquire_\(t)" + case .atomic_fmax_release(let t): + return "atomic_fmax_release_\(t)" + case .atomic_fmax_acqrel(let t): + return "atomic_fmax_acqrel_\(t)" + case .atomic_fmax_seqcst(let t): + return "atomic_fmax_seqcst_\(t)" + case .atomic_min_relaxed(let t): + return "atomic_min_relaxed_\(t)" + case .atomic_min_acquire(let t): + return "atomic_min_acquire_\(t)" + case .atomic_min_release(let t): + return "atomic_min_release_\(t)" + case .atomic_min_acqrel(let t): + return "atomic_min_acqrel_\(t)" + case .atomic_min_seqcst(let t): + return "atomic_min_seqcst_\(t)" + case .atomic_umin_relaxed(let t): + return "atomic_umin_relaxed_\(t)" + case .atomic_umin_acquire(let t): + return "atomic_umin_acquire_\(t)" + case .atomic_umin_release(let t): + return "atomic_umin_release_\(t)" + case .atomic_umin_acqrel(let t): + return "atomic_umin_acqrel_\(t)" + case .atomic_umin_seqcst(let t): + return "atomic_umin_seqcst_\(t)" + case .atomic_fmin_relaxed(let t): + return "atomic_fmin_relaxed_\(t)" + case .atomic_fmin_acquire(let t): + return "atomic_fmin_acquire_\(t)" + case .atomic_fmin_release(let t): + return "atomic_fmin_release_\(t)" + case .atomic_fmin_acqrel(let t): + return "atomic_fmin_acqrel_\(t)" + case .atomic_fmin_seqcst(let t): + return "atomic_fmin_seqcst_\(t)" + case .atomic_and_relaxed(let t): + return "atomic_and_relaxed_\(t)" + case .atomic_and_acquire(let t): + return "atomic_and_acquire_\(t)" + case .atomic_and_release(let t): + return "atomic_and_release_\(t)" + case .atomic_and_acqrel(let t): + return "atomic_and_acqrel_\(t)" + case .atomic_and_seqcst(let t): + return "atomic_and_seqcst_\(t)" + case .atomic_nand_relaxed(let t): + return "atomic_nand_relaxed_\(t)" + case .atomic_nand_acquire(let t): + return "atomic_nand_acquire_\(t)" + case .atomic_nand_release(let t): + return "atomic_nand_release_\(t)" + case .atomic_nand_acqrel(let t): + return "atomic_nand_acqrel_\(t)" + case .atomic_nand_seqcst(let t): + return "atomic_nand_seqcst_\(t)" + case .atomic_or_relaxed(let t): + return "atomic_or_relaxed_\(t)" + case .atomic_or_acquire(let t): + return "atomic_or_acquire_\(t)" + case .atomic_or_release(let t): + return "atomic_or_release_\(t)" + case .atomic_or_acqrel(let t): + return "atomic_or_acqrel_\(t)" + case .atomic_or_seqcst(let t): + return "atomic_or_seqcst_\(t)" + case .atomic_xor_relaxed(let t): + return "atomic_xor_relaxed_\(t)" + case .atomic_xor_acquire(let t): + return "atomic_xor_acquire_\(t)" + case .atomic_xor_release(let t): + return "atomic_xor_release_\(t)" + case .atomic_xor_acqrel(let t): + return "atomic_xor_acqrel_\(t)" + case .atomic_xor_seqcst(let t): + return "atomic_xor_seqcst_\(t)" + case .atomic_cmpxchg_relaxed_relaxed(let t): + return "atomic_cmpxchg_relaxed_relaxed_\(t)" + case .atomic_cmpxchg_relaxed_acquire(let t): + return "atomic_cmpxchg_relaxed_acquire_\(t)" + case .atomic_cmpxchg_relaxed_seqcst(let t): + return "atomic_cmpxchg_relaxed_seqcst_\(t)" + case .atomic_cmpxchg_acquire_relaxed(let t): + return "atomic_cmpxchg_acquire_relaxed_\(t)" + case .atomic_cmpxchg_acquire_acquire(let t): + return "atomic_cmpxchg_acquire_acquire_\(t)" + case .atomic_cmpxchg_acquire_seqcst(let t): + return "atomic_cmpxchg_acquire_seqcst_\(t)" + case .atomic_cmpxchg_release_relaxed(let t): + return "atomic_cmpxchg_release_relaxed_\(t)" + case .atomic_cmpxchg_release_acquire(let t): + return "atomic_cmpxchg_release_acquire_\(t)" + case .atomic_cmpxchg_release_seqcst(let t): + return "atomic_cmpxchg_release_seqcst_\(t)" + case .atomic_cmpxchg_acqrel_relaxed(let t): + return "atomic_cmpxchg_acqrel_relaxed_\(t)" + case .atomic_cmpxchg_acqrel_acquire(let t): + return "atomic_cmpxchg_acqrel_acquire_\(t)" + case .atomic_cmpxchg_acqrel_seqcst(let t): + return "atomic_cmpxchg_acqrel_seqcst_\(t)" + case .atomic_cmpxchg_seqcst_relaxed(let t): + return "atomic_cmpxchg_seqcst_relaxed_\(t)" + case .atomic_cmpxchg_seqcst_acquire(let t): + return "atomic_cmpxchg_seqcst_acquire_\(t)" + case .atomic_cmpxchg_seqcst_seqcst(let t): + return "atomic_cmpxchg_seqcst_seqcst_\(t)" + case .atomic_cmpxchgweak_relaxed_relaxed(let t): + return "atomic_cmpxchgweak_relaxed_relaxed_\(t)" + case .atomic_cmpxchgweak_relaxed_acquire(let t): + return "atomic_cmpxchgweak_relaxed_acquire_\(t)" + case .atomic_cmpxchgweak_relaxed_seqcst(let t): + return "atomic_cmpxchgweak_relaxed_seqcst_\(t)" + case .atomic_cmpxchgweak_acquire_relaxed(let t): + return "atomic_cmpxchgweak_acquire_relaxed_\(t)" + case .atomic_cmpxchgweak_acquire_acquire(let t): + return "atomic_cmpxchgweak_acquire_acquire_\(t)" + case .atomic_cmpxchgweak_acquire_seqcst(let t): + return "atomic_cmpxchgweak_acquire_seqcst_\(t)" + case .atomic_cmpxchgweak_release_relaxed(let t): + return "atomic_cmpxchgweak_release_relaxed_\(t)" + case .atomic_cmpxchgweak_release_acquire(let t): + return "atomic_cmpxchgweak_release_acquire_\(t)" + case .atomic_cmpxchgweak_release_seqcst(let t): + return "atomic_cmpxchgweak_release_seqcst_\(t)" + case .atomic_cmpxchgweak_acqrel_relaxed(let t): + return "atomic_cmpxchgweak_acqrel_relaxed_\(t)" + case .atomic_cmpxchgweak_acqrel_acquire(let t): + return "atomic_cmpxchgweak_acqrel_acquire_\(t)" + case .atomic_cmpxchgweak_acqrel_seqcst(let t): + return "atomic_cmpxchgweak_acqrel_seqcst_\(t)" + case .atomic_cmpxchgweak_seqcst_relaxed(let t): + return "atomic_cmpxchgweak_seqcst_relaxed_\(t)" + case .atomic_cmpxchgweak_seqcst_acquire(let t): + return "atomic_cmpxchgweak_seqcst_acquire_\(t)" + case .atomic_cmpxchgweak_seqcst_seqcst(let t): + return "atomic_cmpxchgweak_seqcst_seqcst_\(t)" + case .atomic_fence_acquire: + return "atomic_fence_acquire" + case .atomic_fence_release: + return "atomic_fence_release" + case .atomic_fence_acqrel: + return "atomic_fence_acqrel" + case .atomic_fence_seqcst: + return "atomic_fence_seqcst" + case .atomic_singlethreadfence_acquire: + return "atomic_singlethreadfence_acquire" + case .atomic_singlethreadfence_release: + return "atomic_singlethreadfence_release" + case .atomic_singlethreadfence_acqrel: + return "atomic_singlethreadfence_acqrel" + case .atomic_singlethreadfence_seqcst: + return "atomic_singlethreadfence_seqcst" } } diff --git a/Tests/HyloTests/BuiltinFunctionTests.swift b/Tests/HyloTests/BuiltinFunctionTests.swift index 0c3b95e5d..433ad5cf6 100644 --- a/Tests/HyloTests/BuiltinFunctionTests.swift +++ b/Tests/HyloTests/BuiltinFunctionTests.swift @@ -230,6 +230,110 @@ final class BuiltinFunctionTests: XCTestCase { createInstanceWithType: expectedType) } + func testAtomicRMWForSignedIntegers() throws { + let expectedType = ArrowType(.builtin(.ptr), .builtin(.i(64)), to: .builtin(.i(64))) + try assertParse( + instructions: [ + "atomic_swap", + "atomic_add", + "atomic_sub", + "atomic_max", + "atomic_min", + "atomic_and", + "atomic_nand", + "atomic_or", + "atomic_xor" + ], + parameterizedBy: [ + ["relaxed", "i64"], + ["acquire", "i64"], + ["release", "i64"], + ["acqrel", "i64"], + ["seqcst", "i64"] + ], + createInstanceWithType: expectedType) + } + + func testAtomicRMWForUnsignedIntegers() throws { + let expectedType = ArrowType(.builtin(.ptr), .builtin(.i(64)), to: .builtin(.i(64))) + try assertParse( + instructions: [ + "atomic_umax", + "atomic_umin" + ], + parameterizedBy: [ + ["relaxed", "i64"], + ["acquire", "i64"], + ["release", "i64"], + ["acqrel", "i64"], + ["seqcst", "i64"] + ], + createInstanceWithType: expectedType) + } + + func testAtomicRMWForFloatingNumbers() throws { + let expectedType = ArrowType(.builtin(.ptr), .builtin(.float64), to: .builtin(.float64)) + try assertParse( + instructions: [ + "atomic_swap", + "atomic_fadd", + "atomic_fsub", + "atomic_fmax", + "atomic_fmin" + ], + parameterizedBy: [ + ["relaxed", "float64"], + ["acquire", "float64"], + ["release", "float64"], + ["acqrel", "float64"], + ["seqcst", "float64"] + ], + createInstanceWithType: expectedType) + } + + func testAtomicCompareExchange() throws { + let expectedType = ArrowType(.builtin(.ptr), .builtin(.i(64)), .builtin(.i(64)), to: ^TupleType(types: [.builtin(.i(64)), .builtin(.i(1))])) + try assertParse( + instructions: [ + "atomic_cmpxchg", + "atomic_cmpxchgweak" + ], + parameterizedBy: [ + ["relaxed", "relaxed", "i64"], + ["relaxed", "acquire", "i64"], + ["relaxed", "seqcst", "i64"], + ["acquire", "relaxed", "i64"], + ["acquire", "acquire", "i64"], + ["acquire", "seqcst", "i64"], + ["release", "relaxed", "i64"], + ["release", "acquire", "i64"], + ["release", "seqcst", "i64"], + ["acqrel", "relaxed", "i64"], + ["acqrel", "acquire", "i64"], + ["acqrel", "seqcst", "i64"], + ["seqcst", "relaxed", "i64"], + ["seqcst", "acquire", "i64"], + ["seqcst", "seqcst", "i64"] + ], + createInstanceWithType: expectedType) + } + + func testAtomicFence() throws { + let expectedType = ArrowType(to: .void) + try assertParse( + instructions: [ + "atomic_fence", + "atomic_singlethreadfence" + ], + parameterizedBy: [ + ["acquire"], + ["release"], + ["acqrel"], + ["seqcst"] + ], + createInstanceWithType: expectedType) + } + /// For each element in `instructions` and `parameters`, assert that parsing a built-in functions /// named after their concatenation creates an instance with the same stem and parameters, and /// whose type is `expectedType`.