diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 59c0d4dd2376d..6312c2621f170 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -164,6 +164,13 @@ Changes to the C API * Added ``LLVMCreateConstantRangeAttribute`` function for creating ConstantRange Attributes. +* Added the following functions for creating and accessing data for CallBr instructions: + + * ``LLVMBuildCallBr`` + * ``LLVMGetCallBrDefaultDest`` + * ``LLVMGetCallBrNumIndirectDests`` + * ``LLVMGetCallBrIndirectDest`` + Changes to the CodeGen infrastructure ------------------------------------- diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index ba02ca4825753..9d09546513f0e 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -3737,6 +3737,28 @@ void LLVMSetNormalDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B); */ void LLVMSetUnwindDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B); +/** + * Get the default destination of a CallBr instruction. + * + * @see llvm::CallBrInst::getDefaultDest() + */ +LLVMBasicBlockRef LLVMGetCallBrDefaultDest(LLVMValueRef CallBr); + +/** + * Get the number of indirect destinations of a CallBr instruction. + * + * @see llvm::CallBrInst::getNumIndirectDests() + + */ +unsigned LLVMGetCallBrNumIndirectDests(LLVMValueRef CallBr); + +/** + * Get the indirect destination of a CallBr instruction at the given index. + * + * @see llvm::CallBrInst::getIndirectDest() + */ +LLVMBasicBlockRef LLVMGetCallBrIndirectDest(LLVMValueRef CallBr, unsigned Idx); + /** * @} */ @@ -4023,6 +4045,12 @@ LLVMValueRef LLVMBuildSwitch(LLVMBuilderRef, LLVMValueRef V, LLVMBasicBlockRef Else, unsigned NumCases); LLVMValueRef LLVMBuildIndirectBr(LLVMBuilderRef B, LLVMValueRef Addr, unsigned NumDests); +LLVMValueRef LLVMBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, + LLVMBasicBlockRef DefaultDest, + LLVMBasicBlockRef *IndirectDests, + unsigned NumIndirectDests, LLVMValueRef *Args, + unsigned NumArgs, LLVMOperandBundleRef *Bundles, + unsigned NumBundles, const char *Name); LLVMValueRef LLVMBuildInvoke2(LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index 1b84527d5e874..df90b88341123 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -47,6 +47,10 @@ using namespace llvm; DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OperandBundleDef, LLVMOperandBundleRef) +inline BasicBlock **unwrap(LLVMBasicBlockRef *BBs) { + return reinterpret_cast(BBs); +} + #define DEBUG_TYPE "ir" void llvm::initializeCore(PassRegistry &Registry) { @@ -3031,6 +3035,18 @@ void LLVMSetUnwindDest(LLVMValueRef Invoke, LLVMBasicBlockRef B) { unwrap(Invoke)->setUnwindDest(unwrap(B)); } +LLVMBasicBlockRef LLVMGetCallBrDefaultDest(LLVMValueRef CallBr) { + return wrap(unwrap(CallBr)->getDefaultDest()); +} + +unsigned LLVMGetCallBrNumIndirectDests(LLVMValueRef CallBr) { + return unwrap(CallBr)->getNumIndirectDests(); +} + +LLVMBasicBlockRef LLVMGetCallBrIndirectDest(LLVMValueRef CallBr, unsigned Idx) { + return wrap(unwrap(CallBr)->getIndirectDest(Idx)); +} + /*--.. Operations on terminators ...........................................--*/ unsigned LLVMGetNumSuccessors(LLVMValueRef Term) { @@ -3258,6 +3274,25 @@ LLVMValueRef LLVMBuildIndirectBr(LLVMBuilderRef B, LLVMValueRef Addr, return wrap(unwrap(B)->CreateIndirectBr(unwrap(Addr), NumDests)); } +LLVMValueRef LLVMBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, + LLVMBasicBlockRef DefaultDest, + LLVMBasicBlockRef *IndirectDests, + unsigned NumIndirectDests, LLVMValueRef *Args, + unsigned NumArgs, LLVMOperandBundleRef *Bundles, + unsigned NumBundles, const char *Name) { + + SmallVector OBs; + for (auto *Bundle : ArrayRef(Bundles, NumBundles)) { + OperandBundleDef *OB = unwrap(Bundle); + OBs.push_back(*OB); + } + + return wrap(unwrap(B)->CreateCallBr( + unwrap(Ty), unwrap(Fn), unwrap(DefaultDest), + ArrayRef(unwrap(IndirectDests), NumIndirectDests), + ArrayRef(unwrap(Args), NumArgs), OBs, Name)); +} + LLVMValueRef LLVMBuildInvoke2(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll index 953a16b7e624e..bb5fae0dcd12e 100644 --- a/llvm/test/Bindings/llvm-c/echo.ll +++ b/llvm/test/Bindings/llvm-c/echo.ll @@ -348,6 +348,32 @@ define void @test_func_prologue_data_01() prologue %func_prolog_struct <{ i8 235 ret void } + +define void @test_call_br_01(i32 %input) { +entry: + callbr void asm "nop", "r,!i"(i32 %input) to label %bb_01 [label %bb_02] + +bb_01: + ret void +bb_02: + ret void +} + +define void @test_call_br_02(i32 %input0, i32 %input1) { +entry: + ; Multiple indirect destinations, operand bundles, and arguments + callbr void asm "nop", "r,r,!i,!i"(i32 %input0, i32 %input1) + ["op0"(i32 %input1), "op1"(label %bb_02)] + to label %bb_01 [label %bb_03, label %bb_02] + +bb_01: + ret void +bb_02: + ret void +bb_03: + ret void +} + !llvm.dbg.cu = !{!0, !2} !llvm.module.flags = !{!3} diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index 347863638849c..518716168c423 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -570,6 +570,46 @@ struct FunCloner { LLVMDisposeOperandBundle(Bundle); break; } + case LLVMCallBr: { + LLVMTypeRef FnTy = CloneType(LLVMGetCalledFunctionType(Src)); + LLVMValueRef Fn = CloneValue(LLVMGetCalledValue(Src)); + + LLVMBasicBlockRef DefaultDest = + DeclareBB(LLVMGetCallBrDefaultDest(Src)); + + // Clone indirect destinations + SmallVector IndirectDests; + unsigned IndirectDestCount = LLVMGetCallBrNumIndirectDests(Src); + for (unsigned i = 0; i < IndirectDestCount; ++i) + IndirectDests.push_back(DeclareBB(LLVMGetCallBrIndirectDest(Src, i))); + + // Clone input arguments + SmallVector Args; + unsigned ArgCount = LLVMGetNumArgOperands(Src); + for (unsigned i = 0; i < ArgCount; ++i) + Args.push_back(CloneValue(LLVMGetOperand(Src, i))); + + // Clone operand bundles + SmallVector Bundles; + unsigned BundleCount = LLVMGetNumOperandBundles(Src); + for (unsigned i = 0; i < BundleCount; ++i) { + auto Bundle = LLVMGetOperandBundleAtIndex(Src, i); + Bundles.push_back(CloneOB(Bundle)); + LLVMDisposeOperandBundle(Bundle); + } + + Dst = LLVMBuildCallBr(Builder, FnTy, Fn, DefaultDest, + IndirectDests.data(), IndirectDests.size(), + Args.data(), Args.size(), Bundles.data(), + Bundles.size(), Name); + + CloneAttrs(Src, Dst); + + for (auto Bundle : Bundles) + LLVMDisposeOperandBundle(Bundle); + + break; + } case LLVMUnreachable: Dst = LLVMBuildUnreachable(Builder); break;