Skip to content

Commit

Permalink
[LLVM-C] Support operand bundles (#73914)
Browse files Browse the repository at this point in the history
Added the following functions for manipulating operand bundles, as well as
building ``call`` and ``invoke`` instructions that use operand bundles:

  * LLVMBuildCallWithOperandBundles
  * LLVMBuildInvokeWithOperandBundles
  * LLVMCreateOperandBundle
  * LLVMDisposeOperandBundle
  * LLVMGetNumOperandBundles
  * LLVMGetOperandBundleAtIndex
  * LLVMGetNumOperandBundleArgs
  * LLVMGetOperandBundleArgAtIndex
  * LLVMGetOperandBundleTag

Fixes #71873.
  • Loading branch information
HertzDevil authored Dec 11, 2023
1 parent bd3e8eb commit 86763a8
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 7 deletions.
13 changes: 13 additions & 0 deletions llvm/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,19 @@ Changes to the C API
on zext instructions, and ``LLVMGetIsDisjoint`` and ``LLVMSetIsDisjoint``
for getting/setting the new disjoint flag on or instructions.

* Added the following functions for manipulating operand bundles, as well as
building ``call`` and ``invoke`` instructions that use operand bundles:

* ``LLVMBuildCallWithOperandBundles``
* ``LLVMBuildInvokeWithOperandBundles``
* ``LLVMCreateOperandBundle``
* ``LLVMDisposeOperandBundle``
* ``LLVMGetNumOperandBundles``
* ``LLVMGetOperandBundleAtIndex``
* ``LLVMGetNumOperandBundleArgs``
* ``LLVMGetOperandBundleArgAtIndex``
* ``LLVMGetOperandBundleTag``

Changes to the CodeGen infrastructure
-------------------------------------

Expand Down
95 changes: 95 additions & 0 deletions llvm/include/llvm-c/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -3000,6 +3000,74 @@ LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals,
/** Deprecated: Use LLVMMDNodeInContext2 instead. */
LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count);

/**
* @}
*/

/**
* @defgroup LLVMCCoreOperandBundle Operand Bundles
*
* Functions in this group operate on LLVMOperandBundleRef instances that
* correspond to llvm::OperandBundleDef instances.
*
* @see llvm::OperandBundleDef
*
* @{
*/

/**
* Create a new operand bundle.
*
* Every invocation should be paired with LLVMDisposeOperandBundle() or memory
* will be leaked.
*
* @param Tag Tag name of the operand bundle
* @param TagLen Length of Tag
* @param Args Memory address of an array of bundle operands
* @param NumArgs Length of Args
*/
LLVMOperandBundleRef LLVMCreateOperandBundle(const char *Tag, size_t TagLen,
LLVMValueRef *Args,
unsigned NumArgs);

/**
* Destroy an operand bundle.
*
* This must be called for every created operand bundle or memory will be
* leaked.
*/
void LLVMDisposeOperandBundle(LLVMOperandBundleRef Bundle);

/**
* Obtain the tag of an operand bundle as a string.
*
* @param Bundle Operand bundle to obtain tag of.
* @param Len Out parameter which holds the length of the returned string.
* @return The tag name of Bundle.
* @see OperandBundleDef::getTag()
*/
const char *LLVMGetOperandBundleTag(LLVMOperandBundleRef Bundle, size_t *Len);

/**
* Obtain the number of operands for an operand bundle.
*
* @param Bundle Operand bundle to obtain operand count of.
* @return The number of operands.
* @see OperandBundleDef::input_size()
*/
unsigned LLVMGetNumOperandBundleArgs(LLVMOperandBundleRef Bundle);

/**
* Obtain the operand for an operand bundle at the given index.
*
* @param Bundle Operand bundle to obtain operand of.
* @param Index An operand index, must be less than
* LLVMGetNumOperandBundleArgs().
* @return The operand.
*/
LLVMValueRef LLVMGetOperandBundleArgAtIndex(LLVMOperandBundleRef Bundle,
unsigned Index);

