Skip to content

Commit

Permalink
Add support for LLVM 12 (#10873)
Browse files Browse the repository at this point in the history
Co-authored-by: Sijawusz Pur Rahnama <[email protected]>
Co-authored-by: Max Fierke <[email protected]>
  • Loading branch information
3 people authored Aug 2, 2021
1 parent 55ebfbf commit 23acc03
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 12 deletions.
7 changes: 6 additions & 1 deletion spec/compiler/codegen/c_abi/c_abi_x86_64_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,12 @@ require "../../../spec_helper"
))
str = mod.to_s
str.scan(/sret/).size.should eq(2)
str.should contain("sret, i32") # sret goes as first argument

if LibLLVM::IS_LT_120
str.should contain("sret, i32") # sret goes as first argument
else
str.should contain("sret(%\"struct.LibFoo::Struct\") %0, i32") # sret goes as first argument
end
end
end
{% end %}
6 changes: 3 additions & 3 deletions src/compiler/crystal/codegen/call.cr
Original file line number Diff line number Diff line change
Expand Up @@ -586,12 +586,12 @@ class Crystal::CodeGenVisitor

abi_arg_type = abi_info.arg_types[i]?
if abi_arg_type && (attr = abi_arg_type.attr)
@last.add_instruction_attribute(i + arg_offset, attr, llvm_context)
@last.add_instruction_attribute(i + arg_offset, attr, llvm_context, abi_arg_type.type)
end
end

if sret
@last.add_instruction_attribute(1, LLVM::Attribute::StructRet, llvm_context)
@last.add_instruction_attribute(1, LLVM::Attribute::StructRet, llvm_context, abi_info.return_type.type)
end
end

Expand All @@ -605,7 +605,7 @@ class Crystal::CodeGenVisitor
arg_types = fun_type.try(&.arg_types) || target_def.try &.args.map &.type
arg_types.try &.each_with_index do |arg_type, i|
if abi_info && (abi_arg_type = abi_info.arg_types[i]?) && (attr = abi_arg_type.attr)
@last.add_instruction_attribute(i + arg_offset, attr, llvm_context)
@last.add_instruction_attribute(i + arg_offset, attr, llvm_context, abi_arg_type.type)
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/crystal/codegen/fun.cr
Original file line number Diff line number Diff line change
Expand Up @@ -365,15 +365,15 @@ class Crystal::CodeGenVisitor
abi_arg_type = abi_info.arg_types[i]

if attr = abi_arg_type.attr
context.fun.add_attribute(attr, i + offset + 1)
context.fun.add_attribute(attr, i + offset + 1, abi_arg_type.type)
end

i += 1 unless abi_arg_type.kind == LLVM::ABI::ArgKind::Ignore
end

# This is for sret
if (attr = abi_info.return_type.attr) && attr == LLVM::Attribute::StructRet
context.fun.add_attribute(attr, 1)
context.fun.add_attribute(attr, 1, abi_info.return_type.type)
end

args
Expand Down
18 changes: 18 additions & 0 deletions src/llvm/enums.cr
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ module LLVM
ZExt

@@kind_ids = load_llvm_kinds_from_names.as(Hash(Attribute, UInt32))
@@typed_attrs = load_llvm_typed_attributes.as(Array(Attribute))

def each_kind(&block)
return if value == 0
Expand Down Expand Up @@ -137,13 +138,30 @@ module LLVM
kinds
end

private def self.load_llvm_typed_attributes
typed_attrs = [] of Attribute

unless LibLLVM::IS_LT_120
# LLVM 12 introduced mandatory type parameters for byval and sret
typed_attrs << ByVal
typed_attrs << StructRet
end

typed_attrs
end

def self.kind_for(member)
@@kind_ids[member]
end

def self.from_kind(kind)
@@kind_ids.key_for(kind)
end

