mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 21:08:36 +00:00
x86_64: add DWARF encoding for vector registers
Clean up how we handle emitting of DWARF debug info for `x86_64` codegen.
This commit is contained in:
parent
02852098ee
commit
df09d9c14a
@ -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;
|
||||
|
||||
@ -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,
|
||||
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,
|
||||
.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,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user