Created
February 5, 2025 18:02
-
-
Save ysbaddaden/f497c0480d9f2dee5f175181d4ca0511 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/compiler/crystal/codegen/ast.cr b/src/compiler/crystal/codegen/ast.cr | |
index ab4fa76d4..ed3465be1 100644 | |
--- a/src/compiler/crystal/codegen/ast.cr | |
+++ b/src/compiler/crystal/codegen/ast.cr | |
@@ -72,6 +72,10 @@ module Crystal | |
nil | |
end | |
+ def linkage | |
+ nil | |
+ end | |
+ | |
@c_calling_convention : Bool? = nil | |
property c_calling_convention | |
diff --git a/src/compiler/crystal/codegen/codegen.cr b/src/compiler/crystal/codegen/codegen.cr | |
index 7e15b1bdc..e4d05ba4a 100644 | |
--- a/src/compiler/crystal/codegen/codegen.cr | |
+++ b/src/compiler/crystal/codegen/codegen.cr | |
@@ -283,6 +283,7 @@ module Crystal | |
ret_type = @llvm_typer.llvm_return_type(@main_ret_type) | |
main_type = LLVM::Type.function([llvm_context.int32, llvm_context.void_pointer.pointer], ret_type) | |
@main = @llvm_mod.functions.add(MAIN_NAME, main_type) | |
+ @main.linkage = LLVM::Linkage::Internal if @single_module | |
@fun_types = { {@llvm_mod, MAIN_NAME} => main_type } | |
if @program.has_flag?("msvc") | |
diff --git a/src/compiler/crystal/codegen/fun.cr b/src/compiler/crystal/codegen/fun.cr | |
index c56bde6e5..69467027d 100644 | |
--- a/src/compiler/crystal/codegen/fun.cr | |
+++ b/src/compiler/crystal/codegen/fun.cr | |
@@ -337,7 +337,7 @@ class Crystal::CodeGenVisitor | |
end | |
end | |
- if @single_module && !target_def.no_inline? && !target_def.is_a?(External) | |
+ if @single_module && !target_def.is_a?(External) | |
context.fun.linkage = LLVM::Linkage::Internal | |
end | |
@@ -395,6 +395,10 @@ class Crystal::CodeGenVisitor | |
context.fun.call_convention = call_convention | |
end | |
+ if @single_module && (linkage = target_def.linkage) | |
+ context.fun.linkage = linkage | |
+ end | |
+ | |
i = 0 | |
args.each do |arg| | |
param = context.fun.params[i + offset] | |
@@ -448,11 +452,7 @@ class Crystal::CodeGenVisitor | |
context.fun.add_attribute LLVM::Attribute::ReturnsTwice if target_def.returns_twice? | |
context.fun.add_attribute LLVM::Attribute::Naked if target_def.naked? | |
context.fun.add_attribute LLVM::Attribute::NoReturn if target_def.no_returns? | |
- | |
- if target_def.no_inline? | |
- context.fun.add_attribute LLVM::Attribute::NoInline | |
- context.fun.linkage = LLVM::Linkage::External | |
- end | |
+ context.fun.add_attribute LLVM::Attribute::NoInline if target_def.no_inline? | |
end | |
def setup_closure_vars(def_vars, closure_vars, context, closure_type, closure_ptr) | |
diff --git a/src/compiler/crystal/program.cr b/src/compiler/crystal/program.cr | |
index 840afd2b6..699da7fe4 100644 | |
--- a/src/compiler/crystal/program.cr | |
+++ b/src/compiler/crystal/program.cr | |
@@ -239,6 +239,7 @@ module Crystal | |
types["Extern"] = @extern_annotation = AnnotationType.new self, self, "Extern" | |
types["Flags"] = @flags_annotation = AnnotationType.new self, self, "Flags" | |
types["Link"] = @link_annotation = AnnotationType.new self, self, "Link" | |
+ types["Linkage"] = @linkage_annotation = AnnotationType.new self, self, "Linkage" | |
types["Naked"] = @naked_annotation = AnnotationType.new self, self, "Naked" | |
types["NoInline"] = @no_inline_annotation = AnnotationType.new self, self, "NoInline" | |
types["Packed"] = @packed_annotation = AnnotationType.new self, self, "Packed" | |
@@ -534,7 +535,8 @@ module Crystal | |
packed_annotation thread_local_annotation no_inline_annotation | |
always_inline_annotation naked_annotation returns_twice_annotation | |
raises_annotation primitive_annotation call_convention_annotation | |
- flags_annotation link_annotation extern_annotation deprecated_annotation experimental_annotation) %} | |
+ flags_annotation link_annotation linkage_annotation extern_annotation | |
+ deprecated_annotation experimental_annotation) %} | |
def {{name.id}} | |
@{{name.id}}.not_nil! | |
end | |
diff --git a/src/compiler/crystal/semantic/ast.cr b/src/compiler/crystal/semantic/ast.cr | |
index f4fa683ef..b2849fbef 100644 | |
--- a/src/compiler/crystal/semantic/ast.cr | |
+++ b/src/compiler/crystal/semantic/ast.cr | |
@@ -689,6 +689,7 @@ module Crystal | |
property real_name : String | |
property! fun_def : FunDef | |
property call_convention : LLVM::CallConvention? | |
+ property linkage : LLVM::Linkage? | |
property wasm_import_module : String? | |
property? dead = false | |
diff --git a/src/compiler/crystal/semantic/top_level_visitor.cr b/src/compiler/crystal/semantic/top_level_visitor.cr | |
index cfc8dddc8..8c93c52a9 100644 | |
--- a/src/compiler/crystal/semantic/top_level_visitor.cr | |
+++ b/src/compiler/crystal/semantic/top_level_visitor.cr | |
@@ -528,6 +528,24 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor | |
node.body = primitive | |
end | |
+ private def process_def_linkage_annotation(node, ann) | |
+ if ann.args.size != 1 | |
+ ann.wrong_number_of_arguments "annotation Linkage", ann.args.size, 1 | |
+ end | |
+ | |
+ arg = ann.args.first | |
+ unless arg.is_a?(StringLiteral) | |
+ arg.raise "argument to Linkage must be a string" | |
+ end | |
+ | |
+ value = LLVM::Linkage.parse?(arg.value) | |
+ unless value | |
+ arg.raise "invalid linkage. Valid values are #{LLVM::Linkage.values.join ", "}" | |
+ end | |
+ | |
+ node.linkage = value | |
+ end | |
+ | |
def visit(node : Include) | |
check_outside_exp node, "include" | |
include_in current_type, node, :included | |
@@ -984,8 +1002,10 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor | |
call_convention = parse_call_convention(ann, call_convention) | |
elsif annotation_type == @program.primitive_annotation | |
process_def_primitive_annotation(external, ann) | |
+ elsif annotation_type == @program.linkage_annotation | |
+ process_def_linkage_annotation(external, ann) | |
else | |
- ann.raise "funs can only be annotated with: NoInline, AlwaysInline, Naked, ReturnsTwice, Raises, CallConvention" | |
+ ann.raise "funs can only be annotated with: NoInline, AlwaysInline, Naked, ReturnsTwice, Raises, CallConvention or Linkage" | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment