From fcc0728a35fe602ff8ad8c28370e901231550dea Mon Sep 17 00:00:00 2001 From: Nicholas Walton Date: Tue, 11 Jun 2019 13:31:03 -0500 Subject: [PATCH 1/9] Update langref.html.in Missing an "it" --- doc/langref.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 9ccf44c05..2623a9d46 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -266,7 +266,7 @@ const Timestamp = struct { {#code_end#}

Doc comments are only allowed in certain places; eventually, it will - become a compile error have a doc comment in an unexpected place, such as + become a compile error to have a doc comment in an unexpected place, such as in the middle of an expression, or just before a non-doc comment.

{#header_close#} From 80fa871f4a087478336692406aaa9ec99eb53754 Mon Sep 17 00:00:00 2001 From: Josh Wolfe Date: Wed, 12 Jun 2019 23:39:53 -0400 Subject: [PATCH 2/9] Add HashMap apis that assert the common case * putNoClobber() for put() * removeAssertDiscard() for remove() --- std/hash_map.zig | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/std/hash_map.zig b/std/hash_map.zig index 733681795..c356f7352 100644 --- a/std/hash_map.zig +++ b/std/hash_map.zig @@ -183,6 +183,11 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 return putAssumeCapacity(self, key, value); } + /// Calls put() and asserts that no kv pair is clobbered. + pub fn putNoClobber(self: *Self, key: K, value: V) !void { + assert((try self.put(key, value)) == null); + } + pub fn putAssumeCapacity(self: *Self, key: K, value: V) ?KV { assert(self.count() < self.entries.len); self.incrementModificationCount(); @@ -203,6 +208,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 return hm.get(key) != null; } + /// Returns any kv pair that was removed. pub fn remove(hm: *Self, key: K) ?KV { if (hm.entries.len == 0) return null; hm.incrementModificationCount(); @@ -236,6 +242,11 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 return null; } + /// Calls remove(), asserts that a kv pair is removed, and discards it. + pub fn removeAssertDiscard(hm: *Self, key: K) void { + assert(hm.remove(key) != null); + } + pub fn iterator(hm: *const Self) Iterator { return Iterator{ .hm = hm, @@ -250,7 +261,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 try other.initCapacity(self.entries.len); var it = self.iterator(); while (it.next()) |entry| { - assert((try other.put(entry.key, entry.value)) == null); + try other.putNoClobber(entry.key, entry.value); } return other; } @@ -392,8 +403,8 @@ test "basic hash map usage" { testing.expect((try map.put(2, 22)) == null); testing.expect((try map.put(3, 33)) == null); testing.expect((try map.put(4, 44)) == null); - testing.expect((try map.put(5, 55)) == null); + map.putNoClobber(5, 55); testing.expect((try map.put(5, 66)).?.value == 55); testing.expect((try map.put(5, 55)).?.value == 66); @@ -422,6 +433,8 @@ test "basic hash map usage" { testing.expect(rmv1.?.value == 22); testing.expect(map.remove(2) == null); testing.expect(map.get(2) == null); + + map.removeAssertDiscard(3); } test "iterator hash map" { @@ -431,9 +444,9 @@ test "iterator hash map" { var reset_map = AutoHashMap(i32, i32).init(&direct_allocator.allocator); defer reset_map.deinit(); - testing.expect((try reset_map.put(1, 11)) == null); - testing.expect((try reset_map.put(2, 22)) == null); - testing.expect((try reset_map.put(3, 33)) == null); + reset_map.putNoClobber(1, 11); + reset_map.putNoClobber(2, 22); + reset_map.putNoClobber(3, 33); var keys = [_]i32{ 3, From 8a2c2da8051c31f75acd93303e87c5cc039207bc Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Wed, 12 Jun 2019 23:48:46 -0600 Subject: [PATCH 3/9] Handle putNoClobber errors --- std/hash_map.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/std/hash_map.zig b/std/hash_map.zig index c356f7352..cb030eab8 100644 --- a/std/hash_map.zig +++ b/std/hash_map.zig @@ -404,7 +404,7 @@ test "basic hash map usage" { testing.expect((try map.put(3, 33)) == null); testing.expect((try map.put(4, 44)) == null); - map.putNoClobber(5, 55); + try map.putNoClobber(5, 55); testing.expect((try map.put(5, 66)).?.value == 55); testing.expect((try map.put(5, 55)).?.value == 66); @@ -444,9 +444,9 @@ test "iterator hash map" { var reset_map = AutoHashMap(i32, i32).init(&direct_allocator.allocator); defer reset_map.deinit(); - reset_map.putNoClobber(1, 11); - reset_map.putNoClobber(2, 22); - reset_map.putNoClobber(3, 33); + try reset_map.putNoClobber(1, 11); + try reset_map.putNoClobber(2, 22); + try reset_map.putNoClobber(3, 33); var keys = [_]i32{ 3, From 82ab006e58230b413277fbffe5c304b83a3767e2 Mon Sep 17 00:00:00 2001 From: Josh Wolfe Date: Thu, 13 Jun 2019 07:26:40 -0400 Subject: [PATCH 4/9] HashMap.getValue() --- std/hash_map.zig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/std/hash_map.zig b/std/hash_map.zig index cb030eab8..df7ba740e 100644 --- a/std/hash_map.zig +++ b/std/hash_map.zig @@ -204,6 +204,10 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 return hm.internalGet(key); } + pub fn getValue(hm: *const Self, key: K) ?V { + return if (hm.get(key)) |kv| kv.value else null; + } + pub fn contains(hm: *const Self, key: K) bool { return hm.get(key) != null; } @@ -427,12 +431,14 @@ test "basic hash map usage" { testing.expect(map.contains(2)); testing.expect(map.get(2).?.value == 22); + testing.expect(map.getValue(2).? == 22); const rmv1 = map.remove(2); testing.expect(rmv1.?.key == 2); testing.expect(rmv1.?.value == 22); testing.expect(map.remove(2) == null); testing.expect(map.get(2) == null); + testing.expect(map.getValue(2) == null); map.removeAssertDiscard(3); } From 9e8db5b7505a6c2e601c8a94b9d8a4282b5df184 Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Wed, 12 Jun 2019 21:09:52 -0600 Subject: [PATCH 5/9] Remove const on argsAlloc --- std/process.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/process.zig b/std/process.zig index 410575297..b39c6e119 100644 --- a/std/process.zig +++ b/std/process.zig @@ -388,7 +388,7 @@ pub fn args() ArgIterator { } /// Caller must call argsFree on result. -pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 { +pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 { if (builtin.os == .wasi) { var count: usize = undefined; var buf_size: usize = undefined; From 42ea2d0d1c3b8cafdfc9a383cbb1bab274eb0140 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 14 Jun 2019 15:20:52 -0400 Subject: [PATCH 6/9] fix `@export` for arrays and allow sections on extern variables previously `@export` for an array would panic with a TODO message. now it will do the export. However, it uses the variable's name rather than the name passed to `@export`. Issue #2679 remains open for that problem. --- src/analyze.cpp | 12 ++---------- src/ir.cpp | 10 +++++++++- test/compile_errors.zig | 20 -------------------- 3 files changed, 11 insertions(+), 31 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index cbf293c7f..04665cc53 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2780,12 +2780,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry); if (fn_proto->section_expr != nullptr) { - if (fn_table_entry->body_node == nullptr) { - add_node_error(g, fn_proto->section_expr, - buf_sprintf("cannot set section of external function '%s'", buf_ptr(&fn_table_entry->symbol_name))); - } else { - analyze_const_string(g, child_scope, fn_proto->section_expr, &fn_table_entry->section_name); - } + analyze_const_string(g, child_scope, fn_proto->section_expr, &fn_table_entry->section_name); } if (fn_table_entry->type_entry->id == ZigTypeIdInvalid) { @@ -3258,10 +3253,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { } if (var_decl->section_expr != nullptr) { - if (var_decl->is_extern) { - add_node_error(g, var_decl->section_expr, - buf_sprintf("cannot set section of external variable '%s'", buf_ptr(var_decl->symbol))); - } else if (!analyze_const_string(g, tld_var->base.parent_scope, var_decl->section_expr, &tld_var->section_name)) { + if (!analyze_const_string(g, tld_var->base.parent_scope, var_decl->section_expr, &tld_var->section_name)) { tld_var->section_name = nullptr; } } diff --git a/src/ir.cpp b/src/ir.cpp index 21d2646c3..a1227fbd9 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -13901,6 +13901,15 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio want_var_export = true; } break; + case ZigTypeIdArray: + if (!type_allowed_in_extern(ira->codegen, target->value.type->data.array.child_type)) { + ir_add_error(ira, target, + buf_sprintf("array element type '%s' not extern-compatible", + buf_ptr(&target->value.type->data.array.child_type->name))); + } else { + want_var_export = true; + } + break; case ZigTypeIdMetaType: { ZigType *type_value = target->value.data.x_type; switch (type_value->id) { @@ -13968,7 +13977,6 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio case ZigTypeIdInt: case ZigTypeIdFloat: case ZigTypeIdPointer: - case ZigTypeIdArray: case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: case ZigTypeIdUndefined: diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 7896a0b73..e85b2f339 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -4645,16 +4645,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:1:1: note: declared here", ); - cases.add( - "setting a section on an extern variable", - \\extern var foo: i32 linksection(".text2"); - \\export fn entry() i32 { - \\ return foo; - \\} - , - "tmp.zig:1:33: error: cannot set section of external variable 'foo'", - ); - cases.add( "setting a section on a local variable", \\export fn entry() i32 { @@ -4665,16 +4655,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:2:30: error: cannot set section of local variable 'foo'", ); - cases.add( - "setting a section on an extern fn", - \\extern fn foo() linksection(".text2") void; - \\export fn entry() void { - \\ foo(); - \\} - , - "tmp.zig:1:29: error: cannot set section of external function 'foo'", - ); - cases.add( "returning address of local variable - simple", \\export fn foo() *i32 { From f8f054b354088eb9e76d9207972022bc1d3dfc28 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 14 Jun 2019 17:23:24 -0400 Subject: [PATCH 7/9] 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 2623a9d46..c18528a2d 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 1a7e2a910..5aa1c78ea 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 04665cc53..c7e35367c 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 57f107235..8d78ef86e 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 12b07ea6b..bdc8de63d 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 a1227fbd9..6c1c84da3 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; From 362c79140fc0638b0f85ed9b2a49f3fead14bb9b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 14 Jun 2019 18:18:43 -0400 Subject: [PATCH 8/9] expose builtin.strip_debug_info zig code now can be made aware that it will not have any debug information available at runtime. --- src/codegen.cpp | 2 ++ src/main.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/codegen.cpp b/src/codegen.cpp index bdc8de63d..88168caff 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7948,6 +7948,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing)); buf_appendf(contents, "pub const valgrind_support = %s;\n", bool_to_str(want_valgrind_support(g))); buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic)); + buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols)); { TargetSubsystem detected_subsystem = detect_subsystem(g); @@ -7988,6 +7989,7 @@ static Error define_builtin_compile_vars(CodeGen *g) { // Only a few things affect builtin.zig cache_buf(&cache_hash, compiler_id); cache_int(&cache_hash, g->build_mode); + cache_bool(&cache_hash, g->strip_debug_symbols); cache_bool(&cache_hash, g->is_test_build); cache_bool(&cache_hash, g->is_single_threaded); cache_int(&cache_hash, g->zig_target->is_native); diff --git a/src/main.cpp b/src/main.cpp index 29c17212c..9c14ba325 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -954,6 +954,7 @@ int main(int argc, char **argv) { case CmdBuiltin: { CodeGen *g = codegen_create(main_pkg_path, nullptr, &target, out_type, build_mode, override_lib_dir, override_std_dir, nullptr, nullptr); + codegen_set_strip(g, strip); g->subsystem = subsystem; g->valgrind_support = valgrind_support; g->want_pic = want_pic; From 7c5ceb0c4cdf5fafadd92b13048bc9878554abc4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 14 Jun 2019 18:45:41 -0400 Subject: [PATCH 9/9] standard library integrates with knowledge of stripped debug info --- src/codegen.cpp | 9 ++++++++- src/target.cpp | 4 ++++ src/target.hpp | 1 + std/debug.zig | 11 +++++++---- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 88168caff..cee8c0ec0 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -203,6 +203,10 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget get_target_triple(&g->triple_str, g->zig_target); g->pointer_size_bytes = target_arch_pointer_bit_width(g->zig_target->arch) / 8; + if (!target_has_debug_info(g->zig_target)) { + g->strip_debug_symbols = true; + } + return g; } @@ -248,6 +252,9 @@ void codegen_set_errmsg_color(CodeGen *g, ErrColor err_color) { void codegen_set_strip(CodeGen *g, bool strip) { g->strip_debug_symbols = strip; + if (!target_has_debug_info(g->zig_target)) { + g->strip_debug_symbols = true; + } } void codegen_set_out_name(CodeGen *g, Buf *out_name) { @@ -7514,7 +7521,7 @@ static bool detect_single_threaded(CodeGen *g) { } static bool detect_err_ret_tracing(CodeGen *g) { - return !target_is_wasm(g->zig_target) && + return !g->strip_debug_symbols && g->build_mode != BuildModeFastRelease && g->build_mode != BuildModeSmallRelease; } diff --git a/src/target.cpp b/src/target.cpp index 7862f6d44..1d7430458 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -1585,3 +1585,7 @@ void target_libc_enum(size_t index, ZigTarget *out_target) { out_target->vendor = ZigLLVM_UnknownVendor; out_target->is_native = false; } + +bool target_has_debug_info(const ZigTarget *target) { + return !target_is_wasm(target); +} diff --git a/src/target.hpp b/src/target.hpp index 7fa99bcda..7fca430df 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -177,6 +177,7 @@ bool target_is_musl(const ZigTarget *target); bool target_is_wasm(const ZigTarget *target); bool target_is_single_threaded(const ZigTarget *target); bool target_supports_stack_probing(const ZigTarget *target); +bool target_has_debug_info(const ZigTarget *target); uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch); diff --git a/std/debug.zig b/std/debug.zig index 253f25071..ae9a5227c 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -85,8 +85,8 @@ fn wantTtyColor() bool { /// TODO multithreaded awareness pub fn dumpCurrentStackTrace(start_addr: ?usize) void { const stderr = getStderrStream() catch return; - if (os.wasi.is_the_target) { - stderr.print("Unable to dump stack trace: unimplemented on WASI\n") catch return; + if (builtin.strip_debug_info) { + stderr.print("Unable to dump stack trace: debug info stripped\n") catch return; return; } const debug_info = getSelfDebugInfo() catch |err| { @@ -151,8 +151,8 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace /// TODO multithreaded awareness pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void { const stderr = getStderrStream() catch return; - if (os.wasi.is_the_target) { - stderr.print("Unable to dump stack trace: unimplemented on WASI\n") catch return; + if (builtin.strip_debug_info) { + stderr.print("Unable to dump stack trace: debug info stripped\n") catch return; return; } const debug_info = getSelfDebugInfo() catch |err| { @@ -223,6 +223,7 @@ pub fn writeStackTrace( debug_info: *DebugInfo, tty_color: bool, ) !void { + if (builtin.strip_debug_info) return error.MissingDebugInfo; var frame_index: usize = 0; var frames_left: usize = std.math.min(stack_trace.index, stack_trace.instruction_addresses.len); @@ -783,6 +784,8 @@ pub const OpenSelfDebugInfoError = error{ }; pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo { + if (builtin.strip_debug_info) + return error.MissingDebugInfo; if (windows.is_the_target) { return openSelfDebugInfoWindows(allocator); }