aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-01-24 10:33:42 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-01-25 23:51:19 +0100
commit53c668d3a9dad430749cbc642d7bf8cf45eefba1 (patch)
tree38b4ab6279aa9cd396b2a6622451c78116f35dea /src/link
parent05c5bb9edd51e73c0d4a2619817fbff73b82f230 (diff)
downloadzig-53c668d3a9dad430749cbc642d7bf8cf45eefba1.tar.gz
zig-53c668d3a9dad430749cbc642d7bf8cf45eefba1.zip
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 ```
Diffstat (limited to 'src/link')
-rw-r--r--src/link/Elf.zig71
-rw-r--r--src/link/MachO.zig6
-rw-r--r--src/link/MachO/DebugSymbols.zig3
3 files changed, 60 insertions, 20 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index a7ce8d0783..2b88458bc9 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -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 {
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index d7385f1f33..cd1d197010 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -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);
diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig
index 88a27ea48f..beef0b6b2c 100644
--- a/src/link/MachO/DebugSymbols.zig
+++ b/src/link/MachO/DebugSymbols.zig
@@ -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,