Skip to content

Commit a9cefc9

Browse files
committed
Add support for LLVM import_module annotation
Used for defining wasm import module for a fun binding
1 parent 0b87ba0 commit a9cefc9

File tree

7 files changed

+49
-2
lines changed

7 files changed

+49
-2
lines changed

src/compiler/crystal/codegen/ast.cr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ module Crystal
3535
class Def
3636
property? abi_info = false
3737

38+
def import_module
39+
nil
40+
end
41+
3842
def mangled_name(program, self_type)
3943
name = String.build do |str|
4044
str << '*'

src/compiler/crystal/codegen/fun.cr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,12 @@ class Crystal::CodeGenVisitor
357357
context.fun.call_convention = call_convention
358358
end
359359

360+
if @program.has_flag?("wasi")
361+
if import_module = target_def.import_module
362+
context.fun.add_target_dependent_attribute("wasm-import-module", import_module)
363+
end
364+
end
365+
360366
i = 0
361367
args.each do |arg|
362368
param = context.fun.params[i + offset]

src/compiler/crystal/program.cr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ module Crystal
219219
# Built-in annotations
220220
types["AlwaysInline"] = @always_inline_annotation = AnnotationType.new self, self, "AlwaysInline"
221221
types["CallConvention"] = @call_convention_annotation = AnnotationType.new self, self, "CallConvention"
222+
types["ImportModule"] = @import_module_annotation = AnnotationType.new self, self, "ImportModule"
222223
types["Extern"] = @extern_annotation = AnnotationType.new self, self, "Extern"
223224
types["Flags"] = @flags_annotation = AnnotationType.new self, self, "Flags"
224225
types["Link"] = @link_annotation = AnnotationType.new self, self, "Link"
@@ -447,7 +448,7 @@ module Crystal
447448
exception tuple named_tuple proc union enum range regex crystal
448449
packed_annotation thread_local_annotation no_inline_annotation
449450
always_inline_annotation naked_annotation returns_twice_annotation
450-
raises_annotation primitive_annotation call_convention_annotation
451+
raises_annotation primitive_annotation call_convention_annotation import_module_annotation
451452
flags_annotation link_annotation extern_annotation deprecated_annotation experimental_annotation) %}
452453
def {{name.id}}
453454
@{{name.id}}.not_nil!

src/compiler/crystal/semantic/ast.cr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ module Crystal
623623
property real_name : String
624624
property! fun_def : FunDef
625625
property call_convention : LLVM::CallConvention?
626+
property import_module : String?
626627

627628
property? dead = false
628629
property? used = false

src/compiler/crystal/semantic/top_level_visitor.cr

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,8 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor
477477
type.add_link_annotation(link_annotation)
478478
when @program.call_convention_annotation
479479
type.call_convention = parse_call_convention(ann, type.call_convention)
480+
when @program.import_module_annotation
481+
type.import_module = parse_import_module(ann, type.import_module)
480482
else
481483
# not a built-in annotation
482484
end
@@ -860,11 +862,15 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor
860862
external = External.new(node.name, ([] of Arg), node.body, node.real_name).at(node)
861863

862864
call_convention = nil
865+
import_module = nil
866+
863867
process_def_annotations(external, annotations) do |annotation_type, ann|
864868
if annotation_type == @program.call_convention_annotation
865869
call_convention = parse_call_convention(ann, call_convention)
870+
elsif annotation_type == @program.import_module_annotation
871+
import_module = parse_import_module(ann, import_module)
866872
else
867-
ann.raise "funs can only be annotated with: NoInline, AlwaysInline, Naked, ReturnsTwice, Raises, CallConvention"
873+
ann.raise "funs can only be annotated with: NoInline, AlwaysInline, Naked, ReturnsTwice, Raises, CallConvention, ImportModule"
868874
end
869875
end
870876

@@ -877,9 +883,14 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor
877883
call_convention = scope.call_convention
878884
end
879885

886+
if !call_convention && scope.is_a?(LibType)
887+
import_module = scope.import_module
888+
end
889+
880890
# We fill the arguments and return type in TypeDeclarationVisitor
881891
external.doc = node.doc
882892
external.call_convention = call_convention
893+
external.import_module = import_module
883894
external.varargs = node.varargs?
884895
external.fun_def = node
885896
node.external = external
@@ -1055,6 +1066,27 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor
10551066
call_convention
10561067
end
10571068

1069+
def parse_import_module(ann, import_module)
1070+
if import_module
1071+
ann.raise "ImportModule already specified"
1072+
end
1073+
1074+
if ann.args.size != 1
1075+
ann.wrong_number_of_arguments "annotation ImportModule", ann.args.size, 1
1076+
end
1077+
1078+
import_module_node = ann.args.first
1079+
unless import_module_node.is_a?(StringLiteral)
1080+
import_module_node.raise "argument to CallConvention must be a string"
1081+
end
1082+
1083+
value = import_module_node.value
1084+
if value.empty?
1085+
import_module_node.raise "invalid import module. cannot be empty."
1086+
end
1087+
value
1088+
end
1089+
10581090
def attach_doc(type, node, annotations)
10591091
if @program.wants_doc?
10601092
type.doc ||= node.doc

src/compiler/crystal/types.cr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2524,6 +2524,7 @@ module Crystal
25242524
getter link_annotations : Array(LinkAnnotation)?
25252525
property? used = false
25262526
property call_convention : LLVM::CallConvention?
2527+
property import_module : String?
25272528

25282529
def add_link_annotation(link_annotation : LinkAnnotation)
25292530
link_annotations = @link_annotations ||= [] of LinkAnnotation

src/llvm/enums.cr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module LLVM
1212
Convergent
1313
Dereferenceable
1414
DereferenceableOrNull
15+
ImportModule
1516
InAlloca
1617
InReg
1718
InaccessibleMemOnly
@@ -88,6 +89,7 @@ module LLVM
8889
kinds[Convergent] = kind_for_name("convergent")
8990
kinds[Dereferenceable] = kind_for_name("dereferenceable")
9091
kinds[DereferenceableOrNull] = kind_for_name("dereferenceable_or_null")
92+
kinds[ImportModule] = kind_for_name("import_module")
9193
kinds[InAlloca] = kind_for_name("inalloca")
9294
kinds[InReg] = kind_for_name("inreg")
9395
kinds[InaccessibleMemOnly] = kind_for_name("inaccessiblememonly")

0 commit comments

Comments
 (0)