Skip to content

Commit 584253c

Browse files
authored
[C API] Add getters and build function for CallBr (#91154)
This adds LLVMBuildCallBr to create CallBr instructions, and getters for the CallBr-specific data. The remainder of its data, e.g. arguments/function, can be accessed using existing getters.
1 parent 34ae226 commit 584253c

File tree

5 files changed

+136
-0
lines changed

5 files changed

+136
-0
lines changed

llvm/docs/ReleaseNotes.rst

+7
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,13 @@ Changes to the C API
168168

169169
* Added ``LLVMCreateConstantRangeAttribute`` function for creating ConstantRange Attributes.
170170

171+
* Added the following functions for creating and accessing data for CallBr instructions:
172+
173+
* ``LLVMBuildCallBr``
174+
* ``LLVMGetCallBrDefaultDest``
175+
* ``LLVMGetCallBrNumIndirectDests``
176+
* ``LLVMGetCallBrIndirectDest``
177+
171178
Changes to the CodeGen infrastructure
172179
-------------------------------------
173180

llvm/include/llvm-c/Core.h

+28
Original file line numberDiff line numberDiff line change
@@ -3737,6 +3737,28 @@ void LLVMSetNormalDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B);
37373737
*/
37383738
void LLVMSetUnwindDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B);
37393739

3740+
/**
3741+
* Get the default destination of a CallBr instruction.
3742+
*
3743+
* @see llvm::CallBrInst::getDefaultDest()
3744+
*/
3745+
LLVMBasicBlockRef LLVMGetCallBrDefaultDest(LLVMValueRef CallBr);
3746+
3747+
/**
3748+
* Get the number of indirect destinations of a CallBr instruction.
3749+
*
3750+
* @see llvm::CallBrInst::getNumIndirectDests()
3751+
3752+
*/
3753+
unsigned LLVMGetCallBrNumIndirectDests(LLVMValueRef CallBr);
3754+
3755+
/**
3756+
* Get the indirect destination of a CallBr instruction at the given index.
3757+
*
3758+
* @see llvm::CallBrInst::getIndirectDest()
3759+
*/
3760+
LLVMBasicBlockRef LLVMGetCallBrIndirectDest(LLVMValueRef CallBr, unsigned Idx);
3761+
37403762
/**
37413763
* @}
37423764
*/
@@ -4023,6 +4045,12 @@ LLVMValueRef LLVMBuildSwitch(LLVMBuilderRef, LLVMValueRef V,
40234045
LLVMBasicBlockRef Else, unsigned NumCases);
40244046
LLVMValueRef LLVMBuildIndirectBr(LLVMBuilderRef B, LLVMValueRef Addr,
40254047
unsigned NumDests);
4048+
LLVMValueRef LLVMBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
4049+
LLVMBasicBlockRef DefaultDest,
4050+
LLVMBasicBlockRef *IndirectDests,
4051+
unsigned NumIndirectDests, LLVMValueRef *Args,
4052+
unsigned NumArgs, LLVMOperandBundleRef *Bundles,
4053+
unsigned NumBundles, const char *Name);
40264054
LLVMValueRef LLVMBuildInvoke2(LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef Fn,
40274055
LLVMValueRef *Args, unsigned NumArgs,
40284056
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,

llvm/lib/IR/Core.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ using namespace llvm;
4747

4848
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OperandBundleDef, LLVMOperandBundleRef)
4949

50+
inline BasicBlock **unwrap(LLVMBasicBlockRef *BBs) {
51+
return reinterpret_cast<BasicBlock **>(BBs);
52+
}
53+
5054
#define DEBUG_TYPE "ir"
5155

