Skip to content

Commit

Permalink
Support the operand bundle API from LLVM 18 (#14082)
Browse files Browse the repository at this point in the history
  • Loading branch information
HertzDevil authored Dec 15, 2023
1 parent e5ab06e commit c53dd72
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 40 deletions.
22 changes: 17 additions & 5 deletions src/llvm/builder.cr
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ class LLVM::Builder
# check_func(func)
# check_values(args)

Value.new LibLLVMExt.build_call2(self, func.function_type, func, (args.to_unsafe.as(LibLLVM::ValueRef*)), args.size, bundle, name)
bundle_ref = bundle.to_unsafe
bundles = bundle_ref ? pointerof(bundle_ref) : Pointer(Void).null.as(LibLLVM::OperandBundleRef*)
num_bundles = bundle_ref ? 1 : 0
Value.new {{ LibLLVM::IS_LT_180 ? LibLLVMExt : LibLLVM }}.build_call_with_operand_bundles(self, func.function_type, func, (args.to_unsafe.as(LibLLVM::ValueRef*)), args.size, bundles, num_bundles, name)
end

def call(type : LLVM::Type, func : LLVM::Function, args : Array(LLVM::Value), name : String = "")
Expand All @@ -102,7 +105,10 @@ class LLVM::Builder
# check_func(func)
# check_values(args)

Value.new LibLLVMExt.build_call2(self, type, func, (args.to_unsafe.as(LibLLVM::ValueRef*)), args.size, bundle, name)
bundle_ref = bundle.to_unsafe
bundles = bundle_ref ? pointerof(bundle_ref) : Pointer(Void).null.as(LibLLVM::OperandBundleRef*)
num_bundles = bundle_ref ? 1 : 0
Value.new {{ LibLLVM::IS_LT_180 ? LibLLVMExt : LibLLVM }}.build_call_with_operand_bundles(self, type, func, (args.to_unsafe.as(LibLLVM::ValueRef*)), args.size, bundles, num_bundles, name)
end

def call(type : LLVM::Type, func : LLVM::Function, args : Array(LLVM::Value), bundle : LLVM::OperandBundleDef)
Expand Down Expand Up @@ -279,7 +285,7 @@ class LLVM::Builder
end

def build_operand_bundle_def(name, values : Array(LLVM::Value))
LLVM::OperandBundleDef.new LibLLVMExt.build_operand_bundle_def(name, values.to_unsafe.as(LibLLVM::ValueRef*), values.size)
LLVM::OperandBundleDef.new {{ LibLLVM::IS_LT_180 ? LibLLVMExt : LibLLVM }}.create_operand_bundle(name, name.bytesize, values.to_unsafe.as(LibLLVM::ValueRef*), values.size)
end

def build_catch_ret(pad, basic_block)
Expand All @@ -290,7 +296,10 @@ class LLVM::Builder
def invoke(fn : LLVM::Function, args : Array(LLVM::Value), a_then, a_catch, bundle : LLVM::OperandBundleDef = LLVM::OperandBundleDef.null, name = "")
# check_func(fn)

Value.new LibLLVMExt.build_invoke2 self, fn.function_type, fn, (args.to_unsafe.as(LibLLVM::ValueRef*)), args.size, a_then, a_catch, bundle, name
bundle_ref = bundle.to_unsafe
bundles = bundle_ref ? pointerof(bundle_ref) : Pointer(Void).null.as(LibLLVM::OperandBundleRef*)
num_bundles = bundle_ref ? 1 : 0
Value.new {{ LibLLVM::IS_LT_180 ? LibLLVMExt : LibLLVM }}.build_invoke_with_operand_bundles(self, fn.function_type, fn, (args.to_unsafe.as(LibLLVM::ValueRef*)), args.size, a_then, a_catch, bundles, num_bundles, name)
end

def invoke(type : LLVM::Type, fn : LLVM::Function, args : Array(LLVM::Value), a_then, a_catch, *, name = "")
Expand All @@ -304,7 +313,10 @@ class LLVM::Builder
# check_type("invoke", type)
# check_func(fn)

Value.new LibLLVMExt.build_invoke2 self, type, fn, (args.to_unsafe.as(LibLLVM::ValueRef*)), args.size, a_then, a_catch, bundle, name
bundle_ref = bundle.to_unsafe
bundles = bundle_ref ? pointerof(bundle_ref) : Pointer(Void).null.as(LibLLVM::OperandBundleRef*)
num_bundles = bundle_ref ? 1 : 0
Value.new {{ LibLLVM::IS_LT_180 ? LibLLVMExt : LibLLVM }}.build_invoke_with_operand_bundles(self, type, fn, (args.to_unsafe.as(LibLLVM::ValueRef*)), args.size, a_then, a_catch, bundles, num_bundles, name)
end

def switch(value, otherwise, cases)
Expand Down
54 changes: 36 additions & 18 deletions src/llvm/ext/llvm_ext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ using namespace llvm;
#define makeArrayRef ArrayRef
#endif

#if !LLVM_VERSION_GE(18, 0)
typedef struct LLVMOpaqueOperandBundle *LLVMOperandBundleRef;
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OperandBundleDef, LLVMOperandBundleRef)
#endif

