aboutsummaryrefslogtreecommitdiffhomepage
path: root/llvm_zluda/src/lib.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm_zluda/src/lib.cpp')
-rw-r--r--llvm_zluda/src/lib.cpp182
1 files changed, 182 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