| ... | @@ -428,8 +428,18 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { | ... | @@ -428,8 +428,18 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { |
| 428 | // compiler as we're telling LLVM (using 'wasm-import-name' and | 428 | // compiler as we're telling LLVM (using 'wasm-import-name' and |
| 429 | // 'wasm-import-name') what the real function name is and where to find | 429 | // 'wasm-import-name') what the real function name is and where to find |
| 430 | // it. | 430 | // it. |
| 431 | const bool use_mangled_name = target_is_wasm(g->zig_target) && | 431 | bool use_mangled_name = target_is_wasm(g->zig_target) && |
| 432 | fn_proto->is_extern && fn_proto->lib_name != nullptr; | 432 | fn_proto->is_extern && fn_proto->lib_name != nullptr; |
| | 433 | // This is subtle but important to match libc symbols at static link time correctly. |
| | 434 | // We treat "c" lib_name as a special library indicating that it should be defined |
| | 435 | // in libc. But if we mangle a libc symbol name here with "c" module name, then wasm-ld cannot resolve |
| | 436 | // the symbol. This is because at the static link time with wasm-ld, the linker does not |
| | 437 | // take module names into account, and instead looking for a pure symbol name (i.e. function name) |
| | 438 | // written into the ".linking" custom section (i.e. it does not use import section). |
| | 439 | // This is the intended behavior of wasm-ld, because Wasm has a concept of host functions, |
| | 440 | // which are undefined functions supposed to be resolved by host runtimes *with module names* |
| | 441 | // at load times even if it is "static linked" with the linker. |
| | 442 | use_mangled_name = use_mangled_name && (strcmp(buf_ptr(fn_proto->lib_name), "c") != 0); |
| 433 | // Pick a weird name to avoid collisions... | 443 | // Pick a weird name to avoid collisions... |
| 434 | // This whole function should be burned to the ground. | 444 | // This whole function should be burned to the ground. |
| 435 | Buf *mangled_symbol_buf = use_mangled_name ? | 445 | Buf *mangled_symbol_buf = use_mangled_name ? |
| ... | @@ -452,6 +462,13 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { | ... | @@ -452,6 +462,13 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { |
| 452 | llvm_fn = LLVMAddFunction(g->module, symbol_name, fn_llvm_type); | 462 | llvm_fn = LLVMAddFunction(g->module, symbol_name, fn_llvm_type); |
| 453 | | 463 | |
| 454 | if (use_mangled_name) { | 464 | if (use_mangled_name) { |
| | 465 | // Note that "wasm-import-module"ed symbols will not be resolved |
| | 466 | // in the future version of wasm-ld since the attribute basically means that |
| | 467 | // "the symbol should be resolved at load time by runtimes", though |
| | 468 | // the symbol is already mangled here and it is written into "linking" section |
| | 469 | // used by wasm-ld to match symbols, so it should not be expected by users. |
| | 470 | // tl;dr is that users should not put the lib_name specifier on extern statements |
| | 471 | // if they want to link symbols with wasm-ld. |
| 455 | addLLVMFnAttrStr(llvm_fn, "wasm-import-name", unmangled_name); | 472 | addLLVMFnAttrStr(llvm_fn, "wasm-import-name", unmangled_name); |
| 456 | addLLVMFnAttrStr(llvm_fn, "wasm-import-module", buf_ptr(fn_proto->lib_name)); | 473 | addLLVMFnAttrStr(llvm_fn, "wasm-import-module", buf_ptr(fn_proto->lib_name)); |
| 457 | } | 474 | } |