/**
* @}
*/
Expand Down Expand Up @@ -3451,6 +3519,24 @@ LLVMTypeRef LLVMGetCalledFunctionType(LLVMValueRef C);
*/
LLVMValueRef LLVMGetCalledValue(LLVMValueRef Instr);

/**
* Obtain the number of operand bundles attached to this instruction.
*
* This only works on llvm::CallInst and llvm::InvokeInst instructions.
*
* @see llvm::CallBase::getNumOperandBundles()
*/
unsigned LLVMGetNumOperandBundles(LLVMValueRef C);

/**
* Obtain the operand bundle attached to this instruction at the given index.
* Use LLVMDisposeOperandBundle to free the operand bundle.
*
* This only works on llvm::CallInst and llvm::InvokeInst instructions.
*/
LLVMOperandBundleRef LLVMGetOperandBundleAtIndex(LLVMValueRef C,
unsigned Index);

/**
* Obtain whether a call instruction is a tail call.
*
Expand Down Expand Up @@ -3815,6 +3901,10 @@ LLVMValueRef LLVMBuildInvoke2(LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
const char *Name);
LLVMValueRef LLVMBuildInvokeWithOperandBundles(
LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef Fn, LLVMValueRef *Args,
unsigned NumArgs, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
LLVMOperandBundleRef *Bundles, unsigned NumBundles, const char *Name);
LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef);

/* Exception Handling */
Expand Down Expand Up @@ -4121,6 +4211,11 @@ LLVMValueRef LLVMBuildPhi(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name);
LLVMValueRef LLVMBuildCall2(LLVMBuilderRef, LLVMTypeRef, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
const char *Name);
LLVMValueRef
LLVMBuildCallWithOperandBundles(LLVMBuilderRef, LLVMTypeRef, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
LLVMOperandBundleRef *Bundles,
unsigned NumBundles, const char *Name);
LLVMValueRef LLVMBuildSelect(LLVMBuilderRef, LLVMValueRef If,
LLVMValueRef Then, LLVMValueRef Else,
const char *Name);
Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm-c/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ typedef struct LLVMOpaquePassManager *LLVMPassManagerRef;
* @see llvm::Use */
typedef struct LLVMOpaqueUse *LLVMUseRef;

/**
* @see llvm::OperandBundleDef
*/
typedef struct LLVMOpaqueOperandBundle *LLVMOperandBundleRef;

/**
* Used to represent an attributes.
*
Expand Down
69 changes: 69 additions & 0 deletions llvm/lib/IR/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@

using namespace llvm;

DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OperandBundleDef, LLVMOperandBundleRef)

#define DEBUG_TYPE "ir"

void llvm::initializeCore(PassRegistry &Registry) {
Expand Down Expand Up @@ -2567,6 +2569,34 @@ void LLVMRemoveGlobalIFunc(LLVMValueRef IFunc) {
unwrap<GlobalIFunc>(IFunc)->removeFromParent();
}

/*--.. Operations on operand bundles........................................--*/

LLVMOperandBundleRef LLVMCreateOperandBundle(const char *Tag, size_t TagLen,
LLVMValueRef *Args,
unsigned NumArgs) {
return wrap(new OperandBundleDef(std::string(Tag, TagLen),
ArrayRef(unwrap(Args), NumArgs)));
}

void LLVMDisposeOperandBundle(LLVMOperandBundleRef Bundle) {
delete unwrap(Bundle);
}

const char *LLVMGetOperandBundleTag(LLVMOperandBundleRef Bundle, size_t *Len) {
StringRef Str = unwrap(Bundle)->getTag();
*Len = Str.size();
return Str.data();
}

unsigned LLVMGetNumOperandBundleArgs(LLVMOperandBundleRef Bundle) {
return unwrap(Bundle)->inputs().size();
}

