authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-08 18:19:48-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-08 18:19:48-07:00
logfd47839064775c0cc956f12a012f0893e1f3a440
tree230142a7a89e36ad5e7a6d9a4ef9c1434ec0e8ac
parent069a6f2432be5fd5e9a3eabd13faa43143001bbd

stage2: fix crash on empty source file


4 files changed, 20 insertions(+), 10 deletions(-)

src-self-hosted/Module.zig+3-5
...@@ -949,10 +949,8 @@ pub fn update(self: *Module) !void {...@@ -949,10 +949,8 @@ pub fn update(self: *Module) !void {
949 try self.deleteDecl(decl);949 try self.deleteDecl(decl);
950 }950 }
951951
952 if (self.totalErrorCount() == 0) {952 // This is needed before reading the error flags.
953 // This is needed before reading the error flags.953 try self.bin_file.flush();
954 try self.bin_file.flush();
955 }
956954
957 self.link_error_flags = self.bin_file.errorFlags();955 self.link_error_flags = self.bin_file.errorFlags();
958956
...@@ -2537,7 +2535,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst...@@ -2537,7 +2535,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst
2537 }2535 }
2538 }2536 }
25392537
2540 return self.fail(scope, inst.src, "TODO implement type coercion from {} to {}", .{ inst.ty, dest_type });2538 return self.fail(scope, inst.src, "expected {}, found {}", .{ dest_type, inst.ty });
2541}2539}
25422540
2543pub fn storePtr(self: *Module, scope: *Scope, src: usize, ptr: *Inst, uncasted_value: *Inst) !*Inst {2541pub fn storePtr(self: *Module, scope: *Scope, src: usize, ptr: *Inst, uncasted_value: *Inst) !*Inst {
src-self-hosted/link.zig+10-4
...@@ -1172,7 +1172,10 @@ pub const File = struct {...@@ -1172,7 +1172,10 @@ pub const File = struct {
11721172
1173 self.debug_aranges_section_dirty = false;1173 self.debug_aranges_section_dirty = false;
1174 }1174 }
1175 if (self.debug_line_header_dirty) {1175 if (self.debug_line_header_dirty) debug_line: {
1176 if (self.dbg_line_fn_first == null) {
1177 break :debug_line; // Error in module; leave debug_line_header_dirty=true.
1178 }
1176 const dbg_line_prg_off = self.getDebugLineProgramOff();1179 const dbg_line_prg_off = self.getDebugLineProgramOff();
1177 const dbg_line_prg_end = self.getDebugLineProgramEnd();1180 const dbg_line_prg_end = self.getDebugLineProgramEnd();
1178 assert(dbg_line_prg_end != 0);1181 assert(dbg_line_prg_end != 0);
...@@ -1403,18 +1406,21 @@ pub const File = struct {...@@ -1403,18 +1406,21 @@ pub const File = struct {
1403 self.shdr_table_dirty = false;1406 self.shdr_table_dirty = false;
1404 }1407 }
1405 if (self.entry_addr == null and self.base.options.output_mode == .Exe) {1408 if (self.entry_addr == null and self.base.options.output_mode == .Exe) {
1406 log.debug(.link, "no_entry_point_found = true\n", .{});1409 log.debug(.link, "flushing. no_entry_point_found = true\n", .{});
1407 self.error_flags.no_entry_point_found = true;1410 self.error_flags.no_entry_point_found = true;
1408 } else {1411 } else {
1412 log.debug(.link, "flushing. no_entry_point_found = false\n", .{});
1409 self.error_flags.no_entry_point_found = false;1413 self.error_flags.no_entry_point_found = false;
1410 try self.writeElfHeader();1414 try self.writeElfHeader();
1411 }1415 }
14121416
1413 // The point of flush() is to commit changes, so nothing should be dirty after this.1417 // The point of flush() is to commit changes, so in theory, nothing should
1418 // be dirty after this. However, it is possible for some things to remain
1419 // dirty because they fail to be written in the event of compile errors,
1420 // such as debug_line_header_dirty.
1414 assert(!self.debug_info_section_dirty);1421 assert(!self.debug_info_section_dirty);
1415 assert(!self.debug_abbrev_section_dirty);1422 assert(!self.debug_abbrev_section_dirty);
1416 assert(!self.debug_aranges_section_dirty);1423 assert(!self.debug_aranges_section_dirty);
1417 assert(!self.debug_line_header_dirty);
1418 assert(!self.phdr_table_dirty);1424 assert(!self.phdr_table_dirty);
1419 assert(!self.shdr_table_dirty);1425 assert(!self.shdr_table_dirty);
1420 assert(!self.shstrtab_dirty);1426 assert(!self.shstrtab_dirty);
src-self-hosted/main.zig+3
...@@ -64,6 +64,9 @@ var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};...@@ -64,6 +64,9 @@ var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
6464
65pub fn main() !void {65pub fn main() !void {
66 const gpa = if (std.builtin.link_libc) std.heap.c_allocator else &general_purpose_allocator.allocator;66 const gpa = if (std.builtin.link_libc) std.heap.c_allocator else &general_purpose_allocator.allocator;
67 defer if (!std.builtin.link_libc) {
68 _ = general_purpose_allocator.deinit();
69 };
67 var arena_instance = std.heap.ArenaAllocator.init(gpa);70 var arena_instance = std.heap.ArenaAllocator.init(gpa);
68 defer arena_instance.deinit();71 defer arena_instance.deinit();
69 const arena = &arena_instance.allocator;72 const arena = &arena_instance.allocator;
test/stage2/compare_output.zig+4-1
...@@ -23,6 +23,9 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -23,6 +23,9 @@ pub fn addCases(ctx: *TestContext) !void {
2323
24 {24 {
25 var case = ctx.exe("hello world with updates", linux_x64);25 var case = ctx.exe("hello world with updates", linux_x64);
26
27 case.addError("", &[_][]const u8{":1:1: error: no entry point found"});
28
26 // Regular old hello world29 // Regular old hello world
27 case.addCompareOutput(30 case.addCompareOutput(
28 \\export fn _start() noreturn {31 \\export fn _start() noreturn {
...@@ -123,7 +126,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -123,7 +126,7 @@ pub fn addCases(ctx: *TestContext) !void {
123 \\126 \\
124 );127 );
125 }128 }
126 129
127 {130 {
128 var case = ctx.exe("hello world", linux_riscv64);131 var case = ctx.exe("hello world", linux_riscv64);
129 // Regular old hello world132 // Regular old hello world