aboutsummaryrefslogtreecommitdiffhomepage
path: root/llvm_zluda
diff options
context:
space:
mode:
Diffstat (limited to 'llvm_zluda')
-rw-r--r--llvm_zluda/src/lib.cpp182
-rw-r--r--llvm_zluda/src/lib.rs71
2 files changed, 253 insertions, 0 deletions
diff --git a/llvm_zluda/src/lib.cpp b/llvm_zluda/src/lib.cpp
index 3da88fb..886aa0d 100644
--- a/llvm_zluda/src/lib.cpp
+++ b/llvm_zluda/src/lib.cpp
@@ -1,6 +1,144 @@
#include <llvm-c/Core.h>
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Type.h"
+#include "llvm/IR/Instructions.h"
+
+using namespace llvm;
+
+typedef enum
+{
+ LLVMZludaAtomicRMWBinOpXchg, /**< Set the new value and return the one old */
+ LLVMZludaAtomicRMWBinOpAdd, /**< Add a value and return the old one */
+ LLVMZludaAtomicRMWBinOpSub, /**< Subtract a value and return the old one */
+ LLVMZludaAtomicRMWBinOpAnd, /**< And a value and return the old one */
+ LLVMZludaAtomicRMWBinOpNand, /**< Not-And a value and return the old one */
+ LLVMZludaAtomicRMWBinOpOr, /**< OR a value and return the old one */
+ LLVMZludaAtomicRMWBinOpXor, /**< Xor a value and return the old one */
+ LLVMZludaAtomicRMWBinOpMax, /**< Sets the value if it's greater than the
+ original using a signed comparison and return
+ the old one */
+ LLVMZludaAtomicRMWBinOpMin, /**< Sets the value if it's Smaller than the
+ original using a signed comparison and return
+ the old one */
+ LLVMZludaAtomicRMWBinOpUMax, /**< Sets the value if it's greater than the
+ original using an unsigned comparison and return
+ the old one */
+ LLVMZludaAtomicRMWBinOpUMin, /**< Sets the value if it's greater than the
+ original using an unsigned comparison and return
+ the old one */
+ LLVMZludaAtomicRMWBinOpFAdd, /**< Add a floating point value and return the
+ old one */
+ LLVMZludaAtomicRMWBinOpFSub, /**< Subtract a floating point value and return the
+ old one */
+ LLVMZludaAtomicRMWBinOpFMax, /**< Sets the value if it's greater than the
+ original using an floating point comparison and
+ return the old one */
+ LLVMZludaAtomicRMWBinOpFMin, /**< Sets the value if it's smaller than the
+ original using an floating point comparison and
+ return the old one */
+ LLVMZludaAtomicRMWBinOpUIncWrap, /**< Increments the value, wrapping back to zero
+ when incremented above input value */
+ LLVMZludaAtomicRMWBinOpUDecWrap, /**< Decrements the value, wrapping back to
+ the input value when decremented below zero */
+} LLVMZludaAtomicRMWBinOp;
+
+static llvm::AtomicRMWInst::BinOp mapFromLLVMRMWBinOp(LLVMZludaAtomicRMWBinOp BinOp)
+{
+ switch (BinOp)
+ {
+ case LLVMZludaAtomicRMWBinOpXchg:
+ return llvm::AtomicRMWInst::Xchg;
+ case LLVMZludaAtomicRMWBinOpAdd:
+ return llvm::AtomicRMWInst::Add;
+ case LLVMZludaAtomicRMWBinOpSub:
+ return llvm::AtomicRMWInst::Sub;
+ case LLVMZludaAtomicRMWBinOpAnd:
+ return llvm::AtomicRMWInst::And;
+ case LLVMZludaAtomicRMWBinOpNand:
+ return llvm::AtomicRMWInst::Nand;
+ case LLVMZludaAtomicRMWBinOpOr:
+ return llvm::AtomicRMWInst::Or;
+ case LLVMZludaAtomicRMWBinOpXor:
+ return llvm::AtomicRMWInst::Xor;
+ case LLVMZludaAtomicRMWBinOpMax:
+ return llvm::AtomicRMWInst::Max;
+ case LLVMZludaAtomicRMWBinOpMin:
+ return llvm::AtomicRMWInst::Min;
+ case LLVMZludaAtomicRMWBinOpUMax:
+ return llvm::AtomicRMWInst::UMax;
+ case LLVMZludaAtomicRMWBinOpUMin:
+ return llvm::AtomicRMWInst::UMin;
+ case LLVMZludaAtomicRMWBinOpFAdd:
+ return llvm::AtomicRMWInst::FAdd;
+ case LLVMZludaAtomicRMWBinOpFSub:
+ return llvm::AtomicRMWInst::FSub;
+ case LLVMZludaAtomicRMWBinOpFMax:
+ return llvm::AtomicRMWInst::FMax;
+ case LLVMZludaAtomicRMWBinOpFMin:
+ return llvm::AtomicRMWInst::FMin;
+ case LLVMZludaAtomicRMWBinOpUIncWrap:
+ return llvm::AtomicRMWInst::UIncWrap;
+ case LLVMZludaAtomicRMWBinOpUDecWrap:
+ return llvm::AtomicRMWInst::UDecWrap;
+ }
+
+ llvm_unreachable("Invalid LLVMZludaAtomicRMWBinOp value!");
+}
+
+static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering)
+{
+ switch (Ordering)
+ {
+ case LLVMAtomicOrderingNotAtomic:
+ return AtomicOrdering::NotAtomic;
+ case LLVMAtomicOrderingUnordered:
+ return AtomicOrdering::Unordered;
+ case LLVMAtomicOrderingMonotonic:
+ return AtomicOrdering::Monotonic;
+ case LLVMAtomicOrderingAcquire:
+ return AtomicOrdering::Acquire;
+ case LLVMAtomicOrderingRelease:
+ return AtomicOrdering::Release;
+ case LLVMAtomicOrderingAcquireRelease:
+ return AtomicOrdering::AcquireRelease;
+ case LLVMAtomicOrderingSequentiallyConsistent:
+ return AtomicOrdering::SequentiallyConsistent;
+ }
+
+ llvm_unreachable("Invalid LLVMAtomicOrdering value!");
+}
+
+typedef unsigned LLVMFastMathFlags;
+
+enum
+{
+ LLVMFastMathAllowReassoc = (1 << 0),
+ LLVMFastMathNoNaNs = (1 << 1),
+ LLVMFastMathNoInfs = (1 << 2),
+ LLVMFastMathNoSignedZeros = (1 << 3),
+ LLVMFastMathAllowReciprocal = (1 << 4),
+ LLVMFastMathAllowContract = (1 << 5),
+ LLVMFastMathApproxFunc = (1 << 6),
+ LLVMFastMathNone = 0,
+ LLVMFastMathAll = LLVMFastMathAllowReassoc | LLVMFastMathNoNaNs |
+ LLVMFastMathNoInfs | LLVMFastMathNoSignedZeros |
+ LLVMFastMathAllowReciprocal | LLVMFastMathAllowContract |
+ LLVMFastMathApproxFunc,
+};
+
+static FastMathFlags mapFromLLVMFastMathFlags(LLVMFastMathFlags FMF)
+{
+ FastMathFlags NewFMF;
+ NewFMF.setAllowReassoc((FMF & LLVMFastMathAllowReassoc) != 0);
+ NewFMF.setNoNaNs((FMF & LLVMFastMathNoNaNs) != 0);
+ NewFMF.setNoInfs((FMF & LLVMFastMathNoInfs) != 0);
+ NewFMF.setNoSignedZeros((FMF & LLVMFastMathNoSignedZeros) != 0);
+ NewFMF.setAllowReciprocal((FMF & LLVMFastMathAllowReciprocal) != 0);
+ NewFMF.setAllowContract((FMF & LLVMFastMathAllowContract) != 0);
+ NewFMF.setApproxFunc((FMF & LLVMFastMathApproxFunc) != 0);
+
+ return NewFMF;
+}
LLVM_C_EXTERN_C_BEGIN
@@ -10,4 +148,48 @@ LLVMValueRef LLVMZludaBuildAlloca(LLVMBuilderRef B, LLVMTypeRef Ty, unsigned Add
return llvm::wrap(llvm::unwrap(B)->CreateAlloca(llvm::unwrap(Ty), AddrSpace, nullptr, Name));
}
+LLVMValueRef LLVMZludaBuildAtomicRMW(LLVMBuilderRef B, LLVMZludaAtomicRMWBinOp op,
+ LLVMValueRef PTR, LLVMValueRef Val,
+ char *scope,
+ LLVMAtomicOrdering ordering)
+{
+ auto builder = llvm::unwrap(B);
+ LLVMContext &context = builder->getContext();
+ llvm::AtomicRMWInst::BinOp intop = mapFromLLVMRMWBinOp(op);
+ return llvm::wrap(builder->CreateAtomicRMW(
+ intop, llvm::unwrap(PTR), llvm::unwrap(Val), llvm::MaybeAlign(),
+ mapFromLLVMOrdering(ordering),
+ context.getOrInsertSyncScopeID(scope)));
+}
+
+LLVMValueRef LLVMZludaBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr,
+ LLVMValueRef Cmp, LLVMValueRef New,
+ char *scope,
+ LLVMAtomicOrdering SuccessOrdering,
+ LLVMAtomicOrdering FailureOrdering)
+{
+ auto builder = llvm::unwrap(B);
+ LLVMContext &context = builder->getContext();
+ return wrap(builder->CreateAtomicCmpXchg(
+ unwrap(Ptr), unwrap(Cmp), unwrap(New), MaybeAlign(),
+ mapFromLLVMOrdering(SuccessOrdering),
+ mapFromLLVMOrdering(FailureOrdering),
+ context.getOrInsertSyncScopeID(scope)));
+}
+
+void LLVMZludaSetFastMathFlags(LLVMValueRef FPMathInst, LLVMFastMathFlags FMF)
+{
+ Value *P = unwrap<Value>(FPMathInst);
+ cast<Instruction>(P)->setFastMathFlags(mapFromLLVMFastMathFlags(FMF));
+}
+
+void LLVMZludaBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering Ordering,
+ char *scope, const char *Name)
+{
+ auto builder = llvm::unwrap(B);
+ LLVMContext &context = builder->getContext();
+ builder->CreateFence(mapFromLLVMOrdering(Ordering),
+ context.getOrInsertSyncScopeID(scope));
+}
+
LLVM_C_EXTERN_C_END \ No newline at end of file
diff --git a/llvm_zluda/src/lib.rs b/llvm_zluda/src/lib.rs
index 18072a8..fb5cc47 100644
--- a/llvm_zluda/src/lib.rs
+++ b/llvm_zluda/src/lib.rs
@@ -1,5 +1,48 @@
+#![allow(non_upper_case_globals)]
use llvm_sys::prelude::*;
pub use llvm_sys::*;
+
+#[repr(C)]
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum LLVMZludaAtomicRMWBinOp {
+ LLVMZludaAtomicRMWBinOpXchg = 0,
+ LLVMZludaAtomicRMWBinOpAdd = 1,
+ LLVMZludaAtomicRMWBinOpSub = 2,
+ LLVMZludaAtomicRMWBinOpAnd = 3,
+ LLVMZludaAtomicRMWBinOpNand = 4,
+ LLVMZludaAtomicRMWBinOpOr = 5,
+ LLVMZludaAtomicRMWBinOpXor = 6,
+ LLVMZludaAtomicRMWBinOpMax = 7,
+ LLVMZludaAtomicRMWBinOpMin = 8,
+ LLVMZludaAtomicRMWBinOpUMax = 9,
+ LLVMZludaAtomicRMWBinOpUMin = 10,
+ LLVMZludaAtomicRMWBinOpFAdd = 11,
+ LLVMZludaAtomicRMWBinOpFSub = 12,
+ LLVMZludaAtomicRMWBinOpFMax = 13,
+ LLVMZludaAtomicRMWBinOpFMin = 14,
+ LLVMZludaAtomicRMWBinOpUIncWrap = 15,
+ LLVMZludaAtomicRMWBinOpUDecWrap = 16,
+}
+
+// Backport from LLVM 19
+pub const LLVMZludaFastMathAllowReassoc: ::std::ffi::c_uint = 1 << 0;
+pub const LLVMZludaFastMathNoNaNs: ::std::ffi::c_uint = 1 << 1;
+pub const LLVMZludaFastMathNoInfs: ::std::ffi::c_uint = 1 << 2;
+pub const LLVMZludaFastMathNoSignedZeros: ::std::ffi::c_uint = 1 << 3;
+pub const LLVMZludaFastMathAllowReciprocal: ::std::ffi::c_uint = 1 << 4;
+pub const LLVMZludaFastMathAllowContract: ::std::ffi::c_uint = 1 << 5;
+pub const LLVMZludaFastMathApproxFunc: ::std::ffi::c_uint = 1 << 6;
+pub const LLVMZludaFastMathNone: ::std::ffi::c_uint = 0;
+pub const LLVMZludaFastMathAll: ::std::ffi::c_uint = LLVMZludaFastMathAllowReassoc
+ | LLVMZludaFastMathNoNaNs
+ | LLVMZludaFastMathNoInfs
+ | LLVMZludaFastMathNoSignedZeros
+ | LLVMZludaFastMathAllowReciprocal
+ | LLVMZludaFastMathAllowContract
+ | LLVMZludaFastMathApproxFunc;
+
+pub type LLVMZludaFastMathFlags = std::ffi::c_uint;
+
extern "C" {
pub fn LLVMZludaBuildAlloca(
B: LLVMBuilderRef,
@@ -7,4 +50,32 @@ extern "C" {
AddrSpace: u32,
Name: *const i8,
) -> LLVMValueRef;
+
+ pub fn LLVMZludaBuildAtomicRMW(
+ B: LLVMBuilderRef,
+ op: LLVMZludaAtomicRMWBinOp,
+ PTR: LLVMValueRef,
+ Val: LLVMValueRef,
+ scope: *const i8,
+ ordering: LLVMAtomicOrdering,
+ ) -> LLVMValueRef;
+
+ pub fn LLVMZludaBuildAtomicCmpXchg(
+ B: LLVMBuilderRef,
+ Ptr: LLVMValueRef,
+ Cmp: LLVMValueRef,
+ New: LLVMValueRef,
+ scope: *const i8,
+ SuccessOrdering: LLVMAtomicOrdering,
+ FailureOrdering: LLVMAtomicOrdering,
+ ) -> LLVMValueRef;
+
+ pub fn LLVMZludaSetFastMathFlags(FPMathInst: LLVMValueRef, FMF: LLVMZludaFastMathFlags);
+
+ pub fn LLVMZludaBuildFence(
+ B: LLVMBuilderRef,
+ ordering: LLVMAtomicOrdering,
+ scope: *const i8,
+ Name: *const i8,
+ ) -> LLVMValueRef;
}