authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-14 17:23:24-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-14 17:23:24-04:00
logf8f054b354088eb9e76d9207972022bc1d3dfc28
treea45396b18548f911ae88067c98c9c5afd1ad3358
parent42ea2d0d1c3b8cafdfc9a383cbb1bab274eb0140
signaturelock-open Commit is signed but in an unrecognized format.

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

6 files changed, 61 insertions(+), 71 deletions(-)

doc/langref.html.in+1-1
...@@ -6648,7 +6648,7 @@ test "main" {...@@ -6648,7 +6648,7 @@ test "main" {
6648 {#header_close#}6648 {#header_close#}
66496649
6650 {#header_open|@export#}6650 {#header_open|@export#}
6651 <pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre>6651 <pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) void{#endsyntax#}</pre>
6652 <p>6652 <p>
6653 Creates a symbol in the output object file.6653 Creates a symbol in the output object file.
6654 </p>6654 </p>
src/all_types.hpp+4-11
...@@ -1334,7 +1334,7 @@ enum FnInline {...@@ -1334,7 +1334,7 @@ enum FnInline {
1334 FnInlineNever,1334 FnInlineNever,
1335};1335};
13361336
1337struct FnExport {1337struct GlobalExport {
1338 Buf name;1338 Buf name;
1339 GlobalLinkageId linkage;1339 GlobalLinkageId linkage;
1340};1340};
...@@ -1372,7 +1372,7 @@ struct ZigFn {...@@ -1372,7 +1372,7 @@ struct ZigFn {
13721372
1373 AstNode *set_cold_node;1373 AstNode *set_cold_node;
13741374
1375 ZigList<FnExport> export_list;1375 ZigList<GlobalExport> export_list;
13761376
1377 LLVMValueRef valgrind_client_request_array;1377 LLVMValueRef valgrind_client_request_array;
13781378
...@@ -1896,14 +1896,6 @@ struct CodeGen {...@@ -1896,14 +1896,6 @@ struct CodeGen {
1896 size_t clang_argv_len;1896 size_t clang_argv_len;
1897};1897};
18981898
1899enum VarLinkage {
1900 VarLinkageInternal,
1901 VarLinkageExportStrong,
1902 VarLinkageExportWeak,
1903 VarLinkageExportLinkOnce,
1904 VarLinkageExternal,
1905};
1906
1907struct ZigVar {1899struct ZigVar {
1908 Buf name;1900 Buf name;
1909 ConstExprValue *const_value;1901 ConstExprValue *const_value;
...@@ -1926,8 +1918,9 @@ struct ZigVar {...@@ -1926,8 +1918,9 @@ struct ZigVar {
1926 // this pointer to the redefined variable.1918 // this pointer to the redefined variable.
1927 ZigVar *next_var;1919 ZigVar *next_var;
19281920
1921 ZigList<GlobalExport> export_list;
1922
1929 uint32_t align_bytes;1923 uint32_t align_bytes;
1930 VarLinkage linkage;
19311924
1932 bool shadowable;1925 bool shadowable;
1933 bool src_is_const;1926 bool src_is_const;
src/analyze.cpp+15-14
...@@ -2712,6 +2712,13 @@ ZigType *get_test_fn_type(CodeGen *g) {...@@ -2712,6 +2712,13 @@ ZigType *get_test_fn_type(CodeGen *g) {
2712 return g->test_fn_type;2712 return g->test_fn_type;
2713}2713}
27142714
2715void add_var_export(CodeGen *g, ZigVar *var, Buf *symbol_name, GlobalLinkageId linkage) {
2716 GlobalExport *global_export = var->export_list.add_one();
2717 memset(global_export, 0, sizeof(GlobalExport));
2718 buf_init_from_buf(&global_export->name, symbol_name);
2719 global_export->linkage = linkage;
2720}
2721
2715void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc) {2722void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc) {
2716 if (ccc) {2723 if (ccc) {
2717 if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) {2724 if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) {
...@@ -2731,8 +2738,8 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi...@@ -2731,8 +2738,8 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
2731 }2738 }
2732 }2739 }
27332740
2734 FnExport *fn_export = fn_table_entry->export_list.add_one();2741 GlobalExport *fn_export = fn_table_entry->export_list.add_one();
2735 memset(fn_export, 0, sizeof(FnExport));2742 memset(fn_export, 0, sizeof(GlobalExport));
2736 buf_init_from_buf(&fn_export->name, symbol_name);2743 buf_init_from_buf(&fn_export->name, symbol_name);
2737 fn_export->linkage = linkage;2744 fn_export->linkage = linkage;
2738}2745}
...@@ -3189,15 +3196,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3189,15 +3196,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
31893196
3190 assert(!is_export || !is_extern);3197 assert(!is_export || !is_extern);
31913198
3192 VarLinkage linkage;
3193 if (is_export) {
3194 linkage = VarLinkageExportStrong;
3195 } else if (is_extern) {
3196 linkage = VarLinkageExternal;
3197 } else {
3198 linkage = VarLinkageInternal;
3199 }
3200
3201 ConstExprValue *init_value = nullptr;3199 ConstExprValue *init_value = nullptr;
32023200
3203 // TODO more validation for types that can't be used for export/extern variables3201 // TODO more validation for types that can't be used for export/extern variables
...@@ -3212,7 +3210,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3212,7 +3210,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3212 if (implicit_type->id == ZigTypeIdUnreachable) {3210 if (implicit_type->id == ZigTypeIdUnreachable) {
3213 add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));3211 add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
3214 implicit_type = g->builtin_types.entry_invalid;3212 implicit_type = g->builtin_types.entry_invalid;
3215 } else if ((!is_const || linkage == VarLinkageExternal) &&3213 } else if ((!is_const || is_extern) &&
3216 (implicit_type->id == ZigTypeIdComptimeFloat ||3214 (implicit_type->id == ZigTypeIdComptimeFloat ||
3217 implicit_type->id == ZigTypeIdComptimeInt ||3215 implicit_type->id == ZigTypeIdComptimeInt ||
3218 implicit_type->id == ZigTypeIdEnumLiteral))3216 implicit_type->id == ZigTypeIdEnumLiteral))
...@@ -3227,7 +3225,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3227,7 +3225,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3227 implicit_type = g->builtin_types.entry_invalid;3225 implicit_type = g->builtin_types.entry_invalid;
3228 }3226 }
3229 assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);3227 assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);
3230 } else if (linkage != VarLinkageExternal) {3228 } else if (!is_extern) {
3231 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));3229 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
3232 implicit_type = g->builtin_types.entry_invalid;3230 implicit_type = g->builtin_types.entry_invalid;
3233 }3231 }
...@@ -3239,7 +3237,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3239,7 +3237,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
32393237
3240 tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,3238 tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,
3241 is_const, init_val, &tld_var->base, type);3239 is_const, init_val, &tld_var->base, type);
3242 tld_var->var->linkage = linkage;
3243 tld_var->var->is_thread_local = is_thread_local;3240 tld_var->var->is_thread_local = is_thread_local;
32443241
3245 if (implicit_type != nullptr && type_is_invalid(implicit_type)) {3242 if (implicit_type != nullptr && type_is_invalid(implicit_type)) {
...@@ -3262,6 +3259,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3262,6 +3259,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3262 add_node_error(g, source_node, buf_sprintf("threadlocal variable cannot be constant"));3259 add_node_error(g, source_node, buf_sprintf("threadlocal variable cannot be constant"));
3263 }3260 }
32643261
3262 if (is_export) {
3263 add_var_export(g, tld_var->var, &tld_var->var->name, GlobalLinkageIdStrong);
3264 }
3265
3265 g->global_vars.append(tld_var);3266 g->global_vars.append(tld_var);
3266}3267}
32673268
src/analyze.hpp+1
...@@ -198,6 +198,7 @@ ZigPackage *new_anonymous_package(void);...@@ -198,6 +198,7 @@ ZigPackage *new_anonymous_package(void);
198198
199Buf *const_value_to_buffer(ConstExprValue *const_val);199Buf *const_value_to_buffer(ConstExprValue *const_val);
200void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc);200void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc);
201void add_var_export(CodeGen *g, ZigVar *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage);
201202
202203
203ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name);204ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name);
src/codegen.cpp+38-29
...@@ -475,7 +475,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -475,7 +475,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
475 symbol_name = get_mangled_name(g, unmangled_name, false);475 symbol_name = get_mangled_name(g, unmangled_name, false);
476 linkage = GlobalLinkageIdInternal;476 linkage = GlobalLinkageIdInternal;
477 } else {477 } else {
478 FnExport *fn_export = &fn_table_entry->export_list.items[0];478 GlobalExport *fn_export = &fn_table_entry->export_list.items[0];
479 symbol_name = &fn_export->name;479 symbol_name = &fn_export->name;
480 linkage = fn_export->linkage;480 linkage = fn_export->linkage;
481 }481 }
...@@ -529,7 +529,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -529,7 +529,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
529 }529 }
530530
531 for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) {531 for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) {
532 FnExport *fn_export = &fn_table_entry->export_list.items[i];532 GlobalExport *fn_export = &fn_table_entry->export_list.items[i];
533 LLVMAddAlias(g->module, LLVMTypeOf(fn_table_entry->llvm_value),533 LLVMAddAlias(g->module, LLVMTypeOf(fn_table_entry->llvm_value),
534 fn_table_entry->llvm_value, buf_ptr(&fn_export->name));534 fn_table_entry->llvm_value, buf_ptr(&fn_export->name));
535 }535 }
...@@ -6691,27 +6691,14 @@ static void validate_inline_fns(CodeGen *g) {...@@ -6691,27 +6691,14 @@ static void validate_inline_fns(CodeGen *g) {
6691}6691}
66926692
6693static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {6693static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
6694 if (var->is_thread_local && (!g->is_single_threaded || var->linkage != VarLinkageInternal)) {6694 bool is_extern = var->decl_node->data.variable_declaration.is_extern;
6695 bool is_export = var->decl_node->data.variable_declaration.is_export;
6696 bool is_internal_linkage = !is_extern && !is_export;
6697 if (var->is_thread_local && (!g->is_single_threaded || !is_internal_linkage)) {
6695 LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);6698 LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
6696 }6699 }
6697}6700}
66986701
6699static LLVMLinkage var_linkage_to_llvm(VarLinkage var_linkage) {
6700 switch (var_linkage) {
6701 case VarLinkageInternal:
6702 return LLVMInternalLinkage;
6703 case VarLinkageExportStrong:
6704 return LLVMExternalLinkage;
6705 case VarLinkageExportWeak:
6706 return LLVMWeakODRLinkage;
6707 case VarLinkageExportLinkOnce:
6708 return LLVMLinkOnceODRLinkage;
6709 case VarLinkageExternal:
6710 return LLVMExternalLinkage;
6711 }
6712 zig_unreachable();
6713}
6714
6715static void do_code_gen(CodeGen *g) {6702static void do_code_gen(CodeGen *g) {
6716 assert(!g->errors.length);6703 assert(!g->errors.length);
67176704
...@@ -6761,31 +6748,48 @@ static void do_code_gen(CodeGen *g) {...@@ -6761,31 +6748,48 @@ static void do_code_gen(CodeGen *g) {
67616748
6762 assert(var->decl_node);6749 assert(var->decl_node);
67636750
6751 GlobalLinkageId linkage;
6752 Buf *unmangled_name = &var->name;
6753 Buf *symbol_name;
6754 if (var->export_list.length == 0) {
6755 if (var->decl_node->data.variable_declaration.is_extern) {
6756 symbol_name = unmangled_name;
6757 linkage = GlobalLinkageIdStrong;
6758 } else {
6759 symbol_name = get_mangled_name(g, unmangled_name, false);
6760 linkage = GlobalLinkageIdInternal;
6761 }
6762 } else {
6763 GlobalExport *global_export = &var->export_list.items[0];
6764 symbol_name = &global_export->name;
6765 linkage = global_export->linkage;
6766 }
6767
6764 LLVMValueRef global_value;6768 LLVMValueRef global_value;
6765 if (var->linkage == VarLinkageExternal) {6769 bool externally_initialized = var->decl_node->data.variable_declaration.expr == nullptr;
6766 LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));6770 if (externally_initialized) {
6771 LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(symbol_name));
6767 if (existing_llvm_var) {6772 if (existing_llvm_var) {
6768 global_value = LLVMConstBitCast(existing_llvm_var,6773 global_value = LLVMConstBitCast(existing_llvm_var,
6769 LLVMPointerType(get_llvm_type(g, var->var_type), 0));6774 LLVMPointerType(get_llvm_type(g, var->var_type), 0));
6770 } else {6775 } else {
6771 global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), buf_ptr(&var->name));6776 global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), buf_ptr(symbol_name));
6772 // TODO debug info for the extern variable6777 // TODO debug info for the extern variable
67736778
6774 LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));6779 LLVMSetLinkage(global_value, to_llvm_linkage(linkage));
6775 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);6780 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
6776 LLVMSetAlignment(global_value, var->align_bytes);6781 LLVMSetAlignment(global_value, var->align_bytes);
6777 LLVMSetGlobalConstant(global_value, var->gen_is_const);6782 LLVMSetGlobalConstant(global_value, var->gen_is_const);
6778 set_global_tls(g, var, global_value);6783 set_global_tls(g, var, global_value);
6779 }6784 }
6780 } else {6785 } else {
6781 bool exported = (var->linkage != VarLinkageInternal);6786 bool exported = (linkage != GlobalLinkageIdInternal);
6782 const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));6787 render_const_val(g, var->const_value, buf_ptr(symbol_name));
6783 render_const_val(g, var->const_value, mangled_name);6788 render_const_val_global(g, var->const_value, buf_ptr(symbol_name));
6784 render_const_val_global(g, var->const_value, mangled_name);
6785 global_value = var->const_value->global_refs->llvm_global;6789 global_value = var->const_value->global_refs->llvm_global;
67866790
6787 if (exported) {6791 if (exported) {
6788 LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));6792 LLVMSetLinkage(global_value, to_llvm_linkage(linkage));
6789 maybe_export_dll(g, global_value, GlobalLinkageIdStrong);6793 maybe_export_dll(g, global_value, GlobalLinkageIdStrong);
6790 }6794 }
6791 if (tld_var->section_name) {6795 if (tld_var->section_name) {
...@@ -6805,6 +6809,11 @@ static void do_code_gen(CodeGen *g) {...@@ -6805,6 +6809,11 @@ static void do_code_gen(CodeGen *g) {
6805 }6809 }
68066810
6807 var->value_ref = global_value;6811 var->value_ref = global_value;
6812
6813 for (size_t export_i = 1; export_i < var->export_list.length; export_i += 1) {
6814 GlobalExport *global_export = &var->export_list.items[export_i];
6815 LLVMAddAlias(g->module, LLVMTypeOf(var->value_ref), var->value_ref, buf_ptr(&global_export->name));
6816 }
6808 }6817 }
68096818
6810 // Generate function definitions.6819 // Generate function definitions.
...@@ -9168,7 +9177,7 @@ static void gen_h_file(CodeGen *g) {...@@ -9168,7 +9177,7 @@ static void gen_h_file(CodeGen *g) {
9168 if (fn_table_entry->export_list.length == 0) {9177 if (fn_table_entry->export_list.length == 0) {
9169 symbol_name = &fn_table_entry->symbol_name;9178 symbol_name = &fn_table_entry->symbol_name;
9170 } else {9179 } else {
9171 FnExport *fn_export = &fn_table_entry->export_list.items[0];9180 GlobalExport *fn_export = &fn_table_entry->export_list.items[0];
9172 symbol_name = &fn_export->name;9181 symbol_name = &fn_export->name;
9173 }9182 }
91749183
src/ir.cpp+2-16
...@@ -13791,20 +13791,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,...@@ -13791,20 +13791,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
13791 return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);13791 return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
13792}13792}
1379313793
13794static VarLinkage global_linkage_to_var_linkage(GlobalLinkageId id) {
13795 switch (id) {
13796 case GlobalLinkageIdStrong:
13797 return VarLinkageExportStrong;
13798 case GlobalLinkageIdWeak:
13799 return VarLinkageExportWeak;
13800 case GlobalLinkageIdLinkOnce:
13801 return VarLinkageExportLinkOnce;
13802 case GlobalLinkageIdInternal:
13803 return VarLinkageInternal;
13804 }
13805 zig_unreachable();
13806}
13807
13808static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {13794static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
13809 IrInstruction *name = instruction->name->child;13795 IrInstruction *name = instruction->name->child;
13810 Buf *symbol_name = ir_resolve_str(ira, name);13796 Buf *symbol_name = ir_resolve_str(ira, name);
...@@ -14002,7 +13988,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio...@@ -14002,7 +13988,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
14002 if (load_ptr->ptr->id == IrInstructionIdVarPtr) {13988 if (load_ptr->ptr->id == IrInstructionIdVarPtr) {
14003 IrInstructionVarPtr *var_ptr = reinterpret_cast<IrInstructionVarPtr *>(load_ptr->ptr);13989 IrInstructionVarPtr *var_ptr = reinterpret_cast<IrInstructionVarPtr *>(load_ptr->ptr);
14004 ZigVar *var = var_ptr->var;13990 ZigVar *var = var_ptr->var;
14005 var->linkage = global_linkage_to_var_linkage(global_linkage_id);13991 add_var_export(ira->codegen, var, symbol_name, global_linkage_id);
14006 }13992 }
14007 }13993 }
1400813994
...@@ -14295,7 +14281,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -14295,7 +14281,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
14295 ConstExprValue *mem_slot = nullptr;14281 ConstExprValue *mem_slot = nullptr;
1429614282
14297 bool comptime_var_mem = ir_get_var_is_comptime(var);14283 bool comptime_var_mem = ir_get_var_is_comptime(var);
14298 bool linkage_makes_it_runtime = var->linkage == VarLinkageExternal;14284 bool linkage_makes_it_runtime = var->decl_node->data.variable_declaration.is_extern;
14299 bool is_const = var->src_is_const;14285 bool is_const = var->src_is_const;
14300 bool is_volatile = false;14286 bool is_volatile = false;
1430114287