authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-30 18:29:44+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-04-04 21:46:53+02:00
log364e53f3bf6b5aa4e5e7eba5d790c5b957007067
tree2c6ce39c91c9f1c070c51a0b3beadb45ee29766d
parent795f075790d641499dee283507fc40a2e609e9ce

dwarf: emit debug info for local variables on x86_64

Add support for emitting debug info for local variables within a subprogram. This required moving bits responsible for populating the debug info back to `CodeGen` from `Emit` as we require the operand to be resolved at callsite plus we need to know its type. Without enforcing this, we could end up with a `dead` mcv.

7 files changed, 216 insertions(+), 188 deletions(-)

src/arch/arm/Emit.zig+2-2
......@@ -417,7 +417,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
417417 .dwarf => |dw| {
418418 const dbg_info = &dw.dbg_info;
419419 try dbg_info.ensureUnusedCapacity(3);
420 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
420 dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter));
421421 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
422422 1, // ULEB128 dwarf expression length
423423 reg.dwarfLocOp(),
......@@ -449,7 +449,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
449449 };
450450
451451 const dbg_info = &dw.dbg_info;
452 try dbg_info.append(link.File.Dwarf.abbrev_parameter);
452 try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.parameter));
453453
454454 // Get length of the LEB128 stack offset
455455 var counting_writer = std.io.countingWriter(std.io.null_writer);
src/arch/riscv64/CodeGen.zig+1-1
......@@ -1574,7 +1574,7 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32
15741574 .dwarf => |dw| {
15751575 const dbg_info = &dw.dbg_info;
15761576 try dbg_info.ensureUnusedCapacity(3);
1577 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
1577 dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter));
15781578 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
15791579 1, // ULEB128 dwarf expression length
15801580 reg.dwarfLocOp(),
src/arch/x86_64/CodeGen.zig+132-16
......@@ -48,6 +48,7 @@ gpa: Allocator,
4848air: Air,
4949liveness: Liveness,
5050bin_file: *link.File,
51debug_output: DebugInfoOutput,
5152target: *const std.Target,
5253mod_fn: *const Module.Fn,
5354err_msg: ?*ErrorMsg,
......@@ -337,6 +338,7 @@ pub fn generate(
337338 .liveness = liveness,
338339 .target = &bin_file.options.target,
339340 .bin_file = bin_file,
341 .debug_output = debug_output,
340342 .mod_fn = module_fn,
341343 .err_msg = null,
342344 .args = undefined, // populated after `resolveCallingConventionValues`
......@@ -382,7 +384,6 @@ pub fn generate(
382384 };
383385
384386 var mir = Mir{
385 .function = &function,
386387 .instructions = function.mir_instructions.toOwnedSlice(),
387388 .extra = function.mir_extra.toOwnedSlice(bin_file.allocator),
388389 };
......@@ -391,7 +392,6 @@ pub fn generate(
391392 var emit = Emit{
392393 .mir = mir,
393394 .bin_file = bin_file,
394 .function = &function,
395395 .debug_output = debug_output,
396396 .target = &bin_file.options.target,
397397 .src_loc = src_loc,
......@@ -3425,17 +3425,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
34253425 const arg_index = self.arg_index;
34263426 self.arg_index += 1;
34273427
3428 const ty = self.air.typeOfIndex(inst);
34283429 const mcv = self.args[arg_index];
3429 const payload = try self.addExtra(Mir.ArgDbgInfo{
3430 .air_inst = inst,
3431 .arg_index = arg_index,
3432 .max_stack = self.max_end_stack,
3433 });
3434 _ = try self.addInst(.{
3435 .tag = .arg_dbg_info,
3436 .ops = undefined,
3437 .data = .{ .payload = payload },
3438 });
3430 const name = self.mod_fn.getParamName(arg_index);
3431 const name_with_null = name.ptr[0 .. name.len + 1];
3432
34393433 if (self.liveness.isUnused(inst))
34403434 return self.finishAirBookkeeping();
34413435
......@@ -3443,10 +3437,46 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
34433437 switch (mcv) {
34443438 .register => |reg| {
34453439 self.register_manager.getRegAssumeFree(reg.to64(), inst);
3440 switch (self.debug_output) {
3441 .dwarf => |dw| {
3442 const dbg_info = &dw.dbg_info;
3443 try dbg_info.ensureUnusedCapacity(3);
3444 dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter));
3445 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
3446 1, // ULEB128 dwarf expression length
3447 reg.dwarfLocOp(),
3448 });
3449 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
3450 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
3451 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
3452 },
3453 .plan9 => {},
3454 .none => {},
3455 }
34463456 break :blk mcv;
34473457 },
34483458 .stack_offset => |off| {
34493459 const offset = @intCast(i32, self.max_end_stack) - off + 16;
3460 switch (self.debug_output) {
3461 .dwarf => |dw| {
3462 const dbg_info = &dw.dbg_info;
3463 try dbg_info.ensureUnusedCapacity(8);
3464 dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter));
3465 const fixup = dbg_info.items.len;
3466 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
3467 1, // we will backpatch it after we encode the displacement in LEB128
3468 DW.OP.breg6, // .rbp TODO handle -fomit-frame-pointer
3469 });
3470 leb128.writeILEB128(dbg_info.writer(), offset) catch unreachable;
3471 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
3472 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
3473 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
3474 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
3475
3476 },
3477 .plan9 => {},
3478 .none => {},
3479 }
34503480 break :blk MCValue{ .stack_offset = -offset };
34513481 },
34523482 else => return self.fail("TODO implement arg for {}", .{mcv}),
......@@ -3885,13 +3915,99 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
38853915
38863916fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
38873917 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3888 const name = self.air.nullTerminatedString(pl_op.payload);
38893918 const operand = pl_op.operand;
3890 // TODO emit debug info for this variable
3891 _ = name;
3919 const ty = self.air.typeOf(operand);
3920
3921 if (!self.liveness.operandDies(inst, 0)) {
3922 const mcv = try self.resolveInst(operand);
3923 const name = self.air.nullTerminatedString(pl_op.payload);
3924
3925 const tag = self.air.instructions.items(.tag)[inst];
3926 switch (tag) {
3927 .dbg_var_ptr => try self.genVarDbgInfo(ty.childType(), mcv, name),
3928 .dbg_var_val => try self.genVarDbgInfo(ty, mcv, name),
3929 else => unreachable,
3930 }
3931 }
3932
38923933 return self.finishAir(inst, .dead, .{ operand, .none, .none });
38933934}
38943935
3936fn genVarDbgInfo(
3937 self: *Self,
3938 ty: Type,
3939 mcv: MCValue,
3940 name: [:0]const u8,
3941) !void {
3942 const name_with_null = name.ptr[0 .. name.len + 1];
3943 switch (mcv) {
3944 .register => |reg| {
3945 switch (self.debug_output) {
3946 .dwarf => |dw| {
3947 const dbg_info = &dw.dbg_info;
3948 try dbg_info.ensureUnusedCapacity(3);
3949 dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.variable));
3950 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
3951 1, // ULEB128 dwarf expression length
3952 reg.dwarfLocOp(),
3953 });
3954 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
3955 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
3956 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
3957 },
3958 .plan9 => {},
3959 .none => {},
3960 }
3961 },
3962 .ptr_stack_offset, .stack_offset => |off| {
3963 switch (self.debug_output) {
3964 .dwarf => |dw| {
3965 const dbg_info = &dw.dbg_info;
3966 try dbg_info.ensureUnusedCapacity(8);
3967 dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.variable));
3968 const fixup = dbg_info.items.len;
3969 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
3970 1, // we will backpatch it after we encode the displacement in LEB128
3971 DW.OP.breg6, // .rbp TODO handle -fomit-frame-pointer
3972 });
3973 leb128.writeILEB128(dbg_info.writer(), -off) catch unreachable;
3974 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
3975 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
3976 try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
3977 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
3978
3979 },
3980 .plan9 => {},
3981 .none => {},
3982 }
3983 },
3984 else => {
3985 log.debug("TODO generate debug info for {}", .{mcv});
3986 },
3987 }
3988}
3989
3990/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
3991/// after codegen for this symbol is done.
3992fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
3993 switch (self.debug_output) {
3994 .dwarf => |dw| {
3995 assert(ty.hasRuntimeBits());
3996 const dbg_info = &dw.dbg_info;
3997 const index = dbg_info.items.len;
3998 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
3999 const atom = switch (self.bin_file.tag) {
4000 .elf => &self.mod_fn.owner_decl.link.elf.dbg_info_atom,
4001 .macho => &self.mod_fn.owner_decl.link.macho.dbg_info_atom,
4002 else => unreachable,
4003 };
4004 try dw.addTypeReloc(atom, ty, @intCast(u32, index), null);
4005 },
4006 .plan9 => {},
4007 .none => {},
4008 }
4009}
4010
38954011fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 {
38964012 const abi_size = ty.abiSize(self.target.*);
38974013 switch (mcv) {
......@@ -5919,7 +6035,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
59196035 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand });
59206036}
59216037
5922fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
6038pub fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
59236039 // First section of indexes correspond to a set number of constant values.
59246040 const ref_int = @enumToInt(inst);
59256041 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
src/arch/x86_64/Emit.zig-88
......@@ -30,7 +30,6 @@ const Type = @import("../../type.zig").Type;
3030
3131mir: Mir,
3232bin_file: *link.File,
33function: *const CodeGen,
3433debug_output: DebugInfoOutput,
3534target: *const std.Target,
3635err_msg: ?*ErrorMsg = null,
......@@ -187,7 +186,6 @@ pub fn lowerMir(emit: *Emit) InnerError!void {
187186 .dbg_line => try emit.mirDbgLine(inst),
188187 .dbg_prologue_end => try emit.mirDbgPrologueEnd(inst),
189188 .dbg_epilogue_begin => try emit.mirDbgEpilogueBegin(inst),
190 .arg_dbg_info => try emit.mirArgDbgInfo(inst),
191189
192190 .push_regs_from_callee_preserved_regs => try emit.mirPushPopRegsFromCalleePreservedRegs(.push, inst),
193191 .pop_regs_from_callee_preserved_regs => try emit.mirPushPopRegsFromCalleePreservedRegs(.pop, inst),
......@@ -1057,92 +1055,6 @@ fn mirDbgEpilogueBegin(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
10571055 }
10581056}
10591057
1060fn mirArgDbgInfo(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
1061 const tag = emit.mir.instructions.items(.tag)[inst];
1062 assert(tag == .arg_dbg_info);
1063 const payload = emit.mir.instructions.items(.data)[inst].payload;
1064 const arg_dbg_info = emit.mir.extraData(Mir.ArgDbgInfo, payload).data;
1065 const mcv = emit.mir.function.args[arg_dbg_info.arg_index];
1066 try emit.genArgDbgInfo(arg_dbg_info.air_inst, mcv, arg_dbg_info.max_stack, arg_dbg_info.arg_index);
1067}
1068
1069fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32, arg_index: u32) !void {
1070 const ty = emit.mir.function.air.instructions.items(.data)[inst].ty;
1071 const name = emit.mir.function.mod_fn.getParamName(arg_index);
1072 const name_with_null = name.ptr[0 .. name.len + 1];
1073
1074 switch (mcv) {
1075 .register => |reg| {
1076 switch (emit.debug_output) {
1077 .dwarf => |dw| {
1078 const dbg_info = &dw.dbg_info;
1079 try dbg_info.ensureUnusedCapacity(3);
1080 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
1081 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1082 1, // ULEB128 dwarf expression length
1083 reg.dwarfLocOp(),
1084 });
1085 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
1086 try emit.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
1087 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
1088 },
1089 .plan9 => {},
1090 .none => {},
1091 }
1092 },
1093 .stack_offset => |off| {
1094 switch (emit.debug_output) {
1095 .dwarf => |dw| {
1096 // we add here +16 like we do in airArg in CodeGen since we refer directly to
1097 // rbp as the start of function frame minus 8 bytes for caller's rbp preserved in the
1098 // prologue, and 8 bytes for return address.
1099 // TODO we need to make this more generic if we don't use rbp as the frame pointer
1100 // for example when -fomit-frame-pointer is set.
1101 const disp = @intCast(i32, max_stack) - off + 16;
1102 const dbg_info = &dw.dbg_info;
1103 try dbg_info.ensureUnusedCapacity(8);
1104 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
1105 const fixup = dbg_info.items.len;
1106 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1107 1, // we will backpatch it after we encode the displacement in LEB128
1108 DW.OP.breg6, // .rbp TODO handle -fomit-frame-pointer
1109 });
1110 leb128.writeILEB128(dbg_info.writer(), disp) catch unreachable;
1111 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
1112 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
1113 try emit.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
1114 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
1115
1116 },
1117 .plan9 => {},
1118 .none => {},
1119 }
1120 },
1121 else => {},
1122 }
1123}
1124
1125/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
1126/// after codegen for this symbol is done.
1127fn addDbgInfoTypeReloc(emit: *Emit, ty: Type) !void {
1128 switch (emit.debug_output) {
1129 .dwarf => |dw| {
1130 assert(ty.hasRuntimeBits());
1131 const dbg_info = &dw.dbg_info;
1132 const index = dbg_info.items.len;
1133 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
1134 const atom = switch (emit.bin_file.tag) {
1135 .elf => &emit.function.mod_fn.owner_decl.link.elf.dbg_info_atom,
1136 .macho => &emit.function.mod_fn.owner_decl.link.macho.dbg_info_atom,
1137 else => unreachable,
1138 };
1139 try dw.addTypeReloc(atom, ty, @intCast(u32, index), null);
1140 },
1141 .plan9 => {},
1142 .none => {},
1143 }
1144}
1145
11461058const Tag = enum {
11471059 adc,
11481060 add,
src/arch/x86_64/Mir.zig+6-16
......@@ -16,7 +16,6 @@ const Air = @import("../../Air.zig");
1616const CodeGen = @import("CodeGen.zig");
1717const Register = bits.Register;
1818
19function: *const CodeGen,
2019instructions: std.MultiArrayList(Inst).Slice,
2120/// The meaning of this data is determined by `Inst.Tag` value.
2221extra: []const u32,
......@@ -364,9 +363,6 @@ pub const Inst = struct {
364363 /// update debug line
365364 dbg_line,
366365
367 /// arg debug info
368 arg_dbg_info,
369
370366 /// push registers from the callee_preserved_regs
371367 /// data is the bitfield of which regs to push
372368 /// for example on x86_64, the callee_preserved_regs are [_]Register{ .rcx, .rsi, .rdi, .r8, .r9, .r10, .r11 }; };
......@@ -453,18 +449,6 @@ pub const DbgLineColumn = struct {
453449 column: u32,
454450};
455451
456pub const ArgDbgInfo = struct {
457 air_inst: Air.Inst.Index,
458 arg_index: u32,
459 max_stack: u32,
460};
461
462pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
463 mir.instructions.deinit(gpa);
464 gpa.free(mir.extra);
465 mir.* = undefined;
466}
467
468452pub const Ops = struct {
469453 reg1: Register = .none,
470454 reg2: Register = .none,
......@@ -490,6 +474,12 @@ pub const Ops = struct {
490474 }
491475};
492476
477pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
478 mir.instructions.deinit(gpa);
479 gpa.free(mir.extra);
480 mir.* = undefined;
481}
482
493483pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end: usize } {
494484 const fields = std.meta.fields(T);
495485 var i: usize = index;
src/arch/x86_64/PrintMir.zig+1-1
......@@ -147,7 +147,7 @@ pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap
147147
148148 .call_extern => try print.mirCallExtern(inst, w),
149149
150 .dbg_line, .dbg_prologue_end, .dbg_epilogue_begin, .arg_dbg_info => try w.print("{s}\n", .{@tagName(tag)}),
150 .dbg_line, .dbg_prologue_end, .dbg_epilogue_begin => try w.print("{s}\n", .{@tagName(tag)}),
151151
152152 .push_regs_from_callee_preserved_regs => try print.mirPushPopRegsFromCalleePreservedRegs(.push, inst, w),
153153 .pop_regs_from_callee_preserved_regs => try print.mirPushPopRegsFromCalleePreservedRegs(.pop, inst, w),
src/link/Dwarf.zig+74-64
......@@ -148,11 +148,11 @@ pub const DeclState = struct {
148148 switch (ty.zigTypeTag()) {
149149 .NoReturn => unreachable,
150150 .Void => {
151 try dbg_info_buffer.append(abbrev_pad1);
151 try dbg_info_buffer.append(@enumToInt(AbbrevKind.pad1));
152152 },
153153 .Bool => {
154154 try dbg_info_buffer.appendSlice(&[_]u8{
155 abbrev_base_type,
155 @enumToInt(AbbrevKind.base_type),
156156 DW.ATE.boolean, // DW.AT.encoding , DW.FORM.data1
157157 1, // DW.AT.byte_size, DW.FORM.data1
158158 'b', 'o', 'o', 'l', 0, // DW.AT.name, DW.FORM.string
......@@ -161,7 +161,7 @@ pub const DeclState = struct {
161161 .Int => {
162162 const info = ty.intInfo(target);
163163 try dbg_info_buffer.ensureUnusedCapacity(12);
164 dbg_info_buffer.appendAssumeCapacity(abbrev_base_type);
164 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type));
165165 // DW.AT.encoding, DW.FORM.data1
166166 dbg_info_buffer.appendAssumeCapacity(switch (info.signedness) {
167167 .signed => DW.ATE.signed,
......@@ -175,7 +175,7 @@ pub const DeclState = struct {
175175 .Optional => {
176176 if (ty.isPtrLikeOptional()) {
177177 try dbg_info_buffer.ensureUnusedCapacity(12);
178 dbg_info_buffer.appendAssumeCapacity(abbrev_base_type);
178 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type));
179179 // DW.AT.encoding, DW.FORM.data1
180180 dbg_info_buffer.appendAssumeCapacity(DW.ATE.address);
181181 // DW.AT.byte_size, DW.FORM.data1
......@@ -187,7 +187,7 @@ pub const DeclState = struct {
187187 var buf = try arena.create(Type.Payload.ElemType);
188188 const payload_ty = ty.optionalChild(buf);
189189 // DW.AT.structure_type
190 try dbg_info_buffer.append(abbrev_struct_type);
190 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
191191 // DW.AT.byte_size, DW.FORM.sdata
192192 const abi_size = ty.abiSize(target);
193193 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
......@@ -195,7 +195,7 @@ pub const DeclState = struct {
195195 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)});
196196 // DW.AT.member
197197 try dbg_info_buffer.ensureUnusedCapacity(7);
198 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
198 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
199199 // DW.AT.name, DW.FORM.string
200200 dbg_info_buffer.appendSliceAssumeCapacity("maybe");
201201 dbg_info_buffer.appendAssumeCapacity(0);
......@@ -207,7 +207,7 @@ pub const DeclState = struct {
207207 try dbg_info_buffer.ensureUnusedCapacity(6);
208208 dbg_info_buffer.appendAssumeCapacity(0);
209209 // DW.AT.member
210 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
210 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
211211 // DW.AT.name, DW.FORM.string
212212 dbg_info_buffer.appendSliceAssumeCapacity("val");
213213 dbg_info_buffer.appendAssumeCapacity(0);
......@@ -227,14 +227,14 @@ pub const DeclState = struct {
227227 // Slices are structs: struct { .ptr = *, .len = N }
228228 // DW.AT.structure_type
229229 try dbg_info_buffer.ensureUnusedCapacity(2);
230 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_type);
230 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_type));
231231 // DW.AT.byte_size, DW.FORM.sdata
232232 dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize) * 2);
233233 // DW.AT.name, DW.FORM.string
234234 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)});
235235 // DW.AT.member
236236 try dbg_info_buffer.ensureUnusedCapacity(5);
237 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
237 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
238238 // DW.AT.name, DW.FORM.string
239239 dbg_info_buffer.appendSliceAssumeCapacity("ptr");
240240 dbg_info_buffer.appendAssumeCapacity(0);
......@@ -248,7 +248,7 @@ pub const DeclState = struct {
248248 try dbg_info_buffer.ensureUnusedCapacity(6);
249249 dbg_info_buffer.appendAssumeCapacity(0);
250250 // DW.AT.member
251 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
251 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
252252 // DW.AT.name, DW.FORM.string
253253 dbg_info_buffer.appendSliceAssumeCapacity("len");
254254 dbg_info_buffer.appendAssumeCapacity(0);
......@@ -263,7 +263,7 @@ pub const DeclState = struct {
263263 dbg_info_buffer.appendAssumeCapacity(0);
264264 } else {
265265 try dbg_info_buffer.ensureUnusedCapacity(5);
266 dbg_info_buffer.appendAssumeCapacity(abbrev_ptr_type);
266 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.ptr_type));
267267 // DW.AT.type, DW.FORM.ref4
268268 const index = dbg_info_buffer.items.len;
269269 try dbg_info_buffer.resize(index + 4);
......@@ -272,7 +272,7 @@ pub const DeclState = struct {
272272 },
273273 .Struct => blk: {
274274 // DW.AT.structure_type
275 try dbg_info_buffer.append(abbrev_struct_type);
275 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
276276 // DW.AT.byte_size, DW.FORM.sdata
277277 const abi_size = ty.abiSize(target);
278278 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
......@@ -285,7 +285,7 @@ pub const DeclState = struct {
285285 const fields = ty.tupleFields();
286286 for (fields.types) |field, field_index| {
287287 // DW.AT.member
288 try dbg_info_buffer.append(abbrev_struct_member);
288 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_member));
289289 // DW.AT.name, DW.FORM.string
290290 try dbg_info_buffer.writer().print("{d}\x00", .{field_index});
291291 // DW.AT.type, DW.FORM.ref4
......@@ -315,7 +315,7 @@ pub const DeclState = struct {
315315 const field = fields.get(field_name).?;
316316 // DW.AT.member
317317 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);
318 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
318 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
319319 // DW.AT.name, DW.FORM.string
320320 dbg_info_buffer.appendSliceAssumeCapacity(field_name);
321321 dbg_info_buffer.appendAssumeCapacity(0);
......@@ -335,7 +335,7 @@ pub const DeclState = struct {
335335 },
336336 .Enum => {
337337 // DW.AT.enumeration_type
338 try dbg_info_buffer.append(abbrev_enum_type);
338 try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type));
339339 // DW.AT.byte_size, DW.FORM.sdata
340340 const abi_size = ty.abiSize(target);
341341 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
......@@ -355,7 +355,7 @@ pub const DeclState = struct {
355355 for (fields.keys()) |field_name, field_i| {
356356 // DW.AT.enumerator
357357 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64));
358 dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant);
358 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.enum_variant));
359359 // DW.AT.name, DW.FORM.string
360360 dbg_info_buffer.appendSliceAssumeCapacity(field_name);
361361 dbg_info_buffer.appendAssumeCapacity(0);
......@@ -385,7 +385,7 @@ pub const DeclState = struct {
385385 // for untagged unions.
386386 if (is_tagged) {
387387 // DW.AT.structure_type
388 try dbg_info_buffer.append(abbrev_struct_type);
388 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
389389 // DW.AT.byte_size, DW.FORM.sdata
390390 try leb128.writeULEB128(dbg_info_buffer.writer(), layout.abi_size);
391391 // DW.AT.name, DW.FORM.string
......@@ -395,7 +395,7 @@ pub const DeclState = struct {
395395
396396 // DW.AT.member
397397 try dbg_info_buffer.ensureUnusedCapacity(9);
398 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
398 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
399399 // DW.AT.name, DW.FORM.string
400400 dbg_info_buffer.appendSliceAssumeCapacity("payload");
401401 dbg_info_buffer.appendAssumeCapacity(0);
......@@ -408,7 +408,7 @@ pub const DeclState = struct {
408408 }
409409
410410 // DW.AT.union_type
411 try dbg_info_buffer.append(abbrev_union_type);
411 try dbg_info_buffer.append(@enumToInt(AbbrevKind.union_type));
412412 // DW.AT.byte_size, DW.FORM.sdata,
413413 try leb128.writeULEB128(dbg_info_buffer.writer(), layout.payload_size);
414414 // DW.AT.name, DW.FORM.string
......@@ -423,7 +423,7 @@ pub const DeclState = struct {
423423 const field = fields.get(field_name).?;
424424 if (!field.ty.hasRuntimeBits()) continue;
425425 // DW.AT.member
426 try dbg_info_buffer.append(abbrev_struct_member);
426 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_member));
427427 // DW.AT.name, DW.FORM.string
428428 try dbg_info_buffer.writer().print("{s}\x00", .{field_name});
429429 // DW.AT.type, DW.FORM.ref4
......@@ -439,7 +439,7 @@ pub const DeclState = struct {
439439 if (is_tagged) {
440440 // DW.AT.member
441441 try dbg_info_buffer.ensureUnusedCapacity(5);
442 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
442 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
443443 // DW.AT.name, DW.FORM.string
444444 dbg_info_buffer.appendSliceAssumeCapacity("tag");
445445 dbg_info_buffer.appendAssumeCapacity(0);
......@@ -471,7 +471,7 @@ pub const DeclState = struct {
471471 const payload_off = mem.alignForwardGeneric(u64, error_ty.abiSize(target), abi_align);
472472
473473 // DW.AT.structure_type
474 try dbg_info_buffer.append(abbrev_struct_type);
474 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
475475 // DW.AT.byte_size, DW.FORM.sdata
476476 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
477477 // DW.AT.name, DW.FORM.string
......@@ -480,7 +480,7 @@ pub const DeclState = struct {
480480
481481 // DW.AT.member
482482 try dbg_info_buffer.ensureUnusedCapacity(7);
483 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
483 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
484484 // DW.AT.name, DW.FORM.string
485485 dbg_info_buffer.appendSliceAssumeCapacity("value");
486486 dbg_info_buffer.appendAssumeCapacity(0);
......@@ -493,7 +493,7 @@ pub const DeclState = struct {
493493
494494 // DW.AT.member
495495 try dbg_info_buffer.ensureUnusedCapacity(5);
496 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
496 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
497497 // DW.AT.name, DW.FORM.string
498498 dbg_info_buffer.appendSliceAssumeCapacity("err");
499499 dbg_info_buffer.appendAssumeCapacity(0);
......@@ -509,7 +509,7 @@ pub const DeclState = struct {
509509 },
510510 else => {
511511 log.debug("TODO implement .debug_info for type '{}'", .{ty.fmtDebug()});
512 try dbg_info_buffer.append(abbrev_pad1);
512 try dbg_info_buffer.append(@enumToInt(AbbrevKind.pad1));
513513 },
514514 }
515515 }
......@@ -550,18 +550,21 @@ pub const SrcFn = struct {
550550
551551pub const PtrWidth = enum { p32, p64 };
552552
553pub const abbrev_compile_unit = 1;
554pub const abbrev_subprogram = 2;
555pub const abbrev_subprogram_retvoid = 3;
556pub const abbrev_base_type = 4;
557pub const abbrev_ptr_type = 5;
558pub const abbrev_struct_type = 6;
559pub const abbrev_struct_member = 7;
560pub const abbrev_enum_type = 8;
561pub const abbrev_enum_variant = 9;
562pub const abbrev_union_type = 10;
563pub const abbrev_pad1 = 11;
564pub const abbrev_parameter = 12;
553pub const AbbrevKind = enum(u8) {
554 compile_unit = 1,
555 subprogram,
556 subprogram_retvoid,
557 base_type,
558 ptr_type,
559 struct_type,
560 struct_member,
561 enum_type,
562 enum_variant,
563 union_type,
564 pad1,
565 parameter,
566 variable,
567};
565568
566569/// The reloc offset for the virtual address of a function in its Line Number Program.
567570/// Size is a virtual address integer.
......@@ -670,9 +673,9 @@ pub fn initDeclState(self: *Dwarf, decl: *Module.Decl) !DeclState {
670673 const fn_ret_type = decl.ty.fnReturnType();
671674 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits();
672675 if (fn_ret_has_bits) {
673 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);
676 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.subprogram));
674677 } else {
675 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram_retvoid);
678 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.subprogram_retvoid));
676679 }
677680 // These get overwritten after generating the machine code. These values are
678681 // "relocations" and have to be in this fixed place so that functions can be
......@@ -926,7 +929,7 @@ pub fn commitDeclState(
926929 else => unreachable,
927930 };
928931
929 {
932 if (decl_state.abbrev_table.items.len > 0) {
930933 // Now we emit the .debug_info types of the Decl. These will count towards the size of
931934 // the buffer, so we have to do it before computing the offset, and we can't perform the actual
932935 // relocations yet.
......@@ -1244,14 +1247,14 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
12441247 // These are LEB encoded but since the values are all less than 127
12451248 // we can simply append these bytes.
12461249 const abbrev_buf = [_]u8{
1247 abbrev_compile_unit, DW.TAG.compile_unit, DW.CHILDREN.yes, // header
1248 DW.AT.stmt_list, DW.FORM.sec_offset, DW.AT.low_pc,
1249 DW.FORM.addr, DW.AT.high_pc, DW.FORM.addr,
1250 DW.AT.name, DW.FORM.strp, DW.AT.comp_dir,
1251 DW.FORM.strp, DW.AT.producer, DW.FORM.strp,
1252 DW.AT.language, DW.FORM.data2, 0,
1250 @enumToInt(AbbrevKind.compile_unit), DW.TAG.compile_unit, DW.CHILDREN.yes, // header
1251 DW.AT.stmt_list, DW.FORM.sec_offset, DW.AT.low_pc,
1252 DW.FORM.addr, DW.AT.high_pc, DW.FORM.addr,
1253 DW.AT.name, DW.FORM.strp, DW.AT.comp_dir,
1254 DW.FORM.strp, DW.AT.producer, DW.FORM.strp,
1255 DW.AT.language, DW.FORM.data2, 0,
12531256 0, // table sentinel
1254 abbrev_subprogram,
1257 @enumToInt(AbbrevKind.subprogram),
12551258 DW.TAG.subprogram,
12561259 DW.CHILDREN.yes, // header
12571260 DW.AT.low_pc,
......@@ -1262,15 +1265,15 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
12621265 DW.FORM.ref4,
12631266 DW.AT.name,
12641267 DW.FORM.string,
1265 0, 0, // table sentinel
1266 abbrev_subprogram_retvoid,
1268 0, 0, // table sentinel
1269 @enumToInt(AbbrevKind.subprogram_retvoid),
12671270 DW.TAG.subprogram, DW.CHILDREN.yes, // header
12681271 DW.AT.low_pc, DW.FORM.addr,
12691272 DW.AT.high_pc, DW.FORM.data4,
12701273 DW.AT.name, DW.FORM.string,
12711274 0,
12721275 0, // table sentinel
1273 abbrev_base_type,
1276 @enumToInt(AbbrevKind.base_type),
12741277 DW.TAG.base_type,
12751278 DW.CHILDREN.no, // header
12761279 DW.AT.encoding,
......@@ -1281,14 +1284,14 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
12811284 DW.FORM.string,
12821285 0,
12831286 0, // table sentinel
1284 abbrev_ptr_type,
1287 @enumToInt(AbbrevKind.ptr_type),
12851288 DW.TAG.pointer_type,
12861289 DW.CHILDREN.no, // header
12871290 DW.AT.type,
12881291 DW.FORM.ref4,
12891292 0,
12901293 0, // table sentinel
1291 abbrev_struct_type,
1294 @enumToInt(AbbrevKind.struct_type),
12921295 DW.TAG.structure_type,
12931296 DW.CHILDREN.yes, // header
12941297 DW.AT.byte_size,
......@@ -1297,7 +1300,7 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
12971300 DW.FORM.string,
12981301 0,
12991302 0, // table sentinel
1300 abbrev_struct_member,
1303 @enumToInt(AbbrevKind.struct_member),
13011304 DW.TAG.member,
13021305 DW.CHILDREN.no, // header
13031306 DW.AT.name,
......@@ -1308,7 +1311,7 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
13081311 DW.FORM.sdata,
13091312 0,
13101313 0, // table sentinel
1311 abbrev_enum_type,
1314 @enumToInt(AbbrevKind.enum_type),
13121315 DW.TAG.enumeration_type,
13131316 DW.CHILDREN.yes, // header
13141317 DW.AT.byte_size,
......@@ -1317,7 +1320,7 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
13171320 DW.FORM.string,
13181321 0,
13191322 0, // table sentinel
1320 abbrev_enum_variant,
1323 @enumToInt(AbbrevKind.enum_variant),
13211324 DW.TAG.enumerator,
13221325 DW.CHILDREN.no, // header
13231326 DW.AT.name,
......@@ -1326,7 +1329,7 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
13261329 DW.FORM.data8,
13271330 0,
13281331 0, // table sentinel
1329 abbrev_union_type,
1332 @enumToInt(AbbrevKind.union_type),
13301333 DW.TAG.union_type,
13311334 DW.CHILDREN.yes, // header
13321335 DW.AT.byte_size,
......@@ -1335,18 +1338,25 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
13351338 DW.FORM.string,
13361339 0,
13371340 0, // table sentinel
1338 abbrev_pad1,
1341 @enumToInt(AbbrevKind.pad1),
13391342 DW.TAG.unspecified_type,
13401343 DW.CHILDREN.no, // header
13411344 0,
13421345 0, // table sentinel
1343 abbrev_parameter,
1346 @enumToInt(AbbrevKind.parameter),
13441347 DW.TAG.formal_parameter, DW.CHILDREN.no, // header
13451348 DW.AT.location, DW.FORM.exprloc,
13461349 DW.AT.type, DW.FORM.ref4,
13471350 DW.AT.name, DW.FORM.string,
13481351 0,
13491352 0, // table sentinel
1353 @enumToInt(AbbrevKind.variable),
1354 DW.TAG.variable, DW.CHILDREN.no, // header
1355 DW.AT.location, DW.FORM.exprloc,
1356 DW.AT.type, DW.FORM.ref4,
1357 DW.AT.name, DW.FORM.string,
1358 0,
1359 0, // table sentinel
13501360 0,
13511361 0,
13521362 0, // section sentinel
......@@ -1459,7 +1469,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6
14591469 const comp_dir_strp = try self.makeString(module.root_pkg.root_src_directory.path orelse ".");
14601470 const producer_strp = try self.makeString(link.producer_string);
14611471
1462 di_buf.appendAssumeCapacity(abbrev_compile_unit);
1472 di_buf.appendAssumeCapacity(@enumToInt(AbbrevKind.compile_unit));
14631473 if (self.tag == .macho) {
14641474 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); // DW.AT.stmt_list, DW.FORM.sec_offset
14651475 mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), low_pc);
......@@ -1606,7 +1616,7 @@ fn pwriteDbgInfoNops(
16061616 const tracy = trace(@src());
16071617 defer tracy.end();
16081618
1609 const page_of_nops = [1]u8{abbrev_pad1} ** 4096;
1619 const page_of_nops = [1]u8{@enumToInt(AbbrevKind.pad1)} ** 4096;
16101620 var vecs: [32]std.os.iovec_const = undefined;
16111621 var vec_index: usize = 0;
16121622 {
......@@ -1673,7 +1683,7 @@ pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
16731683 .p32 => @as(usize, 4),
16741684 .p64 => 12,
16751685 };
1676 const ptr_width_bytes: u8 = self.ptrWidthBytes();
1686 const ptr_width_bytes = self.ptrWidthBytes();
16771687
16781688 // Enough for all the data without resizing. When support for more compilation units
16791689 // is added, the size of this section will become more variable.
......@@ -2040,7 +2050,7 @@ fn addDbgInfoErrorSet(
20402050 const target_endian = target.cpu.arch.endian();
20412051
20422052 // DW.AT.enumeration_type
2043 try dbg_info_buffer.append(abbrev_enum_type);
2053 try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type));
20442054 // DW.AT.byte_size, DW.FORM.sdata
20452055 const abi_size = ty.abiSize(target);
20462056 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
......@@ -2051,7 +2061,7 @@ fn addDbgInfoErrorSet(
20512061 // DW.AT.enumerator
20522062 const no_error = "(no error)";
20532063 try dbg_info_buffer.ensureUnusedCapacity(no_error.len + 2 + @sizeOf(u64));
2054 dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant);
2064 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.enum_variant));
20552065 // DW.AT.name, DW.FORM.string
20562066 dbg_info_buffer.appendSliceAssumeCapacity(no_error);
20572067 dbg_info_buffer.appendAssumeCapacity(0);
......@@ -2063,7 +2073,7 @@ fn addDbgInfoErrorSet(
20632073 const kv = module.getErrorValue(error_name) catch unreachable;
20642074 // DW.AT.enumerator
20652075 try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64));
2066 dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant);
2076 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.enum_variant));
20672077 // DW.AT.name, DW.FORM.string
20682078 dbg_info_buffer.appendSliceAssumeCapacity(error_name);
20692079 dbg_info_buffer.appendAssumeCapacity(0);