Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add 'wasm_import_module' option to the @[Link] annotation
Browse files Browse the repository at this point in the history
lbguilherme committed Mar 26, 2022
1 parent 458595f commit 711a9ce
Showing 7 changed files with 40 additions and 3 deletions.
4 changes: 4 additions & 0 deletions src/compiler/crystal/codegen/fun.cr
Original file line number Diff line number Diff line change
@@ -202,6 +202,10 @@ class Crystal::CodeGenVisitor
end
end

if target_def.is_a? External && (wasm_import_module = target_def.wasm_import_module)
context.fun.add_attribute("wasm-import-module", wasm_import_module)
end

context.fun
end
end
11 changes: 8 additions & 3 deletions src/compiler/crystal/codegen/link.cr
Original file line number Diff line number Diff line change
@@ -4,8 +4,9 @@ module Crystal
getter pkg_config : String?
getter ldflags : String?
getter framework : String?
getter wasm_import_module : String?

def initialize(@lib = nil, @pkg_config = @lib, @ldflags = nil, @static = false, @framework = nil)
def initialize(@lib = nil, @pkg_config = @lib, @ldflags = nil, @static = false, @framework = nil, @wasm_import_module = nil)
end

def static?
@@ -25,6 +26,7 @@ module Crystal
lib_static = false
lib_pkg_config = nil
lib_framework = nil
lib_wasm_import_module = nil
count = 0

args.each do |arg|
@@ -71,12 +73,15 @@ module Crystal
when "pkg_config"
named_arg.raise "'pkg_config' link argument must be a String" unless value.is_a?(StringLiteral)
lib_pkg_config = value.value
when "wasm_import_module"
named_arg.raise "'wasm_import_module' link argument must be a String" unless value.is_a?(StringLiteral)
lib_wasm_import_module = value.value
else
named_arg.raise "unknown link argument: '#{named_arg.name}' (valid arguments are 'lib', 'ldflags', 'static', 'pkg_config' and 'framework')"
named_arg.raise "unknown link argument: '#{named_arg.name}' (valid arguments are 'lib', 'ldflags', 'static', 'pkg_config', 'framework', and 'wasm_import_module')"
end
end

new(lib_name, lib_pkg_config, lib_ldflags, lib_static, lib_framework)
new(lib_name, lib_pkg_config, lib_ldflags, lib_static, lib_framework, lib_wasm_import_module)
end
end

1 change: 1 addition & 0 deletions src/compiler/crystal/semantic/ast.cr
Original file line number Diff line number Diff line change
@@ -716,6 +716,7 @@ module Crystal
property real_name : String
property! fun_def : FunDef
property call_convention : LLVM::CallConvention?
property wasm_import_module : String?

property? dead = false
property? used = false
12 changes: 12 additions & 0 deletions src/compiler/crystal/semantic/top_level_visitor.cr
Original file line number Diff line number Diff line change
@@ -483,6 +483,8 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor

type.private = true if node.visibility.private?

wasm_import_module = nil

process_annotations(annotations) do |annotation_type, ann|
case annotation_type
when @program.link_annotation
@@ -496,6 +498,12 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor
@program.report_warning(ann, "using non-named arguments for Link annotations is deprecated")
end

if wasm_import_module && link_annotation.wasm_import_module
ann.raise "multiple wasm import modules specified for lib #{node.name}"
end

wasm_import_module = link_annotation.wasm_import_module

type.add_link_annotation(link_annotation)
when @program.call_convention_annotation
type.call_convention = parse_call_convention(ann, type.call_convention)
@@ -903,6 +911,10 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor
call_convention = scope.call_convention
end

if scope.is_a?(LibType)
external.wasm_import_module = scope.wasm_import_module
end

# We fill the arguments and return type in TypeDeclarationVisitor
external.doc = node.doc
external.call_convention = call_convention
4 changes: 4 additions & 0 deletions src/compiler/crystal/types.cr
Original file line number Diff line number Diff line change
@@ -2600,6 +2600,10 @@ module Crystal
def type_desc
"lib"
end

def wasm_import_module
(@link_annotations.try &.find &.wasm_import_module).try &.wasm_import_module
end
end

# A `type` (typedef) type inside a `lib` declaration.
10 changes: 10 additions & 0 deletions src/llvm/function.cr
Original file line number Diff line number Diff line change
@@ -19,6 +19,16 @@ struct LLVM::Function
LibLLVM.set_function_call_convention(self, cc)
end

def add_attribute(kind : String, value : String, index = AttributeIndex::FunctionIndex)
{% if LibLLVM.has_constant?(:AttributeRef) %}
context = LibLLVM.get_module_context(LibLLVM.get_global_parent(self))
attribute_ref = LibLLVM.create_string_attribute(context, kind, kind.bytesize, value, value.bytesize)
LibLLVM.add_attribute_at_index(self, index, attribute_ref)
{% else %}
raise "Unsupported: can't set string attributes in LLVM < 3.9"
{% end %}
end

def add_attribute(attribute : Attribute, index = AttributeIndex::FunctionIndex, type : Type? = nil)
return if attribute.value == 0
{% if LibLLVM.has_constant?(:AttributeRef) %}
1 change: 1 addition & 0 deletions src/llvm/lib_llvm.cr
Original file line number Diff line number Diff line change
@@ -372,6 +372,7 @@ lib LibLLVM
fun get_last_enum_attribute_kind = LLVMGetLastEnumAttributeKind : UInt
fun get_enum_attribute_kind_for_name = LLVMGetEnumAttributeKindForName(name : Char*, s_len : LibC::SizeT) : UInt
fun create_enum_attribute = LLVMCreateEnumAttribute(c : ContextRef, kind_id : UInt, val : UInt64) : AttributeRef
fun create_string_attribute = LLVMCreateStringAttribute(c : ContextRef, kind : Char*, kind_len : UInt32, val : Char*, val_len : UInt32) : AttributeRef
fun add_attribute_at_index = LLVMAddAttributeAtIndex(f : ValueRef, idx : AttributeIndex, a : AttributeRef)
fun get_enum_attribute_at_index = LLVMGetEnumAttributeAtIndex(f : ValueRef, idx : AttributeIndex, kind_id : UInt) : AttributeRef
fun add_call_site_attribute = LLVMAddCallSiteAttribute(f : ValueRef, idx : AttributeIndex, value : AttributeRef)

0 comments on commit 711a9ce

Please sign in to comment.