diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-12-01 16:32:09 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-12-01 16:32:09 +0100 |
| commit | 5bffc17c42bb6eacd0cc09a61954e98ccf912fa4 (patch) | |
| tree | 410cb2ab56760fd80ed04d8706fceef3fba00fdd | |
| parent | 00016ab6a0bd31bed77c86074a6666822b8d0f20 (diff) | |
| download | zig-5bffc17c42bb6eacd0cc09a61954e98ccf912fa4.tar.gz zig-5bffc17c42bb6eacd0cc09a61954e98ccf912fa4.zip | |
codegen: make LinkerLoad a common struct shared by backends
| -rw-r--r-- | src/arch/aarch64/CodeGen.zig | 176 | ||||
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 22 | ||||
| -rw-r--r-- | src/codegen.zig | 13 | ||||
| -rw-r--r-- | src/link/Dwarf.zig | 6 |
4 files changed, 57 insertions, 160 deletions
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index d258fe2e28..7beec57ebc 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -146,11 +146,8 @@ const MCValue = union(enum) { /// If the type is a pointer, it means the pointer address is at /// this memory location. memory: u64, - /// The value is in memory but requires a linker relocation fixup: - /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc) - /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc) - /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc) - linker_load: struct { type: enum { got, direct, import }, sym_index: u32 }, + /// The value is in memory but requires a linker relocation fixup. + linker_load: codegen.LinkerLoad, /// The value is one of the stack variables. /// /// If the type is a pointer, it means the pointer address is in @@ -217,33 +214,23 @@ const DbgInfoReloc = struct { } fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void { - const name_with_null = reloc.name.ptr[0 .. reloc.name.len + 1]; - const ty = switch (reloc.tag) { - .dbg_var_ptr => reloc.ty.childType(), - .dbg_var_val => reloc.ty, + const is_ptr = switch (reloc.tag) { + .dbg_var_ptr => true, + .dbg_var_val => false, else => unreachable, }; - // const atom= function.getDbgInfoAtomPtr(); + const atom = function.getDbgInfoAtomPtr(); switch (function.debug_output) { .dwarf => |dw| { - const dbg_info = &dw.dbg_info; - try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.variable)); - const endian = function.target.cpu.arch.endian(); - - switch (reloc.mcv) { - .register => |reg| { - try dbg_info.ensureUnusedCapacity(2); - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, // ULEB128 dwarf expression length - reg.dwarfLocOp(), - }); + const loc: link.File.Dwarf.DeclState.VarArgDbgInfoLoc = switch (reloc.mcv) { + .register => |reg| .{ + .register = reg.dwarfLocOp(), }, - .ptr_stack_offset, .stack_offset, .stack_argument_offset, - => |offset| { + => |offset| blk: { const adjusted_offset = switch (reloc.mcv) { .ptr_stack_offset, .stack_offset, @@ -251,110 +238,31 @@ const DbgInfoReloc = struct { .stack_argument_offset => @intCast(i32, function.saved_regs_stack_space + offset), else => unreachable, }; - - 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 - Register.x29.dwarfLocOpDeref(), // frame pointer - }); - leb128.writeILEB128(dbg_info.writer(), adjusted_offset) catch unreachable; - dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); - }, - - .memory, - .linker_load, - => { - const ptr_width = @intCast(u8, @divExact(function.target.cpu.arch.ptrBitWidth(), 8)); - const is_ptr = switch (reloc.tag) { - .dbg_var_ptr => true, - .dbg_var_val => false, - else => unreachable, - }; - try dbg_info.ensureUnusedCapacity(2 + ptr_width); - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1 + ptr_width + @boolToInt(is_ptr), - DW.OP.addr, // literal address - }); - const offset = @intCast(u32, dbg_info.items.len); - const addr = switch (reloc.mcv) { - .memory => |addr| addr, - else => 0, - }; - switch (ptr_width) { - 0...4 => { - try dbg_info.writer().writeInt(u32, @intCast(u32, addr), endian); + break :blk .{ + .stack = .{ + .fp_register = Register.x29.dwarfLocOpDeref(), + .offset = adjusted_offset, }, - 5...8 => { - try dbg_info.writer().writeInt(u64, addr, endian); - }, - else => unreachable, - } - if (is_ptr) { - // We need deref the address as we point to the value via GOT entry. - try dbg_info.append(DW.OP.deref); - } - switch (reloc.mcv) { - .linker_load => |load_struct| try dw.addExprlocReloc( - load_struct.sym_index, - offset, - is_ptr, - ), - else => {}, - } - }, - - .immediate => |x| { - try dbg_info.ensureUnusedCapacity(2); - const fixup = dbg_info.items.len; - dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc - 1, - if (ty.isSignedInt()) DW.OP.consts else DW.OP.constu, - }); - 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) - // DW.OP.implicit_value uleb128(len_of_bytes) bytes - const abi_size = @intCast(u32, ty.abiSize(function.target.*)); - var implicit_value_len = std.ArrayList(u8).init(function.gpa); - defer implicit_value_len.deinit(); - try leb128.writeULEB128(implicit_value_len.writer(), abi_size); - const total_exprloc_len = 1 + implicit_value_len.items.len + abi_size; - try leb128.writeULEB128(dbg_info.writer(), total_exprloc_len); - try dbg_info.ensureUnusedCapacity(total_exprloc_len); - dbg_info.appendAssumeCapacity(DW.OP.implicit_value); - 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 - 1, DW.OP.nop, - }); + .memory => |address| .{ .memory = .{ + .address = address, + .is_ptr = is_ptr, + } }, + .linker_load => |linker_load| .{ .memory = .{ + .address = 0, + .is_ptr = is_ptr, + .linker_load = linker_load, + } }, + .immediate => |x| .{ .immediate = x }, + .undef => .undef, + .none => .none, + else => blk: { log.debug("TODO generate debug info for {}", .{reloc.mcv}); + break :blk .nop; }, - } - - try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); - try function.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 - dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string + }; + try dw.genVarDbgInfo(reloc.name, reloc.ty, atom, loc); }, .plan9 => {}, .none => {}, @@ -1071,28 +979,6 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { try table.ensureUnusedCapacity(self.gpa, additional_count); } -/// 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 { - switch (self.debug_output) { - .dwarf => |dw| { - const dbg_info = &dw.dbg_info; - const index = dbg_info.items.len; - try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 - const mod = self.bin_file.options.module.?; - const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); - const atom = switch (self.bin_file.tag) { - .elf => &fn_owner_decl.link.elf.dbg_info_atom, - .macho => &fn_owner_decl.link.macho.dbg_info_atom, - else => unreachable, - }; - try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); - }, - .plan9 => {}, - .none => {}, - } -} - fn allocMem( self: *Self, abi_size: u32, diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index f15f394f8c..8b3ae1e606 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -128,11 +128,8 @@ pub const MCValue = union(enum) { /// The value is in memory at a hard-coded address. /// If the type is a pointer, it means the pointer address is at this memory location. memory: u64, - /// The value is in memory but requires a linker relocation fixup: - /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc) - /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc) - /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc) - linker_load: struct { type: enum { got, direct, import }, sym_index: u32 }, + /// The value is in memory but requires a linker relocation fixup. + linker_load: codegen.LinkerLoad, /// The value is one of the stack variables. /// If the type is a pointer, it means the pointer address is in the stack at this offset. stack_offset: i32, @@ -3865,12 +3862,15 @@ fn genVarDbgInfo( .fp_register = Register.rbp.dwarfLocOpDeref(), .offset = -off, } }, - .memory => |address| .{ - .memory = .{ - .address = address, - .is_ptr = is_ptr, - }, - }, + .memory => |address| .{ .memory = .{ + .address = address, + .is_ptr = is_ptr, + } }, + .linker_load => |linker_load| .{ .memory = .{ + .address = 0, + .is_ptr = is_ptr, + .linker_load = linker_load, + } }, .immediate => |x| .{ .immediate = x }, .undef => .undef, .none => .none, diff --git a/src/codegen.zig b/src/codegen.zig index 5a28ce1860..d6b2ed7d93 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -68,6 +68,19 @@ pub const DebugInfoOutput = union(enum) { none, }; +/// Helper struct to denote that the value is in memory but requires a linker relocation fixup: +/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc) +/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc) +/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc) +pub const LinkerLoad = struct { + type: enum { + got, + direct, + import, + }, + sym_index: u32, +}; + pub fn generateFunction( bin_file: *link.File, src_loc: Module.SrcLoc, diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 31b7d5b6e6..2c5a948d98 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -16,6 +16,7 @@ const DW = std.dwarf; const File = link.File; const LinkBlock = File.LinkBlock; const LinkFn = File.LinkFn; +const LinkerLoad = @import("../codegen.zig").LinkerLoad; const Module = @import("../Module.zig"); const Value = @import("../value.zig").Value; const Type = @import("../type.zig").Type; @@ -616,10 +617,7 @@ pub const DeclState = struct { memory: struct { address: u64, is_ptr: bool, - linker_load: ?struct { - type: enum { got, direct, import }, - sym_index: u32, - } = null, + linker_load: ?LinkerLoad = null, }, immediate: u64, undef, |
