mirror of
https://github.com/ziglang/zig.git
synced 2026-02-18 23:39:17 +00:00
dwarf: pass DeclState around instead of storing a temp global in Dwarf
Avoids many pitfalls connected with premature/early return in case there are errors with Decl, etc. This is effectively bringing back the old design however in a much nicer packaging, where every mechanism related to tracking Decl's debug info is now nicely wrapped in a single struct (aka the `DeclState`). This includes relocation table, type arena, etc. It is now the caller's responsibility to deinit the state (so that no memory is leaked) after `Decl` has been analysed (or errored out). The caller here is typically a linker such as `Elf` or `MachO`.
This commit is contained in:
parent
b73cf97c93
commit
f5d9160f1b
@ -390,7 +390,7 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
|
||||
// TODO Look into using the DWARF special opcodes to compress this data.
|
||||
// It lets you emit single-byte opcodes that add different numbers to
|
||||
// both the PC and the line number at the same time.
|
||||
const dbg_line = dw.getDeclDebugLineBuffer();
|
||||
const dbg_line = &dw.dbg_line;
|
||||
try dbg_line.ensureUnusedCapacity(11);
|
||||
dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
|
||||
leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;
|
||||
@ -588,7 +588,7 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
fn mirDebugPrologueEnd(self: *Emit) !void {
|
||||
switch (self.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end);
|
||||
try dw.dbg_line.append(DW.LNS.set_prologue_end);
|
||||
try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
|
||||
},
|
||||
.plan9 => {},
|
||||
@ -599,7 +599,7 @@ fn mirDebugPrologueEnd(self: *Emit) !void {
|
||||
fn mirDebugEpilogueBegin(self: *Emit) !void {
|
||||
switch (self.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin);
|
||||
try dw.dbg_line.append(DW.LNS.set_epilogue_begin);
|
||||
try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
|
||||
},
|
||||
.plan9 => {},
|
||||
|
||||
@ -332,7 +332,7 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
|
||||
// TODO Look into using the DWARF special opcodes to compress this data.
|
||||
// It lets you emit single-byte opcodes that add different numbers to
|
||||
// both the PC and the line number at the same time.
|
||||
const dbg_line = dw.getDeclDebugLineBuffer();
|
||||
const dbg_line = &dw.dbg_line;
|
||||
try dbg_line.ensureUnusedCapacity(11);
|
||||
dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
|
||||
leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;
|
||||
@ -382,7 +382,7 @@ fn addDbgInfoTypeReloc(self: *Emit, ty: Type) !void {
|
||||
switch (self.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
assert(ty.hasRuntimeBits());
|
||||
const dbg_info = dw.getDeclDebugInfoBuffer();
|
||||
const dbg_info = &dw.dbg_info;
|
||||
const index = dbg_info.items.len;
|
||||
try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
|
||||
const atom = switch (self.bin_file.tag) {
|
||||
@ -409,7 +409,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
|
||||
.register => |reg| {
|
||||
switch (self.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
const dbg_info = dw.getDeclDebugInfoBuffer();
|
||||
const dbg_info = &dw.dbg_info;
|
||||
try dbg_info.ensureUnusedCapacity(3);
|
||||
dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
|
||||
dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
|
||||
@ -442,7 +442,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
const dbg_info = dw.getDeclDebugInfoBuffer();
|
||||
const dbg_info = &dw.dbg_info;
|
||||
try dbg_info.append(link.File.Dwarf.abbrev_parameter);
|
||||
|
||||
// Get length of the LEB128 stack offset
|
||||
@ -560,7 +560,7 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
fn mirDebugPrologueEnd(emit: *Emit) !void {
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end);
|
||||
try dw.dbg_line.append(DW.LNS.set_prologue_end);
|
||||
try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
|
||||
},
|
||||
.plan9 => {},
|
||||
@ -571,7 +571,7 @@ fn mirDebugPrologueEnd(emit: *Emit) !void {
|
||||
fn mirDebugEpilogueBegin(emit: *Emit) !void {
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin);
|
||||
try dw.dbg_line.append(DW.LNS.set_epilogue_begin);
|
||||
try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
|
||||
},
|
||||
.plan9 => {},
|
||||
|
||||
@ -749,7 +749,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
|
||||
switch (self.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
assert(ty.hasRuntimeBits());
|
||||
const dbg_info = dw.getDeclDebugInfoBuffer();
|
||||
const dbg_info = &dw.dbg_info;
|
||||
const index = dbg_info.items.len;
|
||||
try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
|
||||
const atom = switch (self.bin_file.tag) {
|
||||
@ -1572,7 +1572,7 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32
|
||||
.register => |reg| {
|
||||
switch (self.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
const dbg_info = dw.getDeclDebugInfoBuffer();
|
||||
const dbg_info = &dw.dbg_info;
|
||||
try dbg_info.ensureUnusedCapacity(3);
|
||||
dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
|
||||
dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
|
||||
|
||||
@ -93,7 +93,7 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
|
||||
// TODO Look into using the DWARF special opcodes to compress this data.
|
||||
// It lets you emit single-byte opcodes that add different numbers to
|
||||
// both the PC and the line number at the same time.
|
||||
const dbg_line = dw.getDeclDebugLineBuffer();
|
||||
const dbg_line = &dw.dbg_line;
|
||||
try dbg_line.ensureUnusedCapacity(11);
|
||||
dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
|
||||
leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;
|
||||
@ -184,7 +184,7 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
fn mirDebugPrologueEnd(self: *Emit) !void {
|
||||
switch (self.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end);
|
||||
try dw.dbg_line.append(DW.LNS.set_prologue_end);
|
||||
try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
|
||||
},
|
||||
.plan9 => {},
|
||||
@ -195,7 +195,7 @@ fn mirDebugPrologueEnd(self: *Emit) !void {
|
||||
fn mirDebugEpilogueBegin(self: *Emit) !void {
|
||||
switch (self.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin);
|
||||
try dw.dbg_line.append(DW.LNS.set_epilogue_begin);
|
||||
try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
|
||||
},
|
||||
.plan9 => {},
|
||||
|
||||
@ -977,7 +977,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {
|
||||
// TODO Look into using the DWARF special opcodes to compress this data.
|
||||
// It lets you emit single-byte opcodes that add different numbers to
|
||||
// both the PC and the line number at the same time.
|
||||
const dbg_line = dw.getDeclDebugLineBuffer();
|
||||
const dbg_line = &dw.dbg_line;
|
||||
try dbg_line.ensureUnusedCapacity(11);
|
||||
dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
|
||||
leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;
|
||||
@ -1034,7 +1034,7 @@ fn mirDbgPrologueEnd(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
|
||||
assert(tag == .dbg_prologue_end);
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end);
|
||||
try dw.dbg_line.append(DW.LNS.set_prologue_end);
|
||||
log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column });
|
||||
try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
|
||||
},
|
||||
@ -1048,7 +1048,7 @@ fn mirDbgEpilogueBegin(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
|
||||
assert(tag == .dbg_epilogue_begin);
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin);
|
||||
try dw.dbg_line.append(DW.LNS.set_epilogue_begin);
|
||||
log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column });
|
||||
try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
|
||||
},
|
||||
@ -1075,7 +1075,7 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32
|
||||
.register => |reg| {
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
const dbg_info = dw.getDeclDebugInfoBuffer();
|
||||
const dbg_info = &dw.dbg_info;
|
||||
try dbg_info.ensureUnusedCapacity(3);
|
||||
dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
|
||||
dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
|
||||
@ -1099,7 +1099,7 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32
|
||||
// TODO we need to make this more generic if we don't use rbp as the frame pointer
|
||||
// for example when -fomit-frame-pointer is set.
|
||||
const disp = @intCast(i32, max_stack) - off + 16;
|
||||
const dbg_info = dw.getDeclDebugInfoBuffer();
|
||||
const dbg_info = &dw.dbg_info;
|
||||
try dbg_info.ensureUnusedCapacity(8);
|
||||
dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
|
||||
const fixup = dbg_info.items.len;
|
||||
@ -1128,7 +1128,7 @@ fn addDbgInfoTypeReloc(emit: *Emit, ty: Type) !void {
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
assert(ty.hasRuntimeBits());
|
||||
const dbg_info = dw.getDeclDebugInfoBuffer();
|
||||
const dbg_info = &dw.dbg_info;
|
||||
const index = dbg_info.items.len;
|
||||
try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
|
||||
const atom = switch (emit.bin_file.tag) {
|
||||
|
||||
@ -42,7 +42,7 @@ pub const GenerateSymbolError = error{
|
||||
};
|
||||
|
||||
pub const DebugInfoOutput = union(enum) {
|
||||
dwarf: *link.File.Dwarf,
|
||||
dwarf: *link.File.Dwarf.DeclState,
|
||||
/// the plan9 debuginfo output is a bytecode with 4 opcodes
|
||||
/// assume all numbers/variables are bytes
|
||||
/// 0 w x y z -> interpret w x y z as a big-endian i32, and add it to the line offset
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -2339,19 +2339,12 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
|
||||
const decl = func.owner_decl;
|
||||
self.freeUnnamedConsts(decl);
|
||||
|
||||
if (self.dwarf) |*dw| {
|
||||
try dw.initDeclState(decl);
|
||||
}
|
||||
defer if (self.dwarf) |*dw| {
|
||||
if (dw.decl_state) |*ds| {
|
||||
ds.deinit(dw.allocator);
|
||||
dw.decl_state = null;
|
||||
}
|
||||
};
|
||||
var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(decl) else null;
|
||||
defer if (decl_state) |*ds| ds.deinit();
|
||||
|
||||
const res = if (self.dwarf) |*dw|
|
||||
const res = if (decl_state) |*ds|
|
||||
try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{
|
||||
.dwarf = dw,
|
||||
.dwarf = ds,
|
||||
})
|
||||
else
|
||||
try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);
|
||||
@ -2365,8 +2358,15 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
|
||||
},
|
||||
};
|
||||
const local_sym = try self.updateDeclCode(decl, code, elf.STT_FUNC);
|
||||
if (self.dwarf) |*dw| {
|
||||
try dw.commitDeclState(&self.base, module, decl, local_sym.st_value, local_sym.st_size);
|
||||
if (decl_state) |*ds| {
|
||||
try self.dwarf.?.commitDeclState(
|
||||
&self.base,
|
||||
module,
|
||||
decl,
|
||||
local_sym.st_value,
|
||||
local_sym.st_size,
|
||||
ds,
|
||||
);
|
||||
}
|
||||
|
||||
// Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated.
|
||||
@ -2400,18 +2400,17 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
|
||||
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
|
||||
defer code_buffer.deinit();
|
||||
|
||||
if (self.dwarf) |*dw| {
|
||||
try dw.initDeclState(decl);
|
||||
}
|
||||
var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(decl) else null;
|
||||
defer if (decl_state) |*ds| ds.deinit();
|
||||
|
||||
// TODO implement .debug_info for global variables
|
||||
const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
|
||||
const res = if (self.dwarf) |*dw|
|
||||
const res = if (decl_state) |*ds|
|
||||
try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
|
||||
.ty = decl.ty,
|
||||
.val = decl_val,
|
||||
}, &code_buffer, .{
|
||||
.dwarf = dw,
|
||||
.dwarf = ds,
|
||||
}, .{
|
||||
.parent_atom_index = decl.link.elf.local_sym_index,
|
||||
})
|
||||
@ -2434,8 +2433,15 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
|
||||
};
|
||||
|
||||
const local_sym = try self.updateDeclCode(decl, code, elf.STT_OBJECT);
|
||||
if (self.dwarf) |*dw| {
|
||||
try dw.commitDeclState(&self.base, module, decl, local_sym.st_value, local_sym.st_size);
|
||||
if (decl_state) |*ds| {
|
||||
try self.dwarf.?.commitDeclState(
|
||||
&self.base,
|
||||
module,
|
||||
decl,
|
||||
local_sym.st_value,
|
||||
local_sym.st_size,
|
||||
ds,
|
||||
);
|
||||
}
|
||||
|
||||
// Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated.
|
||||
|
||||
@ -27,6 +27,7 @@ const Atom = @import("MachO/Atom.zig");
|
||||
const Cache = @import("../Cache.zig");
|
||||
const CodeSignature = @import("MachO/CodeSignature.zig");
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const Dwarf = File.Dwarf;
|
||||
const Dylib = @import("MachO/Dylib.zig");
|
||||
const File = link.File;
|
||||
const Object = @import("MachO/Object.zig");
|
||||
@ -3676,13 +3677,15 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
|
||||
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
|
||||
defer code_buffer.deinit();
|
||||
|
||||
if (self.d_sym) |*d_sym| {
|
||||
try d_sym.dwarf.initDeclState(decl);
|
||||
}
|
||||
var decl_state = if (self.d_sym) |*d_sym|
|
||||
try d_sym.dwarf.initDeclState(decl)
|
||||
else
|
||||
null;
|
||||
defer if (decl_state) |*ds| ds.deinit();
|
||||
|
||||
const res = if (self.d_sym) |*d_sym|
|
||||
const res = if (decl_state) |*ds|
|
||||
try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{
|
||||
.dwarf = &d_sym.dwarf,
|
||||
.dwarf = ds,
|
||||
})
|
||||
else
|
||||
try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);
|
||||
@ -3700,8 +3703,15 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
|
||||
|
||||
const symbol = try self.placeDecl(decl, decl.link.macho.code.items.len);
|
||||
|
||||
if (self.d_sym) |*d_sym| {
|
||||
try d_sym.dwarf.commitDeclState(&self.base, module, decl, symbol.n_value, decl.link.macho.size);
|
||||
if (decl_state) |*ds| {
|
||||
try self.d_sym.?.dwarf.commitDeclState(
|
||||
&self.base,
|
||||
module,
|
||||
decl,
|
||||
symbol.n_value,
|
||||
decl.link.macho.size,
|
||||
ds,
|
||||
);
|
||||
}
|
||||
|
||||
// Since we updated the vaddr and the size, each corresponding export symbol also
|
||||
@ -3801,17 +3811,19 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
|
||||
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
|
||||
defer code_buffer.deinit();
|
||||
|
||||
if (self.d_sym) |*d_sym| {
|
||||
try d_sym.dwarf.initDeclState(decl);
|
||||
}
|
||||
var decl_state: ?Dwarf.DeclState = if (self.d_sym) |*d_sym|
|
||||
try d_sym.dwarf.initDeclState(decl)
|
||||
else
|
||||
null;
|
||||
defer if (decl_state) |*ds| ds.deinit();
|
||||
|
||||
const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
|
||||
const res = if (self.d_sym) |*d_sym|
|
||||
const res = if (decl_state) |*ds|
|
||||
try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
|
||||
.ty = decl.ty,
|
||||
.val = decl_val,
|
||||
}, &code_buffer, .{
|
||||
.dwarf = &d_sym.dwarf,
|
||||
.dwarf = ds,
|
||||
}, .{
|
||||
.parent_atom_index = decl.link.macho.local_sym_index,
|
||||
})
|
||||
@ -3845,8 +3857,15 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
|
||||
};
|
||||
const symbol = try self.placeDecl(decl, code.len);
|
||||
|
||||
if (self.d_sym) |*d_sym| {
|
||||
try d_sym.dwarf.commitDeclState(&self.base, module, decl, symbol.n_value, decl.link.macho.size);
|
||||
if (decl_state) |*ds| {
|
||||
try self.d_sym.?.dwarf.commitDeclState(
|
||||
&self.base,
|
||||
module,
|
||||
decl,
|
||||
symbol.n_value,
|
||||
decl.link.macho.size,
|
||||
ds,
|
||||
);
|
||||
}
|
||||
|
||||
// Since we updated the vaddr and the size, each corresponding export symbol also
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user