mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 21:38:33 +00:00
stage2: add naive impl of pointer type in ELF
Augment relocation tracking mechanism to de-duplicate potential
creation of base as well as composite types while unrolling
composite types in the linker - there is still potential for
further space optimisation by moving all type information into
a separate section `.debug_types` and providing references to
entries within that section whenever required (e.g., `ref4` form).
Currently, we duplicate type definitions on a per-decl basis.
Anyhow, with this patch, an example function signature of the following
type:
```zig
fn byPtrPtr(ptr_ptr_x: **u32, ptr_x: *u32) void {
ptr_ptr_x.* = ptr_x;
}
```
will generate the following `.debug_info` for formal parameters:
```
<1><1aa>: Abbrev Number: 3 (DW_TAG_subprogram)
<1ab> DW_AT_low_pc : 0x8000197
<1b3> DW_AT_high_pc : 0x2c
<1b7> DW_AT_name : byPtrPtr
<2><1c0>: Abbrev Number: 7 (DW_TAG_formal_parameter)
<1c1> DW_AT_location : 1 byte block: 55 (DW_OP_reg5 (rdi))
<1c3> DW_AT_type : <0x1df>
<1c7> DW_AT_name : ptr_ptr_x
<2><1d1>: Abbrev Number: 7 (DW_TAG_formal_parameter)
<1d2> DW_AT_location : 1 byte block: 54 (DW_OP_reg4 (rsi))
<1d4> DW_AT_type : <0x1e4>
<1d8> DW_AT_name : ptr_x
<2><1de>: Abbrev Number: 0
<1><1df>: Abbrev Number: 5 (DW_TAG_pointer_type)
<1e0> DW_AT_type : <0x1e4>
<1><1e4>: Abbrev Number: 5 (DW_TAG_pointer_type)
<1e5> DW_AT_type : <0x1e9>
<1><1e9>: Abbrev Number: 4 (DW_TAG_base_type)
<1ea> DW_AT_encoding : 7 (unsigned)
<1eb> DW_AT_byte_size : 4
<1ec> DW_AT_name : u32
```
This commit is contained in:
parent
05c5bb9edd
commit
53c668d3a9
@ -235,7 +235,12 @@ pub const File = struct {
|
||||
};
|
||||
|
||||
/// For DWARF .debug_info.
|
||||
pub const DbgInfoTypeRelocsTable = std.HashMapUnmanaged(Type, DbgInfoTypeReloc, Type.HashContext64, std.hash_map.default_max_load_percentage);
|
||||
pub const DbgInfoTypeRelocsTable = std.ArrayHashMapUnmanaged(
|
||||
Type,
|
||||
DbgInfoTypeReloc,
|
||||
Type.HashContext32,
|
||||
true,
|
||||
);
|
||||
|
||||
/// For DWARF .debug_info.
|
||||
pub const DbgInfoTypeReloc = struct {
|
||||
|
||||
@ -783,8 +783,9 @@ pub const abbrev_compile_unit = 1;
|
||||
pub const abbrev_subprogram = 2;
|
||||
pub const abbrev_subprogram_retvoid = 3;
|
||||
pub const abbrev_base_type = 4;
|
||||
pub const abbrev_pad1 = 5;
|
||||
pub const abbrev_parameter = 6;
|
||||
pub const abbrev_ptr_type = 5;
|
||||
pub const abbrev_pad1 = 6;
|
||||
pub const abbrev_parameter = 7;
|
||||
|
||||
pub fn flush(self: *Elf, comp: *Compilation) !void {
|
||||
if (self.base.options.emit == null) {
|
||||
@ -871,9 +872,21 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
|
||||
DW.AT.byte_size,
|
||||
DW.FORM.data1,
|
||||
DW.AT.name,
|
||||
DW.FORM.string, 0, 0, // table sentinel
|
||||
abbrev_pad1, DW.TAG.unspecified_type, DW.CHILDREN.no, // header
|
||||
0, 0, // table sentinel
|
||||
DW.FORM.string,
|
||||
0,
|
||||
0, // table sentinel
|
||||
abbrev_ptr_type,
|
||||
DW.TAG.pointer_type,
|
||||
DW.CHILDREN.no, // header
|
||||
DW.AT.type,
|
||||
DW.FORM.ref4,
|
||||
0,
|
||||
0, // table sentinel
|
||||
abbrev_pad1,
|
||||
DW.TAG.unspecified_type,
|
||||
DW.CHILDREN.no, // header
|
||||
0,
|
||||
0, // table sentinel
|
||||
abbrev_parameter,
|
||||
DW.TAG.formal_parameter, DW.CHILDREN.no, // header
|
||||
DW.AT.location, DW.FORM.exprloc,
|
||||
@ -2309,8 +2322,7 @@ pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {
|
||||
}
|
||||
|
||||
fn deinitRelocs(gpa: Allocator, table: *File.DbgInfoTypeRelocsTable) void {
|
||||
var it = table.valueIterator();
|
||||
while (it.next()) |value| {
|
||||
for (table.values()) |*value| {
|
||||
value.relocs.deinit(gpa);
|
||||
}
|
||||
table.deinit(gpa);
|
||||
@ -2387,10 +2399,12 @@ fn finishUpdateDecl(
|
||||
// the buffer, so we have to do it before computing the offset, and we can't perform the actual
|
||||
// relocations yet.
|
||||
{
|
||||
var it = dbg_info_type_relocs.iterator();
|
||||
while (it.next()) |entry| {
|
||||
entry.value_ptr.off = @intCast(u32, dbg_info_buffer.items.len);
|
||||
try self.addDbgInfoType(entry.key_ptr.*, dbg_info_buffer);
|
||||
var it: usize = 0;
|
||||
while (it < dbg_info_type_relocs.count()) : (it += 1) {
|
||||
const ty = dbg_info_type_relocs.keys()[it];
|
||||
const value_ptr = dbg_info_type_relocs.getPtr(ty).?;
|
||||
value_ptr.off = @intCast(u32, dbg_info_buffer.items.len);
|
||||
try self.addDbgInfoType(ty, dbg_info_buffer, dbg_info_type_relocs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2401,8 +2415,7 @@ fn finishUpdateDecl(
|
||||
|
||||
{
|
||||
// Now that we have the offset assigned we can finally perform type relocations.
|
||||
var it = dbg_info_type_relocs.valueIterator();
|
||||
while (it.next()) |value| {
|
||||
for (dbg_info_type_relocs.values()) |value| {
|
||||
for (value.relocs.items) |off| {
|
||||
mem.writeInt(
|
||||
u32,
|
||||
@ -2706,7 +2719,14 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
|
||||
}
|
||||
|
||||
/// Asserts the type has codegen bits.
|
||||
fn addDbgInfoType(self: *Elf, ty: Type, dbg_info_buffer: *std.ArrayList(u8)) !void {
|
||||
fn addDbgInfoType(
|
||||
self: *Elf,
|
||||
ty: Type,
|
||||
dbg_info_buffer: *std.ArrayList(u8),
|
||||
dbg_info_type_relocs: *File.DbgInfoTypeRelocsTable,
|
||||
) error{OutOfMemory}!void {
|
||||
var reloc: ?struct { ty: Type, reloc: u32 } = null;
|
||||
|
||||
switch (ty.zigTypeTag()) {
|
||||
.Void => unreachable,
|
||||
.NoReturn => unreachable,
|
||||
@ -2747,11 +2767,34 @@ fn addDbgInfoType(self: *Elf, ty: Type, dbg_info_buffer: *std.ArrayList(u8)) !vo
|
||||
try dbg_info_buffer.append(abbrev_pad1);
|
||||
}
|
||||
},
|
||||
.Pointer => blk: {
|
||||
if (ty.isSlice()) {
|
||||
log.debug("TODO implement .debug_info for type '{}'", .{ty});
|
||||
try dbg_info_buffer.append(abbrev_pad1);
|
||||
break :blk;
|
||||
}
|
||||
try dbg_info_buffer.ensureUnusedCapacity(5);
|
||||
dbg_info_buffer.appendAssumeCapacity(abbrev_ptr_type);
|
||||
const index = dbg_info_buffer.items.len;
|
||||
try dbg_info_buffer.resize(index + 4); // DW.AT.type, DW.FORM.ref4
|
||||
reloc = .{ .ty = ty.childType(), .reloc = @intCast(u32, index) };
|
||||
},
|
||||
else => {
|
||||
log.debug("TODO implement .debug_info for type '{}'", .{ty});
|
||||
try dbg_info_buffer.append(abbrev_pad1);
|
||||
},
|
||||
}
|
||||
|
||||
if (reloc) |rel| {
|
||||
const gop = try dbg_info_type_relocs.getOrPut(self.base.allocator, rel.ty);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = .{
|
||||
.off = undefined,
|
||||
.relocs = .{},
|
||||
};
|
||||
}
|
||||
try gop.value_ptr.relocs.append(self.base.allocator, rel.reloc);
|
||||
}
|
||||
}
|
||||
|
||||
fn updateDeclDebugInfoAllocation(self: *Elf, text_block: *TextBlock, len: u32) !void {
|
||||
|
||||
@ -3578,8 +3578,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
|
||||
if (debug_buffers) |dbg| {
|
||||
dbg.dbg_line_buffer.deinit();
|
||||
dbg.dbg_info_buffer.deinit();
|
||||
var it = dbg.dbg_info_type_relocs.valueIterator();
|
||||
while (it.next()) |value| {
|
||||
for (dbg.dbg_info_type_relocs.values()) |*value| {
|
||||
value.relocs.deinit(self.base.allocator);
|
||||
}
|
||||
dbg.dbg_info_type_relocs.deinit(self.base.allocator);
|
||||
@ -3659,8 +3658,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
|
||||
if (debug_buffers) |dbg| {
|
||||
dbg.dbg_line_buffer.deinit();
|
||||
dbg.dbg_info_buffer.deinit();
|
||||
var it = dbg.dbg_info_type_relocs.valueIterator();
|
||||
while (it.next()) |value| {
|
||||
for (dbg.dbg_info_type_relocs.values()) |*value| {
|
||||
value.relocs.deinit(self.base.allocator);
|
||||
}
|
||||
dbg.dbg_info_type_relocs.deinit(self.base.allocator);
|
||||
|
||||
@ -1112,8 +1112,7 @@ pub fn commitDeclDebugInfo(
|
||||
|
||||
{
|
||||
// Now that we have the offset assigned we can finally perform type relocations.
|
||||
var it = dbg_info_type_relocs.valueIterator();
|
||||
while (it.next()) |value| {
|
||||
for (dbg_info_type_relocs.values()) |value| {
|
||||
for (value.relocs.items) |off| {
|
||||
mem.writeIntLittle(
|
||||
u32,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user