authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-11-01 15:05:09+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-11-01 15:05:09+01:00
log66bcc55e0196bd43746a09a79668c7c495bd1f89
treece5e5918602e157634415093009183ba370a44ec
parentbd32206b4449e329c9ef6ba4fd19746234f474f8
signaturelock-open Commit is signed but in an unrecognized format.

llvm: mangle extern Wasm functions

When Wasm extern functions contain the same name, but have a different module name such as `extern "a"` vs `extern "b"` LLVM will currently resolve the two functions to the same symbol. By mangling the name of the symbol, we ensure the functions are resolved seperately. We mangle the name by applying <name>|<module> where module is also known as the library name.

1 files changed, 12 insertions(+), 2 deletions(-)

src/codegen/llvm.zig+12-2
......@@ -1279,8 +1279,18 @@ pub const Object = struct {
12791279 const llvm_global = self.decl_map.get(decl_index) orelse return;
12801280 const decl = module.declPtr(decl_index);
12811281 if (decl.isExtern()) {
1282 llvm_global.setValueName(decl.name);
1283 if (self.getLlvmGlobal(decl.name)) |other_global| {
1282 const is_wasm_fn = module.getTarget().isWasm() and try decl.isFunction();
1283 const mangle_name = is_wasm_fn and
1284 decl.getExternFn().?.lib_name != null and
1285 !std.mem.eql(u8, std.mem.sliceTo(decl.getExternFn().?.lib_name.?, 0), "c");
1286 const decl_name = if (mangle_name) name: {
1287 const tmp = try std.fmt.allocPrintZ(module.gpa, "{s}|{s}", .{ decl.name, decl.getExternFn().?.lib_name.? });
1288 break :name tmp.ptr;
1289 } else decl.name;
1290 defer if (mangle_name) module.gpa.free(std.mem.sliceTo(decl_name, 0));
1291
1292 llvm_global.setValueName(decl_name);
1293 if (self.getLlvmGlobal(decl_name)) |other_global| {
12841294 if (other_global != llvm_global) {
12851295 log.debug("updateDeclExports isExtern()=true setValueName({s}) conflict", .{decl.name});
12861296 try self.extern_collisions.put(module.gpa, decl_index, {});