Commit 5f11e341d8

Andrew Kelley <andrew@ziglang.org>
2022-11-02 19:10:07
Merge pull request #13396 from Luukdegram/fix-12880
llvm: mangle extern function names for Wasm target
1 parent f354ad6
Changed files (6)
src
codegen
test
link
wasm
src/codegen/llvm.zig
@@ -1279,8 +1279,18 @@ pub const Object = struct {
         const llvm_global = self.decl_map.get(decl_index) orelse return;
         const decl = module.declPtr(decl_index);
         if (decl.isExtern()) {
-            llvm_global.setValueName(decl.name);
-            if (self.getLlvmGlobal(decl.name)) |other_global| {
+            const is_wasm_fn = module.getTarget().isWasm() and try decl.isFunction();
+            const mangle_name = is_wasm_fn and
+                decl.getExternFn().?.lib_name != null and
+                !std.mem.eql(u8, std.mem.sliceTo(decl.getExternFn().?.lib_name.?, 0), "c");
+            const decl_name = if (mangle_name) name: {
+                const tmp = try std.fmt.allocPrintZ(module.gpa, "{s}|{s}", .{ decl.name, decl.getExternFn().?.lib_name.? });
+                break :name tmp.ptr;
+            } else decl.name;
+            defer if (mangle_name) module.gpa.free(std.mem.sliceTo(decl_name, 0));
+
+            llvm_global.setValueName(decl_name);
+            if (self.getLlvmGlobal(decl_name)) |other_global| {
                 if (other_global != llvm_global) {
                     log.debug("updateDeclExports isExtern()=true setValueName({s}) conflict", .{decl.name});
                     try self.extern_collisions.put(module.gpa, decl_index, {});
test/link/wasm/extern-mangle/a.zig
@@ -0,0 +1,1 @@
+pub extern "a" fn hello() i32;
test/link/wasm/extern-mangle/b.zig
@@ -0,0 +1,1 @@
+pub extern "b" fn hello() i32;
test/link/wasm/extern-mangle/build.zig
@@ -0,0 +1,24 @@
+const std = @import("std");
+const Builder = std.build.Builder;
+
+pub fn build(b: *Builder) void {
+    const mode = b.standardReleaseOptions();
+
+    const test_step = b.step("test", "Test");
+    test_step.dependOn(b.getInstallStep());
+
+    const lib = b.addSharedLibrary("lib", "lib.zig", .unversioned);
+    lib.setBuildMode(mode);
+    lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
+    lib.install();
+
+    const check_lib = lib.checkObject(.wasm);
+    check_lib.checkStart("Section import");
+    check_lib.checkNext("entries 2"); // a.hello & b.hello
+    check_lib.checkNext("module a");
+    check_lib.checkNext("name hello");
+    check_lib.checkNext("module b");
+    check_lib.checkNext("name hello");
+
+    test_step.dependOn(&check_lib.step);
+}
test/link/wasm/extern-mangle/lib.zig
@@ -0,0 +1,6 @@
+const a = @import("a.zig").hello;
+const b = @import("b.zig").hello;
+export fn foo() void {
+    _ = a();
+    _ = b();
+}
test/link.zig
@@ -48,6 +48,11 @@ fn addWasmCases(cases: *tests.StandaloneContext) void {
         .use_emulation = true,
     });
 
+    cases.addBuildFile("test/link/wasm/extern-mangle/build.zig", .{
+        .build_modes = true,
+        .requires_stage2 = true,
+    });
+
     cases.addBuildFile("test/link/wasm/infer-features/build.zig", .{
         .requires_stage2 = true,
     });