mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 21:08:36 +00:00
fix liveness analysis and not correctly propagating link errors
We still flush the ELF file even when there are compile errors.
This commit is contained in:
parent
12737c9a30
commit
4d01385e14
@ -867,15 +867,16 @@ pub fn update(self: *Module) !void {
|
||||
try self.deleteDecl(decl);
|
||||
}
|
||||
|
||||
// This is needed before reading the error flags.
|
||||
try self.bin_file.flush();
|
||||
|
||||
self.link_error_flags = self.bin_file.error_flags;
|
||||
std.log.debug(.module, "link_error_flags: {}\n", .{self.link_error_flags});
|
||||
|
||||
// If there are any errors, we anticipate the source files being loaded
|
||||
// to report error messages. Otherwise we unload all source files to save memory.
|
||||
if (self.totalErrorCount() == 0) {
|
||||
if (!self.keep_source_files_loaded) {
|
||||
self.root_scope.unload(self.gpa);
|
||||
}
|
||||
try self.bin_file.flush();
|
||||
if (self.totalErrorCount() == 0 and !self.keep_source_files_loaded) {
|
||||
self.root_scope.unload(self.gpa);
|
||||
}
|
||||
}
|
||||
|
||||
@ -975,6 +976,7 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
|
||||
// lifetime annotations in the ZIR.
|
||||
var decl_arena = decl.typed_value.most_recent.arena.?.promote(self.gpa);
|
||||
defer decl.typed_value.most_recent.arena.?.* = decl_arena.state;
|
||||
std.log.debug(.module, "analyze liveness of {}\n", .{decl.name});
|
||||
try liveness.analyze(self.gpa, &decl_arena.allocator, payload.func.analysis.success);
|
||||
}
|
||||
|
||||
|
||||
@ -369,7 +369,7 @@ pub const ElfFile = struct {
|
||||
const file_size = self.options.program_code_size_hint;
|
||||
const p_align = 0x1000;
|
||||
const off = self.findFreeSpace(file_size, p_align);
|
||||
//std.log.debug(.link, "found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
|
||||
std.log.debug(.link, "found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
|
||||
try self.program_headers.append(self.allocator, .{
|
||||
.p_type = elf.PT_LOAD,
|
||||
.p_offset = off,
|
||||
@ -390,7 +390,7 @@ pub const ElfFile = struct {
|
||||
// page align.
|
||||
const p_align = 0x1000;
|
||||
const off = self.findFreeSpace(file_size, p_align);
|
||||
//std.log.debug(.link, "found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
|
||||
std.log.debug(.link, "found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
|
||||
// TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at.
|
||||
// we'll need to re-use that function anyway, in case the GOT grows and overlaps something
|
||||
// else in virtual memory.
|
||||
@ -412,7 +412,7 @@ pub const ElfFile = struct {
|
||||
assert(self.shstrtab.items.len == 0);
|
||||
try self.shstrtab.append(self.allocator, 0); // need a 0 at position 0
|
||||
const off = self.findFreeSpace(self.shstrtab.items.len, 1);
|
||||
//std.log.debug(.link, "found shstrtab free space 0x{x} to 0x{x}\n", .{ off, off + self.shstrtab.items.len });
|
||||
std.log.debug(.link, "found shstrtab free space 0x{x} to 0x{x}\n", .{ off, off + self.shstrtab.items.len });
|
||||
try self.sections.append(self.allocator, .{
|
||||
.sh_name = try self.makeString(".shstrtab"),
|
||||
.sh_type = elf.SHT_STRTAB,
|
||||
@ -470,7 +470,7 @@ pub const ElfFile = struct {
|
||||
const each_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym);
|
||||
const file_size = self.options.symbol_count_hint * each_size;
|
||||
const off = self.findFreeSpace(file_size, min_align);
|
||||
//std.log.debug(.link, "found symtab free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
|
||||
std.log.debug(.link, "found symtab free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
|
||||
|
||||
try self.sections.append(self.allocator, .{
|
||||
.sh_name = try self.makeString(".symtab"),
|
||||
@ -586,7 +586,7 @@ pub const ElfFile = struct {
|
||||
shstrtab_sect.sh_offset = self.findFreeSpace(needed_size, 1);
|
||||
}
|
||||
shstrtab_sect.sh_size = needed_size;
|
||||
//std.log.debug(.link, "shstrtab start=0x{x} end=0x{x}\n", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size });
|
||||
std.log.debug(.link, "shstrtab start=0x{x} end=0x{x}\n", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size });
|
||||
|
||||
try self.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset);
|
||||
if (!self.shdr_table_dirty) {
|
||||
@ -632,7 +632,7 @@ pub const ElfFile = struct {
|
||||
|
||||
for (buf) |*shdr, i| {
|
||||
shdr.* = self.sections.items[i];
|
||||
//std.log.debug(.link, "writing section {}\n", .{shdr.*});
|
||||
std.log.debug(.link, "writing section {}\n", .{shdr.*});
|
||||
if (foreign_endian) {
|
||||
bswapAllFields(elf.Elf64_Shdr, shdr);
|
||||
}
|
||||
@ -643,6 +643,7 @@ pub const ElfFile = struct {
|
||||
self.shdr_table_dirty = false;
|
||||
}
|
||||
if (self.entry_addr == null and self.options.output_mode == .Exe) {
|
||||
std.log.debug(.link, "no_entry_point_found = true\n", .{});
|
||||
self.error_flags.no_entry_point_found = true;
|
||||
} else {
|
||||
self.error_flags.no_entry_point_found = false;
|
||||
@ -956,10 +957,10 @@ pub const ElfFile = struct {
|
||||
try self.offset_table_free_list.ensureCapacity(self.allocator, self.local_symbols.items.len);
|
||||
|
||||
if (self.local_symbol_free_list.popOrNull()) |i| {
|
||||
//std.log.debug(.link, "reusing symbol index {} for {}\n", .{i, decl.name});
|
||||
std.log.debug(.link, "reusing symbol index {} for {}\n", .{i, decl.name});
|
||||
decl.link.local_sym_index = i;
|
||||
} else {
|
||||
//std.log.debug(.link, "allocating symbol index {} for {}\n", .{self.local_symbols.items.len, decl.name});
|
||||
std.log.debug(.link, "allocating symbol index {} for {}\n", .{self.local_symbols.items.len, decl.name});
|
||||
decl.link.local_sym_index = @intCast(u32, self.local_symbols.items.len);
|
||||
_ = self.local_symbols.addOneAssumeCapacity();
|
||||
}
|
||||
@ -1027,11 +1028,11 @@ pub const ElfFile = struct {
|
||||
!mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment);
|
||||
if (need_realloc) {
|
||||
const vaddr = try self.growTextBlock(&decl.link, code.len, required_alignment);
|
||||
//std.log.debug(.link, "growing {} from 0x{x} to 0x{x}\n", .{ decl.name, local_sym.st_value, vaddr });
|
||||
std.log.debug(.link, "growing {} from 0x{x} to 0x{x}\n", .{ decl.name, local_sym.st_value, vaddr });
|
||||
if (vaddr != local_sym.st_value) {
|
||||
local_sym.st_value = vaddr;
|
||||
|
||||
//std.log.debug(.link, " (writing new offset table entry)\n", .{});
|
||||
std.log.debug(.link, " (writing new offset table entry)\n", .{});
|
||||
self.offset_table.items[decl.link.offset_table_index] = vaddr;
|
||||
try self.writeOffsetTableEntry(decl.link.offset_table_index);
|
||||
}
|
||||
@ -1049,7 +1050,7 @@ pub const ElfFile = struct {
|
||||
const decl_name = mem.spanZ(decl.name);
|
||||
const name_str_index = try self.makeString(decl_name);
|
||||
const vaddr = try self.allocateTextBlock(&decl.link, code.len, required_alignment);
|
||||
//std.log.debug(.link, "allocated text block for {} at 0x{x}\n", .{ decl_name, vaddr });
|
||||
std.log.debug(.link, "allocated text block for {} at 0x{x}\n", .{ decl_name, vaddr });
|
||||
errdefer self.freeTextBlock(&decl.link);
|
||||
|
||||
local_sym.* = .{
|
||||
|
||||
@ -25,24 +25,27 @@ fn analyzeWithTable(arena: *std.mem.Allocator, table: *std.AutoHashMap(*ir.Inst,
|
||||
while (i != 0) {
|
||||
i -= 1;
|
||||
const base = body.instructions[i];
|
||||
|
||||
// Obtain the corresponding instruction type based on the tag type.
|
||||
inline for (std.meta.declarations(ir.Inst)) |decl| {
|
||||
switch (decl.data) {
|
||||
.Type => |T| {
|
||||
if (@hasDecl(T, "base_tag")) {
|
||||
if (T.base_tag == base.tag) {
|
||||
return analyzeInst(arena, table, T, @fieldParentPtr(T, "base", base));
|
||||
}
|
||||
}
|
||||
},
|
||||
else => continue,
|
||||
}
|
||||
}
|
||||
unreachable;
|
||||
try analyzeInstGeneric(arena, table, base);
|
||||
}
|
||||
}
|
||||
|
||||
fn analyzeInstGeneric(arena: *std.mem.Allocator, table: *std.AutoHashMap(*ir.Inst, void), base: *ir.Inst) error{OutOfMemory}!void {
|
||||
// Obtain the corresponding instruction type based on the tag type.
|
||||
inline for (std.meta.declarations(ir.Inst)) |decl| {
|
||||
switch (decl.data) {
|
||||
.Type => |T| {
|
||||
if (@hasDecl(T, "base_tag")) {
|
||||
if (T.base_tag == base.tag) {
|
||||
return analyzeInst(arena, table, T, @fieldParentPtr(T, "base", base));
|
||||
}
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
unreachable;
|
||||
}
|
||||
|
||||
fn analyzeInst(arena: *std.mem.Allocator, table: *std.AutoHashMap(*ir.Inst, void), comptime T: type, inst: *T) error{OutOfMemory}!void {
|
||||
inst.base.deaths = 0;
|
||||
|
||||
@ -131,4 +134,6 @@ fn analyzeInst(arena: *std.mem.Allocator, table: *std.AutoHashMap(*ir.Inst, void
|
||||
arg_index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
std.log.debug(.liveness, "analyze {}: 0b{b}\n", .{inst.base.tag, inst.base.deaths});
|
||||
}
|
||||
|
||||
@ -50,7 +50,10 @@ pub fn log(
|
||||
const scope_prefix = "(" ++ switch (scope) {
|
||||
// Uncomment to hide logs
|
||||
//.compiler,
|
||||
.link => return,
|
||||
.module,
|
||||
.liveness,
|
||||
.link,
|
||||
=> return,
|
||||
|
||||
else => @tagName(scope),
|
||||
} ++ "): ";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user