authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-11-12 20:16:58+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-13 14:33:20-07:00
log2d280825cdde1d546f80d12b333bf670ac3bfbeb
tree1e4efc6670234cf4468831911b4d8143b16d3f21
parent10617593f856cf0011926ea2a833d51f8d7c136d

stage1: Disambiguate Wasm imports with same name

Closes #7088

1 files changed, 33 insertions(+), 6 deletions(-)

src/stage1/codegen.cpp+33-6
...@@ -380,9 +380,36 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {...@@ -380,9 +380,36 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
380 LLVMTypeRef fn_llvm_type = fn->raw_type_ref;380 LLVMTypeRef fn_llvm_type = fn->raw_type_ref;
381 LLVMValueRef llvm_fn = nullptr;381 LLVMValueRef llvm_fn = nullptr;
382 if (fn->body_node == nullptr) {382 if (fn->body_node == nullptr) {
383 assert(fn->proto_node->type == NodeTypeFnProto);
384 AstNodeFnProto *fn_proto = &fn->proto_node->data.fn_proto;
385
383 const unsigned fn_addrspace = ZigLLVMDataLayoutGetProgramAddressSpace(g->target_data_ref);386 const unsigned fn_addrspace = ZigLLVMDataLayoutGetProgramAddressSpace(g->target_data_ref);
387
388 // The compiler tries to deduplicate extern definitions by looking up
389 // their name, this was introduced to allow the declaration of the same
390 // extern function with differing prototypes.
391 // When Wasm is targeted this check becomes a problem as the user may
392 // declare two (or more) extern functions sharing the same name but
393 // imported from different modules!
394 // To overcome this problem we generate a mangled identifier out of the
395 // import and the function name, this name is only visible within the
396 // compiler as we're telling LLVM (using 'wasm-import-name' and
397 // 'wasm-import-name') what the real function name is and where to find
398 // it.
399 const bool use_mangled_name = target_is_wasm(g->zig_target) &&
400 fn_proto->is_extern && fn_proto->lib_name != nullptr;
401 // Pick a weird name to avoid collisions...
402 // This whole function should be burned to the ground.
403 Buf *mangled_symbol_buf = use_mangled_name ?
404 buf_sprintf("%s|%s", unmangled_name, buf_ptr(fn_proto->lib_name)) :
405 nullptr;
406 symbol_name = use_mangled_name ?
407 buf_ptr(mangled_symbol_buf) : unmangled_name;
408
384 LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, symbol_name);409 LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, symbol_name);
410
385 if (existing_llvm_fn) {411 if (existing_llvm_fn) {
412 if (mangled_symbol_buf) buf_destroy(mangled_symbol_buf);
386 return LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, fn_addrspace));413 return LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, fn_addrspace));
387 } else {414 } else {
388 Buf *buf_symbol_name = buf_create_from_str(symbol_name);415 Buf *buf_symbol_name = buf_create_from_str(symbol_name);
...@@ -392,12 +419,9 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {...@@ -392,12 +419,9 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
392 if (entry == nullptr) {419 if (entry == nullptr) {
393 llvm_fn = LLVMAddFunction(g->module, symbol_name, fn_llvm_type);420 llvm_fn = LLVMAddFunction(g->module, symbol_name, fn_llvm_type);
394421
395 if (target_is_wasm(g->zig_target)) {422 if (use_mangled_name) {
396 assert(fn->proto_node->type == NodeTypeFnProto);423 addLLVMFnAttrStr(llvm_fn, "wasm-import-name", unmangled_name);
397 AstNodeFnProto *fn_proto = &fn->proto_node->data.fn_proto;424 addLLVMFnAttrStr(llvm_fn, "wasm-import-module", buf_ptr(fn_proto->lib_name));
398 if (fn_proto-> is_extern && fn_proto->lib_name != nullptr ) {
399 addLLVMFnAttrStr(llvm_fn, "wasm-import-module", buf_ptr(fn_proto->lib_name));
400 }
401 }425 }
402 } else {426 } else {
403 assert(entry->value->id == TldIdFn);427 assert(entry->value->id == TldIdFn);
...@@ -407,8 +431,11 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {...@@ -407,8 +431,11 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
407 tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, symbol_name,431 tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, symbol_name,
408 tld_fn->fn_entry->raw_type_ref);432 tld_fn->fn_entry->raw_type_ref);
409 llvm_fn = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, LLVMPointerType(fn_llvm_type, fn_addrspace));433 llvm_fn = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, LLVMPointerType(fn_llvm_type, fn_addrspace));
434 if (mangled_symbol_buf) buf_destroy(mangled_symbol_buf);
410 return llvm_fn;435 return llvm_fn;
411 }436 }
437
438 if (mangled_symbol_buf) buf_destroy(mangled_symbol_buf);
412 }439 }
413 } else {440 } else {
414 if (llvm_fn == nullptr) {441 if (llvm_fn == nullptr) {