fix @export for arrays not respecting the symbol name

Previously, the symbol name parameter of `@export` would be ignored for
variables, and the variable name would be used for the symbol name.
Now it works as expected.

See #2679
This commit is contained in:
Andrew Kelley
2019-06-14 17:23:24 -04:00
parent 42ea2d0d1c
commit f8f054b354
6 changed files with 61 additions and 71 deletions

View File

@@ -475,7 +475,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
symbol_name = get_mangled_name(g, unmangled_name, false);
linkage = GlobalLinkageIdInternal;
} else {
FnExport *fn_export = &fn_table_entry->export_list.items[0];
GlobalExport *fn_export = &fn_table_entry->export_list.items[0];
symbol_name = &fn_export->name;
linkage = fn_export->linkage;
}
@@ -529,7 +529,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
}
for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) {
FnExport *fn_export = &fn_table_entry->export_list.items[i];
GlobalExport *fn_export = &fn_table_entry->export_list.items[i];
LLVMAddAlias(g->module, LLVMTypeOf(fn_table_entry->llvm_value),
fn_table_entry->llvm_value, buf_ptr(&fn_export->name));
}
@@ -6691,27 +6691,14 @@ static void validate_inline_fns(CodeGen *g) {
}
static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
if (var->is_thread_local && (!g->is_single_threaded || var->linkage != VarLinkageInternal)) {
bool is_extern = var->decl_node->data.variable_declaration.is_extern;
bool is_export = var->decl_node->data.variable_declaration.is_export;
bool is_internal_linkage = !is_extern && !is_export;
if (var->is_thread_local && (!g->is_single_threaded || !is_internal_linkage)) {
LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
}
}
static LLVMLinkage var_linkage_to_llvm(VarLinkage var_linkage) {
switch (var_linkage) {
case VarLinkageInternal:
return LLVMInternalLinkage;
case VarLinkageExportStrong:
return LLVMExternalLinkage;
case VarLinkageExportWeak:
return LLVMWeakODRLinkage;
case VarLinkageExportLinkOnce:
return LLVMLinkOnceODRLinkage;
case VarLinkageExternal:
return LLVMExternalLinkage;
}
zig_unreachable();
}
static void do_code_gen(CodeGen *g) {
assert(!g->errors.length);
@@ -6761,31 +6748,48 @@ static void do_code_gen(CodeGen *g) {
assert(var->decl_node);
GlobalLinkageId linkage;
Buf *unmangled_name = &var->name;
Buf *symbol_name;
if (var->export_list.length == 0) {
if (var->decl_node->data.variable_declaration.is_extern) {
symbol_name = unmangled_name;
linkage = GlobalLinkageIdStrong;
} else {
symbol_name = get_mangled_name(g, unmangled_name, false);
linkage = GlobalLinkageIdInternal;
}
} else {
GlobalExport *global_export = &var->export_list.items[0];
symbol_name = &global_export->name;
linkage = global_export->linkage;
}
LLVMValueRef global_value;
if (var->linkage == VarLinkageExternal) {
LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));
bool externally_initialized = var->decl_node->data.variable_declaration.expr == nullptr;
if (externally_initialized) {
LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(symbol_name));
if (existing_llvm_var) {
global_value = LLVMConstBitCast(existing_llvm_var,
LLVMPointerType(get_llvm_type(g, var->var_type), 0));
} else {
global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), buf_ptr(&var->name));
global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), buf_ptr(symbol_name));
// TODO debug info for the extern variable
LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));
LLVMSetLinkage(global_value, to_llvm_linkage(linkage));
maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
LLVMSetAlignment(global_value, var->align_bytes);
LLVMSetGlobalConstant(global_value, var->gen_is_const);
set_global_tls(g, var, global_value);
}
} else {
bool exported = (var->linkage != VarLinkageInternal);
const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
render_const_val(g, var->const_value, mangled_name);
render_const_val_global(g, var->const_value, mangled_name);
bool exported = (linkage != GlobalLinkageIdInternal);
render_const_val(g, var->const_value, buf_ptr(symbol_name));
render_const_val_global(g, var->const_value, buf_ptr(symbol_name));
global_value = var->const_value->global_refs->llvm_global;
if (exported) {
LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));
LLVMSetLinkage(global_value, to_llvm_linkage(linkage));
maybe_export_dll(g, global_value, GlobalLinkageIdStrong);
}
if (tld_var->section_name) {
@@ -6805,6 +6809,11 @@ static void do_code_gen(CodeGen *g) {
}
var->value_ref = global_value;
for (size_t export_i = 1; export_i < var->export_list.length; export_i += 1) {
GlobalExport *global_export = &var->export_list.items[export_i];
LLVMAddAlias(g->module, LLVMTypeOf(var->value_ref), var->value_ref, buf_ptr(&global_export->name));
}
}
// Generate function definitions.
@@ -9168,7 +9177,7 @@ static void gen_h_file(CodeGen *g) {
if (fn_table_entry->export_list.length == 0) {
symbol_name = &fn_table_entry->symbol_name;
} else {
FnExport *fn_export = &fn_table_entry->export_list.items[0];
GlobalExport *fn_export = &fn_table_entry->export_list.items[0];
symbol_name = &fn_export->name;
}