authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-11-11 16:06:01-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-12 03:21:52-05:00
log2eeb7358227d13ff4d77ef73c54a0e2ae12c1d58
tree94660b851f8734a6b9520e6754937bb30511e648
parent3fc6a2f11399e84b9cfa4cfef65ef40aa6de173b

Dwarf: improve x86_64 backend debug info

Closes #17811

6 files changed, 432 insertions(+), 287 deletions(-)

lib/std/leb128.zig+61-2
...@@ -148,10 +148,10 @@ pub fn writeUnsignedFixed(comptime l: usize, ptr: *[l]u8, int: std.meta.Int(.uns...@@ -148,10 +148,10 @@ pub fn writeUnsignedFixed(comptime l: usize, ptr: *[l]u8, int: std.meta.Int(.uns
148 value >>= 7;148 value >>= 7;
149 ptr[i] = byte;149 ptr[i] = byte;
150 }150 }
151 ptr[i] = @as(u8, @truncate(value));151 ptr[i] = @truncate(value);
152}152}
153153
154test "writeUnsignedFixed" {154test writeUnsignedFixed {
155 {155 {
156 var buf: [4]u8 = undefined;156 var buf: [4]u8 = undefined;
157 writeUnsignedFixed(4, &buf, 0);157 writeUnsignedFixed(4, &buf, 0);
...@@ -174,6 +174,65 @@ test "writeUnsignedFixed" {...@@ -174,6 +174,65 @@ test "writeUnsignedFixed" {
174 }174 }
175}175}
176176
177/// This is an "advanced" function. It allows one to use a fixed amount of memory to store an
178/// ILEB128. This defeats the entire purpose of using this data encoding; it will no longer use
179/// fewer bytes to store smaller numbers. The advantage of using a fixed width is that it makes
180/// fields have a predictable size and so depending on the use case this tradeoff can be worthwhile.
181/// An example use case of this is in emitting DWARF info where one wants to make a ILEB128 field
182/// "relocatable", meaning that it becomes possible to later go back and patch the number to be a
183/// different value without shifting all the following code.
184pub fn writeSignedFixed(comptime l: usize, ptr: *[l]u8, int: std.meta.Int(.signed, l * 7)) void {
185 const T = @TypeOf(int);
186 const U = if (@typeInfo(T).Int.bits < 8) u8 else T;
187 var value: U = @intCast(int);
188
189 comptime var i = 0;
190 inline while (i < (l - 1)) : (i += 1) {
191 const byte: u8 = @bitCast(@as(i8, @truncate(value)) | -0b1000_0000);
192 value >>= 7;
193 ptr[i] = byte;
194 }
195 ptr[i] = @as(u7, @bitCast(@as(i7, @truncate(value))));
196}
197
198test writeSignedFixed {
199 {
200 var buf: [4]u8 = undefined;
201 writeSignedFixed(4, &buf, 0);
202 try testing.expect((try test_read_ileb128(i64, &buf)) == 0);
203 }
204 {
205 var buf: [4]u8 = undefined;
206 writeSignedFixed(4, &buf, 1);
207 try testing.expect((try test_read_ileb128(i64, &buf)) == 1);
208 }
209 {
210 var buf: [4]u8 = undefined;
211 writeSignedFixed(4, &buf, -1);
212 try testing.expect((try test_read_ileb128(i64, &buf)) == -1);
213 }
214 {
215 var buf: [4]u8 = undefined;
216 writeSignedFixed(4, &buf, 1000);
217 try testing.expect((try test_read_ileb128(i64, &buf)) == 1000);
218 }
219 {
220 var buf: [4]u8 = undefined;
221 writeSignedFixed(4, &buf, -1000);
222 try testing.expect((try test_read_ileb128(i64, &buf)) == -1000);
223 }
224 {
225 var buf: [4]u8 = undefined;
226 writeSignedFixed(4, &buf, -10000000);
227 try testing.expect((try test_read_ileb128(i64, &buf)) == -10000000);
228 }
229 {
230 var buf: [4]u8 = undefined;
231 writeSignedFixed(4, &buf, 10000000);
232 try testing.expect((try test_read_ileb128(i64, &buf)) == 10000000);
233 }
234}
235
177// tests236// tests
178fn test_read_stream_ileb128(comptime T: type, encoded: []const u8) !T {237fn test_read_stream_ileb128(comptime T: type, encoded: []const u8) !T {
179 var reader = std.io.fixedBufferStream(encoded);238 var reader = std.io.fixedBufferStream(encoded);
src/arch/x86_64/CodeGen.zig+17-16
...@@ -10576,12 +10576,12 @@ fn genVarDbgInfo(...@@ -10576,12 +10576,12 @@ fn genVarDbgInfo(
1057610576
10577fn airTrap(self: *Self) !void {10577fn airTrap(self: *Self) !void {
10578 try self.asmOpOnly(.{ ._, .ud2 });10578 try self.asmOpOnly(.{ ._, .ud2 });
10579 return self.finishAirBookkeeping();10579 self.finishAirBookkeeping();
10580}10580}
1058110581
10582fn airBreakpoint(self: *Self) !void {10582fn airBreakpoint(self: *Self) !void {
10583 try self.asmOpOnly(.{ ._, .int3 });10583 try self.asmOpOnly(.{ ._, .int3 });
10584 return self.finishAirBookkeeping();10584 self.finishAirBookkeeping();
10585}10585}
1058610586
10587fn airRetAddr(self: *Self, inst: Air.Inst.Index) !void {10587fn airRetAddr(self: *Self, inst: Air.Inst.Index) !void {
...@@ -10603,7 +10603,7 @@ fn airFence(self: *Self, inst: Air.Inst.Index) !void {...@@ -10603,7 +10603,7 @@ fn airFence(self: *Self, inst: Air.Inst.Index) !void {
10603 .Acquire, .Release, .AcqRel => {},10603 .Acquire, .Release, .AcqRel => {},
10604 .SeqCst => try self.asmOpOnly(.{ ._, .mfence }),10604 .SeqCst => try self.asmOpOnly(.{ ._, .mfence }),
10605 }10605 }
10606 return self.finishAirBookkeeping();10606 self.finishAirBookkeeping();
10607}10607}
1060810608
10609fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {10609fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {
...@@ -11419,21 +11419,23 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -11419,21 +11419,23 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
11419 .column = dbg_stmt.column,11419 .column = dbg_stmt.column,
11420 } },11420 } },
11421 });11421 });
11422 return self.finishAirBookkeeping();11422 self.finishAirBookkeeping();
11423}11423}
1142411424
11425fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {11425fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
11426 const mod = self.bin_file.options.module.?;
11427 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;11426 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
11428 const func = mod.funcInfo(ty_fn.func);11427 _ = try self.addInst(.{
11429 // TODO emit debug info for function change11428 .tag = .pseudo,
11430 _ = func;11429 .ops = .pseudo_dbg_inline_func,
11431 return self.finishAir(inst, .unreach, .{ .none, .none, .none });11430 .data = .{ .func = ty_fn.func },
11431 });
11432 self.finishAirBookkeeping();
11432}11433}
1143311434
11434fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {11435fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
11436 _ = inst;
11435 // TODO emit debug info lexical block11437 // TODO emit debug info lexical block
11436 return self.finishAir(inst, .unreach, .{ .none, .none, .none });11438 self.finishAirBookkeeping();
11437}11439}
1143811440
11439fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {11441fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
...@@ -11518,9 +11520,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -11518,9 +11520,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
11518 .close_scope = true,11520 .close_scope = true,
11519 });11521 });
1152011522
11521 // We already took care of pl_op.operand earlier, so we're going11523 // We already took care of pl_op.operand earlier, so there's nothing left to do.
11522 // to pass .none here11524 self.finishAirBookkeeping();
11523 return self.finishAir(inst, .unreach, .{ .none, .none, .none });
11524}11525}
1152511526
11526fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MCValue {11527fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MCValue {
...@@ -11865,7 +11866,7 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void {...@@ -11865,7 +11866,7 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void {
11865 });11866 });
11866 _ = try self.asmJmpReloc(jmp_target);11867 _ = try self.asmJmpReloc(jmp_target);
1186711868
11868 return self.finishAirBookkeeping();11869 self.finishAirBookkeeping();
11869}11870}
1187011871
11871fn airBlock(self: *Self, inst: Air.Inst.Index) !void {11872fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
...@@ -11977,8 +11978,8 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -11977,8 +11978,8 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
11977 });11978 });
11978 }11979 }
1197911980
11980 // We already took care of pl_op.operand earlier, so we're going to pass .none here11981 // We already took care of pl_op.operand earlier, so there's nothing left to do
11981 return self.finishAir(inst, .unreach, .{ .none, .none, .none });11982 self.finishAirBookkeeping();
11982}11983}
1198311984
11984fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void {11985fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void {
src/arch/x86_64/Emit.zig+23-10
...@@ -151,7 +151,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -151,7 +151,7 @@ pub fn emitMir(emit: *Emit) Error!void {
151 else => unreachable,151 else => unreachable,
152 },152 },
153 .target = target,153 .target = target,
154 .offset = @as(u32, @intCast(end_offset - 4)),154 .offset = @intCast(end_offset - 4),
155 .addend = 0,155 .addend = 0,
156 .pcrel = true,156 .pcrel = true,
157 .length = 2,157 .length = 2,
...@@ -173,7 +173,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -173,7 +173,7 @@ pub fn emitMir(emit: *Emit) Error!void {
173 else => unreachable,173 else => unreachable,
174 },174 },
175 .target = target,175 .target = target,
176 .offset = @as(u32, @intCast(end_offset - 4)),176 .offset = @intCast(end_offset - 4),
177 .addend = 0,177 .addend = 0,
178 .pcrel = true,178 .pcrel = true,
179 .length = 2,179 .length = 2,
...@@ -182,7 +182,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -182,7 +182,7 @@ pub fn emitMir(emit: *Emit) Error!void {
182 const atom_index = symbol.atom_index;182 const atom_index = symbol.atom_index;
183 try p9_file.addReloc(atom_index, .{ // TODO we may need to add a .type field to the relocs if they are .linker_got instead of just .linker_direct183 try p9_file.addReloc(atom_index, .{ // TODO we may need to add a .type field to the relocs if they are .linker_got instead of just .linker_direct
184 .target = symbol.sym_index, // we set sym_index to just be the atom index184 .target = symbol.sym_index, // we set sym_index to just be the atom index
185 .offset = @as(u32, @intCast(end_offset - 4)),185 .offset = @intCast(end_offset - 4),
186 .addend = 0,186 .addend = 0,
187 .type = .pcrel,187 .type = .pcrel,
188 });188 });
...@@ -229,6 +229,18 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -229,6 +229,18 @@ pub fn emitMir(emit: *Emit) Error!void {
229 .none => {},229 .none => {},
230 }230 }
231 },231 },
232 .pseudo_dbg_inline_func => {
233 switch (emit.debug_output) {
234 .dwarf => |dw| {
235 log.debug("mirDbgInline (line={d}, col={d})", .{
236 emit.prev_di_line, emit.prev_di_column,
237 });
238 try dw.setInlineFunc(mir_inst.data.func);
239 },
240 .plan9 => {},
241 .none => {},
242 }
243 },
232 .pseudo_dead_none => {},244 .pseudo_dead_none => {},
233 },245 },
234 }246 }
...@@ -269,17 +281,18 @@ fn fixupRelocs(emit: *Emit) Error!void {...@@ -269,17 +281,18 @@ fn fixupRelocs(emit: *Emit) Error!void {
269 for (emit.relocs.items) |reloc| {281 for (emit.relocs.items) |reloc| {
270 const target = emit.code_offset_mapping.get(reloc.target) orelse282 const target = emit.code_offset_mapping.get(reloc.target) orelse
271 return emit.fail("JMP/CALL relocation target not found!", .{});283 return emit.fail("JMP/CALL relocation target not found!", .{});
272 const disp = @as(i32, @intCast(@as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length))));284 const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length));
273 mem.writeInt(i32, emit.code.items[reloc.offset..][0..4], disp, .little);285 mem.writeInt(i32, emit.code.items[reloc.offset..][0..4], @intCast(disp), .little);
274 }286 }
275}287}
276288
277fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {289fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
278 const delta_line = @as(i32, @intCast(line)) - @as(i32, @intCast(emit.prev_di_line));290 const delta_line = @as(i33, line) - @as(i33, emit.prev_di_line);
279 const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;291 const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;
280 log.debug(" (advance pc={d} and line={d})", .{ delta_line, delta_pc });292 log.debug(" (advance pc={d} and line={d})", .{ delta_line, delta_pc });
281 switch (emit.debug_output) {293 switch (emit.debug_output) {
282 .dwarf => |dw| {294 .dwarf => |dw| {
295 if (column != emit.prev_di_column) try dw.setColumn(column);
283 try dw.advancePCAndLine(delta_line, delta_pc);296 try dw.advancePCAndLine(delta_line, delta_pc);
284 emit.prev_di_line = line;297 emit.prev_di_line = line;
285 emit.prev_di_column = column;298 emit.prev_di_column = column;
...@@ -289,7 +302,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {...@@ -289,7 +302,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
289 if (delta_pc <= 0) return; // only do this when the pc changes302 if (delta_pc <= 0) return; // only do this when the pc changes
290303
291 // increasing the line number304 // increasing the line number
292 try link.File.Plan9.changeLine(&dbg_out.dbg_line, delta_line);305 try link.File.Plan9.changeLine(&dbg_out.dbg_line, @intCast(delta_line));
293 // increasing the pc306 // increasing the pc
294 const d_pc_p9 = @as(i64, @intCast(delta_pc)) - dbg_out.pc_quanta;307 const d_pc_p9 = @as(i64, @intCast(delta_pc)) - dbg_out.pc_quanta;
295 if (d_pc_p9 > 0) {308 if (d_pc_p9 > 0) {
...@@ -297,16 +310,16 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {...@@ -297,16 +310,16 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
297 var diff = @divExact(d_pc_p9, dbg_out.pc_quanta) - dbg_out.pc_quanta;310 var diff = @divExact(d_pc_p9, dbg_out.pc_quanta) - dbg_out.pc_quanta;
298 while (diff > 0) {311 while (diff > 0) {
299 if (diff < 64) {312 if (diff < 64) {
300 try dbg_out.dbg_line.append(@as(u8, @intCast(diff + 128)));313 try dbg_out.dbg_line.append(@intCast(diff + 128));
301 diff = 0;314 diff = 0;
302 } else {315 } else {
303 try dbg_out.dbg_line.append(@as(u8, @intCast(64 + 128)));316 try dbg_out.dbg_line.append(@intCast(64 + 128));
304 diff -= 64;317 diff -= 64;
305 }318 }
306 }319 }
307 if (dbg_out.pcop_change_index) |pci|320 if (dbg_out.pcop_change_index) |pci|
308 dbg_out.dbg_line.items[pci] += 1;321 dbg_out.dbg_line.items[pci] += 1;
309 dbg_out.pcop_change_index = @as(u32, @intCast(dbg_out.dbg_line.items.len - 1));322 dbg_out.pcop_change_index = @intCast(dbg_out.dbg_line.items.len - 1);
310 } else if (d_pc_p9 == 0) {323 } else if (d_pc_p9 == 0) {
311 // we don't need to do anything, because adding the pc quanta does it for us324 // we don't need to do anything, because adding the pc quanta does it for us
312 } else unreachable;325 } else unreachable;
src/arch/x86_64/Lower.zig+1
...@@ -259,6 +259,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -259,6 +259,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
259 .pseudo_dbg_prologue_end_none,259 .pseudo_dbg_prologue_end_none,
260 .pseudo_dbg_line_line_column,260 .pseudo_dbg_line_line_column,
261 .pseudo_dbg_epilogue_begin_none,261 .pseudo_dbg_epilogue_begin_none,
262 .pseudo_dbg_inline_func,
262 .pseudo_dead_none,263 .pseudo_dead_none,
263 => {},264 => {},
264 else => unreachable,265 else => unreachable,
src/arch/x86_64/Mir.zig+14-13
...@@ -6,19 +6,6 @@...@@ -6,19 +6,6 @@
6//! The main purpose of MIR is to postpone the assignment of offsets until Isel,6//! The main purpose of MIR is to postpone the assignment of offsets until Isel,
7//! so that, for example, the smaller encodings of jump instructions can be used.7//! so that, for example, the smaller encodings of jump instructions can be used.
88
9const Mir = @This();
10const std = @import("std");
11const builtin = @import("builtin");
12const assert = std.debug.assert;
13
14const bits = @import("bits.zig");
15const encoder = @import("encoder.zig");
16
17const Air = @import("../../Air.zig");
18const CodeGen = @import("CodeGen.zig");
19const IntegerBitSet = std.bit_set.IntegerBitSet;
20const Register = bits.Register;
21
22instructions: std.MultiArrayList(Inst).Slice,9instructions: std.MultiArrayList(Inst).Slice,
23/// The meaning of this data is determined by `Inst.Tag` value.10/// The meaning of this data is determined by `Inst.Tag` value.
24extra: []const u32,11extra: []const u32,
...@@ -884,6 +871,8 @@ pub const Inst = struct {...@@ -884,6 +871,8 @@ pub const Inst = struct {
884 pseudo_dbg_line_line_column,871 pseudo_dbg_line_line_column,
885 /// Start of epilogue872 /// Start of epilogue
886 pseudo_dbg_epilogue_begin_none,873 pseudo_dbg_epilogue_begin_none,
874 /// Start or end of inline function
875 pseudo_dbg_inline_func,
887876
888 /// Tombstone877 /// Tombstone
889 /// Emitter should skip this instruction.878 /// Emitter should skip this instruction.
...@@ -987,6 +976,7 @@ pub const Inst = struct {...@@ -987,6 +976,7 @@ pub const Inst = struct {
987 line: u32,976 line: u32,
988 column: u32,977 column: u32,
989 },978 },
979 func: InternPool.Index,
990 /// Register list980 /// Register list
991 reg_list: RegisterList,981 reg_list: RegisterList,
992 };982 };
...@@ -1198,3 +1188,14 @@ pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {...@@ -1198,3 +1188,14 @@ pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {
1198 } else mem,1188 } else mem,
1199 };1189 };
1200}1190}
1191
1192const assert = std.debug.assert;
1193const bits = @import("bits.zig");
1194const builtin = @import("builtin");
1195const encoder = @import("encoder.zig");
1196const std = @import("std");
1197
1198const IntegerBitSet = std.bit_set.IntegerBitSet;
1199const InternPool = @import("../../InternPool.zig");
1200const Mir = @This();
1201const Register = bits.Register;
src/link/Dwarf.zig+316-246
...@@ -19,6 +19,8 @@ di_atom_last_index: ?Atom.Index = null,...@@ -19,6 +19,8 @@ di_atom_last_index: ?Atom.Index = null,
19di_atoms: std.ArrayListUnmanaged(Atom) = .{},19di_atoms: std.ArrayListUnmanaged(Atom) = .{},
20di_atom_decls: AtomTable = .{},20di_atom_decls: AtomTable = .{},
2121
22dbg_line_header: DbgLineHeader,
23
22abbrev_table_offset: ?u64 = null,24abbrev_table_offset: ?u64 = null,
2325
24/// TODO replace with InternPool26/// TODO replace with InternPool
...@@ -50,48 +52,48 @@ const Atom = struct {...@@ -50,48 +52,48 @@ const Atom = struct {
50 pub const Index = u32;52 pub const Index = u32;
51};53};
5254
55const DbgLineHeader = struct {
56 minimum_instruction_length: u8,
57 maximum_operations_per_instruction: u8,
58 default_is_stmt: bool,
59 line_base: i8,
60 line_range: u8,
61 opcode_base: u8,
62};
63
53/// Represents state of the analysed Decl.64/// Represents state of the analysed Decl.
54/// Includes Decl's abbrev table of type Types, matching arena65/// Includes Decl's abbrev table of type Types, matching arena
55/// and a set of relocations that will be resolved once this66/// and a set of relocations that will be resolved once this
56/// Decl's inner Atom is assigned an offset within the DWARF section.67/// Decl's inner Atom is assigned an offset within the DWARF section.
57pub const DeclState = struct {68pub const DeclState = struct {
58 gpa: Allocator,69 dwarf: *Dwarf,
59 mod: *Module,70 mod: *Module,
60 di_atom_decls: *const AtomTable,71 di_atom_decls: *const AtomTable,
72 dbg_line_func: InternPool.Index,
61 dbg_line: std.ArrayList(u8),73 dbg_line: std.ArrayList(u8),
62 dbg_info: std.ArrayList(u8),74 dbg_info: std.ArrayList(u8),
63 abbrev_type_arena: std.heap.ArenaAllocator,75 abbrev_type_arena: std.heap.ArenaAllocator,
64 abbrev_table: std.ArrayListUnmanaged(AbbrevEntry) = .{},76 abbrev_table: std.ArrayListUnmanaged(AbbrevEntry),
65 abbrev_resolver: std.AutoHashMapUnmanaged(InternPool.Index, u32) = .{},77 abbrev_resolver: std.AutoHashMapUnmanaged(InternPool.Index, u32),
66 abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{},78 abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation),
67 exprloc_relocs: std.ArrayListUnmanaged(ExprlocRelocation) = .{},79 exprloc_relocs: std.ArrayListUnmanaged(ExprlocRelocation),
68
69 fn init(gpa: Allocator, mod: *Module, di_atom_decls: *const AtomTable) DeclState {
70 return .{
71 .gpa = gpa,
72 .mod = mod,
73 .di_atom_decls = di_atom_decls,
74 .dbg_line = std.ArrayList(u8).init(gpa),
75 .dbg_info = std.ArrayList(u8).init(gpa),
76 .abbrev_type_arena = std.heap.ArenaAllocator.init(gpa),
77 };
78 }
7980
80 pub fn deinit(self: *DeclState) void {81 pub fn deinit(self: *DeclState) void {
82 const gpa = self.dwarf.allocator;
81 self.dbg_line.deinit();83 self.dbg_line.deinit();
82 self.dbg_info.deinit();84 self.dbg_info.deinit();
83 self.abbrev_type_arena.deinit();85 self.abbrev_type_arena.deinit();
84 self.abbrev_table.deinit(self.gpa);86 self.abbrev_table.deinit(gpa);
85 self.abbrev_resolver.deinit(self.gpa);87 self.abbrev_resolver.deinit(gpa);
86 self.abbrev_relocs.deinit(self.gpa);88 self.abbrev_relocs.deinit(gpa);
87 self.exprloc_relocs.deinit(self.gpa);89 self.exprloc_relocs.deinit(gpa);
88 }90 }
8991
90 /// Adds local type relocation of the form: @offset => @this + addend92 /// Adds local type relocation of the form: @offset => @this + addend
91 /// @this signifies the offset within the .debug_abbrev section of the containing atom.93 /// @this signifies the offset within the .debug_abbrev section of the containing atom.
92 fn addTypeRelocLocal(self: *DeclState, atom_index: Atom.Index, offset: u32, addend: u32) !void {94 fn addTypeRelocLocal(self: *DeclState, atom_index: Atom.Index, offset: u32, addend: u32) !void {
93 log.debug("{x}: @this + {x}", .{ offset, addend });95 log.debug("{x}: @this + {x}", .{ offset, addend });
94 try self.abbrev_relocs.append(self.gpa, .{96 try self.abbrev_relocs.append(self.dwarf.allocator, .{
95 .target = null,97 .target = null,
96 .atom_index = atom_index,98 .atom_index = atom_index,
97 .offset = offset,99 .offset = offset,
...@@ -103,19 +105,20 @@ pub const DeclState = struct {...@@ -103,19 +105,20 @@ pub const DeclState = struct {
103 /// @symbol signifies a type abbreviation posititioned somewhere in the .debug_abbrev section105 /// @symbol signifies a type abbreviation posititioned somewhere in the .debug_abbrev section
104 /// which we use as our target of the relocation.106 /// which we use as our target of the relocation.
105 fn addTypeRelocGlobal(self: *DeclState, atom_index: Atom.Index, ty: Type, offset: u32) !void {107 fn addTypeRelocGlobal(self: *DeclState, atom_index: Atom.Index, ty: Type, offset: u32) !void {
108 const gpa = self.dwarf.allocator;
106 const resolv = self.abbrev_resolver.get(ty.toIntern()) orelse blk: {109 const resolv = self.abbrev_resolver.get(ty.toIntern()) orelse blk: {
107 const sym_index = @as(u32, @intCast(self.abbrev_table.items.len));110 const sym_index: u32 = @intCast(self.abbrev_table.items.len);
108 try self.abbrev_table.append(self.gpa, .{111 try self.abbrev_table.append(gpa, .{
109 .atom_index = atom_index,112 .atom_index = atom_index,
110 .type = ty,113 .type = ty,
111 .offset = undefined,114 .offset = undefined,
112 });115 });
113 log.debug("%{d}: {}", .{ sym_index, ty.fmt(self.mod) });116 log.debug("%{d}: {}", .{ sym_index, ty.fmt(self.mod) });
114 try self.abbrev_resolver.putNoClobber(self.gpa, ty.toIntern(), sym_index);117 try self.abbrev_resolver.putNoClobber(gpa, ty.toIntern(), sym_index);
115 break :blk sym_index;118 break :blk sym_index;
116 };119 };
117 log.debug("{x}: %{d} + 0", .{ offset, resolv });120 log.debug("{x}: %{d} + 0", .{ offset, resolv });
118 try self.abbrev_relocs.append(self.gpa, .{121 try self.abbrev_relocs.append(gpa, .{
119 .target = resolv,122 .target = resolv,
120 .atom_index = atom_index,123 .atom_index = atom_index,
121 .offset = offset,124 .offset = offset,
...@@ -192,7 +195,7 @@ pub const DeclState = struct {...@@ -192,7 +195,7 @@ pub const DeclState = struct {
192 // DW.AT.type, DW.FORM.ref4195 // DW.AT.type, DW.FORM.ref4
193 var index = dbg_info_buffer.items.len;196 var index = dbg_info_buffer.items.len;
194 try dbg_info_buffer.resize(index + 4);197 try dbg_info_buffer.resize(index + 4);
195 try self.addTypeRelocGlobal(atom_index, Type.bool, @as(u32, @intCast(index)));198 try self.addTypeRelocGlobal(atom_index, Type.bool, @intCast(index));
196 // DW.AT.data_member_location, DW.FORM.udata199 // DW.AT.data_member_location, DW.FORM.udata
197 try dbg_info_buffer.ensureUnusedCapacity(6);200 try dbg_info_buffer.ensureUnusedCapacity(6);
198 dbg_info_buffer.appendAssumeCapacity(0);201 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -204,7 +207,7 @@ pub const DeclState = struct {...@@ -204,7 +207,7 @@ pub const DeclState = struct {
204 // DW.AT.type, DW.FORM.ref4207 // DW.AT.type, DW.FORM.ref4
205 index = dbg_info_buffer.items.len;208 index = dbg_info_buffer.items.len;
206 try dbg_info_buffer.resize(index + 4);209 try dbg_info_buffer.resize(index + 4);
207 try self.addTypeRelocGlobal(atom_index, payload_ty, @as(u32, @intCast(index)));210 try self.addTypeRelocGlobal(atom_index, payload_ty, @intCast(index));
208 // DW.AT.data_member_location, DW.FORM.udata211 // DW.AT.data_member_location, DW.FORM.udata
209 const offset = abi_size - payload_ty.abiSize(mod);212 const offset = abi_size - payload_ty.abiSize(mod);
210 try leb128.writeULEB128(dbg_info_buffer.writer(), offset);213 try leb128.writeULEB128(dbg_info_buffer.writer(), offset);
...@@ -216,7 +219,7 @@ pub const DeclState = struct {...@@ -216,7 +219,7 @@ pub const DeclState = struct {
216 if (ty.isSlice(mod)) {219 if (ty.isSlice(mod)) {
217 // Slices are structs: struct { .ptr = *, .len = N }220 // Slices are structs: struct { .ptr = *, .len = N }
218 const ptr_bits = target.ptrBitWidth();221 const ptr_bits = target.ptrBitWidth();
219 const ptr_bytes = @as(u8, @intCast(@divExact(ptr_bits, 8)));222 const ptr_bytes: u8 = @intCast(@divExact(ptr_bits, 8));
220 // DW.AT.structure_type223 // DW.AT.structure_type
221 try dbg_info_buffer.ensureUnusedCapacity(2);224 try dbg_info_buffer.ensureUnusedCapacity(2);
222 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_type));225 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_type));
...@@ -234,7 +237,7 @@ pub const DeclState = struct {...@@ -234,7 +237,7 @@ pub const DeclState = struct {
234 var index = dbg_info_buffer.items.len;237 var index = dbg_info_buffer.items.len;
235 try dbg_info_buffer.resize(index + 4);238 try dbg_info_buffer.resize(index + 4);
236 const ptr_ty = ty.slicePtrFieldType(mod);239 const ptr_ty = ty.slicePtrFieldType(mod);
237 try self.addTypeRelocGlobal(atom_index, ptr_ty, @as(u32, @intCast(index)));240 try self.addTypeRelocGlobal(atom_index, ptr_ty, @intCast(index));
238 // DW.AT.data_member_location, DW.FORM.udata241 // DW.AT.data_member_location, DW.FORM.udata
239 try dbg_info_buffer.ensureUnusedCapacity(6);242 try dbg_info_buffer.ensureUnusedCapacity(6);
240 dbg_info_buffer.appendAssumeCapacity(0);243 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -246,7 +249,7 @@ pub const DeclState = struct {...@@ -246,7 +249,7 @@ pub const DeclState = struct {
246 // DW.AT.type, DW.FORM.ref4249 // DW.AT.type, DW.FORM.ref4
247 index = dbg_info_buffer.items.len;250 index = dbg_info_buffer.items.len;
248 try dbg_info_buffer.resize(index + 4);251 try dbg_info_buffer.resize(index + 4);
249 try self.addTypeRelocGlobal(atom_index, Type.usize, @as(u32, @intCast(index)));252 try self.addTypeRelocGlobal(atom_index, Type.usize, @intCast(index));
250 // DW.AT.data_member_location, DW.FORM.udata253 // DW.AT.data_member_location, DW.FORM.udata
251 try dbg_info_buffer.ensureUnusedCapacity(2);254 try dbg_info_buffer.ensureUnusedCapacity(2);
252 dbg_info_buffer.appendAssumeCapacity(ptr_bytes);255 dbg_info_buffer.appendAssumeCapacity(ptr_bytes);
...@@ -258,7 +261,7 @@ pub const DeclState = struct {...@@ -258,7 +261,7 @@ pub const DeclState = struct {
258 // DW.AT.type, DW.FORM.ref4261 // DW.AT.type, DW.FORM.ref4
259 const index = dbg_info_buffer.items.len;262 const index = dbg_info_buffer.items.len;
260 try dbg_info_buffer.resize(index + 4);263 try dbg_info_buffer.resize(index + 4);
261 try self.addTypeRelocGlobal(atom_index, ty.childType(mod), @as(u32, @intCast(index)));264 try self.addTypeRelocGlobal(atom_index, ty.childType(mod), @intCast(index));
262 }265 }
263 },266 },
264 .Array => {267 .Array => {
...@@ -269,13 +272,13 @@ pub const DeclState = struct {...@@ -269,13 +272,13 @@ pub const DeclState = struct {
269 // DW.AT.type, DW.FORM.ref4272 // DW.AT.type, DW.FORM.ref4
270 var index = dbg_info_buffer.items.len;273 var index = dbg_info_buffer.items.len;
271 try dbg_info_buffer.resize(index + 4);274 try dbg_info_buffer.resize(index + 4);
272 try self.addTypeRelocGlobal(atom_index, ty.childType(mod), @as(u32, @intCast(index)));275 try self.addTypeRelocGlobal(atom_index, ty.childType(mod), @intCast(index));
273 // DW.AT.subrange_type276 // DW.AT.subrange_type
274 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.array_dim));277 try dbg_info_buffer.append(@intFromEnum(AbbrevKind.array_dim));
275 // DW.AT.type, DW.FORM.ref4278 // DW.AT.type, DW.FORM.ref4
276 index = dbg_info_buffer.items.len;279 index = dbg_info_buffer.items.len;
277 try dbg_info_buffer.resize(index + 4);280 try dbg_info_buffer.resize(index + 4);
278 try self.addTypeRelocGlobal(atom_index, Type.usize, @as(u32, @intCast(index)));281 try self.addTypeRelocGlobal(atom_index, Type.usize, @intCast(index));
279 // DW.AT.count, DW.FORM.udata282 // DW.AT.count, DW.FORM.udata
280 const len = ty.arrayLenIncludingSentinel(mod);283 const len = ty.arrayLenIncludingSentinel(mod);
281 try leb128.writeULEB128(dbg_info_buffer.writer(), len);284 try leb128.writeULEB128(dbg_info_buffer.writer(), len);
...@@ -302,7 +305,7 @@ pub const DeclState = struct {...@@ -302,7 +305,7 @@ pub const DeclState = struct {
302 // DW.AT.type, DW.FORM.ref4305 // DW.AT.type, DW.FORM.ref4
303 var index = dbg_info_buffer.items.len;306 var index = dbg_info_buffer.items.len;
304 try dbg_info_buffer.resize(index + 4);307 try dbg_info_buffer.resize(index + 4);
305 try self.addTypeRelocGlobal(atom_index, field_ty.toType(), @as(u32, @intCast(index)));308 try self.addTypeRelocGlobal(atom_index, field_ty.toType(), @intCast(index));
306 // DW.AT.data_member_location, DW.FORM.udata309 // DW.AT.data_member_location, DW.FORM.udata
307 const field_off = ty.structFieldOffset(field_index, mod);310 const field_off = ty.structFieldOffset(field_index, mod);
308 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);311 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
...@@ -328,7 +331,7 @@ pub const DeclState = struct {...@@ -328,7 +331,7 @@ pub const DeclState = struct {
328 // DW.AT.type, DW.FORM.ref4331 // DW.AT.type, DW.FORM.ref4
329 var index = dbg_info_buffer.items.len;332 var index = dbg_info_buffer.items.len;
330 try dbg_info_buffer.resize(index + 4);333 try dbg_info_buffer.resize(index + 4);
331 try self.addTypeRelocGlobal(atom_index, field_ty.toType(), @as(u32, @intCast(index)));334 try self.addTypeRelocGlobal(atom_index, field_ty.toType(), @intCast(index));
332 // DW.AT.data_member_location, DW.FORM.udata335 // DW.AT.data_member_location, DW.FORM.udata
333 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);336 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
334 }337 }
...@@ -387,7 +390,7 @@ pub const DeclState = struct {...@@ -387,7 +390,7 @@ pub const DeclState = struct {
387 // TODO do not assume a 64bit enum value - could be bigger.390 // TODO do not assume a 64bit enum value - could be bigger.
388 // See https://github.com/ziglang/zig/issues/645391 // See https://github.com/ziglang/zig/issues/645
389 const field_int_val = try value.toValue().intFromEnum(ty, mod);392 const field_int_val = try value.toValue().intFromEnum(ty, mod);
390 break :value @as(u64, @bitCast(field_int_val.toSignedInt(mod)));393 break :value @bitCast(field_int_val.toSignedInt(mod));
391 };394 };
392 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian);395 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian);
393 }396 }
...@@ -422,7 +425,7 @@ pub const DeclState = struct {...@@ -422,7 +425,7 @@ pub const DeclState = struct {
422 // DW.AT.type, DW.FORM.ref4425 // DW.AT.type, DW.FORM.ref4
423 const inner_union_index = dbg_info_buffer.items.len;426 const inner_union_index = dbg_info_buffer.items.len;
424 try dbg_info_buffer.resize(inner_union_index + 4);427 try dbg_info_buffer.resize(inner_union_index + 4);
425 try self.addTypeRelocLocal(atom_index, @as(u32, @intCast(inner_union_index)), 5);428 try self.addTypeRelocLocal(atom_index, @intCast(inner_union_index), 5);
426 // DW.AT.data_member_location, DW.FORM.udata429 // DW.AT.data_member_location, DW.FORM.udata
427 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset);430 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset);
428 }431 }
...@@ -502,7 +505,7 @@ pub const DeclState = struct {...@@ -502,7 +505,7 @@ pub const DeclState = struct {
502 // DW.AT.type, DW.FORM.ref4505 // DW.AT.type, DW.FORM.ref4
503 const index = dbg_info_buffer.items.len;506 const index = dbg_info_buffer.items.len;
504 try dbg_info_buffer.resize(index + 4);507 try dbg_info_buffer.resize(index + 4);
505 try self.addTypeRelocGlobal(atom_index, payload_ty, @as(u32, @intCast(index)));508 try self.addTypeRelocGlobal(atom_index, payload_ty, @intCast(index));
506 // DW.AT.data_member_location, DW.FORM.udata509 // DW.AT.data_member_location, DW.FORM.udata
507 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_off);510 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_off);
508 }511 }
...@@ -517,7 +520,7 @@ pub const DeclState = struct {...@@ -517,7 +520,7 @@ pub const DeclState = struct {
517 // DW.AT.type, DW.FORM.ref4520 // DW.AT.type, DW.FORM.ref4
518 const index = dbg_info_buffer.items.len;521 const index = dbg_info_buffer.items.len;
519 try dbg_info_buffer.resize(index + 4);522 try dbg_info_buffer.resize(index + 4);
520 try self.addTypeRelocGlobal(atom_index, error_ty, @as(u32, @intCast(index)));523 try self.addTypeRelocGlobal(atom_index, error_ty, @intCast(index));
521 // DW.AT.data_member_location, DW.FORM.udata524 // DW.AT.data_member_location, DW.FORM.udata
522 try leb128.writeULEB128(dbg_info_buffer.writer(), error_off);525 try leb128.writeULEB128(dbg_info_buffer.writer(), error_off);
523 }526 }
...@@ -581,7 +584,7 @@ pub const DeclState = struct {...@@ -581,7 +584,7 @@ pub const DeclState = struct {
581 },584 },
582 .register_pair => |regs| {585 .register_pair => |regs| {
583 const reg_bits = self.mod.getTarget().ptrBitWidth();586 const reg_bits = self.mod.getTarget().ptrBitWidth();
584 const reg_bytes = @as(u8, @intCast(@divExact(reg_bits, 8)));587 const reg_bytes: u8 = @intCast(@divExact(reg_bits, 8));
585 const abi_size = ty.abiSize(self.mod);588 const abi_size = ty.abiSize(self.mod);
586 try dbg_info.ensureUnusedCapacity(10);589 try dbg_info.ensureUnusedCapacity(10);
587 dbg_info.appendAssumeCapacity(@intFromEnum(AbbrevKind.parameter));590 dbg_info.appendAssumeCapacity(@intFromEnum(AbbrevKind.parameter));
...@@ -658,7 +661,7 @@ pub const DeclState = struct {...@@ -658,7 +661,7 @@ pub const DeclState = struct {
658 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);661 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
659 const index = dbg_info.items.len;662 const index = dbg_info.items.len;
660 try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4663 try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4
661 try self.addTypeRelocGlobal(atom_index, ty, @as(u32, @intCast(index))); // DW.AT.type, DW.FORM.ref4664 try self.addTypeRelocGlobal(atom_index, ty, @intCast(index)); // DW.AT.type, DW.FORM.ref4
662 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string665 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
663 }666 }
664667
...@@ -674,6 +677,7 @@ pub const DeclState = struct {...@@ -674,6 +677,7 @@ pub const DeclState = struct {
674 const atom_index = self.di_atom_decls.get(owner_decl).?;677 const atom_index = self.di_atom_decls.get(owner_decl).?;
675 const name_with_null = name.ptr[0 .. name.len + 1];678 const name_with_null = name.ptr[0 .. name.len + 1];
676 try dbg_info.append(@intFromEnum(AbbrevKind.variable));679 try dbg_info.append(@intFromEnum(AbbrevKind.variable));
680 const gpa = self.dwarf.allocator;
677 const mod = self.mod;681 const mod = self.mod;
678 const target = mod.getTarget();682 const target = mod.getTarget();
679 const endian = target.cpu.arch.endian();683 const endian = target.cpu.arch.endian();
...@@ -701,7 +705,7 @@ pub const DeclState = struct {...@@ -701,7 +705,7 @@ pub const DeclState = struct {
701705
702 .register_pair => |regs| {706 .register_pair => |regs| {
703 const reg_bits = self.mod.getTarget().ptrBitWidth();707 const reg_bits = self.mod.getTarget().ptrBitWidth();
704 const reg_bytes = @as(u8, @intCast(@divExact(reg_bits, 8)));708 const reg_bytes: u8 = @intCast(@divExact(reg_bits, 8));
705 const abi_size = child_ty.abiSize(self.mod);709 const abi_size = child_ty.abiSize(self.mod);
706 try dbg_info.ensureUnusedCapacity(9);710 try dbg_info.ensureUnusedCapacity(9);
707 // DW.AT.location, DW.FORM.exprloc711 // DW.AT.location, DW.FORM.exprloc
...@@ -775,20 +779,20 @@ pub const DeclState = struct {...@@ -775,20 +779,20 @@ pub const DeclState = struct {
775 .memory,779 .memory,
776 .linker_load,780 .linker_load,
777 => {781 => {
778 const ptr_width = @as(u8, @intCast(@divExact(target.ptrBitWidth(), 8)));782 const ptr_width: u8 = @intCast(@divExact(target.ptrBitWidth(), 8));
779 try dbg_info.ensureUnusedCapacity(2 + ptr_width);783 try dbg_info.ensureUnusedCapacity(2 + ptr_width);
780 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc784 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
781 1 + ptr_width + @intFromBool(is_ptr),785 1 + ptr_width + @intFromBool(is_ptr),
782 DW.OP.addr, // literal address786 DW.OP.addr, // literal address
783 });787 });
784 const offset = @as(u32, @intCast(dbg_info.items.len));788 const offset: u32 = @intCast(dbg_info.items.len);
785 const addr = switch (loc) {789 const addr = switch (loc) {
786 .memory => |x| x,790 .memory => |x| x,
787 else => 0,791 else => 0,
788 };792 };
789 switch (ptr_width) {793 switch (ptr_width) {
790 0...4 => {794 0...4 => {
791 try dbg_info.writer().writeInt(u32, @as(u32, @intCast(addr)), endian);795 try dbg_info.writer().writeInt(u32, @intCast(addr), endian);
792 },796 },
793 5...8 => {797 5...8 => {
794 try dbg_info.writer().writeInt(u64, addr, endian);798 try dbg_info.writer().writeInt(u64, addr, endian);
...@@ -803,7 +807,7 @@ pub const DeclState = struct {...@@ -803,7 +807,7 @@ pub const DeclState = struct {
803 .linker_load => |load_struct| switch (load_struct.type) {807 .linker_load => |load_struct| switch (load_struct.type) {
804 .direct => {808 .direct => {
805 log.debug("{x}: target sym %{d}", .{ offset, load_struct.sym_index });809 log.debug("{x}: target sym %{d}", .{ offset, load_struct.sym_index });
806 try self.exprloc_relocs.append(self.gpa, .{810 try self.exprloc_relocs.append(gpa, .{
807 .type = .direct_load,811 .type = .direct_load,
808 .target = load_struct.sym_index,812 .target = load_struct.sym_index,
809 .offset = offset,813 .offset = offset,
...@@ -811,7 +815,7 @@ pub const DeclState = struct {...@@ -811,7 +815,7 @@ pub const DeclState = struct {
811 },815 },
812 .got => {816 .got => {
813 log.debug("{x}: target sym %{d} via GOT", .{ offset, load_struct.sym_index });817 log.debug("{x}: target sym %{d} via GOT", .{ offset, load_struct.sym_index });
814 try self.exprloc_relocs.append(self.gpa, .{818 try self.exprloc_relocs.append(gpa, .{
815 .type = .got_load,819 .type = .got_load,
816 .target = load_struct.sym_index,820 .target = load_struct.sym_index,
817 .offset = offset,821 .offset = offset,
...@@ -836,15 +840,15 @@ pub const DeclState = struct {...@@ -836,15 +840,15 @@ pub const DeclState = struct {
836 try leb128.writeULEB128(dbg_info.writer(), x);840 try leb128.writeULEB128(dbg_info.writer(), x);
837 }841 }
838 try dbg_info.append(DW.OP.stack_value);842 try dbg_info.append(DW.OP.stack_value);
839 dbg_info.items[fixup] += @as(u8, @intCast(dbg_info.items.len - fixup - 2));843 dbg_info.items[fixup] += @intCast(dbg_info.items.len - fixup - 2);
840 },844 },
841845
842 .undef => {846 .undef => {
843 // DW.AT.location, DW.FORM.exprloc847 // DW.AT.location, DW.FORM.exprloc
844 // uleb128(exprloc_len)848 // uleb128(exprloc_len)
845 // DW.OP.implicit_value uleb128(len_of_bytes) bytes849 // DW.OP.implicit_value uleb128(len_of_bytes) bytes
846 const abi_size = @as(u32, @intCast(child_ty.abiSize(mod)));850 const abi_size: u32 = @intCast(child_ty.abiSize(mod));
847 var implicit_value_len = std.ArrayList(u8).init(self.gpa);851 var implicit_value_len = std.ArrayList(u8).init(gpa);
848 defer implicit_value_len.deinit();852 defer implicit_value_len.deinit();
849 try leb128.writeULEB128(implicit_value_len.writer(), abi_size);853 try leb128.writeULEB128(implicit_value_len.writer(), abi_size);
850 const total_exprloc_len = 1 + implicit_value_len.items.len + abi_size;854 const total_exprloc_len = 1 + implicit_value_len.items.len + abi_size;
...@@ -873,27 +877,55 @@ pub const DeclState = struct {...@@ -873,27 +877,55 @@ pub const DeclState = struct {
873 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);877 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
874 const index = dbg_info.items.len;878 const index = dbg_info.items.len;
875 try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4879 try dbg_info.resize(index + 4); // dw.at.type, dw.form.ref4
876 try self.addTypeRelocGlobal(atom_index, child_ty, @as(u32, @intCast(index)));880 try self.addTypeRelocGlobal(atom_index, child_ty, @intCast(index));
877 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string881 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
878 }882 }
879883
880 pub fn advancePCAndLine(884 pub fn advancePCAndLine(
881 self: *DeclState,885 self: *DeclState,
882 delta_line: i32,886 delta_line: i33,
883 delta_pc: usize,887 delta_pc: u64,
884 ) error{OutOfMemory}!void {888 ) error{OutOfMemory}!void {
885 // TODO Look into using the DWARF special opcodes to compress this data.
886 // It lets you emit single-byte opcodes that add different numbers to
887 // both the PC and the line number at the same time.
888 const dbg_line = &self.dbg_line;889 const dbg_line = &self.dbg_line;
889 try dbg_line.ensureUnusedCapacity(11);890 try dbg_line.ensureUnusedCapacity(5 + 5 + 1);
890 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);891
891 leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;892 const header = self.dwarf.dbg_line_header;
892 if (delta_line != 0) {893 assert(header.maximum_operations_per_instruction == 1);
894 const delta_op: u64 = 0;
895
896 const remaining_delta_line: i9 = @intCast(if (delta_line < header.line_base or
897 delta_line - header.line_base >= header.line_range)
898 remaining: {
899 assert(delta_line != 0);
893 dbg_line.appendAssumeCapacity(DW.LNS.advance_line);900 dbg_line.appendAssumeCapacity(DW.LNS.advance_line);
894 leb128.writeILEB128(dbg_line.writer(), delta_line) catch unreachable;901 leb128.writeILEB128(dbg_line.writer(), delta_line) catch unreachable;
902 break :remaining 0;
903 } else delta_line);
904
905 const op_advance = @divExact(delta_pc, header.minimum_instruction_length) *
906 header.maximum_operations_per_instruction + delta_op;
907 const max_op_advance: u9 = (std.math.maxInt(u8) - header.opcode_base) / header.line_range;
908 const remaining_op_advance: u8 = @intCast(if (op_advance >= 2 * max_op_advance) remaining: {
909 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
910 leb128.writeULEB128(dbg_line.writer(), op_advance) catch unreachable;
911 break :remaining 0;
912 } else if (op_advance >= max_op_advance) remaining: {
913 dbg_line.appendAssumeCapacity(DW.LNS.const_add_pc);
914 break :remaining op_advance - max_op_advance;
915 } else op_advance);
916
917 if (remaining_delta_line == 0 and remaining_op_advance == 0) {
918 dbg_line.appendAssumeCapacity(DW.LNS.copy);
919 } else {
920 dbg_line.appendAssumeCapacity(@intCast((remaining_delta_line - header.line_base) +
921 (header.line_range * remaining_op_advance) + header.opcode_base));
895 }922 }
896 dbg_line.appendAssumeCapacity(DW.LNS.copy);923 }
924
925 pub fn setColumn(self: *DeclState, column: u32) error{OutOfMemory}!void {
926 try self.dbg_line.ensureUnusedCapacity(1 + 5);
927 self.dbg_line.appendAssumeCapacity(DW.LNS.set_column);
928 leb128.writeULEB128(self.dbg_line.writer(), column + 1) catch unreachable;
897 }929 }
898930
899 pub fn setPrologueEnd(self: *DeclState) error{OutOfMemory}!void {931 pub fn setPrologueEnd(self: *DeclState) error{OutOfMemory}!void {
...@@ -903,6 +935,31 @@ pub const DeclState = struct {...@@ -903,6 +935,31 @@ pub const DeclState = struct {
903 pub fn setEpilogueBegin(self: *DeclState) error{OutOfMemory}!void {935 pub fn setEpilogueBegin(self: *DeclState) error{OutOfMemory}!void {
904 try self.dbg_line.append(DW.LNS.set_epilogue_begin);936 try self.dbg_line.append(DW.LNS.set_epilogue_begin);
905 }937 }
938
939 pub fn setInlineFunc(self: *DeclState, func: InternPool.Index) error{OutOfMemory}!void {
940 if (self.dbg_line_func == func) return;
941
942 try self.dbg_line.ensureUnusedCapacity((1 + 4) + (1 + 5));
943
944 const old_func_info = self.mod.funcInfo(self.dbg_line_func);
945 const new_func_info = self.mod.funcInfo(func);
946
947 const old_file = try self.dwarf.addDIFile(self.mod, old_func_info.owner_decl);
948 const new_file = try self.dwarf.addDIFile(self.mod, new_func_info.owner_decl);
949 if (old_file != new_file) {
950 self.dbg_line.appendAssumeCapacity(DW.LNS.set_file);
951 leb128.writeUnsignedFixed(4, self.dbg_line.addManyAsArrayAssumeCapacity(4), new_file);
952 }
953
954 const old_src_line: i33 = self.mod.declPtr(old_func_info.owner_decl).src_line;
955 const new_src_line: i33 = self.mod.declPtr(new_func_info.owner_decl).src_line;
956 if (new_src_line != old_src_line) {
957 self.dbg_line.appendAssumeCapacity(DW.LNS.advance_line);
958 leb128.writeSignedFixed(5, self.dbg_line.addManyAsArrayAssumeCapacity(5), new_src_line - old_src_line);
959 }
960
961 self.dbg_line_func = func;
962 }
906};963};
907964
908pub const AbbrevEntry = struct {965pub const AbbrevEntry = struct {
...@@ -966,7 +1023,8 @@ const min_nop_size = 2;...@@ -966,7 +1023,8 @@ const min_nop_size = 2;
966const ideal_factor = 3;1023const ideal_factor = 3;
9671024
968pub fn init(allocator: Allocator, bin_file: *File, format: Format) Dwarf {1025pub fn init(allocator: Allocator, bin_file: *File, format: Format) Dwarf {
969 const ptr_width: PtrWidth = switch (bin_file.options.target.ptrBitWidth()) {1026 const target = &bin_file.options.target;
1027 const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {
970 0...32 => .p32,1028 0...32 => .p32,
971 33...64 => .p64,1029 33...64 => .p64,
972 else => unreachable,1030 else => unreachable,
...@@ -976,6 +1034,24 @@ pub fn init(allocator: Allocator, bin_file: *File, format: Format) Dwarf {...@@ -976,6 +1034,24 @@ pub fn init(allocator: Allocator, bin_file: *File, format: Format) Dwarf {
976 .bin_file = bin_file,1034 .bin_file = bin_file,
977 .format = format,1035 .format = format,
978 .ptr_width = ptr_width,1036 .ptr_width = ptr_width,
1037 .dbg_line_header = switch (target.cpu.arch) {
1038 .x86_64 => .{
1039 .minimum_instruction_length = 1,
1040 .maximum_operations_per_instruction = 1,
1041 .default_is_stmt = true,
1042 .line_base = -5,
1043 .line_range = 14,
1044 .opcode_base = DW.LNS.set_isa + 1,
1045 },
1046 else => .{
1047 .minimum_instruction_length = 1,
1048 .maximum_operations_per_instruction = 1,
1049 .default_is_stmt = true,
1050 .line_base = 1,
1051 .line_range = 1,
1052 .opcode_base = DW.LNS.set_isa + 1,
1053 },
1054 },
979 };1055 };
980}1056}
9811057
...@@ -1002,12 +1078,24 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)...@@ -1002,12 +1078,24 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
1002 defer tracy.end();1078 defer tracy.end();
10031079
1004 const decl = mod.declPtr(decl_index);1080 const decl = mod.declPtr(decl_index);
1005 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));1081 const decl_linkage_name = try decl.getFullyQualifiedName(mod);
10061082
1007 log.debug("initDeclState {s}{*}", .{ decl_name, decl });1083 log.debug("initDeclState {}{*}", .{ decl_linkage_name.fmt(&mod.intern_pool), decl });
10081084
1009 const gpa = self.allocator;1085 const gpa = self.allocator;
1010 var decl_state = DeclState.init(gpa, mod, &self.di_atom_decls);1086 var decl_state: DeclState = .{
1087 .dwarf = self,
1088 .mod = mod,
1089 .di_atom_decls = &self.di_atom_decls,
1090 .dbg_line_func = undefined,
1091 .dbg_line = std.ArrayList(u8).init(gpa),
1092 .dbg_info = std.ArrayList(u8).init(gpa),
1093 .abbrev_type_arena = std.heap.ArenaAllocator.init(gpa),
1094 .abbrev_table = .{},
1095 .abbrev_resolver = .{},
1096 .abbrev_relocs = .{},
1097 .exprloc_relocs = .{},
1098 };
1011 errdefer decl_state.deinit();1099 errdefer decl_state.deinit();
1012 const dbg_line_buffer = &decl_state.dbg_line;1100 const dbg_line_buffer = &decl_state.dbg_line;
1013 const dbg_info_buffer = &decl_state.dbg_info;1101 const dbg_info_buffer = &decl_state.dbg_info;
...@@ -1021,18 +1109,19 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)...@@ -1021,18 +1109,19 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
1021 _ = try self.getOrCreateAtomForDecl(.src_fn, decl_index);1109 _ = try self.getOrCreateAtomForDecl(.src_fn, decl_index);
10221110
1023 // For functions we need to add a prologue to the debug line program.1111 // For functions we need to add a prologue to the debug line program.
1024 try dbg_line_buffer.ensureTotalCapacity(26);1112 const ptr_width_bytes = self.ptrWidthBytes();
1113 try dbg_line_buffer.ensureTotalCapacity((3 + ptr_width_bytes) + (1 + 4) + (1 + 4) + (1 + 5) + 1);
10251114
1115 decl_state.dbg_line_func = decl.val.toIntern();
1026 const func = decl.val.getFunction(mod).?;1116 const func = decl.val.getFunction(mod).?;
1027 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{1117 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{
1028 decl.src_line,1118 decl.src_line,
1029 func.lbrace_line,1119 func.lbrace_line,
1030 func.rbrace_line,1120 func.rbrace_line,
1031 });1121 });
1032 const line = @as(u28, @intCast(decl.src_line + func.lbrace_line));1122 const line: u28 = @intCast(decl.src_line + func.lbrace_line);
10331123
1034 const ptr_width_bytes = self.ptrWidthBytes();1124 dbg_line_buffer.appendSliceAssumeCapacity(&.{
1035 dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{
1036 DW.LNS.extended_op,1125 DW.LNS.extended_op,
1037 ptr_width_bytes + 1,1126 ptr_width_bytes + 1,
1038 DW.LNE.set_address,1127 DW.LNE.set_address,
...@@ -1055,21 +1144,24 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)...@@ -1055,21 +1144,24 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
1055 const file_index = try self.addDIFile(mod, decl_index);1144 const file_index = try self.addDIFile(mod, decl_index);
1056 leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), file_index);1145 leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), file_index);
10571146
1147 dbg_line_buffer.appendAssumeCapacity(DW.LNS.set_column);
1148 leb128.writeULEB128(dbg_line_buffer.writer(), func.lbrace_column + 1) catch unreachable;
1149
1058 // Emit a line for the begin curly with prologue_end=false. The codegen will1150 // Emit a line for the begin curly with prologue_end=false. The codegen will
1059 // do the work of setting prologue_end=true and epilogue_begin=true.1151 // do the work of setting prologue_end=true and epilogue_begin=true.
1060 dbg_line_buffer.appendAssumeCapacity(DW.LNS.copy);1152 dbg_line_buffer.appendAssumeCapacity(DW.LNS.copy);
10611153
1062 // .debug_info subprogram1154 // .debug_info subprogram
1063 const decl_name_with_null = decl_name[0 .. decl_name.len + 1];1155 const decl_name_slice = mod.intern_pool.stringToSlice(decl.name);
1064 try dbg_info_buffer.ensureUnusedCapacity(25 + decl_name_with_null.len);1156 const decl_linkage_name_slice = mod.intern_pool.stringToSlice(decl_linkage_name);
1157 try dbg_info_buffer.ensureUnusedCapacity(1 + ptr_width_bytes + 4 + 4 +
1158 (decl_name_slice.len + 1) + (decl_linkage_name_slice.len + 1));
10651159
1066 const fn_ret_type = decl.ty.fnReturnType(mod);1160 const fn_ret_type = decl.ty.fnReturnType(mod);
1067 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(mod);1161 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(mod);
1068 if (fn_ret_has_bits) {1162 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(
1069 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.subprogram));1163 @as(AbbrevKind, if (fn_ret_has_bits) .subprogram else .subprogram_retvoid),
1070 } else {1164 ));
1071 dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.subprogram_retvoid));
1072 }
1073 // These get overwritten after generating the machine code. These values are1165 // These get overwritten after generating the machine code. These values are
1074 // "relocations" and have to be in this fixed place so that functions can be1166 // "relocations" and have to be in this fixed place so that functions can be
1075 // moved in virtual address space.1167 // moved in virtual address space.
...@@ -1077,14 +1169,16 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)...@@ -1077,14 +1169,16 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
1077 dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT.low_pc, DW.FORM.addr1169 dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT.low_pc, DW.FORM.addr
1078 assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len);1170 assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len);
1079 dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data41171 dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data4
1080 //
1081 if (fn_ret_has_bits) {1172 if (fn_ret_has_bits) {
1082 try decl_state.addTypeRelocGlobal(di_atom_index, fn_ret_type, @as(u32, @intCast(dbg_info_buffer.items.len)));1173 try decl_state.addTypeRelocGlobal(di_atom_index, fn_ret_type, @intCast(dbg_info_buffer.items.len));
1083 dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref41174 dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4
1084 }1175 }
10851176 dbg_info_buffer.appendSliceAssumeCapacity(
1086 dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT.name, DW.FORM.string1177 decl_name_slice[0 .. decl_name_slice.len + 1],
10871178 ); // DW.AT.name, DW.FORM.string
1179 dbg_info_buffer.appendSliceAssumeCapacity(
1180 decl_linkage_name_slice[0 .. decl_linkage_name_slice.len + 1],
1181 ); // DW.AT.linkage_name, DW.FORM.string
1088 },1182 },
1089 else => {1183 else => {
1090 // TODO implement .debug_info for global variables1184 // TODO implement .debug_info for global variables
...@@ -1116,17 +1210,19 @@ pub fn commitDeclState(...@@ -1116,17 +1210,19 @@ pub fn commitDeclState(
1116 assert(decl.has_tv);1210 assert(decl.has_tv);
1117 switch (decl.ty.zigTypeTag(mod)) {1211 switch (decl.ty.zigTypeTag(mod)) {
1118 .Fn => {1212 .Fn => {
1213 try decl_state.setInlineFunc(decl.val.toIntern());
1214
1119 // Since the Decl is a function, we need to update the .debug_line program.1215 // Since the Decl is a function, we need to update the .debug_line program.
1120 // Perform the relocations based on vaddr.1216 // Perform the relocations based on vaddr.
1121 switch (self.ptr_width) {1217 switch (self.ptr_width) {
1122 .p32 => {1218 .p32 => {
1123 {1219 {
1124 const ptr = dbg_line_buffer.items[dbg_line_vaddr_reloc_index..][0..4];1220 const ptr = dbg_line_buffer.items[dbg_line_vaddr_reloc_index..][0..4];
1125 mem.writeInt(u32, ptr, @as(u32, @intCast(sym_addr)), target_endian);1221 mem.writeInt(u32, ptr, @intCast(sym_addr), target_endian);
1126 }1222 }
1127 {1223 {
1128 const ptr = dbg_info_buffer.items[dbg_info_low_pc_reloc_index..][0..4];1224 const ptr = dbg_info_buffer.items[dbg_info_low_pc_reloc_index..][0..4];
1129 mem.writeInt(u32, ptr, @as(u32, @intCast(sym_addr)), target_endian);1225 mem.writeInt(u32, ptr, @intCast(sym_addr), target_endian);
1130 }1226 }
1131 },1227 },
1132 .p64 => {1228 .p64 => {
...@@ -1146,7 +1242,7 @@ pub fn commitDeclState(...@@ -1146,7 +1242,7 @@ pub fn commitDeclState(
1146 sym_size,1242 sym_size,
1147 });1243 });
1148 const ptr = dbg_info_buffer.items[self.getRelocDbgInfoSubprogramHighPC()..][0..4];1244 const ptr = dbg_info_buffer.items[self.getRelocDbgInfoSubprogramHighPC()..][0..4];
1149 mem.writeInt(u32, ptr, @as(u32, @intCast(sym_size)), target_endian);1245 mem.writeInt(u32, ptr, @intCast(sym_size), target_endian);
1150 }1246 }
11511247
1152 try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS.extended_op, 1, DW.LNE.end_sequence });1248 try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS.extended_op, 1, DW.LNE.end_sequence });
...@@ -1158,7 +1254,7 @@ pub fn commitDeclState(...@@ -1158,7 +1254,7 @@ pub fn commitDeclState(
1158 // probably need to edit that logic too.1254 // probably need to edit that logic too.
1159 const src_fn_index = self.src_fn_decls.get(decl_index).?;1255 const src_fn_index = self.src_fn_decls.get(decl_index).?;
1160 const src_fn = self.getAtomPtr(.src_fn, src_fn_index);1256 const src_fn = self.getAtomPtr(.src_fn, src_fn_index);
1161 src_fn.len = @as(u32, @intCast(dbg_line_buffer.items.len));1257 src_fn.len = @intCast(dbg_line_buffer.items.len);
11621258
1163 if (self.src_fn_last_index) |last_index| blk: {1259 if (self.src_fn_last_index) |last_index| blk: {
1164 if (src_fn_index == last_index) break :blk;1260 if (src_fn_index == last_index) break :blk;
...@@ -1315,7 +1411,7 @@ pub fn commitDeclState(...@@ -1315,7 +1411,7 @@ pub fn commitDeclState(
1315 }1411 }
1316 }1412 }
13171413
1318 try self.updateDeclDebugInfoAllocation(di_atom_index, @as(u32, @intCast(dbg_info_buffer.items.len)));1414 try self.updateDeclDebugInfoAllocation(di_atom_index, @intCast(dbg_info_buffer.items.len));
13191415
1320 while (decl_state.abbrev_relocs.popOrNull()) |reloc| {1416 while (decl_state.abbrev_relocs.popOrNull()) |reloc| {
1321 if (reloc.target) |target| {1417 if (reloc.target) |target| {
...@@ -1448,7 +1544,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32)...@@ -1448,7 +1544,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32)
1448 self.di_atom_first_index = atom_index;1544 self.di_atom_first_index = atom_index;
1449 self.di_atom_last_index = atom_index;1545 self.di_atom_last_index = atom_index;
14501546
1451 atom.off = @as(u32, @intCast(padToIdeal(self.dbgInfoHeaderBytes())));1547 atom.off = @intCast(padToIdeal(self.dbgInfoHeaderBytes()));
1452 }1548 }
1453}1549}
14541550
...@@ -1559,7 +1655,7 @@ pub fn updateDeclLineNumber(self: *Dwarf, mod: *Module, decl_index: Module.Decl....@@ -1559,7 +1655,7 @@ pub fn updateDeclLineNumber(self: *Dwarf, mod: *Module, decl_index: Module.Decl.
1559 func.lbrace_line,1655 func.lbrace_line,
1560 func.rbrace_line,1656 func.rbrace_line,
1561 });1657 });
1562 const line = @as(u28, @intCast(decl.src_line + func.lbrace_line));1658 const line: u28 = @intCast(decl.src_line + func.lbrace_line);
1563 var data: [4]u8 = undefined;1659 var data: [4]u8 = undefined;
1564 leb128.writeUnsignedFixed(4, &data, line);1660 leb128.writeUnsignedFixed(4, &data, line);
15651661
...@@ -1647,131 +1743,122 @@ pub fn freeDecl(self: *Dwarf, decl_index: Module.Decl.Index) void {...@@ -1647,131 +1743,122 @@ pub fn freeDecl(self: *Dwarf, decl_index: Module.Decl.Index) void {
1647pub fn writeDbgAbbrev(self: *Dwarf) !void {1743pub fn writeDbgAbbrev(self: *Dwarf) !void {
1648 // These are LEB encoded but since the values are all less than 1271744 // These are LEB encoded but since the values are all less than 127
1649 // we can simply append these bytes.1745 // we can simply append these bytes.
1746 // zig fmt: off
1650 const abbrev_buf = [_]u8{1747 const abbrev_buf = [_]u8{
1651 @intFromEnum(AbbrevKind.compile_unit), DW.TAG.compile_unit, DW.CHILDREN.yes, // header1748 @intFromEnum(AbbrevKind.compile_unit),
1652 DW.AT.stmt_list, DW.FORM.sec_offset, DW.AT.low_pc,1749 DW.TAG.compile_unit,
1653 DW.FORM.addr, DW.AT.high_pc, DW.FORM.addr,1750 DW.CHILDREN.yes,
1654 DW.AT.name, DW.FORM.strp, DW.AT.comp_dir,1751 DW.AT.stmt_list, DW.FORM.sec_offset,
1655 DW.FORM.strp, DW.AT.producer, DW.FORM.strp,1752 DW.AT.low_pc, DW.FORM.addr,
1656 DW.AT.language, DW.FORM.data2, 0,1753 DW.AT.high_pc, DW.FORM.addr,
1657 0, // table sentinel1754 DW.AT.name, DW.FORM.strp,
1755 DW.AT.comp_dir, DW.FORM.strp,
1756 DW.AT.producer, DW.FORM.strp,
1757 DW.AT.language, DW.FORM.data2,
1758 0, 0,
1759
1658 @intFromEnum(AbbrevKind.subprogram),1760 @intFromEnum(AbbrevKind.subprogram),
1659 DW.TAG.subprogram,1761 DW.TAG.subprogram,
1660 DW.CHILDREN.yes, // header1762 DW.CHILDREN.yes,
1661 DW.AT.low_pc,1763 DW.AT.low_pc, DW.FORM.addr,
1662 DW.FORM.addr,1764 DW.AT.high_pc, DW.FORM.data4,
1663 DW.AT.high_pc,1765 DW.AT.type, DW.FORM.ref4,
1664 DW.FORM.data4,1766 DW.AT.name, DW.FORM.string,
1665 DW.AT.type,1767 DW.AT.linkage_name, DW.FORM.string,
1666 DW.FORM.ref4,1768 0, 0,
1667 DW.AT.name,1769
1668 DW.FORM.string,
1669 0, 0, // table sentinel
1670 @intFromEnum(AbbrevKind.subprogram_retvoid),1770 @intFromEnum(AbbrevKind.subprogram_retvoid),
1671 DW.TAG.subprogram, DW.CHILDREN.yes, // header1771 DW.TAG.subprogram,
1672 DW.AT.low_pc, DW.FORM.addr,1772 DW.CHILDREN.yes,
1673 DW.AT.high_pc, DW.FORM.data4,1773 DW.AT.low_pc, DW.FORM.addr,
1674 DW.AT.name, DW.FORM.string,1774 DW.AT.high_pc, DW.FORM.data4,
1675 0,1775 DW.AT.name, DW.FORM.string,
1676 0, // table sentinel1776 DW.AT.linkage_name, DW.FORM.string,
1777 0, 0,
1778
1677 @intFromEnum(AbbrevKind.base_type),1779 @intFromEnum(AbbrevKind.base_type),
1678 DW.TAG.base_type,1780 DW.TAG.base_type, DW.CHILDREN.no,
1679 DW.CHILDREN.no, // header1781 DW.AT.encoding, DW.FORM.data1,
1680 DW.AT.encoding,1782 DW.AT.byte_size, DW.FORM.udata,
1681 DW.FORM.data1,1783 DW.AT.name, DW.FORM.string,
1682 DW.AT.byte_size,1784 0, 0,
1683 DW.FORM.udata,1785
1684 DW.AT.name,
1685 DW.FORM.string,
1686 0,
1687 0, // table sentinel
1688 @intFromEnum(AbbrevKind.ptr_type),1786 @intFromEnum(AbbrevKind.ptr_type),
1689 DW.TAG.pointer_type,1787 DW.TAG.pointer_type, DW.CHILDREN.no,
1690 DW.CHILDREN.no, // header1788 DW.AT.type, DW.FORM.ref4,
1691 DW.AT.type,1789 0, 0,
1692 DW.FORM.ref4,1790
1693 0,
1694 0, // table sentinel
1695 @intFromEnum(AbbrevKind.struct_type),1791 @intFromEnum(AbbrevKind.struct_type),
1696 DW.TAG.structure_type,1792 DW.TAG.structure_type, DW.CHILDREN.yes,
1697 DW.CHILDREN.yes, // header1793 DW.AT.byte_size, DW.FORM.udata,
1698 DW.AT.byte_size,1794 DW.AT.name, DW.FORM.string,
1699 DW.FORM.udata,1795 0, 0,
1700 DW.AT.name,1796
1701 DW.FORM.string,
1702 0,
1703 0, // table sentinel
1704 @intFromEnum(AbbrevKind.struct_member),1797 @intFromEnum(AbbrevKind.struct_member),
1705 DW.TAG.member,1798 DW.TAG.member,
1706 DW.CHILDREN.no, // header1799 DW.CHILDREN.no,
1707 DW.AT.name,1800 DW.AT.name, DW.FORM.string,
1708 DW.FORM.string,1801 DW.AT.type, DW.FORM.ref4,
1709 DW.AT.type,1802 DW.AT.data_member_location, DW.FORM.udata,
1710 DW.FORM.ref4,1803 0, 0,
1711 DW.AT.data_member_location,1804
1712 DW.FORM.udata,
1713 0,
1714 0, // table sentinel
1715 @intFromEnum(AbbrevKind.enum_type),1805 @intFromEnum(AbbrevKind.enum_type),
1716 DW.TAG.enumeration_type,1806 DW.TAG.enumeration_type,
1717 DW.CHILDREN.yes, // header1807 DW.CHILDREN.yes,
1718 DW.AT.byte_size,1808 DW.AT.byte_size, DW.FORM.udata,
1719 DW.FORM.udata,1809 DW.AT.name, DW.FORM.string,
1720 DW.AT.name,1810 0, 0,
1721 DW.FORM.string,1811
1722 0,
1723 0, // table sentinel
1724 @intFromEnum(AbbrevKind.enum_variant),1812 @intFromEnum(AbbrevKind.enum_variant),
1725 DW.TAG.enumerator,1813 DW.TAG.enumerator, DW.CHILDREN.no,
1726 DW.CHILDREN.no, // header1814 DW.AT.name, DW.FORM.string,
1727 DW.AT.name,1815 DW.AT.const_value, DW.FORM.data8,
1728 DW.FORM.string,1816 0, 0,
1729 DW.AT.const_value,1817
1730 DW.FORM.data8,
1731 0,
1732 0, // table sentinel
1733 @intFromEnum(AbbrevKind.union_type),1818 @intFromEnum(AbbrevKind.union_type),
1734 DW.TAG.union_type,1819 DW.TAG.union_type, DW.CHILDREN.yes,
1735 DW.CHILDREN.yes, // header1820 DW.AT.byte_size, DW.FORM.udata,
1736 DW.AT.byte_size,1821 DW.AT.name, DW.FORM.string,
1737 DW.FORM.udata,1822 0, 0,
1738 DW.AT.name,1823
1739 DW.FORM.string,
1740 0,
1741 0, // table sentinel
1742 @intFromEnum(AbbrevKind.pad1),1824 @intFromEnum(AbbrevKind.pad1),
1743 DW.TAG.unspecified_type,1825 DW.TAG.unspecified_type,
1744 DW.CHILDREN.no, // header1826 DW.CHILDREN.no,
1745 0,1827 0, 0,
1746 0, // table sentinel1828
1747 @intFromEnum(AbbrevKind.parameter),1829 @intFromEnum(AbbrevKind.parameter),
1748 DW.TAG.formal_parameter, DW.CHILDREN.no, // header1830 DW.TAG.formal_parameter,
1749 DW.AT.location, DW.FORM.exprloc,1831 DW.CHILDREN.no,
1750 DW.AT.type, DW.FORM.ref4,1832 DW.AT.location, DW.FORM.exprloc,
1751 DW.AT.name, DW.FORM.string,1833 DW.AT.type, DW.FORM.ref4,
1752 0,1834 DW.AT.name, DW.FORM.string,
1753 0, // table sentinel1835 0, 0,
1836
1754 @intFromEnum(AbbrevKind.variable),1837 @intFromEnum(AbbrevKind.variable),
1755 DW.TAG.variable, DW.CHILDREN.no, // header1838 DW.TAG.variable,
1756 DW.AT.location, DW.FORM.exprloc,1839 DW.CHILDREN.no,
1757 DW.AT.type, DW.FORM.ref4,1840 DW.AT.location, DW.FORM.exprloc,
1758 DW.AT.name, DW.FORM.string,1841 DW.AT.type, DW.FORM.ref4,
1759 0,1842 DW.AT.name, DW.FORM.string,
1760 0, // table sentinel1843 0, 0,
1844
1761 @intFromEnum(AbbrevKind.array_type),1845 @intFromEnum(AbbrevKind.array_type),
1762 DW.TAG.array_type, DW.CHILDREN.yes, // header1846 DW.TAG.array_type,
1763 DW.AT.name, DW.FORM.string,1847 DW.CHILDREN.yes,
1764 DW.AT.type, DW.FORM.ref4,1848 DW.AT.name, DW.FORM.string,
1765 0,1849 DW.AT.type, DW.FORM.ref4,
1766 0, // table sentinel1850 0, 0,
1851
1767 @intFromEnum(AbbrevKind.array_dim),1852 @intFromEnum(AbbrevKind.array_dim),
1768 DW.TAG.subrange_type, DW.CHILDREN.no, // header1853 DW.TAG.subrange_type,
1769 DW.AT.type, DW.FORM.ref4,1854 DW.CHILDREN.no,
1770 DW.AT.count, DW.FORM.udata,1855 DW.AT.type, DW.FORM.ref4,
1856 DW.AT.count, DW.FORM.udata,
1857 0, 0,
1858
1771 0,1859 0,
1772 0, // table sentinel
1773 0, // section sentinel
1774 };1860 };
1861 // zig fmt: on
1775 const abbrev_offset = 0;1862 const abbrev_offset = 0;
1776 self.abbrev_table_offset = abbrev_offset;1863 self.abbrev_table_offset = abbrev_offset;
17771864
...@@ -1910,7 +1997,7 @@ fn resolveCompilationDir(module: *Module, buffer: *[std.fs.MAX_PATH_BYTES]u8) []...@@ -1910,7 +1997,7 @@ fn resolveCompilationDir(module: *Module, buffer: *[std.fs.MAX_PATH_BYTES]u8) []
1910fn writeAddrAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), addr: u64) void {1997fn writeAddrAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), addr: u64) void {
1911 const target_endian = self.bin_file.options.target.cpu.arch.endian();1998 const target_endian = self.bin_file.options.target.cpu.arch.endian();
1912 switch (self.ptr_width) {1999 switch (self.ptr_width) {
1913 .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(addr)), target_endian),2000 .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @intCast(addr), target_endian),
1914 .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian),2001 .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian),
1915 }2002 }
1916}2003}
...@@ -1918,12 +2005,7 @@ fn writeAddrAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), addr: u64) voi...@@ -1918,12 +2005,7 @@ fn writeAddrAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), addr: u64) voi
1918fn writeOffsetAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), off: u64) void {2005fn writeOffsetAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), off: u64) void {
1919 const target_endian = self.bin_file.options.target.cpu.arch.endian();2006 const target_endian = self.bin_file.options.target.cpu.arch.endian();
1920 switch (self.format) {2007 switch (self.format) {
1921 .dwarf32 => mem.writeInt(2008 .dwarf32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @intCast(off), target_endian),
1922 u32,
1923 buf.addManyAsArrayAssumeCapacity(4),
1924 @as(u32, @intCast(off)),
1925 target_endian,
1926 ),
1927 .dwarf64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), off, target_endian),2009 .dwarf64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), off, target_endian),
1928 }2010 }
1929}2011}
...@@ -2182,16 +2264,11 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {...@@ -2182,16 +2264,11 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
2182 // Go back and populate the initial length.2264 // Go back and populate the initial length.
2183 const init_len = di_buf.items.len - after_init_len;2265 const init_len = di_buf.items.len - after_init_len;
2184 switch (self.format) {2266 switch (self.format) {
2185 .dwarf32 => mem.writeInt(2267 .dwarf32 => mem.writeInt(u32, di_buf.items[init_len_index..][0..4], @intCast(init_len), target_endian),
2186 u32,
2187 di_buf.items[init_len_index..][0..4],
2188 @as(u32, @intCast(init_len)),
2189 target_endian,
2190 ),
2191 .dwarf64 => mem.writeInt(u64, di_buf.items[init_len_index..][0..8], init_len, target_endian),2268 .dwarf64 => mem.writeInt(u64, di_buf.items[init_len_index..][0..8], init_len, target_endian),
2192 }2269 }
21932270
2194 const needed_size = @as(u32, @intCast(di_buf.items.len));2271 const needed_size: u32 = @intCast(di_buf.items.len);
2195 switch (self.bin_file.tag) {2272 switch (self.bin_file.tag) {
2196 .elf => {2273 .elf => {
2197 const elf_file = self.bin_file.cast(File.Elf).?;2274 const elf_file = self.bin_file.cast(File.Elf).?;
...@@ -2256,14 +2333,14 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2256,14 +2333,14 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
2256 self.writeOffsetAssumeCapacity(&di_buf, 0); // We will come back and write this.2333 self.writeOffsetAssumeCapacity(&di_buf, 0); // We will come back and write this.
2257 const after_header_len = di_buf.items.len;2334 const after_header_len = di_buf.items.len;
22582335
2259 const opcode_base = DW.LNS.set_isa + 1;2336 assert(self.dbg_line_header.opcode_base == DW.LNS.set_isa + 1);
2260 di_buf.appendSliceAssumeCapacity(&[_]u8{2337 di_buf.appendSliceAssumeCapacity(&[_]u8{
2261 1, // minimum_instruction_length2338 self.dbg_line_header.minimum_instruction_length,
2262 1, // maximum_operations_per_instruction2339 self.dbg_line_header.maximum_operations_per_instruction,
2263 1, // default_is_stmt2340 @intFromBool(self.dbg_line_header.default_is_stmt),
2264 1, // line_base (signed)2341 @bitCast(self.dbg_line_header.line_base),
2265 1, // line_range2342 self.dbg_line_header.line_range,
2266 opcode_base,2343 self.dbg_line_header.opcode_base,
22672344
2268 // Standard opcode lengths. The number of items here is based on `opcode_base`.2345 // Standard opcode lengths. The number of items here is based on `opcode_base`.
2269 // The value is the number of LEB128 operands the instruction takes.2346 // The value is the number of LEB128 operands the instruction takes.
...@@ -2298,7 +2375,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2298,7 +2375,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
2298 di_buf.appendSliceAssumeCapacity(file);2375 di_buf.appendSliceAssumeCapacity(file);
2299 di_buf.appendSliceAssumeCapacity(&[_]u8{2376 di_buf.appendSliceAssumeCapacity(&[_]u8{
2300 0, // null byte for the relative path name2377 0, // null byte for the relative path name
2301 @as(u8, @intCast(dir_index)), // directory_index2378 @intCast(dir_index), // directory_index
2302 0, // mtime (TODO supply this)2379 0, // mtime (TODO supply this)
2303 0, // file size bytes (TODO supply this)2380 0, // file size bytes (TODO supply this)
2304 });2381 });
...@@ -2307,12 +2384,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2307,12 +2384,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
23072384
2308 const header_len = di_buf.items.len - after_header_len;2385 const header_len = di_buf.items.len - after_header_len;
2309 switch (self.format) {2386 switch (self.format) {
2310 .dwarf32 => mem.writeInt(2387 .dwarf32 => mem.writeInt(u32, di_buf.items[before_header_len..][0..4], @intCast(header_len), target_endian),
2311 u32,
2312 di_buf.items[before_header_len..][0..4],
2313 @as(u32, @intCast(header_len)),
2314 target_endian,
2315 ),
2316 .dwarf64 => mem.writeInt(u64, di_buf.items[before_header_len..][0..8], header_len, target_endian),2388 .dwarf64 => mem.writeInt(u64, di_buf.items[before_header_len..][0..8], header_len, target_endian),
2317 }2389 }
23182390
...@@ -2348,7 +2420,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2348,7 +2420,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
2348 .macho => {2420 .macho => {
2349 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;2421 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;
2350 const sect_index = d_sym.debug_line_section_index.?;2422 const sect_index = d_sym.debug_line_section_index.?;
2351 const needed_size = @as(u32, @intCast(d_sym.getSection(sect_index).size + delta));2423 const needed_size: u32 = @intCast(d_sym.getSection(sect_index).size + delta);
2352 try d_sym.growSection(sect_index, needed_size, true);2424 try d_sym.growSection(sect_index, needed_size, true);
2353 const file_pos = d_sym.getSection(sect_index).offset + first_fn.off;2425 const file_pos = d_sym.getSection(sect_index).offset + first_fn.off;
23542426
...@@ -2384,7 +2456,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2384,7 +2456,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
2384 const init_len = self.getDebugLineProgramEnd().? - init_len_size;2456 const init_len = self.getDebugLineProgramEnd().? - init_len_size;
2385 switch (self.format) {2457 switch (self.format) {
2386 .dwarf32 => {2458 .dwarf32 => {
2387 mem.writeInt(u32, di_buf.items[0..4], @as(u32, @intCast(init_len)), target_endian);2459 mem.writeInt(u32, di_buf.items[0..4], @intCast(init_len), target_endian);
2388 },2460 },
2389 .dwarf64 => {2461 .dwarf64 => {
2390 mem.writeInt(u64, di_buf.items[4..][0..8], init_len, target_endian);2462 mem.writeInt(u64, di_buf.items[4..][0..8], init_len, target_endian);
...@@ -2449,12 +2521,12 @@ fn ptrWidthBytes(self: Dwarf) u8 {...@@ -2449,12 +2521,12 @@ fn ptrWidthBytes(self: Dwarf) u8 {
24492521
2450fn dbgLineNeededHeaderBytes(self: Dwarf, dirs: []const []const u8, files: []const []const u8) u32 {2522fn dbgLineNeededHeaderBytes(self: Dwarf, dirs: []const []const u8, files: []const []const u8) u32 {
2451 var size: usize = switch (self.format) { // length field2523 var size: usize = switch (self.format) { // length field
2452 .dwarf32 => @as(usize, 4),2524 .dwarf32 => 4,
2453 .dwarf64 => 12,2525 .dwarf64 => 12,
2454 };2526 };
2455 size += @sizeOf(u16); // version field2527 size += @sizeOf(u16); // version field
2456 size += switch (self.format) { // offset to end-of-header2528 size += switch (self.format) { // offset to end-of-header
2457 .dwarf32 => @as(usize, 4),2529 .dwarf32 => 4,
2458 .dwarf64 => 8,2530 .dwarf64 => 8,
2459 };2531 };
2460 size += 18; // opcodes2532 size += 18; // opcodes
...@@ -2469,7 +2541,7 @@ fn dbgLineNeededHeaderBytes(self: Dwarf, dirs: []const []const u8, files: []cons...@@ -2469,7 +2541,7 @@ fn dbgLineNeededHeaderBytes(self: Dwarf, dirs: []const []const u8, files: []cons
2469 }2541 }
2470 size += 1; // file names sentinel2542 size += 1; // file names sentinel
24712543
2472 return @as(u32, @intCast(size));2544 return @intCast(size);
2473}2545}
24742546
2475/// The reloc offset for the line offset of a function from the previous function's line.2547/// The reloc offset for the line offset of a function from the previous function's line.
...@@ -2514,22 +2586,20 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {...@@ -2514,22 +2586,20 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
2514 log.debug("writeDeclDebugInfo in flushModule", .{});2586 log.debug("writeDeclDebugInfo in flushModule", .{});
2515 try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items);2587 try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items);
25162588
2517 const file_pos = blk: {2589 const file_pos = switch (self.bin_file.tag) {
2518 switch (self.bin_file.tag) {2590 .elf => pos: {
2519 .elf => {2591 const elf_file = self.bin_file.cast(File.Elf).?;
2520 const elf_file = self.bin_file.cast(File.Elf).?;2592 const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?];
2521 const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?];2593 break :pos debug_info_sect.sh_offset;
2522 break :blk debug_info_sect.sh_offset;2594 },
2523 },2595 .macho => pos: {
2524 .macho => {2596 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;
2525 const d_sym = self.bin_file.cast(File.MachO).?.getDebugSymbols().?;2597 const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?);
2526 const debug_info_sect = d_sym.getSectionPtr(d_sym.debug_info_section_index.?);2598 break :pos debug_info_sect.offset;
2527 break :blk debug_info_sect.offset;2599 },
2528 },2600 // for wasm, the offset is always 0 as we write to memory first
2529 // for wasm, the offset is always 0 as we write to memory first2601 .wasm => 0,
2530 .wasm => break :blk @as(u32, 0),2602 else => unreachable,
2531 else => unreachable,
2532 }
2533 };2603 };
25342604
2535 var buf: [@sizeOf(u32)]u8 = undefined;2605 var buf: [@sizeOf(u32)]u8 = undefined;
...@@ -2575,7 +2645,7 @@ fn addDIFile(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) !u28 {...@@ -2575,7 +2645,7 @@ fn addDIFile(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) !u28 {
2575 else => unreachable,2645 else => unreachable,
2576 }2646 }
2577 }2647 }
2578 return @as(u28, @intCast(gop.index + 1));2648 return @intCast(gop.index + 1);
2579}2649}
25802650
2581fn genIncludeDirsAndFileNames(self: *Dwarf, arena: Allocator) !struct {2651fn genIncludeDirsAndFileNames(self: *Dwarf, arena: Allocator) !struct {
...@@ -2603,9 +2673,9 @@ fn genIncludeDirsAndFileNames(self: *Dwarf, arena: Allocator) !struct {...@@ -2603,9 +2673,9 @@ fn genIncludeDirsAndFileNames(self: *Dwarf, arena: Allocator) !struct {
2603 else2673 else
2604 dir_path;2674 dir_path;
26052675
2606 const dir_index: u28 = blk: {2676 const dir_index: u28 = index: {
2607 const dirs_gop = dirs.getOrPutAssumeCapacity(try arena.dupe(u8, resolved));2677 const dirs_gop = dirs.getOrPutAssumeCapacity(try arena.dupe(u8, resolved));
2608 break :blk @as(u28, @intCast(dirs_gop.index + 1));2678 break :index @intCast(dirs_gop.index + 1);
2609 };2679 };
26102680
2611 files_dir_indexes.appendAssumeCapacity(dir_index);2681 files_dir_indexes.appendAssumeCapacity(dir_index);
...@@ -2680,12 +2750,12 @@ fn createAtom(self: *Dwarf, comptime kind: Kind) !Atom.Index {...@@ -2680,12 +2750,12 @@ fn createAtom(self: *Dwarf, comptime kind: Kind) !Atom.Index {
2680 const index = blk: {2750 const index = blk: {
2681 switch (kind) {2751 switch (kind) {
2682 .src_fn => {2752 .src_fn => {
2683 const index = @as(Atom.Index, @intCast(self.src_fns.items.len));2753 const index: Atom.Index = @intCast(self.src_fns.items.len);
2684 _ = try self.src_fns.addOne(self.allocator);2754 _ = try self.src_fns.addOne(self.allocator);
2685 break :blk index;2755 break :blk index;
2686 },2756 },
2687 .di_atom => {2757 .di_atom => {
2688 const index = @as(Atom.Index, @intCast(self.di_atoms.items.len));2758 const index: Atom.Index = @intCast(self.di_atoms.items.len);
2689 _ = try self.di_atoms.addOne(self.allocator);2759 _ = try self.di_atoms.addOne(self.allocator);
2690 break :blk index;2760 break :blk index;
2691 },2761 },