authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-27 17:04:20+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-27 20:53:06+02:00
log366ec2105249050fe88e5fa9f241e14f708db891
tree9b01747e24d6a1b28be90af333c53dc8567ddfa6
parent4ca9b4c44a4fbe2b64b11d2c8a951c2c3e961619

dwarf: track type relocation state in Dwarf module


11 files changed, 436 insertions(+), 518 deletions(-)

src/arch/aarch64/Emit.zig+12-11
......@@ -386,18 +386,19 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
386386 const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line);
387387 const delta_pc: usize = self.code.items.len - self.prev_di_pc;
388388 switch (self.debug_output) {
389 .dwarf => |dbg_out| {
389 .dwarf => |dw| {
390390 // TODO Look into using the DWARF special opcodes to compress this data.
391391 // It lets you emit single-byte opcodes that add different numbers to
392392 // both the PC and the line number at the same time.
393 try dbg_out.dbg_line.ensureUnusedCapacity(11);
394 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
395 leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable;
393 const dbg_line = dw.getDeclDebugLineBuffer();
394 try dbg_line.ensureUnusedCapacity(11);
395 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
396 leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;
396397 if (delta_line != 0) {
397 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line);
398 leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable;
398 dbg_line.appendAssumeCapacity(DW.LNS.advance_line);
399 leb128.writeILEB128(dbg_line.writer(), delta_line) catch unreachable;
399400 }
400 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy);
401 dbg_line.appendAssumeCapacity(DW.LNS.copy);
401402 self.prev_di_pc = self.code.items.len;
402403 self.prev_di_line = line;
403404 self.prev_di_column = column;
......@@ -586,8 +587,8 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {
586587
587588fn mirDebugPrologueEnd(self: *Emit) !void {
588589 switch (self.debug_output) {
589 .dwarf => |dbg_out| {
590 try dbg_out.dbg_line.append(DW.LNS.set_prologue_end);
590 .dwarf => |dw| {
591 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end);
591592 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
592593 },
593594 .plan9 => {},
......@@ -597,8 +598,8 @@ fn mirDebugPrologueEnd(self: *Emit) !void {
597598
598599fn mirDebugEpilogueBegin(self: *Emit) !void {
599600 switch (self.debug_output) {
600 .dwarf => |dbg_out| {
601 try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin);
601 .dwarf => |dw| {
602 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin);
602603 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
603604 },
604605 .plan9 => {},
src/arch/arm/Emit.zig+37-36
......@@ -328,18 +328,19 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
328328 const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line);
329329 const delta_pc: usize = self.code.items.len - self.prev_di_pc;
330330 switch (self.debug_output) {
331 .dwarf => |dbg_out| {
331 .dwarf => |dw| {
332332 // TODO Look into using the DWARF special opcodes to compress this data.
333333 // It lets you emit single-byte opcodes that add different numbers to
334334 // both the PC and the line number at the same time.
335 try dbg_out.dbg_line.ensureUnusedCapacity(11);
336 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
337 leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable;
335 const dbg_line = dw.getDeclDebugLineBuffer();
336 try dbg_line.ensureUnusedCapacity(11);
337 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
338 leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;
338339 if (delta_line != 0) {
339 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line);
340 leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable;
340 dbg_line.appendAssumeCapacity(DW.LNS.advance_line);
341 leb128.writeILEB128(dbg_line.writer(), delta_line) catch unreachable;
341342 }
342 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy);
343 dbg_line.appendAssumeCapacity(DW.LNS.copy);
343344 self.prev_di_pc = self.code.items.len;
344345 self.prev_di_line = line;
345346 self.prev_di_column = column;
......@@ -379,19 +380,17 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
379380/// after codegen for this symbol is done.
380381fn addDbgInfoTypeReloc(self: *Emit, ty: Type) !void {
381382 switch (self.debug_output) {
382 .dwarf => |dbg_out| {
383 .dwarf => |dw| {
383384 assert(ty.hasRuntimeBits());
384 const index = dbg_out.dbg_info.items.len;
385 try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
386
387 const gop = try dbg_out.dbg_info_type_relocs.getOrPutContext(self.bin_file.allocator, ty, .{ .target = self.target.* });
388 if (!gop.found_existing) {
389 gop.value_ptr.* = .{
390 .off = undefined,
391 .relocs = .{},
392 };
393 }
394 try gop.value_ptr.relocs.append(self.bin_file.allocator, @intCast(u32, index));
385 const dbg_info = dw.getDeclDebugInfoBuffer();
386 const index = dbg_info.items.len;
387 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
388 const atom = switch (self.bin_file.tag) {
389 .elf => &self.function.mod_fn.owner_decl.link.elf.dbg_info_atom,
390 .macho => unreachable,
391 else => unreachable,
392 };
393 try dw.addTypeReloc(atom, ty, @intCast(u32, index), null);
395394 },
396395 .plan9 => {},
397396 .none => {},
......@@ -409,16 +408,17 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
409408 switch (mcv) {
410409 .register => |reg| {
411410 switch (self.debug_output) {
412 .dwarf => |dbg_out| {
413 try dbg_out.dbg_info.ensureUnusedCapacity(3);
414 dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
415 dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
411 .dwarf => |dw| {
412 const dbg_info = dw.getDeclDebugInfoBuffer();
413 try dbg_info.ensureUnusedCapacity(3);
414 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
415 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
416416 1, // ULEB128 dwarf expression length
417417 reg.dwarfLocOp(),
418418 });
419 try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
419 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
420420 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
421 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
421 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
422422 },
423423 .plan9 => {},
424424 .none => {},
......@@ -428,7 +428,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
428428 .stack_argument_offset,
429429 => {
430430 switch (self.debug_output) {
431 .dwarf => |dbg_out| {
431 .dwarf => |dw| {
432432 const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch {
433433 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(target)});
434434 };
......@@ -442,7 +442,8 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
442442 else => unreachable,
443443 };
444444
445 try dbg_out.dbg_info.append(link.File.Dwarf.abbrev_parameter);
445 const dbg_info = dw.getDeclDebugInfoBuffer();
446 try dbg_info.append(link.File.Dwarf.abbrev_parameter);
446447
447448 // Get length of the LEB128 stack offset
448449 var counting_writer = std.io.countingWriter(std.io.null_writer);
......@@ -450,13 +451,13 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
450451
451452 // DW.AT.location, DW.FORM.exprloc
452453 // ULEB128 dwarf expression length
453 try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1);
454 try dbg_out.dbg_info.append(DW.OP.breg11);
455 try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset);
454 try leb128.writeULEB128(dbg_info.writer(), counting_writer.bytes_written + 1);
455 try dbg_info.append(DW.OP.breg11);
456 try leb128.writeILEB128(dbg_info.writer(), adjusted_stack_offset);
456457
457 try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
458 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
458459 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
459 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
460 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
460461 },
461462 .plan9 => {},
462463 .none => {},
......@@ -558,8 +559,8 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {
558559
559560fn mirDebugPrologueEnd(emit: *Emit) !void {
560561 switch (emit.debug_output) {
561 .dwarf => |dbg_out| {
562 try dbg_out.dbg_line.append(DW.LNS.set_prologue_end);
562 .dwarf => |dw| {
563 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end);
563564 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
564565 },
565566 .plan9 => {},
......@@ -569,8 +570,8 @@ fn mirDebugPrologueEnd(emit: *Emit) !void {
569570
570571fn mirDebugEpilogueBegin(emit: *Emit) !void {
571572 switch (emit.debug_output) {
572 .dwarf => |dbg_out| {
573 try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin);
573 .dwarf => |dw| {
574 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin);
574575 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
575576 },
576577 .plan9 => {},
src/arch/riscv64/CodeGen.zig+17-20
......@@ -745,21 +745,17 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {
745745/// after codegen for this symbol is done.
746746fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
747747 switch (self.debug_output) {
748 .dwarf => |dbg_out| {
748 .dwarf => |dw| {
749749 assert(ty.hasRuntimeBits());
750 const index = dbg_out.dbg_info.items.len;
751 try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
752
753 const gop = try dbg_out.dbg_info_type_relocs.getOrPutContext(self.gpa, ty, .{
754 .target = self.target.*,
755 });
756 if (!gop.found_existing) {
757 gop.value_ptr.* = .{
758 .off = undefined,
759 .relocs = .{},
760 };
761 }
762 try gop.value_ptr.relocs.append(self.gpa, @intCast(u32, index));
750 const dbg_info = dw.getDeclDebugInfoBuffer();
751 const index = dbg_info.items.len;
752 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
753 const atom = switch (self.bin_file.tag) {
754 .elf => &self.mod_fn.owner_decl.link.elf.dbg_info_atom,
755 .macho => unreachable,
756 else => unreachable,
757 };
758 try dw.addTypeReloc(atom, ty, @intCast(u32, index), null);
763759 },
764760 .plan9 => {},
765761 .none => {},
......@@ -1573,16 +1569,17 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32
15731569 switch (mcv) {
15741570 .register => |reg| {
15751571 switch (self.debug_output) {
1576 .dwarf => |dbg_out| {
1577 try dbg_out.dbg_info.ensureUnusedCapacity(3);
1578 dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
1579 dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1572 .dwarf => |dw| {
1573 const dbg_info = dw.getDeclDebugInfoBuffer();
1574 try dbg_info.ensureUnusedCapacity(3);
1575 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
1576 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
15801577 1, // ULEB128 dwarf expression length
15811578 reg.dwarfLocOp(),
15821579 });
1583 try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
1580 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
15841581 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
1585 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
1582 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
15861583 },
15871584 .plan9 => {},
15881585 .none => {},
src/arch/riscv64/Emit.zig+12-11
......@@ -89,18 +89,19 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
8989 const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line);
9090 const delta_pc: usize = self.code.items.len - self.prev_di_pc;
9191 switch (self.debug_output) {
92 .dwarf => |dbg_out| {
92 .dwarf => |dw| {
9393 // TODO Look into using the DWARF special opcodes to compress this data.
9494 // It lets you emit single-byte opcodes that add different numbers to
9595 // both the PC and the line number at the same time.
96 try dbg_out.dbg_line.ensureUnusedCapacity(11);
97 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
98 leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable;
96 const dbg_line = dw.getDeclDebugLineBuffer();
97 try dbg_line.ensureUnusedCapacity(11);
98 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
99 leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;
99100 if (delta_line != 0) {
100 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line);
101 leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable;
101 dbg_line.appendAssumeCapacity(DW.LNS.advance_line);
102 leb128.writeILEB128(dbg_line.writer(), delta_line) catch unreachable;
102103 }
103 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy);
104 dbg_line.appendAssumeCapacity(DW.LNS.copy);
104105 self.prev_di_pc = self.code.items.len;
105106 self.prev_di_line = line;
106107 self.prev_di_column = column;
......@@ -182,8 +183,8 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {
182183
183184fn mirDebugPrologueEnd(self: *Emit) !void {
184185 switch (self.debug_output) {
185 .dwarf => |dbg_out| {
186 try dbg_out.dbg_line.append(DW.LNS.set_prologue_end);
186 .dwarf => |dw| {
187 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end);
187188 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
188189 },
189190 .plan9 => {},
......@@ -193,8 +194,8 @@ fn mirDebugPrologueEnd(self: *Emit) !void {
193194
194195fn mirDebugEpilogueBegin(self: *Emit) !void {
195196 switch (self.debug_output) {
196 .dwarf => |dbg_out| {
197 try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin);
197 .dwarf => |dw| {
198 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin);
198199 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
199200 },
200201 .plan9 => {},
src/arch/x86_64/CodeGen.zig+1
......@@ -350,6 +350,7 @@ pub fn generate(
350350 var emit = Emit{
351351 .mir = mir,
352352 .bin_file = bin_file,
353 .function = &function,
353354 .debug_output = debug_output,
354355 .target = &bin_file.options.target,
355356 .src_loc = src_loc,
src/arch/x86_64/Emit.zig+41-40
......@@ -16,6 +16,7 @@ const testing = std.testing;
1616
1717const Air = @import("../../Air.zig");
1818const Allocator = mem.Allocator;
19const CodeGen = @import("CodeGen.zig");
1920const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
2021const DW = std.dwarf;
2122const Encoder = bits.Encoder;
......@@ -29,6 +30,7 @@ const Type = @import("../../type.zig").Type;
2930
3031mir: Mir,
3132bin_file: *link.File,
33function: *const CodeGen,
3234debug_output: DebugInfoOutput,
3335target: *const std.Target,
3436err_msg: ?*ErrorMsg = null,
......@@ -963,18 +965,19 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {
963965 const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;
964966 log.debug(" (advance pc={d} and line={d})", .{ delta_line, delta_pc });
965967 switch (emit.debug_output) {
966 .dwarf => |dbg_out| {
968 .dwarf => |dw| {
967969 // TODO Look into using the DWARF special opcodes to compress this data.
968970 // It lets you emit single-byte opcodes that add different numbers to
969971 // both the PC and the line number at the same time.
970 try dbg_out.dbg_line.ensureUnusedCapacity(11);
971 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
972 leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable;
972 const dbg_line = dw.getDeclDebugLineBuffer();
973 try dbg_line.ensureUnusedCapacity(11);
974 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
975 leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;
973976 if (delta_line != 0) {
974 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line);
975 leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable;
977 dbg_line.appendAssumeCapacity(DW.LNS.advance_line);
978 leb128.writeILEB128(dbg_line.writer(), delta_line) catch unreachable;
976979 }
977 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy);
980 dbg_line.appendAssumeCapacity(DW.LNS.copy);
978981 emit.prev_di_line = line;
979982 emit.prev_di_column = column;
980983 emit.prev_di_pc = emit.code.items.len;
......@@ -1022,8 +1025,8 @@ fn mirDbgPrologueEnd(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
10221025 const tag = emit.mir.instructions.items(.tag)[inst];
10231026 assert(tag == .dbg_prologue_end);
10241027 switch (emit.debug_output) {
1025 .dwarf => |dbg_out| {
1026 try dbg_out.dbg_line.append(DW.LNS.set_prologue_end);
1028 .dwarf => |dw| {
1029 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end);
10271030 log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column });
10281031 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
10291032 },
......@@ -1036,8 +1039,8 @@ fn mirDbgEpilogueBegin(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
10361039 const tag = emit.mir.instructions.items(.tag)[inst];
10371040 assert(tag == .dbg_epilogue_begin);
10381041 switch (emit.debug_output) {
1039 .dwarf => |dbg_out| {
1040 try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin);
1042 .dwarf => |dw| {
1043 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin);
10411044 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column });
10421045 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
10431046 },
......@@ -1063,16 +1066,17 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32
10631066 switch (mcv) {
10641067 .register => |reg| {
10651068 switch (emit.debug_output) {
1066 .dwarf => |dbg_out| {
1067 try dbg_out.dbg_info.ensureUnusedCapacity(3);
1068 dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
1069 dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1069 .dwarf => |dw| {
1070 const dbg_info = dw.getDeclDebugInfoBuffer();
1071 try dbg_info.ensureUnusedCapacity(3);
1072 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
1073 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
10701074 1, // ULEB128 dwarf expression length
10711075 reg.dwarfLocOp(),
10721076 });
1073 try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
1077 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
10741078 try emit.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
1075 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
1079 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
10761080 },
10771081 .plan9 => {},
10781082 .none => {},
......@@ -1080,25 +1084,26 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32
10801084 },
10811085 .stack_offset => |off| {
10821086 switch (emit.debug_output) {
1083 .dwarf => |dbg_out| {
1087 .dwarf => |dw| {
10841088 // we add here +16 like we do in airArg in CodeGen since we refer directly to
10851089 // rbp as the start of function frame minus 8 bytes for caller's rbp preserved in the
10861090 // prologue, and 8 bytes for return address.
10871091 // TODO we need to make this more generic if we don't use rbp as the frame pointer
10881092 // for example when -fomit-frame-pointer is set.
10891093 const disp = @intCast(i32, max_stack) - off + 16;
1090 try dbg_out.dbg_info.ensureUnusedCapacity(8);
1091 dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
1092 const fixup = dbg_out.dbg_info.items.len;
1093 dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1094 const dbg_info = dw.getDeclDebugInfoBuffer();
1095 try dbg_info.ensureUnusedCapacity(8);
1096 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
1097 const fixup = dbg_info.items.len;
1098 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
10941099 1, // we will backpatch it after we encode the displacement in LEB128
10951100 DW.OP.breg6, // .rbp TODO handle -fomit-frame-pointer
10961101 });
1097 leb128.writeILEB128(dbg_out.dbg_info.writer(), disp) catch unreachable;
1098 dbg_out.dbg_info.items[fixup] += @intCast(u8, dbg_out.dbg_info.items.len - fixup - 2);
1099 try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
1102 leb128.writeILEB128(dbg_info.writer(), disp) catch unreachable;
1103 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
1104 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
11001105 try emit.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
1101 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
1106 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
11021107
11031108 },
11041109 .plan9 => {},
......@@ -1113,21 +1118,17 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32
11131118/// after codegen for this symbol is done.
11141119fn addDbgInfoTypeReloc(emit: *Emit, ty: Type) !void {
11151120 switch (emit.debug_output) {
1116 .dwarf => |dbg_out| {
1121 .dwarf => |dw| {
11171122 assert(ty.hasRuntimeBits());
1118 const index = dbg_out.dbg_info.items.len;
1119 try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
1120
1121 const gop = try dbg_out.dbg_info_type_relocs.getOrPutContext(emit.bin_file.allocator, ty, .{
1122 .target = emit.target.*,
1123 });
1124 if (!gop.found_existing) {
1125 gop.value_ptr.* = .{
1126 .off = undefined,
1127 .relocs = .{},
1128 };
1129 }
1130 try gop.value_ptr.relocs.append(emit.bin_file.allocator, @intCast(u32, index));
1123 const dbg_info = dw.getDeclDebugInfoBuffer();
1124 const index = dbg_info.items.len;
1125 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
1126 const atom = switch (emit.bin_file.tag) {
1127 .elf => &emit.function.mod_fn.owner_decl.link.elf.dbg_info_atom,
1128 .macho => &emit.function.mod_fn.owner_decl.link.macho.dbg_info_atom,
1129 else => unreachable,
1130 };
1131 try dw.addTypeReloc(atom, ty, @intCast(u32, index), null);
11311132 },
11321133 .plan9 => {},
11331134 .none => {},
src/codegen.zig+1-5
......@@ -42,11 +42,7 @@ pub const GenerateSymbolError = error{
4242};
4343
4444pub const DebugInfoOutput = union(enum) {
45 dwarf: struct {
46 dbg_line: *std.ArrayList(u8),
47 dbg_info: *std.ArrayList(u8),
48 dbg_info_type_relocs: *link.File.Dwarf.DbgInfoTypeRelocsTable,
49 },
45 dwarf: *link.File.Dwarf,
5046 /// the plan9 debuginfo output is a bytecode with 4 opcodes
5147 /// assume all numbers/variables are bytes
5248 /// 0 w x y z -> interpret w x y z as a big-endian i32, and add it to the line offset
src/link/Dwarf.zig+276-272
......@@ -39,16 +39,22 @@ atom_last: ?*Atom = null,
3939
4040abbrev_table_offset: ?u64 = null,
4141
42/// TODO replace with InternArena
4243/// Table of debug symbol names.
4344strtab: std.ArrayListUnmanaged(u8) = .{},
4445
45deferred_error_sets_relocs: std.ArrayListUnmanaged(u32) = .{},
46/// Lives only as long as the analysed Decl.
47/// Allocated with `initDeclState`.
48/// Freed with `commitDeclState`.
49decl_state: ?DeclState = null,
4650
4751/// List of atoms that are owned directly by the DWARF module.
4852/// TODO convert links in DebugInfoAtom into indices and make
4953/// sure every atom is owned by this module.
5054managed_atoms: std.ArrayListUnmanaged(*Atom) = .{},
5155
56global_abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{},
57
5258pub const Atom = struct {
5359 /// Previous/next linked list pointers.
5460 /// This is the linked list node for this Decl's corresponding .debug_info tag.
......@@ -60,6 +66,54 @@ pub const Atom = struct {
6066 len: u32,
6167};
6268
69/// Represents state of the analysed Decl.
70/// Includes Decl's abbrev table of type Types, matching arena
71/// and a set of relocations that will be resolved once this
72/// Decl's inner Atom is assigned an offset within the DWARF section.
73pub const DeclState = struct {
74 dbg_line: std.ArrayList(u8),
75 dbg_info: std.ArrayList(u8),
76 abbrev_type_arena: std.heap.ArenaAllocator,
77 abbrev_table: std.ArrayListUnmanaged(AbbrevEntry) = .{},
78 abbrev_resolver: std.HashMapUnmanaged(
79 Type,
80 u32,
81 Type.HashContext64,
82 std.hash_map.default_max_load_percentage,
83 ) = .{},
84 abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{},
85
86 fn init(gpa: Allocator) DeclState {
87 return .{
88 .dbg_line = std.ArrayList(u8).init(gpa),
89 .dbg_info = std.ArrayList(u8).init(gpa),
90 .abbrev_type_arena = std.heap.ArenaAllocator.init(gpa),
91 };
92 }
93
94 fn deinit(self: *DeclState, gpa: Allocator) void {
95 self.dbg_line.deinit();
96 self.dbg_info.deinit();
97 self.abbrev_type_arena.deinit();
98 self.abbrev_table.deinit(gpa);
99 self.abbrev_resolver.deinit(gpa);
100 self.abbrev_relocs.deinit(gpa);
101 }
102};
103
104pub const AbbrevEntry = struct {
105 atom: *const Atom,
106 @"type": Type,
107 offset: u32,
108};
109
110pub const AbbrevRelocation = struct {
111 target: u32,
112 atom: *const Atom,
113 offset: u32,
114 addend: u32,
115};
116
63117pub const SrcFn = struct {
64118 /// Offset from the beginning of the Debug Line Program header that contains this function.
65119 off: u32,
......@@ -82,22 +136,6 @@ pub const SrcFn = struct {
82136
83137pub const PtrWidth = enum { p32, p64 };
84138
85pub const DbgInfoTypeRelocsTable = std.ArrayHashMapUnmanaged(
86 Type,
87 DbgInfoTypeReloc,
88 Type.HashContext32,
89 true,
90);
91
92pub const DbgInfoTypeReloc = struct {
93 /// Offset from `TextBlock.dbg_info_off` (the buffer that is local to a Decl).
94 /// This is where the .debug_info tag for the type is.
95 off: u32,
96 /// Offset from `TextBlock.dbg_info_off` (the buffer that is local to a Decl).
97 /// List of DW.AT.type / DW.FORM.ref4 that points to the type.
98 relocs: std.ArrayListUnmanaged(u32),
99};
100
101139pub const abbrev_compile_unit = 1;
102140pub const abbrev_subprogram = 2;
103141pub const abbrev_subprogram_retvoid = 3;
......@@ -143,7 +181,7 @@ pub fn deinit(self: *Dwarf) void {
143181 self.dbg_line_fn_free_list.deinit(gpa);
144182 self.atom_free_list.deinit(gpa);
145183 self.strtab.deinit(gpa);
146 self.deferred_error_sets_relocs.deinit(gpa);
184 self.global_abbrev_relocs.deinit(gpa);
147185
148186 for (self.managed_atoms.items) |atom| {
149187 gpa.destroy(atom);
......@@ -151,25 +189,22 @@ pub fn deinit(self: *Dwarf) void {
151189 self.managed_atoms.deinit(gpa);
152190}
153191
154pub const DeclDebugBuffers = struct {
155 dbg_line_buffer: std.ArrayList(u8),
156 dbg_info_buffer: std.ArrayList(u8),
157 dbg_info_type_relocs: DbgInfoTypeRelocsTable,
158};
159
160pub fn initDeclDebugInfo(self: *Dwarf, decl: *Module.Decl) !DeclDebugBuffers {
192/// Initializes Decl's state and its matching output buffers.
193/// Call this before `commitDeclState`.
194pub fn initDeclState(self: *Dwarf, decl: *Module.Decl) !void {
161195 const tracy = trace(@src());
162196 defer tracy.end();
163197
164198 const decl_name = try decl.getFullyQualifiedName(self.allocator);
165199 defer self.allocator.free(decl_name);
166200
167 log.debug("initDeclDebugInfo {s}{*}", .{ decl_name, decl });
201 log.debug("initDeclState {s}{*}", .{ decl_name, decl });
168202
169203 const gpa = self.allocator;
170 var dbg_line_buffer = std.ArrayList(u8).init(gpa);
171 var dbg_info_buffer = std.ArrayList(u8).init(gpa);
172 var dbg_info_type_relocs: DbgInfoTypeRelocsTable = .{};
204 assert(self.decl_state == null);
205 self.decl_state = DeclState.init(gpa);
206 const dbg_line_buffer = &self.decl_state.?.dbg_line;
207 const dbg_info_buffer = &self.decl_state.?.dbg_info;
173208
174209 assert(decl.has_tv);
175210
......@@ -232,19 +267,17 @@ pub fn initDeclDebugInfo(self: *Dwarf, decl: *Module.Decl) !DeclDebugBuffers {
232267 dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT.low_pc, DW.FORM.addr
233268 assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len);
234269 dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data4
270 //
235271 if (fn_ret_has_bits) {
236 const gop = try dbg_info_type_relocs.getOrPutContext(gpa, fn_ret_type, .{
237 .target = self.target,
238 });
239 if (!gop.found_existing) {
240 gop.value_ptr.* = .{
241 .off = undefined,
242 .relocs = .{},
243 };
244 }
245 try gop.value_ptr.relocs.append(gpa, @intCast(u32, dbg_info_buffer.items.len));
272 const atom = switch (self.tag) {
273 .elf => &decl.link.elf.dbg_info_atom,
274 .macho => &decl.link.macho.dbg_info_atom,
275 else => unreachable,
276 };
277 try self.addTypeReloc(atom, fn_ret_type, @intCast(u32, dbg_info_buffer.items.len), null);
246278 dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4
247279 }
280
248281 dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT.name, DW.FORM.string
249282
250283 },
......@@ -252,30 +285,28 @@ pub fn initDeclDebugInfo(self: *Dwarf, decl: *Module.Decl) !DeclDebugBuffers {
252285 // TODO implement .debug_info for global variables
253286 },
254287 }
255
256 return DeclDebugBuffers{
257 .dbg_info_buffer = dbg_info_buffer,
258 .dbg_line_buffer = dbg_line_buffer,
259 .dbg_info_type_relocs = dbg_info_type_relocs,
260 };
261288}
262289
263pub fn commitDeclDebugInfo(
290pub fn commitDeclState(
264291 self: *Dwarf,
265292 file: *File,
266293 module: *Module,
267294 decl: *Module.Decl,
268295 sym_addr: u64,
269296 sym_size: u64,
270 debug_buffers: *DeclDebugBuffers,
271297) !void {
272298 const tracy = trace(@src());
273299 defer tracy.end();
274300
301 assert(self.decl_state != null); // Caller forgot to call `initDeclState`
302 defer {
303 self.decl_state.?.deinit(self.allocator);
304 self.decl_state = null;
305 }
306
275307 const gpa = self.allocator;
276 var dbg_line_buffer = &debug_buffers.dbg_line_buffer;
277 var dbg_info_buffer = &debug_buffers.dbg_info_buffer;
278 var dbg_info_type_relocs = &debug_buffers.dbg_info_type_relocs;
308 var dbg_line_buffer = &self.decl_state.?.dbg_line;
309 var dbg_info_buffer = &self.decl_state.?.dbg_info;
279310
280311 const target_endian = self.target.cpu.arch.endian();
281312
......@@ -473,25 +504,21 @@ pub fn commitDeclDebugInfo(
473504 if (dbg_info_buffer.items.len == 0)
474505 return;
475506
476 // We need this for the duration of this function only so that for composite
477 // types such as []const u32, if the type *u32 is non-existent, we create
478 // it synthetically and store the backing bytes in this arena. After we are
479 // done with the relocations, we can safely deinit the entire memory slab.
480 // TODO currently, we do not store the relocations for future use, however,
481 // if that is the case, we should move memory management to a higher scope,
482 // such as linker scope, or whatnot.
483 var dbg_type_arena = std.heap.ArenaAllocator.init(gpa);
484 defer dbg_type_arena.deinit();
485
486 var nested_ref4_relocs = std.ArrayList(u32).init(gpa);
487 defer nested_ref4_relocs.deinit();
507 const atom = switch (self.tag) {
508 .elf => &decl.link.elf.dbg_info_atom,
509 .macho => &decl.link.macho.dbg_info_atom,
510 else => unreachable,
511 };
512 const decl_state = &self.decl_state.?;
513
488514 {
489515 // Now we emit the .debug_info types of the Decl. These will count towards the size of
490516 // the buffer, so we have to do it before computing the offset, and we can't perform the actual
491517 // relocations yet.
492 var it: usize = 0;
493 while (it < dbg_info_type_relocs.count()) : (it += 1) {
494 const ty = dbg_info_type_relocs.keys()[it];
518 var sym_index: usize = 0;
519 while (sym_index < decl_state.abbrev_table.items.len) : (sym_index += 1) {
520 const symbol = &decl_state.abbrev_table.items[sym_index];
521 const ty = symbol.@"type";
495522 const deferred: bool = blk: {
496523 if (ty.isAnyError()) break :blk true;
497524 switch (ty.tag()) {
......@@ -504,68 +531,38 @@ pub fn commitDeclDebugInfo(
504531 };
505532 if (deferred) continue;
506533
507 const value_ptr = dbg_info_type_relocs.getPtrContext(ty, .{
508 .target = self.target,
509 }).?;
510 value_ptr.off = @intCast(u32, dbg_info_buffer.items.len);
511 try self.addDbgInfoType(
512 dbg_type_arena.allocator(),
513 module,
514 ty,
515 dbg_info_buffer,
516 dbg_info_type_relocs,
517 &nested_ref4_relocs,
518 );
534 symbol.offset = @intCast(u32, dbg_info_buffer.items.len);
535 try self.addDbgInfoType(decl_state.abbrev_type_arena.allocator(), module, atom, ty, dbg_info_buffer);
519536 }
520537 }
521538
522 const atom = switch (self.tag) {
523 .elf => &decl.link.elf.dbg_info_atom,
524 .macho => &decl.link.macho.dbg_info_atom,
525 else => unreachable,
526 };
527539 try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len));
528540
529 {
530 // Now that we have the offset assigned we can finally perform type relocations.
531 for (dbg_info_type_relocs.keys()) |ty| {
532 const value = dbg_info_type_relocs.getContext(ty, .{
533 .target = self.target,
534 }).?;
535 for (value.relocs.items) |off| {
536 const deferred: bool = blk: {
537 if (ty.isAnyError()) break :blk true;
538 switch (ty.tag()) {
539 .error_set_inferred => {
540 if (!ty.castTag(.error_set_inferred).?.data.is_resolved) break :blk true;
541 },
542 else => {},
543 }
544 break :blk false;
545 };
546 if (deferred) {
547 // Defer until later
548 try self.deferred_error_sets_relocs.append(self.allocator, atom.off + off);
549 } else {
550 mem.writeInt(
551 u32,
552 dbg_info_buffer.items[off..][0..4],
553 atom.off + value.off,
554 target_endian,
555 );
556 }
541 while (decl_state.abbrev_relocs.popOrNull()) |reloc| {
542 const symbol = decl_state.abbrev_table.items[reloc.target];
543 const ty = symbol.@"type";
544 const deferred: bool = blk: {
545 if (ty.isAnyError()) break :blk true;
546 switch (ty.tag()) {
547 .error_set_inferred => {
548 if (!ty.castTag(.error_set_inferred).?.data.is_resolved) break :blk true;
549 },
550 else => {},
557551 }
558 }
559 // Offsets to positions with known a priori relative displacement values.
560 // Here, we just need to add the offset of the atom to the read value in the
561 // relocated cell.
562 // TODO Should probably generalise this with type relocs.
563 for (nested_ref4_relocs.items) |off| {
564 const addend = mem.readInt(u32, dbg_info_buffer.items[off..][0..4], target_endian);
552 break :blk false;
553 };
554 if (deferred) {
555 try self.global_abbrev_relocs.append(gpa, .{
556 .target = undefined,
557 .offset = reloc.offset,
558 .atom = reloc.atom,
559 .addend = reloc.addend,
560 });
561 } else {
565562 mem.writeInt(
566563 u32,
567 dbg_info_buffer.items[off..][0..4],
568 atom.off + addend,
564 dbg_info_buffer.items[reloc.offset..][0..@sizeOf(u32)],
565 symbol.atom.off + symbol.offset + reloc.addend,
569566 target_endian,
570567 );
571568 }
......@@ -574,77 +571,6 @@ pub fn commitDeclDebugInfo(
574571 try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items);
575572}
576573
577pub fn commitErrorSetDebugInfo(self: *Dwarf, file: *File, module: *Module) !void {
578 if (self.deferred_error_sets_relocs.items.len == 0) return; // Nothing to do
579
580 const gpa = self.allocator;
581 var arena_alloc = std.heap.ArenaAllocator.init(gpa);
582 defer arena_alloc.deinit();
583 const arena = arena_alloc.allocator();
584
585 const error_set = try arena.create(Module.ErrorSet);
586 const ty = try Type.Tag.error_set.create(arena, error_set);
587 var names = Module.ErrorSet.NameMap{};
588 try names.ensureUnusedCapacity(arena, module.global_error_set.count());
589 var it = module.global_error_set.keyIterator();
590 while (it.next()) |key| {
591 names.putAssumeCapacityNoClobber(key.*, {});
592 }
593 error_set.names = names;
594
595 var dbg_info_buffer = std.ArrayList(u8).init(arena);
596 try self.addDbgInfoErrorSet(arena, module, ty, &dbg_info_buffer);
597
598 const atom = try gpa.create(Atom);
599 errdefer gpa.destroy(atom);
600 atom.* = .{
601 .prev = null,
602 .next = null,
603 .off = 0,
604 .len = 0,
605 };
606 try self.managed_atoms.append(gpa, atom);
607 try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len));
608 try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items);
609
610 const file_pos = blk: {
611 switch (self.tag) {
612 .elf => {
613 const elf_file = file.cast(File.Elf).?;
614 const debug_info_sect = &elf_file.sections.items[elf_file.debug_info_section_index.?];
615 break :blk debug_info_sect.sh_offset;
616 },
617 .macho => {
618 const macho_file = file.cast(File.MachO).?;
619 const d_sym = &macho_file.d_sym.?;
620 const dwarf_segment = &d_sym.load_commands.items[d_sym.dwarf_segment_cmd_index.?].segment;
621 const debug_info_sect = &dwarf_segment.sections.items[d_sym.debug_info_section_index.?];
622 break :blk debug_info_sect.offset;
623 },
624 else => unreachable,
625 }
626 };
627
628 const target_endian = self.target.cpu.arch.endian();
629 var buf: [@sizeOf(u32)]u8 = undefined;
630 while (self.deferred_error_sets_relocs.popOrNull()) |reloc| {
631 mem.writeInt(u32, &buf, atom.off, target_endian);
632
633 switch (self.tag) {
634 .elf => {
635 const elf_file = file.cast(File.Elf).?;
636 try elf_file.base.file.?.pwriteAll(&buf, file_pos + reloc);
637 },
638 .macho => {
639 const macho_file = file.cast(File.MachO).?;
640 const d_sym = &macho_file.d_sym.?;
641 try d_sym.file.pwriteAll(&buf, file_pos + reloc);
642 },
643 else => unreachable,
644 }
645 }
646}
647
648574fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u32) !void {
649575 const tracy = trace(@src());
650576 defer tracy.end();
......@@ -904,14 +830,12 @@ fn addDbgInfoType(
904830 self: *Dwarf,
905831 arena: Allocator,
906832 module: *Module,
833 atom: *Atom,
907834 ty: Type,
908835 dbg_info_buffer: *std.ArrayList(u8),
909 dbg_info_type_relocs: *DbgInfoTypeRelocsTable,
910 nested_ref4_relocs: *std.ArrayList(u32),
911836) error{OutOfMemory}!void {
912837 const target = self.target;
913838 const target_endian = self.target.cpu.arch.endian();
914 var relocs = std.ArrayList(struct { ty: Type, reloc: u32 }).init(arena);
915839
916840 switch (ty.zigTypeTag()) {
917841 .NoReturn => unreachable,
......@@ -970,7 +894,7 @@ fn addDbgInfoType(
970894 // DW.AT.type, DW.FORM.ref4
971895 var index = dbg_info_buffer.items.len;
972896 try dbg_info_buffer.resize(index + 4);
973 try relocs.append(.{ .ty = Type.bool, .reloc = @intCast(u32, index) });
897 try self.addTypeReloc(atom, Type.bool, @intCast(u32, index), null);
974898 // DW.AT.data_member_location, DW.FORM.sdata
975899 try dbg_info_buffer.ensureUnusedCapacity(6);
976900 dbg_info_buffer.appendAssumeCapacity(0);
......@@ -982,7 +906,7 @@ fn addDbgInfoType(
982906 // DW.AT.type, DW.FORM.ref4
983907 index = dbg_info_buffer.items.len;
984908 try dbg_info_buffer.resize(index + 4);
985 try relocs.append(.{ .ty = payload_ty, .reloc = @intCast(u32, index) });
909 try self.addTypeReloc(atom, payload_ty, @intCast(u32, index), null);
986910 // DW.AT.data_member_location, DW.FORM.sdata
987911 const offset = abi_size - payload_ty.abiSize(target);
988912 try leb128.writeULEB128(dbg_info_buffer.writer(), offset);
......@@ -1011,7 +935,7 @@ fn addDbgInfoType(
1011935 try dbg_info_buffer.resize(index + 4);
1012936 var buf = try arena.create(Type.SlicePtrFieldTypeBuffer);
1013937 const ptr_ty = ty.slicePtrFieldType(buf);
1014 try relocs.append(.{ .ty = ptr_ty, .reloc = @intCast(u32, index) });
938 try self.addTypeReloc(atom, ptr_ty, @intCast(u32, index), null);
1015939 // DW.AT.data_member_location, DW.FORM.sdata
1016940 try dbg_info_buffer.ensureUnusedCapacity(6);
1017941 dbg_info_buffer.appendAssumeCapacity(0);
......@@ -1023,7 +947,7 @@ fn addDbgInfoType(
1023947 // DW.AT.type, DW.FORM.ref4
1024948 index = dbg_info_buffer.items.len;
1025949 try dbg_info_buffer.resize(index + 4);
1026 try relocs.append(.{ .ty = Type.initTag(.usize), .reloc = @intCast(u32, index) });
950 try self.addTypeReloc(atom, Type.usize, @intCast(u32, index), null);
1027951 // DW.AT.data_member_location, DW.FORM.sdata
1028952 try dbg_info_buffer.ensureUnusedCapacity(2);
1029953 dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize));
......@@ -1035,7 +959,7 @@ fn addDbgInfoType(
1035959 // DW.AT.type, DW.FORM.ref4
1036960 const index = dbg_info_buffer.items.len;
1037961 try dbg_info_buffer.resize(index + 4);
1038 try relocs.append(.{ .ty = ty.childType(), .reloc = @intCast(u32, index) });
962 try self.addTypeReloc(atom, ty.childType(), @intCast(u32, index), null);
1039963 }
1040964 },
1041965 .Struct => blk: {
......@@ -1059,7 +983,7 @@ fn addDbgInfoType(
1059983 // DW.AT.type, DW.FORM.ref4
1060984 var index = dbg_info_buffer.items.len;
1061985 try dbg_info_buffer.resize(index + 4);
1062 try relocs.append(.{ .ty = field, .reloc = @intCast(u32, index) });
986 try self.addTypeReloc(atom, field, @intCast(u32, index), null);
1063987 // DW.AT.data_member_location, DW.FORM.sdata
1064988 const field_off = ty.structFieldOffset(field_index, target);
1065989 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
......@@ -1090,7 +1014,7 @@ fn addDbgInfoType(
10901014 // DW.AT.type, DW.FORM.ref4
10911015 var index = dbg_info_buffer.items.len;
10921016 try dbg_info_buffer.resize(index + 4);
1093 try relocs.append(.{ .ty = field.ty, .reloc = @intCast(u32, index) });
1017 try self.addTypeReloc(atom, field.ty, @intCast(u32, index), null);
10941018 // DW.AT.data_member_location, DW.FORM.sdata
10951019 const field_off = ty.structFieldOffset(field_index, target);
10961020 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
......@@ -1169,14 +1093,8 @@ fn addDbgInfoType(
11691093 dbg_info_buffer.appendAssumeCapacity(0);
11701094 // DW.AT.type, DW.FORM.ref4
11711095 const inner_union_index = dbg_info_buffer.items.len;
1172 try dbg_info_buffer.ensureUnusedCapacity(4);
1173 mem.writeInt(
1174 u32,
1175 dbg_info_buffer.addManyAsArrayAssumeCapacity(4),
1176 @intCast(u32, inner_union_index + 5),
1177 target_endian,
1178 );
1179 try nested_ref4_relocs.append(@intCast(u32, inner_union_index));
1096 try dbg_info_buffer.resize(inner_union_index + 4);
1097 try self.addTypeReloc(atom, ty, @intCast(u32, inner_union_index), 5);
11801098 // DW.AT.data_member_location, DW.FORM.sdata
11811099 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset);
11821100 }
......@@ -1203,7 +1121,7 @@ fn addDbgInfoType(
12031121 // DW.AT.type, DW.FORM.ref4
12041122 const index = dbg_info_buffer.items.len;
12051123 try dbg_info_buffer.resize(index + 4);
1206 try relocs.append(.{ .ty = field.ty, .reloc = @intCast(u32, index) });
1124 try self.addTypeReloc(atom, field.ty, @intCast(u32, index), null);
12071125 // DW.AT.data_member_location, DW.FORM.sdata
12081126 try dbg_info_buffer.append(0);
12091127 }
......@@ -1220,7 +1138,7 @@ fn addDbgInfoType(
12201138 // DW.AT.type, DW.FORM.ref4
12211139 const index = dbg_info_buffer.items.len;
12221140 try dbg_info_buffer.resize(index + 4);
1223 try relocs.append(.{ .ty = union_obj.tag_ty, .reloc = @intCast(u32, index) });
1141 try self.addTypeReloc(atom, union_obj.tag_ty, @intCast(u32, index), null);
12241142 // DW.AT.data_member_location, DW.FORM.sdata
12251143 try leb128.writeULEB128(dbg_info_buffer.writer(), tag_offset);
12261144
......@@ -1229,7 +1147,40 @@ fn addDbgInfoType(
12291147 }
12301148 },
12311149 .ErrorSet => {
1232 try self.addDbgInfoErrorSet(arena, module, ty, dbg_info_buffer);
1150 // DW.AT.enumeration_type
1151 try dbg_info_buffer.append(abbrev_enum_type);
1152 // DW.AT.byte_size, DW.FORM.sdata
1153 const abi_size = ty.abiSize(target);
1154 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
1155 // DW.AT.name, DW.FORM.string
1156 const name = try ty.nameAllocArena(arena, target);
1157 try dbg_info_buffer.writer().print("{s}\x00", .{name});
1158
1159 // DW.AT.enumerator
1160 const no_error = "(no error)";
1161 try dbg_info_buffer.ensureUnusedCapacity(no_error.len + 2 + @sizeOf(u64));
1162 dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant);
1163 // DW.AT.name, DW.FORM.string
1164 dbg_info_buffer.appendSliceAssumeCapacity(no_error);
1165 dbg_info_buffer.appendAssumeCapacity(0);
1166 // DW.AT.const_value, DW.FORM.data8
1167 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);
1168
1169 const error_names = ty.errorSetNames();
1170 for (error_names) |error_name| {
1171 const kv = module.getErrorValue(error_name) catch unreachable;
1172 // DW.AT.enumerator
1173 try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64));
1174 dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant);
1175 // DW.AT.name, DW.FORM.string
1176 dbg_info_buffer.appendSliceAssumeCapacity(error_name);
1177 dbg_info_buffer.appendAssumeCapacity(0);
1178 // DW.AT.const_value, DW.FORM.data8
1179 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), kv.value, target_endian);
1180 }
1181
1182 // DW.AT.enumeration_type delimit children
1183 try dbg_info_buffer.append(0);
12331184 },
12341185 .ErrorUnion => {
12351186 const error_ty = ty.errorUnionSet();
......@@ -1255,7 +1206,7 @@ fn addDbgInfoType(
12551206 // DW.AT.type, DW.FORM.ref4
12561207 var index = dbg_info_buffer.items.len;
12571208 try dbg_info_buffer.resize(index + 4);
1258 try relocs.append(.{ .ty = payload_ty, .reloc = @intCast(u32, index) });
1209 try self.addTypeReloc(atom, payload_ty, @intCast(u32, index), null);
12591210 // DW.AT.data_member_location, DW.FORM.sdata
12601211 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_off);
12611212
......@@ -1268,7 +1219,7 @@ fn addDbgInfoType(
12681219 // DW.AT.type, DW.FORM.ref4
12691220 index = dbg_info_buffer.items.len;
12701221 try dbg_info_buffer.resize(index + 4);
1271 try relocs.append(.{ .ty = error_ty, .reloc = @intCast(u32, index) });
1222 try self.addTypeReloc(atom, error_ty, @intCast(u32, index), null);
12721223 // DW.AT.data_member_location, DW.FORM.sdata
12731224 try dbg_info_buffer.append(0);
12741225
......@@ -1280,65 +1231,6 @@ fn addDbgInfoType(
12801231 try dbg_info_buffer.append(abbrev_pad1);
12811232 },
12821233 }
1283
1284 for (relocs.items) |rel| {
1285 const gop = try dbg_info_type_relocs.getOrPutContext(self.allocator, rel.ty, .{
1286 .target = self.target,
1287 });
1288 if (!gop.found_existing) {
1289 gop.value_ptr.* = .{
1290 .off = undefined,
1291 .relocs = .{},
1292 };
1293 }
1294 try gop.value_ptr.relocs.append(self.allocator, rel.reloc);
1295 }
1296}
1297
1298fn addDbgInfoErrorSet(
1299 self: *Dwarf,
1300 arena: Allocator,
1301 module: *Module,
1302 ty: Type,
1303 dbg_info_buffer: *std.ArrayList(u8),
1304) error{OutOfMemory}!void {
1305 const target = self.target;
1306 const target_endian = self.target.cpu.arch.endian();
1307
1308 // DW.AT.enumeration_type
1309 try dbg_info_buffer.append(abbrev_enum_type);
1310 // DW.AT.byte_size, DW.FORM.sdata
1311 const abi_size = ty.abiSize(target);
1312 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
1313 // DW.AT.name, DW.FORM.string
1314 const name = try ty.nameAllocArena(arena, target);
1315 try dbg_info_buffer.writer().print("{s}\x00", .{name});
1316
1317 // DW.AT.enumerator
1318 const no_error = "(no error)";
1319 try dbg_info_buffer.ensureUnusedCapacity(no_error.len + 2 + @sizeOf(u64));
1320 dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant);
1321 // DW.AT.name, DW.FORM.string
1322 dbg_info_buffer.appendSliceAssumeCapacity(no_error);
1323 dbg_info_buffer.appendAssumeCapacity(0);
1324 // DW.AT.const_value, DW.FORM.data8
1325 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);
1326
1327 const error_names = ty.errorSetNames();
1328 for (error_names) |error_name| {
1329 const kv = module.getErrorValue(error_name) catch unreachable;
1330 // DW.AT.enumerator
1331 try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64));
1332 dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant);
1333 // DW.AT.name, DW.FORM.string
1334 dbg_info_buffer.appendSliceAssumeCapacity(error_name);
1335 dbg_info_buffer.appendAssumeCapacity(0);
1336 // DW.AT.const_value, DW.FORM.data8
1337 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), kv.value, target_endian);
1338 }
1339
1340 // DW.AT.enumeration_type delimit children
1341 try dbg_info_buffer.append(0);
13421234}
13431235
13441236pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
......@@ -2059,3 +1951,115 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
20591951 return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch
20601952 std.math.maxInt(@TypeOf(actual_size));
20611953}
1954
1955pub fn addTypeReloc(self: *Dwarf, atom: *const Atom, ty: Type, offset: u32, addend: ?u32) !void {
1956 const decl_state = &self.decl_state.?;
1957 const gpa = self.allocator;
1958 const resolv = decl_state.abbrev_resolver.getContext(ty, .{
1959 .target = self.target,
1960 }) orelse blk: {
1961 const sym_index = @intCast(u32, decl_state.abbrev_table.items.len);
1962 try decl_state.abbrev_table.append(gpa, .{
1963 .atom = atom,
1964 .@"type" = ty,
1965 .offset = undefined,
1966 });
1967 log.debug("@{d}: {}", .{ sym_index, ty.fmtDebug() });
1968 try decl_state.abbrev_resolver.putNoClobberContext(gpa, ty, sym_index, .{
1969 .target = self.target,
1970 });
1971 break :blk decl_state.abbrev_resolver.getContext(ty, .{
1972 .target = self.target,
1973 }).?;
1974 };
1975 const add: u32 = addend orelse 0;
1976
1977 log.debug("{x}: @{d} + {x}", .{ offset, resolv, add });
1978 try decl_state.abbrev_relocs.append(gpa, .{
1979 .target = resolv,
1980 .atom = atom,
1981 .offset = offset,
1982 .addend = add,
1983 });
1984}
1985
1986pub fn getDeclDebugLineBuffer(self: *Dwarf) *std.ArrayList(u8) {
1987 return &self.decl_state.?.dbg_line;
1988}
1989
1990pub fn getDeclDebugInfoBuffer(self: *Dwarf) *std.ArrayList(u8) {
1991 return &self.decl_state.?.dbg_info;
1992}
1993
1994pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {
1995 if (self.global_abbrev_relocs.items.len > 0) {
1996 const gpa = self.allocator;
1997 var arena_alloc = std.heap.ArenaAllocator.init(gpa);
1998 defer arena_alloc.deinit();
1999 const arena = arena_alloc.allocator();
2000
2001 const error_set = try arena.create(Module.ErrorSet);
2002 const error_ty = try Type.Tag.error_set.create(arena, error_set);
2003 var names = Module.ErrorSet.NameMap{};
2004 try names.ensureUnusedCapacity(arena, module.global_error_set.count());
2005 var it = module.global_error_set.keyIterator();
2006 while (it.next()) |key| {
2007 names.putAssumeCapacityNoClobber(key.*, {});
2008 }
2009 error_set.names = names;
2010
2011 const atom = try gpa.create(Atom);
2012 errdefer gpa.destroy(atom);
2013 atom.* = .{
2014 .prev = null,
2015 .next = null,
2016 .off = 0,
2017 .len = 0,
2018 };
2019
2020 var dbg_info_buffer = std.ArrayList(u8).init(arena);
2021 try self.addDbgInfoType(arena, module, atom, error_ty, &dbg_info_buffer);
2022
2023 try self.managed_atoms.append(gpa, atom);
2024 try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len));
2025 try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items);
2026
2027 const file_pos = blk: {
2028 switch (self.tag) {
2029 .elf => {
2030 const elf_file = file.cast(File.Elf).?;
2031 const debug_info_sect = &elf_file.sections.items[elf_file.debug_info_section_index.?];
2032 break :blk debug_info_sect.sh_offset;
2033 },
2034 .macho => {
2035 const macho_file = file.cast(File.MachO).?;
2036 const d_sym = &macho_file.d_sym.?;
2037 const dwarf_segment = &d_sym.load_commands.items[d_sym.dwarf_segment_cmd_index.?].segment;
2038 const debug_info_sect = &dwarf_segment.sections.items[d_sym.debug_info_section_index.?];
2039 break :blk debug_info_sect.offset;
2040 },
2041 else => unreachable,
2042 }
2043 };
2044
2045 var buf: [@sizeOf(u32)]u8 = undefined;
2046 mem.writeInt(u32, &buf, atom.off, self.target.cpu.arch.endian());
2047
2048 while (self.global_abbrev_relocs.popOrNull()) |reloc| {
2049 switch (self.tag) {
2050 .elf => {
2051 const elf_file = file.cast(File.Elf).?;
2052 try elf_file.base.file.?.pwriteAll(&buf, file_pos + reloc.atom.off + reloc.offset);
2053 },
2054 .macho => {
2055 const macho_file = file.cast(File.MachO).?;
2056 const d_sym = &macho_file.d_sym.?;
2057 try d_sym.file.pwriteAll(&buf, file_pos + reloc.atom.off + reloc.offset);
2058 },
2059 else => unreachable,
2060 }
2061 }
2062 }
2063
2064 assert(self.decl_state == null);
2065}
src/link/Elf.zig+14-54
......@@ -958,8 +958,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
958958 const target_endian = self.base.options.target.cpu.arch.endian();
959959 const foreign_endian = target_endian != builtin.cpu.arch.endian();
960960
961 if (self.dwarf) |*dwarf| {
962 try dwarf.commitErrorSetDebugInfo(&self.base, module);
961 if (self.dwarf) |*dw| {
962 try dw.flushModule(&self.base, module);
963963 }
964964
965965 {
......@@ -2232,13 +2232,6 @@ pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {
22322232 }
22332233}
22342234
2235fn deinitRelocs(gpa: Allocator, table: *link.File.Dwarf.DbgInfoTypeRelocsTable) void {
2236 for (table.values()) |*value| {
2237 value.relocs.deinit(gpa);
2238 }
2239 table.deinit(gpa);
2240}
2241
22422235fn getDeclPhdrIndex(self: *Elf, decl: *Module.Decl) !u16 {
22432236 const ty = decl.ty;
22442237 const zig_ty = ty.zigTypeTag();
......@@ -2346,26 +2339,13 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
23462339 const decl = func.owner_decl;
23472340 self.freeUnnamedConsts(decl);
23482341
2349 var debug_buffers_buf: Dwarf.DeclDebugBuffers = undefined;
2350 const debug_buffers = if (self.dwarf) |*dw| blk: {
2351 debug_buffers_buf = try dw.initDeclDebugInfo(decl);
2352 break :blk &debug_buffers_buf;
2353 } else null;
2354 defer {
2355 if (debug_buffers) |dbg| {
2356 dbg.dbg_line_buffer.deinit();
2357 dbg.dbg_info_buffer.deinit();
2358 deinitRelocs(self.base.allocator, &dbg.dbg_info_type_relocs);
2359 }
2342 if (self.dwarf) |*dw| {
2343 try dw.initDeclState(decl);
23602344 }
23612345
2362 const res = if (debug_buffers) |dbg|
2346 const res = if (self.dwarf) |*dw|
23632347 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{
2364 .dwarf = .{
2365 .dbg_line = &dbg.dbg_line_buffer,
2366 .dbg_info = &dbg.dbg_info_buffer,
2367 .dbg_info_type_relocs = &dbg.dbg_info_type_relocs,
2368 },
2348 .dwarf = dw,
23692349 })
23702350 else
23712351 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);
......@@ -2379,15 +2359,8 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
23792359 },
23802360 };
23812361 const local_sym = try self.updateDeclCode(decl, code, elf.STT_FUNC);
2382 if (debug_buffers) |dbg| {
2383 try self.dwarf.?.commitDeclDebugInfo(
2384 &self.base,
2385 module,
2386 decl,
2387 local_sym.st_value,
2388 local_sym.st_size,
2389 dbg,
2390 );
2362 if (self.dwarf) |*dw| {
2363 try dw.commitDeclState(&self.base, module, decl, local_sym.st_value, local_sym.st_size);
23912364 }
23922365
23932366 // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated.
......@@ -2421,31 +2394,18 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
24212394 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
24222395 defer code_buffer.deinit();
24232396
2424 var debug_buffers_buf: Dwarf.DeclDebugBuffers = undefined;
2425 const debug_buffers = if (self.dwarf) |*dw| blk: {
2426 debug_buffers_buf = try dw.initDeclDebugInfo(decl);
2427 break :blk &debug_buffers_buf;
2428 } else null;
2429 defer {
2430 if (debug_buffers) |dbg| {
2431 dbg.dbg_line_buffer.deinit();
2432 dbg.dbg_info_buffer.deinit();
2433 deinitRelocs(self.base.allocator, &dbg.dbg_info_type_relocs);
2434 }
2397 if (self.dwarf) |*dw| {
2398 try dw.initDeclState(decl);
24352399 }
24362400
24372401 // TODO implement .debug_info for global variables
24382402 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
2439 const res = if (debug_buffers) |dbg|
2403 const res = if (self.dwarf) |*dw|
24402404 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
24412405 .ty = decl.ty,
24422406 .val = decl_val,
24432407 }, &code_buffer, .{
2444 .dwarf = .{
2445 .dbg_line = &dbg.dbg_line_buffer,
2446 .dbg_info = &dbg.dbg_info_buffer,
2447 .dbg_info_type_relocs = &dbg.dbg_info_type_relocs,
2448 },
2408 .dwarf = dw,
24492409 }, .{
24502410 .parent_atom_index = decl.link.elf.local_sym_index,
24512411 })
......@@ -2468,8 +2428,8 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
24682428 };
24692429
24702430 const local_sym = try self.updateDeclCode(decl, code, elf.STT_OBJECT);
2471 if (debug_buffers) |dbg| {
2472 try self.dwarf.?.commitDeclDebugInfo(&self.base, module, decl, local_sym.st_value, local_sym.st_size, dbg);
2431 if (self.dwarf) |*dw| {
2432 try dw.commitDeclState(&self.base, module, decl, local_sym.st_value, local_sym.st_size);
24732433 }
24742434
24752435 // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated.
src/link/MachO.zig+25-47
......@@ -453,6 +453,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
453453 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.
454454 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
455455
456 if (self.d_sym) |*d_sym| {
457 if (self.base.options.module) |module| {
458 try d_sym.dwarf.flushModule(&self.base, module);
459 }
460 }
461
456462 // If there is no Zig code to compile, then we should skip flushing the output file because it
457463 // will not be part of the linker line anyway.
458464 const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {
......@@ -3670,32 +3676,17 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
36703676 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
36713677 defer code_buffer.deinit();
36723678
3673 var debug_buffers_buf: link.File.Dwarf.DeclDebugBuffers = undefined;
3674 const debug_buffers = if (self.d_sym) |*d_sym| blk: {
3675 debug_buffers_buf = try d_sym.initDeclDebugInfo(module, decl);
3676 break :blk &debug_buffers_buf;
3677 } else null;
3678 defer {
3679 if (debug_buffers) |dbg| {
3680 dbg.dbg_line_buffer.deinit();
3681 dbg.dbg_info_buffer.deinit();
3682 for (dbg.dbg_info_type_relocs.values()) |*value| {
3683 value.relocs.deinit(self.base.allocator);
3684 }
3685 dbg.dbg_info_type_relocs.deinit(self.base.allocator);
3686 }
3679 if (self.d_sym) |*d_sym| {
3680 try d_sym.dwarf.initDeclState(decl);
36873681 }
36883682
3689 const res = if (debug_buffers) |dbg|
3683 const res = if (self.d_sym) |*d_sym|
36903684 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{
3691 .dwarf = .{
3692 .dbg_line = &dbg.dbg_line_buffer,
3693 .dbg_info = &dbg.dbg_info_buffer,
3694 .dbg_info_type_relocs = &dbg.dbg_info_type_relocs,
3695 },
3685 .dwarf = &d_sym.dwarf,
36963686 })
36973687 else
36983688 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);
3689
36993690 switch (res) {
37003691 .appended => {
37013692 try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items);
......@@ -3707,12 +3698,10 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
37073698 },
37083699 }
37093700
3710 _ = try self.placeDecl(decl, decl.link.macho.code.items.len);
3701 const symbol = try self.placeDecl(decl, decl.link.macho.code.items.len);
37113702
3712 if (debug_buffers) |db| {
3713 if (self.d_sym) |*d_sym| {
3714 try d_sym.commitDeclDebugInfo(module, decl, db);
3715 }
3703 if (self.d_sym) |*d_sym| {
3704 try d_sym.dwarf.commitDeclState(&self.base, module, decl, symbol.n_value, decl.link.macho.size);
37163705 }
37173706
37183707 // Since we updated the vaddr and the size, each corresponding export symbol also
......@@ -3812,33 +3801,17 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
38123801 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
38133802 defer code_buffer.deinit();
38143803
3815 var debug_buffers_buf: link.File.Dwarf.DeclDebugBuffers = undefined;
3816 const debug_buffers = if (self.d_sym) |*d_sym| blk: {
3817 debug_buffers_buf = try d_sym.initDeclDebugInfo(module, decl);
3818 break :blk &debug_buffers_buf;
3819 } else null;
3820 defer {
3821 if (debug_buffers) |dbg| {
3822 dbg.dbg_line_buffer.deinit();
3823 dbg.dbg_info_buffer.deinit();
3824 for (dbg.dbg_info_type_relocs.values()) |*value| {
3825 value.relocs.deinit(self.base.allocator);
3826 }
3827 dbg.dbg_info_type_relocs.deinit(self.base.allocator);
3828 }
3804 if (self.d_sym) |*d_sym| {
3805 try d_sym.dwarf.initDeclState(decl);
38293806 }
38303807
38313808 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
3832 const res = if (debug_buffers) |dbg|
3809 const res = if (self.d_sym) |*d_sym|
38333810 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
38343811 .ty = decl.ty,
38353812 .val = decl_val,
38363813 }, &code_buffer, .{
3837 .dwarf = .{
3838 .dbg_line = &dbg.dbg_line_buffer,
3839 .dbg_info = &dbg.dbg_info_buffer,
3840 .dbg_info_type_relocs = &dbg.dbg_info_type_relocs,
3841 },
3814 .dwarf = &d_sym.dwarf,
38423815 }, .{
38433816 .parent_atom_index = decl.link.macho.local_sym_index,
38443817 })
......@@ -3870,7 +3843,11 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
38703843 },
38713844 }
38723845 };
3873 _ = try self.placeDecl(decl, code.len);
3846 const symbol = try self.placeDecl(decl, code.len);
3847
3848 if (self.d_sym) |*d_sym| {
3849 try d_sym.dwarf.commitDeclState(&self.base, module, decl, symbol.n_value, decl.link.macho.size);
3850 }
38743851
38753852 // Since we updated the vaddr and the size, each corresponding export symbol also
38763853 // needs to be updated.
......@@ -4084,8 +4061,9 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64
40844061}
40854062
40864063pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void {
4064 _ = module;
40874065 if (self.d_sym) |*d_sym| {
4088 try d_sym.updateDeclLineNumber(module, decl);
4066 try d_sym.dwarf.updateDeclLineNumber(&self.base, decl);
40894067 }
40904068}
40914069
src/link/MachO/DebugSymbols.zig-22
......@@ -645,25 +645,3 @@ fn writeStringTable(self: *DebugSymbols) !void {
645645
646646 self.load_commands_dirty = true;
647647}
648
649pub fn updateDeclLineNumber(self: *DebugSymbols, module: *Module, decl: *const Module.Decl) !void {
650 _ = module;
651 return self.dwarf.updateDeclLineNumber(&self.base.base, decl);
652}
653
654/// Caller owns the returned memory.
655pub fn initDeclDebugInfo(self: *DebugSymbols, module: *Module, decl: *Module.Decl) !Dwarf.DeclDebugBuffers {
656 _ = module;
657 return self.dwarf.initDeclDebugInfo(decl);
658}
659
660pub fn commitDeclDebugInfo(
661 self: *DebugSymbols,
662 module: *Module,
663 decl: *Module.Decl,
664 debug_buffers: *Dwarf.DeclDebugBuffers,
665) !void {
666 const symbol = self.base.locals.items[decl.link.macho.local_sym_index];
667 const atom = &decl.link.macho;
668 return self.dwarf.commitDeclDebugInfo(&self.base.base, module, decl, symbol.n_value, atom.size, debug_buffers);
669}