aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-11-09 16:53:33 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-11-09 18:35:06 +0100
commitdf09d9c14a22098709bd8816e622e6dd785ac954 (patch)
tree3ab43f2421eef00e709a33d27debde04a8f19285 /src
parent02852098eebda52ce6373d0440cec4965e6d4478 (diff)
downloadzig-df09d9c14a22098709bd8816e622e6dd785ac954.tar.gz
zig-df09d9c14a22098709bd8816e622e6dd785ac954.zip
x86_64: add DWARF encoding for vector registers
Clean up how we handle emitting of DWARF debug info for `x86_64` codegen.
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86_64/CodeGen.zig138
-rw-r--r--src/arch/x86_64/bits.zig83
2 files changed, 134 insertions, 87 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index 7b9ef863ae..2bafbfb3d7 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -3797,64 +3797,68 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
const ty = self.air.typeOfIndex(inst);
const mcv = self.args[arg_index];
const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index);
- const name_with_null = name.ptr[0 .. name.len + 1];
if (self.liveness.isUnused(inst))
return self.finishAirBookkeeping();
- const dst_mcv: MCValue = blk: {
- switch (mcv) {
- .register => |reg| {
- self.register_manager.getRegAssumeFree(reg.to64(), inst);
- switch (self.debug_output) {
- .dwarf => |dw| {
- const dbg_info = &dw.dbg_info;
- try dbg_info.ensureUnusedCapacity(3);
- dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter));
- dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
- 1, // ULEB128 dwarf expression length
- reg.dwarfLocOp(),
- });
- try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
- try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
- dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
- },
- .plan9 => {},
- .none => {},
- }
- break :blk mcv;
- },
- .stack_offset => |off| {
- const offset = @intCast(i32, self.max_end_stack) - off + 16;
- switch (self.debug_output) {
- .dwarf => |dw| {
- const dbg_info = &dw.dbg_info;
- try dbg_info.ensureUnusedCapacity(8);
- dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter));
- const fixup = dbg_info.items.len;
- dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
- 1, // we will backpatch it after we encode the displacement in LEB128
- DW.OP.breg6, // .rbp TODO handle -fomit-frame-pointer
- });
- leb128.writeILEB128(dbg_info.writer(), offset) catch unreachable;
- dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
- try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
- try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
- dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
-
- },
- .plan9 => {},
- .none => {},
- }
- break :blk MCValue{ .stack_offset = -offset };
- },
- else => return self.fail("TODO implement arg for {}", .{mcv}),
- }
+ const dst_mcv: MCValue = switch (mcv) {
+ .register => |reg| blk: {
+ self.register_manager.getRegAssumeFree(reg.to64(), inst);
+ break :blk MCValue{ .register = reg };
+ },
+ .stack_offset => |off| blk: {
+ const offset = @intCast(i32, self.max_end_stack) - off + 16;
+ break :blk MCValue{ .stack_offset = -offset };
+ },
+ else => return self.fail("TODO implement arg for {}", .{mcv}),
};
+ try self.genArgDbgInfo(ty, name, dst_mcv);
return self.finishAir(inst, dst_mcv, .{ .none, .none, .none });
}
+fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void {
+ const name_with_null = name.ptr[0 .. name.len + 1];
+ switch (self.debug_output) {
+ .dwarf => |dw| {
+ const dbg_info = &dw.dbg_info;
+ switch (mcv) {
+ .register => |reg| {
+ try dbg_info.ensureUnusedCapacity(3);
+ dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter));
+ dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
+ 1, // ULEB128 dwarf expression length
+ reg.dwarfLocOp(),
+ });
+ try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
+ try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
+ dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
+ },
+
+ .stack_offset => |off| {
+ try dbg_info.ensureUnusedCapacity(8);
+ dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter));
+ const fixup = dbg_info.items.len;
+ dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
+ 1, // we will backpatch it after we encode the displacement in LEB128
+ Register.rbp.dwarfLocOpDeref(), // TODO handle -fomit-frame-pointer
+ });
+ leb128.writeILEB128(dbg_info.writer(), -off) catch unreachable;
+ dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
+ try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
+ try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
+ dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
+
+ },
+
+ else => unreachable, // not a valid function parameter
+ }
+ },
+ .plan9 => {},
+ .none => {},
+ }
+}
+
fn airBreakpoint(self: *Self) !void {
_ = try self.addInst(.{
.tag = .interrupt,
@@ -4424,7 +4428,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
}
fn genVarDbgInfo(
- self: *Self,
+ self: Self,
tag: Air.Inst.Tag,
ty: Type,
mcv: MCValue,
@@ -4445,17 +4449,23 @@ fn genVarDbgInfo(
reg.dwarfLocOp(),
});
},
- .ptr_stack_offset, .stack_offset => |off| {
+
+ .ptr_stack_offset,
+ .stack_offset,
+ => |off| {
try dbg_info.ensureUnusedCapacity(7);
const fixup = dbg_info.items.len;
dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1, // we will backpatch it after we encode the displacement in LEB128
- DW.OP.breg6, // .rbp TODO handle -fomit-frame-pointer
+ Register.rbp.dwarfLocOpDeref(), // TODO handle -fomit-frame-pointer
});
leb128.writeILEB128(dbg_info.writer(), -off) catch unreachable;
dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
},
- .memory, .linker_load => {
+
+ .memory,
+ .linker_load,
+ => {
const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8));
const is_ptr = switch (tag) {
.dbg_var_ptr => true,
@@ -4494,27 +4504,23 @@ fn genVarDbgInfo(
else => {},
}
},
+
.immediate => |x| {
- const signedness: std.builtin.Signedness = blk: {
- if (ty.zigTypeTag() != .Int) break :blk .unsigned;
- break :blk ty.intInfo(self.target.*).signedness;
- };
try dbg_info.ensureUnusedCapacity(2);
const fixup = dbg_info.items.len;
dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1,
- switch (signedness) {
- .signed => DW.OP.consts,
- .unsigned => DW.OP.constu,
- },
+ if (ty.isSignedInt()) DW.OP.consts else DW.OP.constu,
});
- switch (signedness) {
- .signed => try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x)),
- .unsigned => try leb128.writeULEB128(dbg_info.writer(), x),
+ if (ty.isSignedInt()) {
+ try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x));
+ } else {
+ try leb128.writeULEB128(dbg_info.writer(), x);
}
try dbg_info.append(DW.OP.stack_value);
dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
},
+
.undef => {
// DW.AT.location, DW.FORM.exprloc
// uleb128(exprloc_len)
@@ -4530,12 +4536,14 @@ fn genVarDbgInfo(
dbg_info.appendSliceAssumeCapacity(implicit_value_len.items);
dbg_info.appendNTimesAssumeCapacity(0xaa, abi_size);
},
+
.none => {
try dbg_info.ensureUnusedCapacity(3);
dbg_info.appendSliceAssumeCapacity(&[3]u8{ // DW.AT.location, DW.FORM.exprloc
2, DW.OP.lit0, DW.OP.stack_value,
});
},
+
else => {
try dbg_info.ensureUnusedCapacity(2);
dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
@@ -4556,7 +4564,7 @@ fn genVarDbgInfo(
/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
/// after codegen for this symbol is done.
-fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
+fn addDbgInfoTypeReloc(self: Self, ty: Type) !void {
switch (self.debug_output) {
.dwarf => |dw| {
const dbg_info = &dw.dbg_info;
diff --git a/src/arch/x86_64/bits.zig b/src/arch/x86_64/bits.zig
index a2d523e84c..cc123b96b6 100644
--- a/src/arch/x86_64/bits.zig
+++ b/src/arch/x86_64/bits.zig
@@ -135,8 +135,6 @@ pub const Condition = enum(u5) {
}
};
-// zig fmt: off
-
/// Definitions of all of the general purpose x64 registers. The order is semantically meaningful.
/// The registers are defined such that IDs go in descending order of 64-bit,
/// 32-bit, 16-bit, and then 8-bit, and each set contains exactly sixteen
@@ -152,6 +150,7 @@ pub const Condition = enum(u5) {
/// The ID can be easily determined by figuring out what range the register is
/// in, and then subtracting the base.
pub const Register = enum(u7) {
+ // zig fmt: off
// 0 through 15, 64-bit registers. 8-15 are extended.
// id is just the int value.
rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
@@ -184,6 +183,7 @@ pub const Register = enum(u7) {
// Pseudo-value for MIR instructions.
none,
+ // zig fmt: on
pub fn id(self: Register) u7 {
return switch (@enumToInt(self)) {
@@ -192,7 +192,7 @@ pub const Register = enum(u7) {
else => unreachable,
};
}
-
+
/// Returns the bit-width of the register.
pub fn size(self: Register) u9 {
return switch (@enumToInt(self)) {
@@ -258,27 +258,66 @@ pub const Register = enum(u7) {
}
pub fn dwarfLocOp(self: Register) u8 {
- return switch (self.to64()) {
- .rax => DW.OP.reg0,
- .rdx => DW.OP.reg1,
- .rcx => DW.OP.reg2,
- .rbx => DW.OP.reg3,
- .rsi => DW.OP.reg4,
- .rdi => DW.OP.reg5,
- .rbp => DW.OP.reg6,
- .rsp => DW.OP.reg7,
-
- .r8 => DW.OP.reg8,
- .r9 => DW.OP.reg9,
- .r10 => DW.OP.reg10,
- .r11 => DW.OP.reg11,
- .r12 => DW.OP.reg12,
- .r13 => DW.OP.reg13,
- .r14 => DW.OP.reg14,
- .r15 => DW.OP.reg15,
+ switch (@enumToInt(self)) {
+ 0...63 => return switch (self.to64()) {
+ .rax => DW.OP.reg0,
+ .rdx => DW.OP.reg1,
+ .rcx => DW.OP.reg2,
+ .rbx => DW.OP.reg3,
+ .rsi => DW.OP.reg4,
+ .rdi => DW.OP.reg5,
+ .rbp => DW.OP.reg6,
+ .rsp => DW.OP.reg7,
+
+ .r8 => DW.OP.reg8,
+ .r9 => DW.OP.reg9,
+ .r10 => DW.OP.reg10,
+ .r11 => DW.OP.reg11,
+ .r12 => DW.OP.reg12,
+ .r13 => DW.OP.reg13,
+ .r14 => DW.OP.reg14,
+ .r15 => DW.OP.reg15,
+
+ else => unreachable,
+ },
+
+ 64...79 => return @as(u8, self.enc()) + DW.OP.reg17,
else => unreachable,
- };
+ }
+ }
+
+ /// DWARF encodings that push a value onto the DWARF stack that is either
+ /// the contents of a register or the result of adding the contents a given
+ /// register to a given signed offset.
+ pub fn dwarfLocOpDeref(self: Register) u8 {
+ switch (@enumToInt(self)) {
+ 0...63 => return switch (self.to64()) {
+ .rax => DW.OP.breg0,
+ .rdx => DW.OP.breg1,
+ .rcx => DW.OP.breg2,
+ .rbx => DW.OP.breg3,
+ .rsi => DW.OP.breg4,
+ .rdi => DW.OP.breg5,
+ .rbp => DW.OP.breg6,
+ .rsp => DW.OP.fbreg,
+
+ .r8 => DW.OP.breg8,
+ .r9 => DW.OP.breg9,
+ .r10 => DW.OP.breg10,
+ .r11 => DW.OP.breg11,
+ .r12 => DW.OP.breg12,
+ .r13 => DW.OP.breg13,
+ .r14 => DW.OP.breg14,
+ .r15 => DW.OP.breg15,
+
+ else => unreachable,
+ },
+
+ 64...79 => return @as(u8, self.enc()) + DW.OP.breg17,
+
+ else => unreachable,
+ }
}
};