def self.requires_type?(kind)
member = from_kind(kind)
@@typed_attrs.includes?(member)
end
end
{% else %}
@[Flags]
Expand Down
2 changes: 1 addition & 1 deletion src/llvm/ext/llvm-versions.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
11.1 11.0 10.0 9.0 8.0 7.1 6.0 5.0 4.0 3.9 3.8
12.0 11.1 11.0 10.0 9.0 8.0 7.1 6.0 5.0 4.0 3.9 3.8
25 changes: 25 additions & 0 deletions src/llvm/ext/llvm_ext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -351,11 +351,36 @@ void LLVMMetadataReplaceAllUsesWith2(
void LLVMExtSetCurrentDebugLocation(
LLVMBuilderRef Bref, unsigned Line, unsigned Col, LLVMMetadataRef Scope,
LLVMMetadataRef InlinedAt) {
#if LLVM_VERSION_GE(12, 0)
if (!Scope)
unwrap(Bref)->SetCurrentDebugLocation(DebugLoc());
else
unwrap(Bref)->SetCurrentDebugLocation(
DILocation::get(unwrap<MDNode>(Scope)->getContext(), Line, Col,
unwrapDI<DILocalScope>(Scope),
unwrapDI<DILocation>(InlinedAt)));
#else
unwrap(Bref)->SetCurrentDebugLocation(
DebugLoc::get(Line, Col, Scope ? unwrap<MDNode>(Scope) : nullptr,
InlinedAt ? unwrap<MDNode>(InlinedAt) : nullptr));
#endif
}

#if LLVM_VERSION_GE(3, 9)
// A backported LLVMCreateTypeAttribute for LLVM < 13
// from https://github.com/llvm/llvm-project/blob/bb8ce25e88218be60d2a4ea9c9b0b721809eff27/llvm/lib/IR/Core.cpp#L167
LLVMAttributeRef LLVMExtCreateTypeAttribute(
LLVMContextRef C, unsigned KindID, LLVMTypeRef Ty) {
auto &Ctx = *unwrap(C);
auto AttrKind = (Attribute::AttrKind)KindID;
#if LLVM_VERSION_GE(12, 0)
return wrap(Attribute::get(Ctx, AttrKind, unwrap(Ty)));
#else
return wrap(Attribute::get(Ctx, AttrKind));
#endif
}
#endif

LLVMValueRef LLVMExtBuildCmpxchg(
LLVMBuilderRef B, LLVMValueRef PTR, LLVMValueRef Cmp, LLVMValueRef New,
LLVMAtomicOrdering SuccessOrdering, LLVMAtomicOrdering FailureOrdering) {
Expand Down
8 changes: 6 additions & 2 deletions src/llvm/function.cr
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ struct LLVM::Function
LibLLVM.set_function_call_convention(self, cc)
end

def add_attribute(attribute : Attribute, index = AttributeIndex::FunctionIndex)
def add_attribute(attribute : Attribute, index = AttributeIndex::FunctionIndex, type : Type? = nil)
return if attribute.value == 0
{% if LibLLVM.has_constant?(:AttributeRef) %}
context = LibLLVM.get_module_context(LibLLVM.get_global_parent(self))
attribute.each_kind do |kind|
attribute_ref = LibLLVM.create_enum_attribute(context, kind, 0)
if type && LLVM::Attribute.requires_type?(kind)
attribute_ref = LibLLVMExt.create_type_attribute(context, kind, type)
else
attribute_ref = LibLLVM.create_enum_attribute(context, kind, 0)
end
LibLLVM.add_attribute_at_index(self, index, attribute_ref)
end
{% else %}
Expand Down
6 changes: 5 additions & 1 deletion src/llvm/lib_llvm.cr
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ end

{% begin %}
lib LibLLVM
IS_120 = {{LibLLVM::VERSION.starts_with?("12.0")}}
IS_110 = {{LibLLVM::VERSION.starts_with?("11.0")}}
IS_100 = {{LibLLVM::VERSION.starts_with?("10.0")}}
IS_90 = {{LibLLVM::VERSION.starts_with?("9.0")}}
Expand All @@ -33,7 +34,10 @@ end

IS_LT_70 = IS_38 || IS_39 || IS_40 || IS_50 || IS_60
IS_LT_80 = IS_LT_70 || IS_70 || IS_71
IS_LT_110 = IS_LT_80 || IS_90 || IS_100
IS_LT_90 = IS_LT_80 || IS_80
IS_LT_100 = IS_LT_90 || IS_90
IS_LT_110 = IS_LT_100 || IS_100
IS_LT_120 = IS_LT_110 || IS_110
end
{% end %}

Expand Down
5 changes: 5 additions & 0 deletions src/llvm/lib_llvm_ext.cr
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,9 @@ lib LibLLVMExt

fun target_machine_enable_global_isel = LLVMExtTargetMachineEnableGlobalIsel(machine : LibLLVM::TargetMachineRef, enable : Bool)
fun create_mc_jit_compiler_for_module = LLVMExtCreateMCJITCompilerForModule(jit : LibLLVM::ExecutionEngineRef*, m : LibLLVM::ModuleRef, options : LibLLVM::JITCompilerOptions*, options_length : UInt32, enable_global_isel : Bool, error : UInt8**) : Int32

{% unless LibLLVM::IS_38 %}
# LLVMCreateTypeAttribute is implemented in LLVM 13, but needed in 12
fun create_type_attribute = LLVMExtCreateTypeAttribute(ctx : LibLLVM::ContextRef, kind_id : LibC::UInt, ty : LibLLVM::TypeRef) : LibLLVM::AttributeRef
{% end %}
end
9 changes: 7 additions & 2 deletions src/llvm/value_methods.cr
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,16 @@ module LLVM::ValueMethods
LibLLVM.get_value_kind(self)
end

def add_instruction_attribute(index : Int, attribute : LLVM::Attribute, context : LLVM::Context)
def add_instruction_attribute(index : Int, attribute : LLVM::Attribute, context : LLVM::Context, type : LLVM::Type? = nil)
return if attribute.value == 0
{% if LibLLVM.has_constant?(:AttributeRef) %}
attribute.each_kind do |kind|
attribute_ref = LibLLVM.create_enum_attribute(context, kind, 0)
if type && LLVM::Attribute.requires_type?(kind)
attribute_ref = LibLLVMExt.create_type_attribute(context, kind, type)
else
attribute_ref = LibLLVM.create_enum_attribute(context, kind, 0)
end

LibLLVM.add_call_site_attribute(self, index, attribute_ref)
end
{% else %}
Expand Down

0 comments on commit 23acc03

Please sign in to comment.