From f8f054b354088eb9e76d9207972022bc1d3dfc28 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 14 Jun 2019 17:23:24 -0400 Subject: [PATCH] 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 --- doc/langref.html.in | 2 +- src/all_types.hpp | 15 +++------- src/analyze.cpp | 29 ++++++++++---------- src/analyze.hpp | 1 + src/codegen.cpp | 67 +++++++++++++++++++++++++-------------------- src/ir.cpp | 18 ++---------- 6 files changed, 61 insertions(+), 71 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 2623a9d467..c18528a2db 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -6648,7 +6648,7 @@ test "main" { {#header_close#} {#header_open|@export#} -
{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}
+
{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) void{#endsyntax#}

Creates a symbol in the output object file.

diff --git a/src/all_types.hpp b/src/all_types.hpp index 1a7e2a910b..5aa1c78ea1 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1334,7 +1334,7 @@ enum FnInline { FnInlineNever, }; -struct FnExport { +struct GlobalExport { Buf name; GlobalLinkageId linkage; }; @@ -1372,7 +1372,7 @@ struct ZigFn { AstNode *set_cold_node; - ZigList export_list; + ZigList export_list; LLVMValueRef valgrind_client_request_array; @@ -1896,14 +1896,6 @@ struct CodeGen { size_t clang_argv_len; }; -enum VarLinkage { - VarLinkageInternal, - VarLinkageExportStrong, - VarLinkageExportWeak, - VarLinkageExportLinkOnce, - VarLinkageExternal, -}; - struct ZigVar { Buf name; ConstExprValue *const_value; @@ -1926,8 +1918,9 @@ struct ZigVar { // this pointer to the redefined variable. ZigVar *next_var; + ZigList export_list; + uint32_t align_bytes; - VarLinkage linkage; bool shadowable; bool src_is_const; diff --git a/src/analyze.cpp b/src/analyze.cpp index 04665cc53b..c7e35367c3 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2712,6 +2712,13 @@ ZigType *get_test_fn_type(CodeGen *g) { return g->test_fn_type; } +void add_var_export(CodeGen *g, ZigVar *var, Buf *symbol_name, GlobalLinkageId linkage) { + GlobalExport *global_export = var->export_list.add_one(); + memset(global_export, 0, sizeof(GlobalExport)); + buf_init_from_buf(&global_export->name, symbol_name); + global_export->linkage = linkage; +} + void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc) { if (ccc) { 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 } } - FnExport *fn_export = fn_table_entry->export_list.add_one(); - memset(fn_export, 0, sizeof(FnExport)); + GlobalExport *fn_export = fn_table_entry->export_list.add_one(); + memset(fn_export, 0, sizeof(GlobalExport)); buf_init_from_buf(&fn_export->name, symbol_name); fn_export->linkage = linkage; } @@ -3189,15 +3196,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { assert(!is_export || !is_extern); - VarLinkage linkage; - if (is_export) { - linkage = VarLinkageExportStrong; - } else if (is_extern) { - linkage = VarLinkageExternal; - } else { - linkage = VarLinkageInternal; - } - ConstExprValue *init_value = nullptr; // 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) { if (implicit_type->id == ZigTypeIdUnreachable) { add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable")); implicit_type = g->builtin_types.entry_invalid; - } else if ((!is_const || linkage == VarLinkageExternal) && + } else if ((!is_const || is_extern) && (implicit_type->id == ZigTypeIdComptimeFloat || implicit_type->id == ZigTypeIdComptimeInt || implicit_type->id == ZigTypeIdEnumLiteral)) @@ -3227,7 +3225,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { implicit_type = g->builtin_types.entry_invalid; } assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime); - } else if (linkage != VarLinkageExternal) { + } else if (!is_extern) { add_node_error(g, source_node, buf_sprintf("variables must be initialized")); implicit_type = g->builtin_types.entry_invalid; } @@ -3239,7 +3237,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol, is_const, init_val, &tld_var->base, type); - tld_var->var->linkage = linkage; tld_var->var->is_thread_local = is_thread_local; if (implicit_type != nullptr && type_is_invalid(implicit_type)) { @@ -3262,6 +3259,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { add_node_error(g, source_node, buf_sprintf("threadlocal variable cannot be constant")); } + if (is_export) { + add_var_export(g, tld_var->var, &tld_var->var->name, GlobalLinkageIdStrong); + } + g->global_vars.append(tld_var); } diff --git a/src/analyze.hpp b/src/analyze.hpp index 57f1072355..8d78ef86e2 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -198,6 +198,7 @@ ZigPackage *new_anonymous_package(void); Buf *const_value_to_buffer(ConstExprValue *const_val); void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc); +void add_var_export(CodeGen *g, ZigVar *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage); ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name); diff --git a/src/codegen.cpp b/src/codegen.cpp index 12b07ea6bc..bdc8de63d1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -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; } diff --git a/src/ir.cpp b/src/ir.cpp index a1227fbd93..6c1c84da3b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -13791,20 +13791,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value); } -static VarLinkage global_linkage_to_var_linkage(GlobalLinkageId id) { - switch (id) { - case GlobalLinkageIdStrong: - return VarLinkageExportStrong; - case GlobalLinkageIdWeak: - return VarLinkageExportWeak; - case GlobalLinkageIdLinkOnce: - return VarLinkageExportLinkOnce; - case GlobalLinkageIdInternal: - return VarLinkageInternal; - } - zig_unreachable(); -} - static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) { IrInstruction *name = instruction->name->child; Buf *symbol_name = ir_resolve_str(ira, name); @@ -14002,7 +13988,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio if (load_ptr->ptr->id == IrInstructionIdVarPtr) { IrInstructionVarPtr *var_ptr = reinterpret_cast(load_ptr->ptr); ZigVar *var = var_ptr->var; - var->linkage = global_linkage_to_var_linkage(global_linkage_id); + add_var_export(ira->codegen, var, symbol_name, global_linkage_id); } } @@ -14295,7 +14281,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ConstExprValue *mem_slot = nullptr; bool comptime_var_mem = ir_get_var_is_comptime(var); - bool linkage_makes_it_runtime = var->linkage == VarLinkageExternal; + bool linkage_makes_it_runtime = var->decl_node->data.variable_declaration.is_extern; bool is_const = var->src_is_const; bool is_volatile = false;