Skip to content

Commit a9a4fd3

Browse files
mathetakeandrewrk
authored andcommitted
Wasm,libc: fix wasm-ld failure in matching libc symbols.
Signed-off-by: Takeshi Yoneda <[email protected]>
1 parent 24bfd7b commit a9a4fd3

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

src/stage1/codegen.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,18 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
428428
// compiler as we're telling LLVM (using 'wasm-import-name' and
429429
// 'wasm-import-name') what the real function name is and where to find
430430
// it.
431-
const bool use_mangled_name = target_is_wasm(g->zig_target) &&
431+
bool use_mangled_name = target_is_wasm(g->zig_target) &&
432432
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);
433443
// Pick a weird name to avoid collisions...
434444
// This whole function should be burned to the ground.
435445
Buf *mangled_symbol_buf = use_mangled_name ?
@@ -452,6 +462,13 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
452462
llvm_fn = LLVMAddFunction(g->module, symbol_name, fn_llvm_type);
453463

454464
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.
455472
addLLVMFnAttrStr(llvm_fn, "wasm-import-name", unmangled_name);
456473
addLLVMFnAttrStr(llvm_fn, "wasm-import-module", buf_ptr(fn_proto->lib_name));
457474
}

0 commit comments

Comments
 (0)