diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index fcb671cf1dfa20..6b70146efe8246 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -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 ------------------------------------- diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index a575ec3709fe4b..7cb809d378c957 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -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); + /** * @} */ @@ -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. * @@ -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 */ @@ -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); diff --git a/llvm/include/llvm-c/Types.h b/llvm/include/llvm-c/Types.h index 4e9967372d79f5..d5474d986309fa 100644 --- a/llvm/include/llvm-c/Types.h +++ b/llvm/include/llvm-c/Types.h @@ -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. * diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index 7832028bf36711..96629de8a7534e 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -43,6 +43,8 @@ using namespace llvm; +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OperandBundleDef, LLVMOperandBundleRef) + #define DEBUG_TYPE "ir" void llvm::initializeCore(PassRegistry &Registry) { @@ -2567,6 +2569,34 @@ void LLVMRemoveGlobalIFunc(LLVMValueRef IFunc) { unwrap(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) { @@ -2858,6 +2888,16 @@ LLVMTypeRef LLVMGetCalledFunctionType(LLVMValueRef Instr) { return wrap(unwrap(Instr)->getFunctionType()); } +unsigned LLVMGetNumOperandBundles(LLVMValueRef C) { + return unwrap(C)->getNumOperandBundles(); +} + +LLVMOperandBundleRef LLVMGetOperandBundleAtIndex(LLVMValueRef C, + unsigned Index) { + return wrap( + new OperandBundleDef(unwrap(C)->getOperandBundleAt(Index))); +} + /*--.. Operations on call instructions (only) ..............................--*/ LLVMBool LLVMIsTailCall(LLVMValueRef Call) { @@ -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 OBs; + for (auto *Bundle : ArrayRef(Bundles, NumBundles)) { + OperandBundleDef *OB = unwrap(Bundle); + OBs.push_back(*OB); + } + return wrap(unwrap(B)->CreateInvoke( + unwrap(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) { @@ -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(Ty); + SmallVector 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) { diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll index 0775cbb673e4ee..2e195beebd7bb3 100644 --- a/llvm/test/Bindings/llvm-c/echo.ll +++ b/llvm/test/Bindings/llvm-c/echo.ll @@ -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 } diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index e2617583ff9bab..bfc14e85a12bff 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -548,16 +548,26 @@ struct FunCloner { break; case LLVMInvoke: { SmallVector Args; - int ArgCount = LLVMGetNumArgOperands(Src); - for (int i = 0; i < ArgCount; i++) + SmallVector 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: @@ -764,14 +774,25 @@ struct FunCloner { } case LLVMCall: { SmallVector Args; - int ArgCount = LLVMGetNumArgOperands(Src); - for (int i = 0; i < ArgCount; i++) + SmallVector 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: { @@ -935,6 +956,17 @@ struct FunCloner { return VMap[Src] = Dst; } + LLVMOperandBundleRef CloneOB(LLVMOperandBundleRef Src) { + size_t TagLen; + const char *Tag = LLVMGetOperandBundleTag(Src, &TagLen); + + SmallVector 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. {