diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -255,6 +255,9 @@ Changes to the C API -------------------- +* Added ``LLVMGetTailCallKind`` and ``LLVMSetTailCallKind``. + They allow to get and set ``tail``, ``musttail``, and ``notail`` + attributes. * ``LLVMContextSetOpaquePointers``, a temporary API to pin to legacy typed pointer, has been removed. * Functions for adding legacy passes like ``LLVMAddInstructionCombiningPass`` diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -468,6 +468,20 @@ LLVMAttributeFunctionIndex = -1, }; +/** + * Tail call kind for LLVMSetTailCallKind and LLVMGetTailCallKind. + * + * Note that 'musttail' implies 'tail'. + * + * @see CallInst::TailCallKind + */ +typedef enum { + LLVMTailCallKindNone = 0, + LLVMTailCallKindTail = 1, + LLVMTailCallKindMustTail = 2, + LLVMTailCallKindNoTail = 3, +} LLVMTailCallKind; + typedef unsigned LLVMAttributeIndex; /** @@ -3429,6 +3443,20 @@ */ void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall); +/** + * Obtain a tail call kind of the call instruction. + * + * @see llvm::CallInst::setTailCallKind() + */ +LLVMTailCallKind LLVMGetTailCallKind(LLVMValueRef CallInst); + +/** + * Set the call kind of the call instruction. + * + * @see llvm::CallInst::getTailCallKind() + */ +void LLVMSetTailCallKind(LLVMValueRef CallInst, LLVMTailCallKind kind); + /** * Return the normal destination basic block. * diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -2896,6 +2896,14 @@ unwrap(Call)->setTailCall(isTailCall); } +LLVMTailCallKind LLVMGetTailCallKind(LLVMValueRef Call) { + return (LLVMTailCallKind)unwrap(Call)->getTailCallKind(); +} + +void LLVMSetTailCallKind(LLVMValueRef Call, LLVMTailCallKind kind) { + unwrap(Call)->setTailCallKind((CallInst::TailCallKind)kind); +} + /*--.. Operations on invoke instructions (only) ............................--*/ LLVMBasicBlockRef LLVMGetNormalDest(LLVMValueRef Invoke) { diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll --- a/llvm/test/Bindings/llvm-c/echo.ll +++ b/llvm/test/Bindings/llvm-c/echo.ll @@ -98,6 +98,21 @@ ret i32 %1 } +define i32 @tailcall() { + %1 = tail call i32 @call() + ret i32 %1 +} + +define i32 @musttailcall() { + %1 = musttail call i32 @call() + ret i32 %1 +} + +define i32 @notailcall() { + %1 = notail call i32 @call() + ret i32 %1 +} + define i32 @cond(i32 %a, i32 %b) { br label %br unreachable: diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -736,7 +736,7 @@ LLVMTypeRef FnTy = CloneType(LLVMGetCalledFunctionType(Src)); LLVMValueRef Fn = CloneValue(LLVMGetCalledValue(Src)); Dst = LLVMBuildCall2(Builder, FnTy, Fn, Args.data(), ArgCount, Name); - LLVMSetTailCall(Dst, LLVMIsTailCall(Src)); + LLVMSetTailCallKind(Dst, LLVMGetTailCallKind(Src)); CloneAttrs(Src, Dst); break; }