From 627f10cd18c2d10439a2535cdabc85f211c86920 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 19 Dec 2024 20:39:23 +0100 Subject: [PATCH] Fix bug when a macro calling an extern function was called in another module also declaring and calling the same function. #1690 --- releasenotes.md | 2 +- src/compiler/llvm_codegen.c | 7 ++++++- test/test_suite/abi/linking_extern.c3t | 24 ++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 test/test_suite/abi/linking_extern.c3t diff --git a/releasenotes.md b/releasenotes.md index 390e54a68..373b3b761 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -8,7 +8,7 @@ None ### Fixes - Fix case trying to initialize a `char[*]*` from a String. - Fix Map & HashMap `put_all_for_create` not copying all elements, causing `init_from_map` to create incomplete copy. - +- Fix bug when a macro calling an extern function was called in another module also declaring and calling the same function. #1690 ### Stdlib changes - Increase BitWriter.write_bits limit up to 32 bits. - Updates to `Slice2d`, like `get_xy` and others. diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 8909afdec..d310c345a 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -1298,7 +1298,12 @@ LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl) } else { - backend_ref = decl->backend_ref = LLVMAddFunction(c->module, scratch_buffer_to_string(), type); + const char *name = scratch_buffer_to_string(); + if (decl->is_extern && (backend_ref = LLVMGetNamedFunction(c->module, name))) + { + return decl->backend_ref = backend_ref; + } + backend_ref = decl->backend_ref = LLVMAddFunction(c->module, name, type); } llvm_append_function_attributes(c, decl); llvm_set_decl_linkage(c, decl); diff --git a/test/test_suite/abi/linking_extern.c3t b/test/test_suite/abi/linking_extern.c3t new file mode 100644 index 000000000..231fdae30 --- /dev/null +++ b/test/test_suite/abi/linking_extern.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 +module abc; +extern fn void puts(char*); +macro void test() +{ + puts("b"); +} +module test; +import abc; +extern fn void puts(char*); +fn void main() +{ + puts("a"); + abc::test(); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + call void @puts(ptr @.str) + call void @puts(ptr @.str.1) + ret void +}