extern "C" {

#if !LLVM_VERSION_GE(9, 0)
Expand All @@ -32,30 +37,43 @@ void LLVMExtClearCurrentDebugLocation(LLVMBuilderRef B) {
}
#endif

OperandBundleDef *LLVMExtBuildOperandBundleDef(
const char *Name, LLVMValueRef *Inputs, unsigned NumInputs) {
return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
#if !LLVM_VERSION_GE(18, 0)
LLVMOperandBundleRef LLVMExtCreateOperandBundle(const char *Tag, size_t TagLen,
LLVMValueRef *Args,
unsigned NumArgs) {
return wrap(new OperandBundleDef(std::string(Tag, TagLen),
makeArrayRef(unwrap(Args), NumArgs)));
}

LLVMValueRef LLVMExtBuildCall2(
LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs,
OperandBundleDef *Bundle, const char *Name) {
unsigned Len = Bundle ? 1 : 0;
ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
LLVMValueRef
LLVMExtBuildCallWithOperandBundles(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 : makeArrayRef(Bundles, NumBundles)) {
OperandBundleDef *OB = unwrap(Bundle);
OBs.push_back(*OB);
}
return wrap(unwrap(B)->CreateCall(
(llvm::FunctionType*) unwrap(Ty), unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Bundles, Name));
FTy, unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), OBs, Name));
}

LLVMValueRef LLVMExtBuildInvoke2(
LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, OperandBundleDef *Bundle,
const char *Name) {
unsigned Len = Bundle ? 1 : 0;
ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
return wrap(unwrap(B)->CreateInvoke((llvm::FunctionType*) unwrap(Ty), unwrap(Fn), unwrap(Then), unwrap(Catch),
makeArrayRef(unwrap(Args), NumArgs),
Bundles, Name));
LLVMValueRef LLVMExtBuildInvokeWithOperandBundles(
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 : makeArrayRef(Bundles, NumBundles)) {
OperandBundleDef *OB = unwrap(Bundle);
OBs.push_back(*OB);
}
return wrap(unwrap(B)->CreateInvoke(
unwrap<FunctionType>(Ty), unwrap(Fn), unwrap(Then), unwrap(Catch),
makeArrayRef(unwrap(Args), NumArgs), OBs, Name));
}
#endif

#if !LLVM_VERSION_GE(18, 0)
static TargetMachine *unwrap(LLVMTargetMachineRef P) {
Expand Down
10 changes: 10 additions & 0 deletions src/llvm/lib_llvm/core.cr
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ lib LibLLVM
fun md_string_in_context = LLVMMDStringInContext(c : ContextRef, str : Char*, s_len : UInt) : ValueRef
fun md_node_in_context = LLVMMDNodeInContext(c : ContextRef, vals : ValueRef*, count : UInt) : ValueRef

{% unless LibLLVM::IS_LT_180 %}
fun create_operand_bundle = LLVMCreateOperandBundle(tag : Char*, tag_len : SizeT, args : ValueRef*, num_args : UInt) : OperandBundleRef
{% end %}

fun get_basic_block_name = LLVMGetBasicBlockName(bb : BasicBlockRef) : Char*
fun get_first_basic_block = LLVMGetFirstBasicBlock(fn : ValueRef) : BasicBlockRef
fun get_next_basic_block = LLVMGetNextBasicBlock(bb : BasicBlockRef) : BasicBlockRef
Expand Down Expand Up @@ -197,6 +201,9 @@ lib LibLLVM
fun build_cond = LLVMBuildCondBr(BuilderRef, if : ValueRef, then : BasicBlockRef, else : BasicBlockRef) : ValueRef
fun build_switch = LLVMBuildSwitch(BuilderRef, v : ValueRef, else : BasicBlockRef, num_cases : UInt) : ValueRef
fun build_invoke2 = LLVMBuildInvoke2(BuilderRef, ty : TypeRef, fn : ValueRef, args : ValueRef*, num_args : UInt, then : BasicBlockRef, catch : BasicBlockRef, name : Char*) : ValueRef
{% unless LibLLVM::IS_LT_180 %}
fun build_invoke_with_operand_bundles = LLVMBuildInvokeWithOperandBundles(BuilderRef, ty : TypeRef, fn : ValueRef, args : ValueRef*, num_args : UInt, then : BasicBlockRef, catch : BasicBlockRef, bundles : OperandBundleRef*, num_bundles : UInt, name : Char*) : ValueRef
{% end %}
fun build_unreachable = LLVMBuildUnreachable(BuilderRef) : ValueRef

fun build_landing_pad = LLVMBuildLandingPad(b : BuilderRef, ty : TypeRef, pers_fn : ValueRef, num_clauses : UInt, name : Char*) : ValueRef
Expand Down Expand Up @@ -260,6 +267,9 @@ lib LibLLVM

fun build_phi = LLVMBuildPhi(BuilderRef, ty : TypeRef, name : Char*) : ValueRef
fun build_call2 = LLVMBuildCall2(BuilderRef, TypeRef, fn : ValueRef, args : ValueRef*, num_args : UInt, name : Char*) : ValueRef
{% unless LibLLVM::IS_LT_180 %}
fun build_call_with_operand_bundles = LLVMBuildCallWithOperandBundles(BuilderRef, TypeRef, fn : ValueRef, args : ValueRef*, num_args : UInt, bundles : OperandBundleRef*, num_bundles : UInt, name : Char*) : ValueRef
{% end %}
fun build_select = LLVMBuildSelect(BuilderRef, if : ValueRef, then : ValueRef, else : ValueRef, name : Char*) : ValueRef
fun build_va_arg = LLVMBuildVAArg(BuilderRef, list : ValueRef, ty : TypeRef, name : Char*) : ValueRef
fun build_extract_value = LLVMBuildExtractValue(BuilderRef, agg_val : ValueRef, index : UInt, name : Char*) : ValueRef
Expand Down
1 change: 1 addition & 0 deletions src/llvm/lib_llvm/types.cr
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ lib LibLLVM
{% if LibLLVM::IS_LT_170 %}
type PassRegistryRef = Void*
{% end %}
type OperandBundleRef = Void*
type AttributeRef = Void*
end
27 changes: 12 additions & 15 deletions src/llvm/lib_llvm_ext.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,27 @@ lib LibLLVMExt
alias Char = LibC::Char
alias Int = LibC::Int
alias UInt = LibC::UInt

alias SizeT = LibC::SizeT

type OperandBundleDefRef = Void*

{% if LibLLVM::IS_LT_90 %}
fun di_builder_create_enumerator = LLVMExtDIBuilderCreateEnumerator(builder : LibLLVM::DIBuilderRef, name : Char*, name_len : SizeT, value : Int64, is_unsigned : LibLLVM::Bool) : LibLLVM::MetadataRef
fun clear_current_debug_location = LLVMExtClearCurrentDebugLocation(b : LibLLVM::BuilderRef)
{% end %}

fun build_operand_bundle_def = LLVMExtBuildOperandBundleDef(name : LibC::Char*,
input : LibLLVM::ValueRef*,
num_input : LibC::UInt) : LibLLVMExt::OperandBundleDefRef
fun create_operand_bundle = LLVMExtCreateOperandBundle(tag : Char*, tag_len : SizeT,
args : LibLLVM::ValueRef*,
num_args : UInt) : LibLLVM::OperandBundleRef

fun build_call2 = LLVMExtBuildCall2(builder : LibLLVM::BuilderRef, ty : LibLLVM::TypeRef, fn : LibLLVM::ValueRef,
args : LibLLVM::ValueRef*, arg_count : LibC::UInt,
bundle : LibLLVMExt::OperandBundleDefRef,
name : LibC::Char*) : LibLLVM::ValueRef
fun build_call_with_operand_bundles = LLVMExtBuildCallWithOperandBundles(LibLLVM::BuilderRef, LibLLVM::TypeRef, fn : LibLLVM::ValueRef,
args : LibLLVM::ValueRef*, num_args : UInt,
bundles : LibLLVM::OperandBundleRef*, num_bundles : UInt,
name : Char*) : LibLLVM::ValueRef

fun build_invoke2 = LLVMExtBuildInvoke2(builder : LibLLVM::BuilderRef, ty : LibLLVM::TypeRef, fn : LibLLVM::ValueRef,
args : LibLLVM::ValueRef*, arg_count : LibC::UInt,
then : LibLLVM::BasicBlockRef, catch : LibLLVM::BasicBlockRef,
bundle : LibLLVMExt::OperandBundleDefRef,
name : LibC::Char*) : LibLLVM::ValueRef
fun build_invoke_with_operand_bundles = LLVMExtBuildInvokeWithOperandBundles(LibLLVM::BuilderRef, ty : LibLLVM::TypeRef, fn : LibLLVM::ValueRef,
args : LibLLVM::ValueRef*, num_args : UInt,
then : LibLLVM::BasicBlockRef, catch : LibLLVM::BasicBlockRef,
bundles : LibLLVM::OperandBundleRef*, num_bundles : UInt,
name : Char*) : LibLLVM::ValueRef

fun set_target_machine_global_isel = LLVMExtSetTargetMachineGlobalISel(t : LibLLVM::TargetMachineRef, enable : LibLLVM::Bool)
end
4 changes: 2 additions & 2 deletions src/llvm/operand_bundle_def.cr
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
struct LLVM::OperandBundleDef
def initialize(@unwrap : LibLLVMExt::OperandBundleDefRef)
def initialize(@unwrap : LibLLVM::OperandBundleRef)
end

def self.null
LLVM::OperandBundleDef.new(Pointer(::Void).null.as(LibLLVMExt::OperandBundleDefRef))
new(Pointer(::Void).null.as(LibLLVM::OperandBundleRef))
end

def to_unsafe
Expand Down

0 comments on commit c53dd72

Please sign in to comment.