5256
void llvm::initializeCore(PassRegistry &Registry) {
@@ -3031,6 +3035,18 @@ void LLVMSetUnwindDest(LLVMValueRef Invoke, LLVMBasicBlockRef B) {
30313035
unwrap<InvokeInst>(Invoke)->setUnwindDest(unwrap(B));
30323036
}
30333037

3038+
LLVMBasicBlockRef LLVMGetCallBrDefaultDest(LLVMValueRef CallBr) {
3039+
return wrap(unwrap<CallBrInst>(CallBr)->getDefaultDest());
3040+
}
3041+
3042+
unsigned LLVMGetCallBrNumIndirectDests(LLVMValueRef CallBr) {
3043+
return unwrap<CallBrInst>(CallBr)->getNumIndirectDests();
3044+
}
3045+
3046+
LLVMBasicBlockRef LLVMGetCallBrIndirectDest(LLVMValueRef CallBr, unsigned Idx) {
3047+
return wrap(unwrap<CallBrInst>(CallBr)->getIndirectDest(Idx));
3048+
}
3049+
30343050
/*--.. Operations on terminators ...........................................--*/
30353051

30363052
unsigned LLVMGetNumSuccessors(LLVMValueRef Term) {
@@ -3258,6 +3274,25 @@ LLVMValueRef LLVMBuildIndirectBr(LLVMBuilderRef B, LLVMValueRef Addr,
32583274
return wrap(unwrap(B)->CreateIndirectBr(unwrap(Addr), NumDests));
32593275
}
32603276

3277+
LLVMValueRef LLVMBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
3278+
LLVMBasicBlockRef DefaultDest,
3279+
LLVMBasicBlockRef *IndirectDests,
3280+
unsigned NumIndirectDests, LLVMValueRef *Args,
3281+
unsigned NumArgs, LLVMOperandBundleRef *Bundles,
3282+
unsigned NumBundles, const char *Name) {
3283+
3284+
SmallVector<OperandBundleDef, 8> OBs;
3285+
for (auto *Bundle : ArrayRef(Bundles, NumBundles)) {
3286+
OperandBundleDef *OB = unwrap(Bundle);
3287+
OBs.push_back(*OB);
3288+
}
3289+
3290+
return wrap(unwrap(B)->CreateCallBr(
3291+
unwrap<FunctionType>(Ty), unwrap(Fn), unwrap(DefaultDest),
3292+
ArrayRef(unwrap(IndirectDests), NumIndirectDests),
3293+
ArrayRef<Value *>(unwrap(Args), NumArgs), OBs, Name));
3294+
}
3295+
32613296
LLVMValueRef LLVMBuildInvoke2(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
32623297
LLVMValueRef *Args, unsigned NumArgs,
32633298
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,

llvm/test/Bindings/llvm-c/echo.ll

+26
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,32 @@ define void @test_func_prologue_data_01() prologue %func_prolog_struct <{ i8 235
348348
ret void
349349
}
350350

351+
352+
define void @test_call_br_01(i32 %input) {
353+
entry:
354+
callbr void asm "nop", "r,!i"(i32 %input) to label %bb_01 [label %bb_02]
355+
356+
bb_01:
357+
ret void
358+
bb_02:
359+
ret void
360+
}
361+
362+
define void @test_call_br_02(i32 %input0, i32 %input1) {
363+
entry:
364+
; Multiple indirect destinations, operand bundles, and arguments
365+
callbr void asm "nop", "r,r,!i,!i"(i32 %input0, i32 %input1)
366+
["op0"(i32 %input1), "op1"(label %bb_02)]
367+
to label %bb_01 [label %bb_03, label %bb_02]
368+
369+
bb_01:
370+
ret void
371+
bb_02:
372+
ret void
373+
bb_03:
374+
ret void
375+
}
376+
351377
!llvm.dbg.cu = !{!0, !2}
352378
!llvm.module.flags = !{!3}
353379

llvm/tools/llvm-c-test/echo.cpp

+40
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,46 @@ struct FunCloner {
570570
LLVMDisposeOperandBundle(Bundle);
571571
break;
572572
}
573+
case LLVMCallBr: {
574+
LLVMTypeRef FnTy = CloneType(LLVMGetCalledFunctionType(Src));
575+
LLVMValueRef Fn = CloneValue(LLVMGetCalledValue(Src));
576+
577+
LLVMBasicBlockRef DefaultDest =
578+
DeclareBB(LLVMGetCallBrDefaultDest(Src));
579+
580+
// Clone indirect destinations
581+
SmallVector<LLVMBasicBlockRef, 8> IndirectDests;
582+
unsigned IndirectDestCount = LLVMGetCallBrNumIndirectDests(Src);
583+
for (unsigned i = 0; i < IndirectDestCount; ++i)
584+
IndirectDests.push_back(DeclareBB(LLVMGetCallBrIndirectDest(Src, i)));
585+
586+
// Clone input arguments
587+
SmallVector<LLVMValueRef, 8> Args;
588+
unsigned ArgCount = LLVMGetNumArgOperands(Src);
589+
for (unsigned i = 0; i < ArgCount; ++i)
590+
Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
591+
592+
// Clone operand bundles
593+
SmallVector<LLVMOperandBundleRef, 8> Bundles;
594+
unsigned BundleCount = LLVMGetNumOperandBundles(Src);
595+
for (unsigned i = 0; i < BundleCount; ++i) {
596+
auto Bundle = LLVMGetOperandBundleAtIndex(Src, i);
597+
Bundles.push_back(CloneOB(Bundle));
598+
LLVMDisposeOperandBundle(Bundle);
599+
}
600+
601+
Dst = LLVMBuildCallBr(Builder, FnTy, Fn, DefaultDest,
602+
IndirectDests.data(), IndirectDests.size(),
603+
Args.data(), Args.size(), Bundles.data(),
604+
Bundles.size(), Name);
605+
606+
CloneAttrs(Src, Dst);
607+
608+
for (auto Bundle : Bundles)
609+
LLVMDisposeOperandBundle(Bundle);
610+
611+
break;
612+
}
573613
case LLVMUnreachable:
574614
Dst = LLVMBuildUnreachable(Builder);
575615
break;

0 commit comments

Comments
 (0)