LLVMValueRef LLVMGetOperandBundleArgAtIndex(LLVMOperandBundleRef Bundle,
unsigned Index) {
return wrap(unwrap(Bundle)->inputs()[Index]);
}

/*--.. Operations on basic blocks ..........................................--*/

LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB) {
Expand Down Expand Up @@ -2858,6 +2888,16 @@ LLVMTypeRef LLVMGetCalledFunctionType(LLVMValueRef Instr) {
return wrap(unwrap<CallBase>(Instr)->getFunctionType());
}

unsigned LLVMGetNumOperandBundles(LLVMValueRef C) {
return unwrap<CallBase>(C)->getNumOperandBundles();
}

LLVMOperandBundleRef LLVMGetOperandBundleAtIndex(LLVMValueRef C,
unsigned Index) {
return wrap(
new OperandBundleDef(unwrap<CallBase>(C)->getOperandBundleAt(Index)));
}

/*--.. Operations on call instructions (only) ..............................--*/

LLVMBool LLVMIsTailCall(LLVMValueRef Call) {
Expand Down Expand Up @@ -3140,6 +3180,20 @@ LLVMValueRef LLVMBuildInvoke2(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
ArrayRef(unwrap(Args), NumArgs), Name));
}

LLVMValueRef LLVMBuildInvokeWithOperandBundles(
LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, LLVMValueRef *Args,
unsigned NumArgs, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
LLVMOperandBundleRef *Bundles, unsigned NumBundles, const char *Name) {
SmallVector<OperandBundleDef, 8> OBs;
for (auto *Bundle : ArrayRef(Bundles, NumBundles)) {
OperandBundleDef *OB = unwrap(Bundle);
OBs.push_back(*OB);
}
return wrap(unwrap(B)->CreateInvoke(
unwrap<FunctionType>(Ty), unwrap(Fn), unwrap(Then), unwrap(Catch),
ArrayRef(unwrap(Args), NumArgs), OBs, Name));
}

LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef PersFn, unsigned NumClauses,
const char *Name) {
Expand Down Expand Up @@ -3878,6 +3932,21 @@ LLVMValueRef LLVMBuildCall2(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
ArrayRef(unwrap(Args), NumArgs), Name));
}

LLVMValueRef
LLVMBuildCallWithOperandBundles(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef Fn, LLVMValueRef *Args,
unsigned NumArgs, LLVMOperandBundleRef *Bundles,
unsigned NumBundles, const char *Name) {
FunctionType *FTy = unwrap<FunctionType>(Ty);
SmallVector<OperandBundleDef, 8> OBs;
for (auto *Bundle : ArrayRef(Bundles, NumBundles)) {
OperandBundleDef *OB = unwrap(Bundle);
OBs.push_back(*OB);
}
return wrap(unwrap(B)->CreateCall(
FTy, unwrap(Fn), ArrayRef(unwrap(Args), NumArgs), OBs, Name));
}

LLVMValueRef LLVMBuildSelect(LLVMBuilderRef B, LLVMValueRef If,
LLVMValueRef Then, LLVMValueRef Else,
const char *Name) {
Expand Down
11 changes: 11 additions & 0 deletions llvm/test/Bindings/llvm-c/echo.ll
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,17 @@ exit:
ret void
}

define void @operandbundles() personality ptr @personalityFn {
call void @decl() [ "foo"(), "bar\00x"(i32 0, ptr null, token none) ]
invoke void @decl() [ "baz"(label %bar) ] to label %foo unwind label %bar
foo:
ret void
bar:
%1 = landingpad { ptr, i32 }
cleanup
ret void
}

