wasm: move incremental Dwarf info into ZigObject

This commit is contained in:
Luuk de Gram 2024-01-14 15:36:28 +01:00
parent ba0e84a411
commit e54177e852
No known key found for this signature in database
GPG Key ID: A8CFE58E4DC7D664
4 changed files with 326 additions and 1163 deletions

View File

@ -3191,7 +3191,6 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.Decl
const target_sym_index = atom.sym_index;
if (decl.ty.zigTypeTag(mod) == .Fn) {
try func.bin_file.addTableFunction(target_sym_index);
return WValue{ .function_index = target_sym_index };
} else if (offset == 0) {
return WValue{ .memory = target_sym_index };

View File

@ -1297,9 +1297,9 @@ pub fn commitDeclState(
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_line = wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code;
writeDbgLineNopsBuffered(debug_line.items, src_fn.off, 0, &.{}, src_fn.len);
// const wasm_file = self.bin_file.cast(File.Wasm).?;
// const debug_line = wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code;
// writeDbgLineNopsBuffered(debug_line.items, src_fn.off, 0, &.{}, src_fn.len);
},
else => unreachable,
}
@ -1390,26 +1390,26 @@ pub fn commitDeclState(
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
const atom = wasm_file.getAtomPtr(wasm_file.debug_line_atom.?);
const debug_line = &atom.code;
const segment_size = debug_line.items.len;
if (needed_size != segment_size) {
log.debug(" needed size does not equal allocated size: {d}", .{needed_size});
if (needed_size > segment_size) {
log.debug(" allocating {d} bytes for 'debug line' information", .{needed_size - segment_size});
try debug_line.resize(self.allocator, needed_size);
@memset(debug_line.items[segment_size..], 0);
}
debug_line.items.len = needed_size;
}
writeDbgLineNopsBuffered(
debug_line.items,
src_fn.off,
prev_padding_size,
dbg_line_buffer.items,
next_padding_size,
);
// const wasm_file = self.bin_file.cast(File.Wasm).?;
// const atom = wasm_file.getAtomPtr(wasm_file.debug_line_atom.?);
// const debug_line = &atom.code;
// const segment_size = debug_line.items.len;
// if (needed_size != segment_size) {
// log.debug(" needed size does not equal allocated size: {d}", .{needed_size});
// if (needed_size > segment_size) {
// log.debug(" allocating {d} bytes for 'debug line' information", .{needed_size - segment_size});
// try debug_line.resize(self.allocator, needed_size);
// @memset(debug_line.items[segment_size..], 0);
// }
// debug_line.items.len = needed_size;
// }
// writeDbgLineNopsBuffered(
// debug_line.items,
// src_fn.off,
// prev_padding_size,
// dbg_line_buffer.items,
// next_padding_size,
// );
},
else => unreachable,
}
@ -1553,10 +1553,10 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32)
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_info_index = wasm_file.debug_info_atom.?;
const debug_info = &wasm_file.getAtomPtr(debug_info_index).code;
try writeDbgInfoNopsToArrayList(gpa, debug_info, atom.off, 0, &.{0}, atom.len, false);
// const wasm_file = self.bin_file.cast(File.Wasm).?;
// const debug_info_index = wasm_file.debug_info_atom.?;
// const debug_info = &wasm_file.getAtomPtr(debug_info_index).code;
// try writeDbgInfoNopsToArrayList(gpa, debug_info, atom.off, 0, &.{0}, atom.len, false);
},
else => unreachable,
}
@ -1594,7 +1594,6 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons
// This logic is nearly identical to the logic above in `updateDecl` for
// `SrcFn` and the line number programs. If you are editing this logic, you
// probably need to edit that logic too.
const gpa = self.allocator;
const atom = self.getAtom(.di_atom, atom_index);
const last_decl_index = self.di_atom_last_index.?;
@ -1665,31 +1664,31 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
const info_atom = wasm_file.debug_info_atom.?;
const debug_info = &wasm_file.getAtomPtr(info_atom).code;
const segment_size = debug_info.items.len;
if (needed_size != segment_size) {
log.debug(" needed size does not equal allocated size: {d}", .{needed_size});
if (needed_size > segment_size) {
log.debug(" allocating {d} bytes for 'debug info' information", .{needed_size - segment_size});
try debug_info.resize(self.allocator, needed_size);
@memset(debug_info.items[segment_size..], 0);
}
debug_info.items.len = needed_size;
}
log.debug(" writeDbgInfoNopsToArrayList debug_info_len={d} offset={d} content_len={d} next_padding_size={d}", .{
debug_info.items.len, atom.off, dbg_info_buf.len, next_padding_size,
});
try writeDbgInfoNopsToArrayList(
gpa,
debug_info,
atom.off,
prev_padding_size,
dbg_info_buf,
next_padding_size,
trailing_zero,
);
// const wasm_file = self.bin_file.cast(File.Wasm).?;
// const info_atom = wasm_file.debug_info_atom.?;
// const debug_info = &wasm_file.getAtomPtr(info_atom).code;
// const segment_size = debug_info.items.len;
// if (needed_size != segment_size) {
// log.debug(" needed size does not equal allocated size: {d}", .{needed_size});
// if (needed_size > segment_size) {
// log.debug(" allocating {d} bytes for 'debug info' information", .{needed_size - segment_size});
// try debug_info.resize(self.allocator, needed_size);
// @memset(debug_info.items[segment_size..], 0);
// }
// debug_info.items.len = needed_size;
// }
// log.debug(" writeDbgInfoNopsToArrayList debug_info_len={d} offset={d} content_len={d} next_padding_size={d}", .{
// debug_info.items.len, atom.off, dbg_info_buf.len, next_padding_size,
// });
// try writeDbgInfoNopsToArrayList(
// gpa,
// debug_info,
// atom.off,
// prev_padding_size,
// dbg_info_buf,
// next_padding_size,
// trailing_zero,
// );
},
else => unreachable,
}
@ -1735,10 +1734,10 @@ pub fn updateDeclLineNumber(self: *Dwarf, mod: *Module, decl_index: InternPool.D
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
const offset = atom.off + self.getRelocDbgLineOff();
const line_atom_index = wasm_file.debug_line_atom.?;
wasm_file.getAtomPtr(line_atom_index).code.items[offset..][0..data.len].* = data;
// const wasm_file = self.bin_file.cast(File.Wasm).?;
// const offset = atom.off + self.getRelocDbgLineOff();
// const line_atom_index = wasm_file.debug_line_atom.?;
// wasm_file.getAtomPtr(line_atom_index).code.items[offset..][0..data.len].* = data;
},
else => unreachable,
}
@ -1803,7 +1802,6 @@ pub fn freeDecl(self: *Dwarf, decl_index: InternPool.DeclIndex) void {
}
pub fn writeDbgAbbrev(self: *Dwarf) !void {
const gpa = self.allocator;
// These are LEB encoded but since the values are all less than 127
// we can simply append these bytes.
// zig fmt: off
@ -1960,10 +1958,10 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_abbrev = &wasm_file.getAtomPtr(wasm_file.debug_abbrev_atom.?).code;
try debug_abbrev.resize(gpa, needed_size);
debug_abbrev.items[0..abbrev_buf.len].* = abbrev_buf;
// const wasm_file = self.bin_file.cast(File.Wasm).?;
// const debug_abbrev = &wasm_file.getAtomPtr(wasm_file.debug_abbrev_atom.?).code;
// try debug_abbrev.resize(gpa, needed_size);
// debug_abbrev.items[0..abbrev_buf.len].* = abbrev_buf;
},
else => unreachable,
}
@ -2055,9 +2053,9 @@ pub fn writeDbgInfoHeader(self: *Dwarf, zcu: *Module, low_pc: u64, high_pc: u64)
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_info = &wasm_file.getAtomPtr(wasm_file.debug_info_atom.?).code;
try writeDbgInfoNopsToArrayList(self.allocator, debug_info, 0, 0, di_buf.items, jmp_amt, false);
// const wasm_file = self.bin_file.cast(File.Wasm).?;
// const debug_info = &wasm_file.getAtomPtr(wasm_file.debug_info_atom.?).code;
// try writeDbgInfoNopsToArrayList(self.allocator, debug_info, 0, 0, di_buf.items, jmp_amt, false);
},
else => unreachable,
}
@ -2318,7 +2316,6 @@ fn writeDbgInfoNopsToArrayList(
pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
const comp = self.bin_file.comp;
const gpa = comp.gpa;
const target = comp.root_mod.resolved_target.result;
const target_endian = target.cpu.arch.endian();
const ptr_width_bytes = self.ptrWidthBytes();
@ -2391,10 +2388,10 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_ranges = &wasm_file.getAtomPtr(wasm_file.debug_ranges_atom.?).code;
try debug_ranges.resize(gpa, needed_size);
@memcpy(debug_ranges.items[0..di_buf.items.len], di_buf.items);
// const wasm_file = self.bin_file.cast(File.Wasm).?;
// const debug_ranges = &wasm_file.getAtomPtr(wasm_file.debug_ranges_atom.?).code;
// try debug_ranges.resize(gpa, needed_size);
// @memcpy(debug_ranges.items[0..di_buf.items.len], di_buf.items);
},
else => unreachable,
}
@ -2548,14 +2545,15 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_line = &wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code;
{
const src = debug_line.items[first_fn.off..];
@memcpy(buffer[0..src.len], src);
}
try debug_line.resize(self.allocator, debug_line.items.len + delta);
@memcpy(debug_line.items[first_fn.off + delta ..][0..buffer.len], buffer);
_ = &buffer;
// const wasm_file = self.bin_file.cast(File.Wasm).?;
// const debug_line = &wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code;
// {
// const src = debug_line.items[first_fn.off..];
// @memcpy(buffer[0..src.len], src);
// }
// try debug_line.resize(self.allocator, debug_line.items.len + delta);
// @memcpy(debug_line.items[first_fn.off + delta ..][0..buffer.len], buffer);
},
else => unreachable,
}
@ -2604,9 +2602,9 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_line = &wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code;
writeDbgLineNopsBuffered(debug_line.items, 0, 0, di_buf.items, jmp_amt);
// const wasm_file = self.bin_file.cast(File.Wasm).?;
// const debug_line = &wasm_file.getAtomPtr(wasm_file.debug_line_atom.?).code;
// writeDbgLineNopsBuffered(debug_line.items, 0, 0, di_buf.items, jmp_amt);
},
else => unreachable,
}
@ -2754,9 +2752,9 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
}
},
.wasm => {
const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_info = wasm_file.getAtomPtr(wasm_file.debug_info_atom.?).code;
debug_info.items[atom.off + reloc.offset ..][0..buf.len].* = buf;
// const wasm_file = self.bin_file.cast(File.Wasm).?;
// const debug_info = wasm_file.getAtomPtr(wasm_file.debug_info_atom.?).code;
// debug_info.items[atom.off + reloc.offset ..][0..buf.len].* = buf;
},
else => unreachable,
}

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,36 @@ imported_globals_count: u32 = 0,
/// of a new `ZigObject`. Codegen will make calls into this to create relocations for
/// this symbol each time the stack pointer is moved.
stack_pointer_sym: u32,
/// Debug information for the Zig module.
dwarf: ?Dwarf = null,
// Debug section atoms. These are only set when the current compilation
// unit contains Zig code. The lifetime of these atoms are extended
// until the end of the compiler's lifetime. Meaning they're not freed
// during `flush()` in incremental-mode.
debug_info_atom: ?Atom.Index = null,
debug_line_atom: ?Atom.Index = null,
debug_loc_atom: ?Atom.Index = null,
debug_ranges_atom: ?Atom.Index = null,
debug_abbrev_atom: ?Atom.Index = null,
debug_str_atom: ?Atom.Index = null,
debug_pubnames_atom: ?Atom.Index = null,
debug_pubtypes_atom: ?Atom.Index = null,
/// The index of the segment representing the custom '.debug_info' section.
debug_info_index: ?u32 = null,
/// The index of the segment representing the custom '.debug_line' section.
debug_line_index: ?u32 = null,
/// The index of the segment representing the custom '.debug_loc' section.
debug_loc_index: ?u32 = null,
/// The index of the segment representing the custom '.debug_ranges' section.
debug_ranges_index: ?u32 = null,
/// The index of the segment representing the custom '.debug_pubnames' section.
debug_pubnames_index: ?u32 = null,
/// The index of the segment representing the custom '.debug_pubtypes' section.
debug_pubtypes_index: ?u32 = null,
/// The index of the segment representing the custom '.debug_pubtypes' section.
debug_str_index: ?u32 = null,
/// The index of the segment representing the custom '.debug_pubtypes' section.
debug_abbrev_index: ?u32 = null,
/// Frees and invalidates all memory of the incrementally compiled Zig module.
/// It is illegal behavior to access the `ZigObject` after calling `deinit`.
@ -80,6 +110,9 @@ pub fn deinit(zig_object: *ZigObject, gpa: std.mem.Allocator) void {
zig_object.segment_info.deinit(gpa);
zig_object.string_table.deinit(gpa);
if (zig_object.dwarf) |*dwarf| {
dwarf.deinit();
}
zig_object.* = undefined;
}
@ -976,6 +1009,87 @@ fn setupErrorsLen(zig_object: *ZigObject, wasm_file: *Wasm) !void {
// try wasm.parseAtom(atom_index, .{ .data = .read_only });
}
/// Initializes symbols and atoms for the debug sections
/// Initialization is only done when compiling Zig code.
/// When Zig is invoked as a linker instead, the atoms
/// and symbols come from the object files instead.
pub fn initDebugSections(zig_object: *ZigObject) !void {
if (zig_object.dwarf == null) return; // not compiling Zig code, so no need to pre-initialize debug sections
std.debug.assert(zig_object.debug_info_index == null);
// this will create an Atom and set the index for us.
zig_object.debug_info_atom = try zig_object.createDebugSectionForIndex(&zig_object.debug_info_index, ".debug_info");
zig_object.debug_line_atom = try zig_object.createDebugSectionForIndex(&zig_object.debug_line_index, ".debug_line");
zig_object.debug_loc_atom = try zig_object.createDebugSectionForIndex(&zig_object.debug_loc_index, ".debug_loc");
zig_object.debug_abbrev_atom = try zig_object.createDebugSectionForIndex(&zig_object.debug_abbrev_index, ".debug_abbrev");
zig_object.debug_ranges_atom = try zig_object.createDebugSectionForIndex(&zig_object.debug_ranges_index, ".debug_ranges");
zig_object.debug_str_atom = try zig_object.createDebugSectionForIndex(&zig_object.debug_str_index, ".debug_str");
zig_object.debug_pubnames_atom = try zig_object.createDebugSectionForIndex(&zig_object.debug_pubnames_index, ".debug_pubnames");
zig_object.debug_pubtypes_atom = try zig_object.createDebugSectionForIndex(&zig_object.debug_pubtypes_index, ".debug_pubtypes");
}
/// From a given index variable, creates a new debug section.
/// This initializes the index, appends a new segment,
/// and finally, creates a managed `Atom`.
pub fn createDebugSectionForIndex(zig_object: *ZigObject, wasm_file: *Wasm, index: *?u32, name: []const u8) !Atom.Index {
const gpa = wasm_file.base.comp.gpa;
const new_index: u32 = @intCast(zig_object.segments.items.len);
index.* = new_index;
try zig_object.appendDummySegment();
const sym_index = try zig_object.allocateSymbol(gpa);
const atom_index = try wasm_file.createAtom(sym_index);
const atom = wasm_file.getAtomPtr(atom_index);
zig_object.symbols.items[sym_index] = .{
.tag = .section,
.name = try zig_object.string_table.put(gpa, name),
.index = 0,
.flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL),
};
atom.alignment = .@"1"; // debug sections are always 1-byte-aligned
return atom_index;
}
pub fn updateDeclLineNumber(zig_object: *ZigObject, mod: *Module, decl_index: InternPool.DeclIndex) !void {
if (zig_object.dwarf) |*dw| {
const decl = mod.declPtr(decl_index);
const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });
try dw.updateDeclLineNumber(mod, decl_index);
}
}
/// Allocates debug atoms into their respective debug sections
/// to merge them with maybe-existing debug atoms from object files.
fn allocateDebugAtoms(zig_object: *ZigObject) !void {
if (zig_object.dwarf == null) return;
const allocAtom = struct {
fn f(ctx: *ZigObject, maybe_index: *?u32, atom_index: Atom.Index) !void {
const index = maybe_index.* orelse idx: {
const index = @as(u32, @intCast(ctx.segments.items.len));
try ctx.appendDummySegment();
maybe_index.* = index;
break :idx index;
};
const atom = ctx.getAtomPtr(atom_index);
atom.size = @as(u32, @intCast(atom.code.items.len));
ctx.symbols.items[atom.sym_index].index = index;
try ctx.appendAtomAtIndex(index, atom_index);
}
}.f;
try allocAtom(zig_object, &zig_object.debug_info_index, zig_object.debug_info_atom.?);
try allocAtom(zig_object, &zig_object.debug_line_index, zig_object.debug_line_atom.?);
try allocAtom(zig_object, &zig_object.debug_loc_index, zig_object.debug_loc_atom.?);
try allocAtom(zig_object, &zig_object.debug_str_index, zig_object.debug_str_atom.?);
try allocAtom(zig_object, &zig_object.debug_ranges_index, zig_object.debug_ranges_atom.?);
try allocAtom(zig_object, &zig_object.debug_abbrev_index, zig_object.debug_abbrev_atom.?);
try allocAtom(zig_object, &zig_object.debug_pubnames_index, zig_object.debug_pubnames_atom.?);
try allocAtom(zig_object, &zig_object.debug_pubtypes_index, zig_object.debug_pubtypes_atom.?);
}
const build_options = @import("build_options");
const builtin = @import("builtin");
const codegen = @import("../../codegen.zig");
@ -986,6 +1100,7 @@ const types = @import("types.zig");
const Air = @import("../../Air.zig");
const Atom = @import("Atom.zig");
const Dwarf = @import("../Dwarf.zig");
const InternPool = @import("../../InternPool.zig");
const Liveness = @import("../../Liveness.zig");
const Module = @import("../../Module.zig");