mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
parent
c4fd3fc270
commit
211feea914
@ -380,9 +380,36 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
|
||||
LLVMTypeRef fn_llvm_type = fn->raw_type_ref;
|
||||
LLVMValueRef llvm_fn = nullptr;
|
||||
if (fn->body_node == nullptr) {
|
||||
assert(fn->proto_node->type == NodeTypeFnProto);
|
||||
AstNodeFnProto *fn_proto = &fn->proto_node->data.fn_proto;
|
||||
|
||||
const unsigned fn_addrspace = ZigLLVMDataLayoutGetProgramAddressSpace(g->target_data_ref);
|
||||
|
||||
// The compiler tries to deduplicate extern definitions by looking up
|
||||
// their name, this was introduced to allow the declaration of the same
|
||||
// extern function with differing prototypes.
|
||||
// When Wasm is targeted this check becomes a problem as the user may
|
||||
// declare two (or more) extern functions sharing the same name but
|
||||
// imported from different modules!
|
||||
// To overcome this problem we generate a mangled identifier out of the
|
||||
// import and the function name, this name is only visible within the
|
||||
// compiler as we're telling LLVM (using 'wasm-import-name' and
|
||||
// 'wasm-import-name') what the real function name is and where to find
|
||||
// it.
|
||||
const bool use_mangled_name = target_is_wasm(g->zig_target) &&
|
||||
fn_proto->is_extern && fn_proto->lib_name != nullptr;
|
||||
// Pick a weird name to avoid collisions...
|
||||
// This whole function should be burned to the ground.
|
||||
Buf *mangled_symbol_buf = use_mangled_name ?
|
||||
buf_sprintf("%s|%s", unmangled_name, buf_ptr(fn_proto->lib_name)) :
|
||||
nullptr;
|
||||
symbol_name = use_mangled_name ?
|
||||
buf_ptr(mangled_symbol_buf) : unmangled_name;
|
||||
|
||||
LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, symbol_name);
|
||||
|
||||
if (existing_llvm_fn) {
|
||||
if (mangled_symbol_buf) buf_destroy(mangled_symbol_buf);
|
||||
return LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, fn_addrspace));
|
||||
} else {
|
||||
Buf *buf_symbol_name = buf_create_from_str(symbol_name);
|
||||
@ -392,12 +419,9 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
|
||||
if (entry == nullptr) {
|
||||
llvm_fn = LLVMAddFunction(g->module, symbol_name, fn_llvm_type);
|
||||
|
||||
if (target_is_wasm(g->zig_target)) {
|
||||
assert(fn->proto_node->type == NodeTypeFnProto);
|
||||
AstNodeFnProto *fn_proto = &fn->proto_node->data.fn_proto;
|
||||
if (fn_proto-> is_extern && fn_proto->lib_name != nullptr ) {
|
||||
addLLVMFnAttrStr(llvm_fn, "wasm-import-module", buf_ptr(fn_proto->lib_name));
|
||||
}
|
||||
if (use_mangled_name) {
|
||||
addLLVMFnAttrStr(llvm_fn, "wasm-import-name", unmangled_name);
|
||||
addLLVMFnAttrStr(llvm_fn, "wasm-import-module", buf_ptr(fn_proto->lib_name));
|
||||
}
|
||||
} else {
|
||||
assert(entry->value->id == TldIdFn);
|
||||
@ -407,8 +431,11 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
|
||||
tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, symbol_name,
|
||||
tld_fn->fn_entry->raw_type_ref);
|
||||
llvm_fn = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, LLVMPointerType(fn_llvm_type, fn_addrspace));
|
||||
if (mangled_symbol_buf) buf_destroy(mangled_symbol_buf);
|
||||
return llvm_fn;
|
||||
}
|
||||
|
||||
if (mangled_symbol_buf) buf_destroy(mangled_symbol_buf);
|
||||
}
|
||||
} else {
|
||||
if (llvm_fn == nullptr) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user