define void @with_debuginfo() !dbg !4 {
ret void, !dbg !7
}
Expand Down
46 changes: 39 additions & 7 deletions llvm/tools/llvm-c-test/echo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -548,16 +548,26 @@ struct FunCloner {
break;
case LLVMInvoke: {
SmallVector<LLVMValueRef, 8> Args;
int ArgCount = LLVMGetNumArgOperands(Src);
for (int i = 0; i < ArgCount; i++)
SmallVector<LLVMOperandBundleRef, 8> Bundles;
unsigned ArgCount = LLVMGetNumArgOperands(Src);
for (unsigned i = 0; i < ArgCount; ++i)
Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
unsigned BundleCount = LLVMGetNumOperandBundles(Src);
for (unsigned i = 0; i < BundleCount; ++i) {
auto Bundle = LLVMGetOperandBundleAtIndex(Src, i);
Bundles.push_back(CloneOB(Bundle));
LLVMDisposeOperandBundle(Bundle);
}
LLVMTypeRef FnTy = CloneType(LLVMGetCalledFunctionType(Src));
LLVMValueRef Fn = CloneValue(LLVMGetCalledValue(Src));
LLVMBasicBlockRef Then = DeclareBB(LLVMGetNormalDest(Src));
LLVMBasicBlockRef Unwind = DeclareBB(LLVMGetUnwindDest(Src));
Dst = LLVMBuildInvoke2(Builder, FnTy, Fn, Args.data(), ArgCount,
Then, Unwind, Name);
Dst = LLVMBuildInvokeWithOperandBundles(
Builder, FnTy, Fn, Args.data(), ArgCount, Then, Unwind,
Bundles.data(), Bundles.size(), Name);
CloneAttrs(Src, Dst);
for (auto Bundle : Bundles)
LLVMDisposeOperandBundle(Bundle);
break;
}
case LLVMUnreachable:
Expand Down Expand Up @@ -764,14 +774,25 @@ struct FunCloner {
}
case LLVMCall: {
SmallVector<LLVMValueRef, 8> Args;
int ArgCount = LLVMGetNumArgOperands(Src);
for (int i = 0; i < ArgCount; i++)
SmallVector<LLVMOperandBundleRef, 8> Bundles;
unsigned ArgCount = LLVMGetNumArgOperands(Src);
for (unsigned i = 0; i < ArgCount; ++i)
Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
unsigned BundleCount = LLVMGetNumOperandBundles(Src);
for (unsigned i = 0; i < BundleCount; ++i) {
auto Bundle = LLVMGetOperandBundleAtIndex(Src, i);
Bundles.push_back(CloneOB(Bundle));
LLVMDisposeOperandBundle(Bundle);
}
LLVMTypeRef FnTy = CloneType(LLVMGetCalledFunctionType(Src));
LLVMValueRef Fn = CloneValue(LLVMGetCalledValue(Src));
Dst = LLVMBuildCall2(Builder, FnTy, Fn, Args.data(), ArgCount, Name);
Dst = LLVMBuildCallWithOperandBundles(Builder, FnTy, Fn, Args.data(),
ArgCount, Bundles.data(),
Bundles.size(), Name);
LLVMSetTailCallKind(Dst, LLVMGetTailCallKind(Src));
CloneAttrs(Src, Dst);
for (auto Bundle : Bundles)
LLVMDisposeOperandBundle(Bundle);
break;
}
case LLVMResume: {
Expand Down Expand Up @@ -935,6 +956,17 @@ struct FunCloner {
return VMap[Src] = Dst;
}

LLVMOperandBundleRef CloneOB(LLVMOperandBundleRef Src) {
size_t TagLen;
const char *Tag = LLVMGetOperandBundleTag(Src, &TagLen);

SmallVector<LLVMValueRef, 8> Args;
for (unsigned i = 0, n = LLVMGetNumOperandBundleArgs(Src); i != n; ++i)
Args.push_back(CloneValue(LLVMGetOperandBundleArgAtIndex(Src, i)));

return LLVMCreateOperandBundle(Tag, TagLen, Args.data(), Args.size());
}

LLVMBasicBlockRef DeclareBB(LLVMBasicBlockRef Src) {
// Check if this is something we already computed.
{
Expand Down

0 comments on commit 86763a8

Please sign in to comment.