authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-12-01 16:32:09+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-12-01 16:32:09+01:00
log5bffc17c42bb6eacd0cc09a61954e98ccf912fa4
tree410cb2ab56760fd80ed04d8706fceef3fba00fdd
parent00016ab6a0bd31bed77c86074a6666822b8d0f20

codegen: make LinkerLoad a common struct shared by backends


4 files changed, 57 insertions(+), 160 deletions(-)

src/arch/aarch64/CodeGen.zig+31-145
...@@ -146,11 +146,8 @@ const MCValue = union(enum) {...@@ -146,11 +146,8 @@ const MCValue = union(enum) {
146 /// If the type is a pointer, it means the pointer address is at146 /// If the type is a pointer, it means the pointer address is at
147 /// this memory location.147 /// this memory location.
148 memory: u64,148 memory: u64,
149 /// The value is in memory but requires a linker relocation fixup:149 /// The value is in memory but requires a linker relocation fixup.
150 /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)150 linker_load: codegen.LinkerLoad,
151 /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
152 /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
153 linker_load: struct { type: enum { got, direct, import }, sym_index: u32 },
154 /// The value is one of the stack variables.151 /// The value is one of the stack variables.
155 ///152 ///
156 /// If the type is a pointer, it means the pointer address is in153 /// If the type is a pointer, it means the pointer address is in
...@@ -217,33 +214,23 @@ const DbgInfoReloc = struct {...@@ -217,33 +214,23 @@ const DbgInfoReloc = struct {
217 }214 }
218215
219 fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {216 fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
220 const name_with_null = reloc.name.ptr[0 .. reloc.name.len + 1];217 const is_ptr = switch (reloc.tag) {
221 const ty = switch (reloc.tag) {218 .dbg_var_ptr => true,
222 .dbg_var_ptr => reloc.ty.childType(),219 .dbg_var_val => false,
223 .dbg_var_val => reloc.ty,
224 else => unreachable,220 else => unreachable,
225 };221 };
226 // const atom= function.getDbgInfoAtomPtr();222 const atom = function.getDbgInfoAtomPtr();
227223
228 switch (function.debug_output) {224 switch (function.debug_output) {
229 .dwarf => |dw| {225 .dwarf => |dw| {
230 const dbg_info = &dw.dbg_info;226 const loc: link.File.Dwarf.DeclState.VarArgDbgInfoLoc = switch (reloc.mcv) {
231 try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.variable));227 .register => |reg| .{
232 const endian = function.target.cpu.arch.endian();228 .register = reg.dwarfLocOp(),
233
234 switch (reloc.mcv) {
235 .register => |reg| {
236 try dbg_info.ensureUnusedCapacity(2);
237 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
238 1, // ULEB128 dwarf expression length
239 reg.dwarfLocOp(),
240 });
241 },229 },
242
243 .ptr_stack_offset,230 .ptr_stack_offset,
244 .stack_offset,231 .stack_offset,
245 .stack_argument_offset,232 .stack_argument_offset,
246 => |offset| {233 => |offset| blk: {
247 const adjusted_offset = switch (reloc.mcv) {234 const adjusted_offset = switch (reloc.mcv) {
248 .ptr_stack_offset,235 .ptr_stack_offset,
249 .stack_offset,236 .stack_offset,
...@@ -251,110 +238,31 @@ const DbgInfoReloc = struct {...@@ -251,110 +238,31 @@ const DbgInfoReloc = struct {
251 .stack_argument_offset => @intCast(i32, function.saved_regs_stack_space + offset),238 .stack_argument_offset => @intCast(i32, function.saved_regs_stack_space + offset),
252 else => unreachable,239 else => unreachable,
253 };240 };
254241 break :blk .{
255 try dbg_info.ensureUnusedCapacity(7);242 .stack = .{
256 const fixup = dbg_info.items.len;243 .fp_register = Register.x29.dwarfLocOpDeref(),
257 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc244 .offset = adjusted_offset,
258 1, // we will backpatch it after we encode the displacement in LEB128
259 Register.x29.dwarfLocOpDeref(), // frame pointer
260 });
261 leb128.writeILEB128(dbg_info.writer(), adjusted_offset) catch unreachable;
262 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
263 },
264
265 .memory,
266 .linker_load,
267 => {
268 const ptr_width = @intCast(u8, @divExact(function.target.cpu.arch.ptrBitWidth(), 8));
269 const is_ptr = switch (reloc.tag) {
270 .dbg_var_ptr => true,
271 .dbg_var_val => false,
272 else => unreachable,
273 };
274 try dbg_info.ensureUnusedCapacity(2 + ptr_width);
275 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
276 1 + ptr_width + @boolToInt(is_ptr),
277 DW.OP.addr, // literal address
278 });
279 const offset = @intCast(u32, dbg_info.items.len);
280 const addr = switch (reloc.mcv) {
281 .memory => |addr| addr,
282 else => 0,
283 };
284 switch (ptr_width) {
285 0...4 => {
286 try dbg_info.writer().writeInt(u32, @intCast(u32, addr), endian);
287 },245 },
288 5...8 => {246 };
289 try dbg_info.writer().writeInt(u64, addr, endian);
290 },
291 else => unreachable,
292 }
293 if (is_ptr) {
294 // We need deref the address as we point to the value via GOT entry.
295 try dbg_info.append(DW.OP.deref);
296 }
297 switch (reloc.mcv) {
298 .linker_load => |load_struct| try dw.addExprlocReloc(
299 load_struct.sym_index,
300 offset,
301 is_ptr,
302 ),
303 else => {},
304 }
305 },
306
307 .immediate => |x| {
308 try dbg_info.ensureUnusedCapacity(2);
309 const fixup = dbg_info.items.len;
310 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
311 1,
312 if (ty.isSignedInt()) DW.OP.consts else DW.OP.constu,
313 });
314 if (ty.isSignedInt()) {
315 try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x));
316 } else {
317 try leb128.writeULEB128(dbg_info.writer(), x);
318 }
319 try dbg_info.append(DW.OP.stack_value);
320 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
321 },
322
323 .undef => {
324 // DW.AT.location, DW.FORM.exprloc
325 // uleb128(exprloc_len)
326 // DW.OP.implicit_value uleb128(len_of_bytes) bytes
327 const abi_size = @intCast(u32, ty.abiSize(function.target.*));
328 var implicit_value_len = std.ArrayList(u8).init(function.gpa);
329 defer implicit_value_len.deinit();
330 try leb128.writeULEB128(implicit_value_len.writer(), abi_size);
331 const total_exprloc_len = 1 + implicit_value_len.items.len + abi_size;
332 try leb128.writeULEB128(dbg_info.writer(), total_exprloc_len);
333 try dbg_info.ensureUnusedCapacity(total_exprloc_len);
334 dbg_info.appendAssumeCapacity(DW.OP.implicit_value);
335 dbg_info.appendSliceAssumeCapacity(implicit_value_len.items);
336 dbg_info.appendNTimesAssumeCapacity(0xaa, abi_size);
337 },
338
339 .none => {
340 try dbg_info.ensureUnusedCapacity(3);
341 dbg_info.appendSliceAssumeCapacity(&[3]u8{ // DW.AT.location, DW.FORM.exprloc
342 2, DW.OP.lit0, DW.OP.stack_value,
343 });
344 },247 },
345248 .memory => |address| .{ .memory = .{
346 else => {249 .address = address,
347 try dbg_info.ensureUnusedCapacity(2);250 .is_ptr = is_ptr,
348 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc251 } },
349 1, DW.OP.nop,252 .linker_load => |linker_load| .{ .memory = .{
350 });253 .address = 0,
254 .is_ptr = is_ptr,
255 .linker_load = linker_load,
256 } },
257 .immediate => |x| .{ .immediate = x },
258 .undef => .undef,
259 .none => .none,
260 else => blk: {
351 log.debug("TODO generate debug info for {}", .{reloc.mcv});261 log.debug("TODO generate debug info for {}", .{reloc.mcv});
262 break :blk .nop;
352 },263 },
353 }264 };
354265 try dw.genVarDbgInfo(reloc.name, reloc.ty, atom, loc);
355 try dbg_info.ensureUnusedCapacity(5 + name_with_null.len);
356 try function.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4
357 dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string
358 },266 },
359 .plan9 => {},267 .plan9 => {},
360 .none => {},268 .none => {},
...@@ -1071,28 +979,6 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {...@@ -1071,28 +979,6 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {
1071 try table.ensureUnusedCapacity(self.gpa, additional_count);979 try table.ensureUnusedCapacity(self.gpa, additional_count);
1072}980}
1073981
1074/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
1075/// after codegen for this symbol is done.
1076fn addDbgInfoTypeReloc(self: Self, ty: Type) !void {
1077 switch (self.debug_output) {
1078 .dwarf => |dw| {
1079 const dbg_info = &dw.dbg_info;
1080 const index = dbg_info.items.len;
1081 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
1082 const mod = self.bin_file.options.module.?;
1083 const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl);
1084 const atom = switch (self.bin_file.tag) {
1085 .elf => &fn_owner_decl.link.elf.dbg_info_atom,
1086 .macho => &fn_owner_decl.link.macho.dbg_info_atom,
1087 else => unreachable,
1088 };
1089 try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index));
1090 },
1091 .plan9 => {},
1092 .none => {},
1093 }
1094}
1095
1096fn allocMem(982fn allocMem(
1097 self: *Self,983 self: *Self,
1098 abi_size: u32,984 abi_size: u32,
src/arch/x86_64/CodeGen.zig+11-11
...@@ -128,11 +128,8 @@ pub const MCValue = union(enum) {...@@ -128,11 +128,8 @@ pub const MCValue = union(enum) {
128 /// The value is in memory at a hard-coded address.128 /// The value is in memory at a hard-coded address.
129 /// If the type is a pointer, it means the pointer address is at this memory location.129 /// If the type is a pointer, it means the pointer address is at this memory location.
130 memory: u64,130 memory: u64,
131 /// The value is in memory but requires a linker relocation fixup:131 /// The value is in memory but requires a linker relocation fixup.
132 /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)132 linker_load: codegen.LinkerLoad,
133 /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
134 /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
135 linker_load: struct { type: enum { got, direct, import }, sym_index: u32 },
136 /// The value is one of the stack variables.133 /// The value is one of the stack variables.
137 /// If the type is a pointer, it means the pointer address is in the stack at this offset.134 /// If the type is a pointer, it means the pointer address is in the stack at this offset.
138 stack_offset: i32,135 stack_offset: i32,
...@@ -3865,12 +3862,15 @@ fn genVarDbgInfo(...@@ -3865,12 +3862,15 @@ fn genVarDbgInfo(
3865 .fp_register = Register.rbp.dwarfLocOpDeref(),3862 .fp_register = Register.rbp.dwarfLocOpDeref(),
3866 .offset = -off,3863 .offset = -off,
3867 } },3864 } },
3868 .memory => |address| .{3865 .memory => |address| .{ .memory = .{
3869 .memory = .{3866 .address = address,
3870 .address = address,3867 .is_ptr = is_ptr,
3871 .is_ptr = is_ptr,3868 } },
3872 },3869 .linker_load => |linker_load| .{ .memory = .{
3873 },3870 .address = 0,
3871 .is_ptr = is_ptr,
3872 .linker_load = linker_load,
3873 } },
3874 .immediate => |x| .{ .immediate = x },3874 .immediate => |x| .{ .immediate = x },
3875 .undef => .undef,3875 .undef => .undef,
3876 .none => .none,3876 .none => .none,
src/codegen.zig+13
...@@ -68,6 +68,19 @@ pub const DebugInfoOutput = union(enum) {...@@ -68,6 +68,19 @@ pub const DebugInfoOutput = union(enum) {
68 none,68 none,
69};69};
7070
71/// Helper struct to denote that the value is in memory but requires a linker relocation fixup:
72/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
73/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
74/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
75pub const LinkerLoad = struct {
76 type: enum {
77 got,
78 direct,
79 import,
80 },
81 sym_index: u32,
82};
83
71pub fn generateFunction(84pub fn generateFunction(
72 bin_file: *link.File,85 bin_file: *link.File,
73 src_loc: Module.SrcLoc,86 src_loc: Module.SrcLoc,
src/link/Dwarf.zig+2-4
...@@ -16,6 +16,7 @@ const DW = std.dwarf;...@@ -16,6 +16,7 @@ const DW = std.dwarf;
16const File = link.File;16const File = link.File;
17const LinkBlock = File.LinkBlock;17const LinkBlock = File.LinkBlock;
18const LinkFn = File.LinkFn;18const LinkFn = File.LinkFn;
19const LinkerLoad = @import("../codegen.zig").LinkerLoad;
19const Module = @import("../Module.zig");20const Module = @import("../Module.zig");
20const Value = @import("../value.zig").Value;21const Value = @import("../value.zig").Value;
21const Type = @import("../type.zig").Type;22const Type = @import("../type.zig").Type;
...@@ -616,10 +617,7 @@ pub const DeclState = struct {...@@ -616,10 +617,7 @@ pub const DeclState = struct {
616 memory: struct {617 memory: struct {
617 address: u64,618 address: u64,
618 is_ptr: bool,619 is_ptr: bool,
619 linker_load: ?struct {620 linker_load: ?LinkerLoad = null,
620 type: enum { got, direct, import },
621 sym_index: u32,
622 } = null,
623 },621 },
624 immediate: u64,622 immediate: u64,
625 undef,623 undef,