Index: llvm/trunk/include/llvm-c/Core.h =================================================================== --- llvm/trunk/include/llvm-c/Core.h +++ llvm/trunk/include/llvm-c/Core.h @@ -370,9 +370,13 @@ LLVMAtomicRMWBinOpUMax, /**< Sets the value if it's greater than the original using an unsigned comparison and return the old one */ - LLVMAtomicRMWBinOpUMin /**< Sets the value if it's greater than the - original using an unsigned comparison and return - the old one */ + LLVMAtomicRMWBinOpUMin, /**< Sets the value if it's greater than the + original using an unsigned comparison and return + the old one */ + LLVMAtomicRMWBinOpFAdd, /**< Add a floating point value and return the + old one */ + LLVMAtomicRMWBinOpFSub /**< Subtract a floating point value and return the + old one */ } LLVMAtomicRMWBinOp; typedef enum { @@ -1571,6 +1575,8 @@ macro(ResumeInst) \ macro(CleanupReturnInst) \ macro(CatchReturnInst) \ + macro(CatchSwitchInst) \ + macro(CallBrInst) \ macro(FuncletPadInst) \ macro(CatchPadInst) \ macro(CleanupPadInst) \ @@ -1592,7 +1598,10 @@ macro(ZExtInst) \ macro(ExtractValueInst) \ macro(LoadInst) \ - macro(VAArgInst) + macro(VAArgInst) \ + macro(AtomicCmpXchgInst) \ + macro(AtomicRMWInst) \ + macro(FenceInst) /** * @defgroup LLVMCCoreValueGeneral General APIs @@ -3807,8 +3816,12 @@ const char *Name); LLVMBool LLVMGetVolatile(LLVMValueRef MemoryAccessInst); void LLVMSetVolatile(LLVMValueRef MemoryAccessInst, LLVMBool IsVolatile); +LLVMBool LLVMGetWeak(LLVMValueRef CmpXchgInst); +void LLVMSetWeak(LLVMValueRef CmpXchgInst, LLVMBool IsWeak); LLVMAtomicOrdering LLVMGetOrdering(LLVMValueRef MemoryAccessInst); void LLVMSetOrdering(LLVMValueRef MemoryAccessInst, LLVMAtomicOrdering Ordering); +LLVMAtomicRMWBinOp LLVMGetAtomicRMWBinOp(LLVMValueRef AtomicRMWInst); +void LLVMSetAtomicRMWBinOp(LLVMValueRef AtomicRMWInst, LLVMAtomicRMWBinOp BinOp); /* Casts */ LLVMValueRef LLVMBuildTrunc(LLVMBuilderRef, LLVMValueRef Val, Index: llvm/trunk/lib/IR/Core.cpp =================================================================== --- llvm/trunk/lib/IR/Core.cpp +++ llvm/trunk/lib/IR/Core.cpp @@ -3527,6 +3527,47 @@ llvm_unreachable("Invalid AtomicOrdering value!"); } +static AtomicRMWInst::BinOp mapFromLLVMRMWBinOp(LLVMAtomicRMWBinOp BinOp) { + switch (BinOp) { + case LLVMAtomicRMWBinOpXchg: return AtomicRMWInst::Xchg; + case LLVMAtomicRMWBinOpAdd: return AtomicRMWInst::Add; + case LLVMAtomicRMWBinOpSub: return AtomicRMWInst::Sub; + case LLVMAtomicRMWBinOpAnd: return AtomicRMWInst::And; + case LLVMAtomicRMWBinOpNand: return AtomicRMWInst::Nand; + case LLVMAtomicRMWBinOpOr: return AtomicRMWInst::Or; + case LLVMAtomicRMWBinOpXor: return AtomicRMWInst::Xor; + case LLVMAtomicRMWBinOpMax: return AtomicRMWInst::Max; + case LLVMAtomicRMWBinOpMin: return AtomicRMWInst::Min; + case LLVMAtomicRMWBinOpUMax: return AtomicRMWInst::UMax; + case LLVMAtomicRMWBinOpUMin: return AtomicRMWInst::UMin; + case LLVMAtomicRMWBinOpFAdd: return AtomicRMWInst::FAdd; + case LLVMAtomicRMWBinOpFSub: return AtomicRMWInst::FSub; + } + + llvm_unreachable("Invalid LLVMAtomicRMWBinOp value!"); +} + +static LLVMAtomicRMWBinOp mapToLLVMRMWBinOp(AtomicRMWInst::BinOp BinOp) { + switch (BinOp) { + case AtomicRMWInst::Xchg: return LLVMAtomicRMWBinOpXchg; + case AtomicRMWInst::Add: return LLVMAtomicRMWBinOpAdd; + case AtomicRMWInst::Sub: return LLVMAtomicRMWBinOpSub; + case AtomicRMWInst::And: return LLVMAtomicRMWBinOpAnd; + case AtomicRMWInst::Nand: return LLVMAtomicRMWBinOpNand; + case AtomicRMWInst::Or: return LLVMAtomicRMWBinOpOr; + case AtomicRMWInst::Xor: return LLVMAtomicRMWBinOpXor; + case AtomicRMWInst::Max: return LLVMAtomicRMWBinOpMax; + case AtomicRMWInst::Min: return LLVMAtomicRMWBinOpMin; + case AtomicRMWInst::UMax: return LLVMAtomicRMWBinOpUMax; + case AtomicRMWInst::UMin: return LLVMAtomicRMWBinOpUMin; + case AtomicRMWInst::FAdd: return LLVMAtomicRMWBinOpFAdd; + case AtomicRMWInst::FSub: return LLVMAtomicRMWBinOpFSub; + default: break; + } + + llvm_unreachable("Invalid AtomicRMWBinOp value!"); +} + // TODO: Should this and other atomic instructions support building with // "syncscope"? LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering Ordering, @@ -3602,14 +3643,30 @@ Value *P = unwrap(MemAccessInst); if (LoadInst *LI = dyn_cast(P)) return LI->isVolatile(); - return cast(P)->isVolatile(); + if (StoreInst *SI = dyn_cast(P)) + return SI->isVolatile(); + if (AtomicRMWInst *AI = dyn_cast(P)) + return AI->isVolatile(); + return cast(P)->isVolatile(); } void LLVMSetVolatile(LLVMValueRef MemAccessInst, LLVMBool isVolatile) { Value *P = unwrap(MemAccessInst); if (LoadInst *LI = dyn_cast(P)) return LI->setVolatile(isVolatile); - return cast(P)->setVolatile(isVolatile); + if (StoreInst *SI = dyn_cast(P)) + return SI->setVolatile(isVolatile); + if (AtomicRMWInst *AI = dyn_cast(P)) + return AI->setVolatile(isVolatile); + return cast(P)->setVolatile(isVolatile); +} + +LLVMBool LLVMGetWeak(LLVMValueRef CmpXchgInst) { + return unwrap(CmpXchgInst)->isWeak(); +} + +void LLVMSetWeak(LLVMValueRef CmpXchgInst, LLVMBool isWeak) { + return unwrap(CmpXchgInst)->setWeak(isWeak); } LLVMAtomicOrdering LLVMGetOrdering(LLVMValueRef MemAccessInst) { @@ -3617,8 +3674,10 @@ AtomicOrdering O; if (LoadInst *LI = dyn_cast(P)) O = LI->getOrdering(); + else if (StoreInst *SI = dyn_cast(P)) + O = SI->getOrdering(); else - O = cast(P)->getOrdering(); + O = cast(P)->getOrdering(); return mapToLLVMOrdering(O); } @@ -3631,6 +3690,14 @@ return cast(P)->setOrdering(O); } +LLVMAtomicRMWBinOp LLVMGetAtomicRMWBinOp(LLVMValueRef Inst) { + return mapToLLVMRMWBinOp(unwrap(Inst)->getOperation()); +} + +void LLVMSetAtomicRMWBinOp(LLVMValueRef Inst, LLVMAtomicRMWBinOp BinOp) { + unwrap(Inst)->setOperation(mapFromLLVMRMWBinOp(BinOp)); +} + /*--.. Casts ...............................................................--*/ LLVMValueRef LLVMBuildTrunc(LLVMBuilderRef B, LLVMValueRef Val, @@ -3849,20 +3916,7 @@ LLVMValueRef PTR, LLVMValueRef Val, LLVMAtomicOrdering ordering, LLVMBool singleThread) { - AtomicRMWInst::BinOp intop; - switch (op) { - case LLVMAtomicRMWBinOpXchg: intop = AtomicRMWInst::Xchg; break; - case LLVMAtomicRMWBinOpAdd: intop = AtomicRMWInst::Add; break; - case LLVMAtomicRMWBinOpSub: intop = AtomicRMWInst::Sub; break; - case LLVMAtomicRMWBinOpAnd: intop = AtomicRMWInst::And; break; - case LLVMAtomicRMWBinOpNand: intop = AtomicRMWInst::Nand; break; - case LLVMAtomicRMWBinOpOr: intop = AtomicRMWInst::Or; break; - case LLVMAtomicRMWBinOpXor: intop = AtomicRMWInst::Xor; break; - case LLVMAtomicRMWBinOpMax: intop = AtomicRMWInst::Max; break; - case LLVMAtomicRMWBinOpMin: intop = AtomicRMWInst::Min; break; - case LLVMAtomicRMWBinOpUMax: intop = AtomicRMWInst::UMax; break; - case LLVMAtomicRMWBinOpUMin: intop = AtomicRMWInst::UMin; break; - } + AtomicRMWInst::BinOp intop = mapFromLLVMRMWBinOp(op); return wrap(unwrap(B)->CreateAtomicRMW(intop, unwrap(PTR), unwrap(Val), mapFromLLVMOrdering(ordering), singleThread ? SyncScope::SingleThread : SyncScope::System)); Index: llvm/trunk/test/Bindings/llvm-c/echo.ll =================================================================== --- llvm/trunk/test/Bindings/llvm-c/echo.ll +++ llvm/trunk/test/Bindings/llvm-c/echo.ll @@ -138,6 +138,23 @@ ret i32 %p } +define void @memops(i8* %ptr) { + %a = load i8, i8* %ptr + %b = load volatile i8, i8* %ptr + %c = load i8, i8* %ptr, align 8 + %d = load atomic i8, i8* %ptr acquire, align 32 + store i8 0, i8* %ptr + store volatile i8 0, i8* %ptr + store i8 0, i8* %ptr, align 8 + store atomic i8 0, i8* %ptr release, align 32 + %e = atomicrmw add i8* %ptr, i8 0 monotonic + %f = atomicrmw volatile xchg i8* %ptr, i8 0 acq_rel + %g = cmpxchg i8* %ptr, i8 1, i8 2 seq_cst acquire + %h = cmpxchg weak i8* %ptr, i8 1, i8 2 seq_cst acquire + %i = cmpxchg volatile i8* %ptr, i8 1, i8 2 monotonic monotonic + ret void +} + declare void @personalityFn() define void @exn() personality void ()* @personalityFn { Index: llvm/trunk/tools/llvm-c-test/echo.cpp =================================================================== --- llvm/trunk/tools/llvm-c-test/echo.cpp +++ llvm/trunk/tools/llvm-c-test/echo.cpp @@ -576,6 +576,8 @@ LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 0)); Dst = LLVMBuildLoad(Builder, Ptr, Name); LLVMSetAlignment(Dst, LLVMGetAlignment(Src)); + LLVMSetOrdering(Dst, LLVMGetOrdering(Src)); + LLVMSetVolatile(Dst, LLVMGetVolatile(Src)); break; } case LLVMStore: { @@ -583,6 +585,8 @@ LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 1)); Dst = LLVMBuildStore(Builder, Val, Ptr); LLVMSetAlignment(Dst, LLVMGetAlignment(Src)); + LLVMSetOrdering(Dst, LLVMGetOrdering(Src)); + LLVMSetVolatile(Dst, LLVMGetVolatile(Src)); break; } case LLVMGetElementPtr: { @@ -597,6 +601,17 @@ Dst = LLVMBuildGEP(Builder, Ptr, Idx.data(), NumIdx, Name); break; } + case LLVMAtomicRMW: { + LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 0)); + LLVMValueRef Val = CloneValue(LLVMGetOperand(Src, 1)); + LLVMAtomicRMWBinOp BinOp = LLVMGetAtomicRMWBinOp(Src); + LLVMAtomicOrdering Ord = LLVMGetOrdering(Src); + LLVMBool SingleThread = LLVMIsAtomicSingleThread(Src); + Dst = LLVMBuildAtomicRMW(Builder, BinOp, Ptr, Val, Ord, SingleThread); + LLVMSetVolatile(Dst, LLVMGetVolatile(Src)); + LLVMSetValueName2(Dst, Name, NameLen); + break; + } case LLVMAtomicCmpXchg: { LLVMValueRef Ptr = CloneValue(LLVMGetOperand(Src, 0)); LLVMValueRef Cmp = CloneValue(LLVMGetOperand(Src, 1)); @@ -607,7 +622,11 @@ Dst = LLVMBuildAtomicCmpXchg(Builder, Ptr, Cmp, New, Succ, Fail, SingleThread); - } break; + LLVMSetVolatile(Dst, LLVMGetVolatile(Src)); + LLVMSetWeak(Dst, LLVMGetWeak(Src)); + LLVMSetValueName2(Dst, Name, NameLen); + break; + } case LLVMBitCast: { LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 0)); Dst = LLVMBuildBitCast(Builder, V, CloneType(Src), Name);