authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-08-20 15:07:47-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-08-20 15:08:23-04:00
log55864e98e08c9d44ee2ea6fc1f3a3c2a98042310
tree78344089f8c4cc2bdc07ea74f0a47b8f500d2fcb
parenteaa227449c894a9205d63c2e963b967d13446591

x86_64: support more dwarf locations


6 files changed, 374 insertions(+), 273 deletions(-)

src/arch/x86_64/CodeGen.zig+172-140
......@@ -64,8 +64,8 @@ va_info: union {
6464 sysv: struct {
6565 gp_count: u32,
6666 fp_count: u32,
67 overflow_arg_area: FrameAddr,
68 reg_save_area: FrameAddr,
67 overflow_arg_area: bits.FrameAddr,
68 reg_save_area: bits.FrameAddr,
6969 },
7070 win64: struct {},
7171},
......@@ -110,10 +110,6 @@ air_bookkeeping: @TypeOf(air_bookkeeping_init) = air_bookkeeping_init,
110110
111111const air_bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {};
112112
113const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
114const RegisterOffset = struct { reg: Register, off: i32 = 0 };
115const SymbolOffset = struct { sym: u32, off: i32 = 0 };
116
117113const Owner = union(enum) {
118114 nav_index: InternPool.Nav.Index,
119115 lazy_sym: link.File.LazySymbol,
......@@ -171,7 +167,7 @@ pub const MCValue = union(enum) {
171167 /// The value is split across two registers.
172168 register_pair: [2]Register,
173169 /// The value is a constant offset from the value in a register.
174 register_offset: RegisterOffset,
170 register_offset: bits.RegisterOffset,
175171 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.
176172 register_overflow: struct { reg: Register, eflags: Condition },
177173 /// The value is in memory at a hard-coded address.
......@@ -179,11 +175,11 @@ pub const MCValue = union(enum) {
179175 memory: u64,
180176 /// The value is in memory at an address not-yet-allocated by the linker.
181177 /// This traditionally corresponds to a relocation emitted in a relocatable object file.
182 load_symbol: SymbolOffset,
178 load_symbol: bits.SymbolOffset,
183179 /// The address of the memory location not-yet-allocated by the linker.
184 lea_symbol: SymbolOffset,
180 lea_symbol: bits.SymbolOffset,
185181 /// The value is in memory at a constant offset from the address in a register.
186 indirect: RegisterOffset,
182 indirect: bits.RegisterOffset,
187183 /// The value is in memory.
188184 /// Payload is a symbol index.
189185 load_direct: u32,
......@@ -204,10 +200,10 @@ pub const MCValue = union(enum) {
204200 lea_tlv: u32,
205201 /// The value stored at an offset from a frame index
206202 /// Payload is a frame address.
207 load_frame: FrameAddr,
203 load_frame: bits.FrameAddr,
208204 /// The address of an offset from a frame index
209205 /// Payload is a frame address.
210 lea_frame: FrameAddr,
206 lea_frame: bits.FrameAddr,
211207 /// Supports integer_per_element abi
212208 elementwise_regs_then_frame: packed struct { regs: u3 = 0, frame_off: i29 = 0, frame_index: FrameIndex },
213209 /// This indicates that we have already allocated a frame index for this instruction,
......@@ -423,10 +419,7 @@ pub const MCValue = union(enum) {
423419 .load_symbol => |sym_off| {
424420 assert(sym_off.off == 0);
425421 return .{
426 .base = .{ .reloc = .{
427 .atom_index = try function.owner.getSymbolIndex(function),
428 .sym_index = sym_off.sym,
429 } },
422 .base = .{ .reloc = sym_off.sym_index },
430423 .mod = .{ .rm = .{
431424 .size = size,
432425 .disp = sym_off.off,
......@@ -453,8 +446,8 @@ pub const MCValue = union(enum) {
453446 .register_overflow => |pl| try writer.print("{s}:{s}", .{
454447 @tagName(pl.eflags), @tagName(pl.reg),
455448 }),
456 .load_symbol => |pl| try writer.print("[{} + 0x{x}]", .{ pl.sym, pl.off }),
457 .lea_symbol => |pl| try writer.print("{} + 0x{x}", .{ pl.sym, pl.off }),
449 .load_symbol => |pl| try writer.print("[{} + 0x{x}]", .{ pl.sym_index, pl.off }),
450 .lea_symbol => |pl| try writer.print("{} + 0x{x}", .{ pl.sym_index, pl.off }),
458451 .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
459452 .load_direct => |pl| try writer.print("[direct:{d}]", .{pl}),
460453 .lea_direct => |pl| try writer.print("direct:{d}", .{pl}),
......@@ -921,6 +914,13 @@ pub fn generate(
921914 .link_mode = comp.config.link_mode,
922915 .pic = mod.pic,
923916 },
917 .atom_index = function.owner.getSymbolIndex(&function) catch |err| switch (err) {
918 error.CodegenFail => return Result{ .fail = function.err_msg.? },
919 error.OutOfRegisters => return Result{
920 .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
921 },
922 else => |e| return e,
923 },
924924 .debug_output = debug_output,
925925 .code = code,
926926 .prev_di_pc = 0,
......@@ -1019,6 +1019,13 @@ pub fn generateLazy(
10191019 .link_mode = comp.config.link_mode,
10201020 .pic = mod.pic,
10211021 },
1022 .atom_index = function.owner.getSymbolIndex(&function) catch |err| switch (err) {
1023 error.CodegenFail => return Result{ .fail = function.err_msg.? },
1024 error.OutOfRegisters => return Result{
1025 .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
1026 },
1027 else => |e| return e,
1028 },
10221029 .debug_output = debug_output,
10231030 .code = code,
10241031 .prev_di_pc = undefined, // no debug info yet
......@@ -1192,6 +1199,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
11921199 self.mir_extra.appendAssumeCapacity(switch (field.type) {
11931200 u32 => @field(extra, field.name),
11941201 i32, Mir.Memory.Info => @bitCast(@field(extra, field.name)),
1202 bits.FrameIndex => @intFromEnum(@field(extra, field.name)),
11951203 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
11961204 });
11971205 }
......@@ -1358,26 +1366,94 @@ fn asmAir(self: *Self, tag: MirTagAir, inst: Air.Inst.Index) !void {
13581366}
13591367
13601368fn asmAirImmediate(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, imm: Immediate) !void {
1361 const ops: Mir.Inst.Ops, const i: u32 = switch (imm) {
1362 .signed => |s| .{ switch (tag) {
1363 .dbg_local => .pseudo_dbg_local_ai_s,
1364 }, @bitCast(s) },
1365 .unsigned => |u| if (math.cast(u32, u)) |small|
1366 .{ switch (tag) {
1369 switch (imm) {
1370 .signed => |s| _ = try self.addInst(.{
1371 .tag = .pseudo,
1372 .ops = switch (tag) {
1373 .dbg_local => .pseudo_dbg_local_ai_s,
1374 },
1375 .data = .{ .ai = .{
1376 .air_inst = inst,
1377 .i = @bitCast(s),
1378 } },
1379 }),
1380 .unsigned => |u| _ = if (math.cast(u32, u)) |small| try self.addInst(.{
1381 .tag = .pseudo,
1382 .ops = switch (tag) {
13671383 .dbg_local => .pseudo_dbg_local_ai_u,
1368 }, small }
1369 else
1370 .{ switch (tag) {
1384 },
1385 .data = .{ .ai = .{
1386 .air_inst = inst,
1387 .i = small,
1388 } },
1389 }) else try self.addInst(.{
1390 .tag = .pseudo,
1391 .ops = switch (tag) {
13711392 .dbg_local => .pseudo_dbg_local_ai_64,
1372 }, try self.addExtra(Mir.Imm64.encode(u)) },
1373 .reloc => unreachable,
1374 };
1393 },
1394 .data = .{ .ai = .{
1395 .air_inst = inst,
1396 .i = try self.addExtra(Mir.Imm64.encode(u)),
1397 } },
1398 }),
1399 .reloc => |sym_off| _ = if (sym_off.off == 0) try self.addInst(.{
1400 .tag = .pseudo,
1401 .ops = switch (tag) {
1402 .dbg_local => .pseudo_dbg_local_as,
1403 },
1404 .data = .{ .as = .{
1405 .air_inst = inst,
1406 .sym_index = sym_off.sym_index,
1407 } },
1408 }) else try self.addInst(.{
1409 .tag = .pseudo,
1410 .ops = switch (tag) {
1411 .dbg_local => .pseudo_dbg_local_aso,
1412 },
1413 .data = .{ .ax = .{
1414 .air_inst = inst,
1415 .payload = try self.addExtra(sym_off),
1416 } },
1417 }),
1418 }
1419}
1420
1421fn asmAirRegisterImmediate(
1422 self: *Self,
1423 tag: MirTagAir,
1424 inst: Air.Inst.Index,
1425 reg: Register,
1426 imm: Immediate,
1427) !void {
13751428 _ = try self.addInst(.{
13761429 .tag = .pseudo,
1377 .ops = ops,
1378 .data = .{ .ai = .{
1430 .ops = switch (tag) {
1431 .dbg_local => .pseudo_dbg_local_aro,
1432 },
1433 .data = .{ .rx = .{
1434 .r1 = reg,
1435 .payload = try self.addExtra(Mir.AirOffset{
1436 .air_inst = inst,
1437 .off = imm.signed,
1438 }),
1439 } },
1440 });
1441}
1442
1443fn asmAirFrameAddress(
1444 self: *Self,
1445 tag: MirTagAir,
1446 inst: Air.Inst.Index,
1447 frame_addr: bits.FrameAddr,
1448) !void {
1449 _ = try self.addInst(.{
1450 .tag = .pseudo,
1451 .ops = switch (tag) {
1452 .dbg_local => .pseudo_dbg_local_af,
1453 },
1454 .data = .{ .ax = .{
13791455 .air_inst = inst,
1380 .i = i,
1456 .payload = try self.addExtra(frame_addr),
13811457 } },
13821458 });
13831459}
......@@ -1433,9 +1509,9 @@ fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void {
14331509 .reloc => .rel,
14341510 },
14351511 .data = switch (imm) {
1436 .reloc => |x| reloc: {
1512 .reloc => |sym_off| reloc: {
14371513 assert(tag[0] == ._);
1438 break :reloc .{ .reloc = x };
1514 break :reloc .{ .reloc = sym_off };
14391515 },
14401516 .signed, .unsigned => .{ .i = .{
14411517 .fixes = tag[0],
......@@ -2515,12 +2591,12 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo
25152591 };
25162592}
25172593
2518fn getFrameAddrAlignment(self: *Self, frame_addr: FrameAddr) Alignment {
2594fn getFrameAddrAlignment(self: *Self, frame_addr: bits.FrameAddr) Alignment {
25192595 const alloc_align = self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_align;
25202596 return @enumFromInt(@min(@intFromEnum(alloc_align), @ctz(frame_addr.off)));
25212597}
25222598
2523fn getFrameAddrSize(self: *Self, frame_addr: FrameAddr) u32 {
2599fn getFrameAddrSize(self: *Self, frame_addr: bits.FrameAddr) u32 {
25242600 return self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_size - @as(u31, @intCast(frame_addr.off));
25252601}
25262602
......@@ -11999,6 +12075,8 @@ fn genLocalDebugInfo(
1199912075 .none => try self.asmAir(.dbg_local, inst),
1200012076 .unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
1200112077 .immediate => |imm| try self.asmAirImmediate(.dbg_local, inst, Immediate.u(imm)),
12078 .lea_frame => |frame_addr| try self.asmAirFrameAddress(.dbg_local, inst, frame_addr),
12079 .lea_symbol => |sym_off| try self.asmAirImmediate(.dbg_local, inst, Immediate.rel(sym_off)),
1200212080 else => {
1200312081 const ty = switch (tag) {
1200412082 else => unreachable,
......@@ -12027,14 +12105,14 @@ fn genLocalDebugInfo(
1202712105 } },
1202812106 }),
1202912107 .lea_symbol => |sym_off| try self.asmAirMemory(.dbg_local, inst, .{
12030 .base = .{ .reloc = .{ .atom_index = undefined, .sym_index = sym_off.sym } },
12108 .base = .{ .reloc = sym_off.sym_index },
1203112109 .mod = .{ .rm = .{
1203212110 .size = .qword,
1203312111 .disp = sym_off.off,
1203412112 } },
1203512113 }),
12036 .lea_direct, .lea_got, .lea_tlv => |sym| try self.asmAirMemory(.dbg_local, inst, .{
12037 .base = .{ .reloc = .{ .atom_index = undefined, .sym_index = sym } },
12114 .lea_direct, .lea_got, .lea_tlv => |sym_index| try self.asmAirMemory(.dbg_local, inst, .{
12115 .base = .{ .reloc = sym_index },
1203812116 .mod = .{ .rm = .{ .size = .qword } },
1203912117 }),
1204012118 },
......@@ -12357,10 +12435,7 @@ fn genCall(self: *Self, info: union(enum) {
1235712435 if (self.bin_file.cast(.elf)) |elf_file| {
1235812436 const zo = elf_file.zigObjectPtr().?;
1235912437 const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
12360 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
12361 .atom_index = try self.owner.getSymbolIndex(self),
12362 .sym_index = sym_index,
12363 }));
12438 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index }));
1236412439 } else if (self.bin_file.cast(.coff)) |coff_file| {
1236512440 const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
1236612441 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
......@@ -12370,10 +12445,7 @@ fn genCall(self: *Self, info: union(enum) {
1237012445 const zo = macho_file.getZigObject().?;
1237112446 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);
1237212447 const sym = zo.symbols.items[sym_index];
12373 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
12374 .atom_index = try self.owner.getSymbolIndex(self),
12375 .sym_index = sym.nlist_idx,
12376 }));
12448 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym.nlist_idx }));
1237712449 } else if (self.bin_file.cast(.plan9)) |p9| {
1237812450 const atom_index = try p9.seeNav(pt, func.owner_nav);
1237912451 const atom = p9.getAtom(atom_index);
......@@ -12391,19 +12463,13 @@ fn genCall(self: *Self, info: union(enum) {
1239112463 @"extern".name.toSlice(ip),
1239212464 @"extern".lib_name.toSlice(ip),
1239312465 );
12394 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
12395 .atom_index = try self.owner.getSymbolIndex(self),
12396 .sym_index = target_sym_index,
12397 }));
12466 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
1239812467 } else if (self.bin_file.cast(.macho)) |macho_file| {
1239912468 const target_sym_index = try macho_file.getGlobalSymbol(
1240012469 @"extern".name.toSlice(ip),
1240112470 @"extern".lib_name.toSlice(ip),
1240212471 );
12403 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
12404 .atom_index = try self.owner.getSymbolIndex(self),
12405 .sym_index = target_sym_index,
12406 }));
12472 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
1240712473 } else try self.genExternSymbolRef(
1240812474 .call,
1240912475 @"extern".lib_name.toSlice(ip),
......@@ -12418,16 +12484,10 @@ fn genCall(self: *Self, info: union(enum) {
1241812484 },
1241912485 .lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {
1242012486 const target_sym_index = try elf_file.getGlobalSymbol(lib.callee, lib.lib);
12421 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
12422 .atom_index = try self.owner.getSymbolIndex(self),
12423 .sym_index = target_sym_index,
12424 }));
12487 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
1242512488 } else if (self.bin_file.cast(.macho)) |macho_file| {
1242612489 const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib);
12427 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
12428 .atom_index = try self.owner.getSymbolIndex(self),
12429 .sym_index = target_sym_index,
12430 }));
12490 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
1243112491 } else try self.genExternSymbolRef(.call, lib.lib, lib.callee),
1243212492 }
1243312493 return call_info.return_value.short;
......@@ -14968,10 +15028,7 @@ fn genSetReg(
1496815028 .general_purpose => {
1496915029 assert(sym_off.off == 0);
1497015030 try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(dst_reg, abi_size), .{
14971 .base = .{ .reloc = .{
14972 .atom_index = try self.owner.getSymbolIndex(self),
14973 .sym_index = sym_off.sym,
14974 } },
15031 .base = .{ .reloc = sym_off.sym_index },
1497515032 .mod = .{ .rm = .{
1497615033 .size = self.memSize(ty),
1497715034 .disp = sym_off.off,
......@@ -14989,10 +15046,7 @@ fn genSetReg(
1498915046 .ops = .direct_reloc,
1499015047 .data = .{ .rx = .{
1499115048 .r1 = registerAlias(dst_reg, abi_size),
14992 .payload = try self.addExtra(bits.Symbol{
14993 .atom_index = try self.owner.getSymbolIndex(self),
14994 .sym_index = sym_index,
14995 }),
15049 .payload = try self.addExtra(bits.SymbolOffset{ .sym_index = sym_index }),
1499615050 } },
1499715051 });
1499815052 return;
......@@ -15017,52 +15071,38 @@ fn genSetReg(
1501715071 },
1501815072 );
1501915073 },
15020 .lea_symbol => |sym_index| {
15021 const atom_index = try self.owner.getSymbolIndex(self);
15022 switch (self.bin_file.tag) {
15023 .elf, .macho => {
15024 try self.asmRegisterMemory(
15025 .{ ._, .lea },
15026 dst_reg.to64(),
15027 .{
15028 .base = .{ .reloc = .{
15029 .atom_index = atom_index,
15030 .sym_index = sym_index.sym,
15031 } },
15032 .mod = .{ .rm = .{
15033 .size = .qword,
15034 .disp = sym_index.off,
15035 } },
15036 },
15037 );
15038 },
15039 else => return self.fail("TODO emit symbol sequence on {s}", .{
15040 @tagName(self.bin_file.tag),
15041 }),
15042 }
15043 },
15044 .lea_direct, .lea_got => |sym_index| {
15045 const atom_index = try self.owner.getSymbolIndex(self);
15046 _ = try self.addInst(.{
15047 .tag = switch (src_mcv) {
15048 .lea_direct => .lea,
15049 .lea_got => .mov,
15050 else => unreachable,
15051 },
15052 .ops = switch (src_mcv) {
15053 .lea_direct => .direct_reloc,
15054 .lea_got => .got_reloc,
15055 else => unreachable,
15074 .lea_symbol => |sym_off| switch (self.bin_file.tag) {
15075 .elf, .macho => try self.asmRegisterMemory(
15076 .{ ._, .lea },
15077 dst_reg.to64(),
15078 .{
15079 .base = .{ .reloc = sym_off.sym_index },
15080 .mod = .{ .rm = .{
15081 .size = .qword,
15082 .disp = sym_off.off,
15083 } },
1505615084 },
15057 .data = .{ .rx = .{
15058 .r1 = dst_reg.to64(),
15059 .payload = try self.addExtra(bits.Symbol{
15060 .atom_index = atom_index,
15061 .sym_index = sym_index,
15062 }),
15063 } },
15064 });
15085 ),
15086 else => return self.fail("TODO emit symbol sequence on {s}", .{
15087 @tagName(self.bin_file.tag),
15088 }),
1506515089 },
15090 .lea_direct, .lea_got => |sym_index| _ = try self.addInst(.{
15091 .tag = switch (src_mcv) {
15092 .lea_direct => .lea,
15093 .lea_got => .mov,
15094 else => unreachable,
15095 },
15096 .ops = switch (src_mcv) {
15097 .lea_direct => .direct_reloc,
15098 .lea_got => .got_reloc,
15099 else => unreachable,
15100 },
15101 .data = .{ .rx = .{
15102 .r1 = dst_reg.to64(),
15103 .payload = try self.addExtra(bits.SymbolOffset{ .sym_index = sym_index }),
15104 } },
15105 }),
1506615106 .lea_tlv => unreachable, // TODO: remove this
1506715107 .air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref), opts),
1506815108 }
......@@ -15083,7 +15123,7 @@ fn genSetMem(
1508315123 .none => .{ .immediate = @bitCast(@as(i64, disp)) },
1508415124 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
1508515125 .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },
15086 .reloc => |base_symbol| .{ .lea_symbol = .{ .sym = base_symbol.sym_index, .off = disp } },
15126 .reloc => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index, .off = disp } },
1508715127 };
1508815128 switch (src_mcv) {
1508915129 .none,
......@@ -15326,7 +15366,6 @@ fn genExternSymbolRef(
1532615366 lib: ?[]const u8,
1532715367 callee: []const u8,
1532815368) InnerError!void {
15329 const atom_index = try self.owner.getSymbolIndex(self);
1533015369 if (self.bin_file.cast(.coff)) |coff_file| {
1533115370 const global_index = try coff_file.getGlobalSymbol(callee, lib);
1533215371 _ = try self.addInst(.{
......@@ -15334,8 +15373,7 @@ fn genExternSymbolRef(
1533415373 .ops = .import_reloc,
1533515374 .data = .{ .rx = .{
1533615375 .r1 = .rax,
15337 .payload = try self.addExtra(bits.Symbol{
15338 .atom_index = atom_index,
15376 .payload = try self.addExtra(bits.SymbolOffset{
1533915377 .sym_index = link.File.Coff.global_symbol_bit | global_index,
1534015378 }),
1534115379 } },
......@@ -15362,10 +15400,10 @@ fn genLazySymbolRef(
1536215400 if (self.mod.pic) {
1536315401 switch (tag) {
1536415402 .lea, .call => try self.genSetReg(reg, Type.usize, .{
15365 .lea_symbol = .{ .sym = sym_index },
15403 .lea_symbol = .{ .sym_index = sym_index },
1536615404 }, .{}),
1536715405 .mov => try self.genSetReg(reg, Type.usize, .{
15368 .load_symbol = .{ .sym = sym_index },
15406 .load_symbol = .{ .sym_index = sym_index },
1536915407 }, .{}),
1537015408 else => unreachable,
1537115409 }
......@@ -15374,19 +15412,13 @@ fn genLazySymbolRef(
1537415412 .call => try self.asmRegister(.{ ._, .call }, reg),
1537515413 else => unreachable,
1537615414 }
15377 } else {
15378 const reloc = bits.Symbol{
15379 .atom_index = try self.owner.getSymbolIndex(self),
15380 .sym_index = sym_index,
15381 };
15382 switch (tag) {
15383 .lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{
15384 .base = .{ .reloc = reloc },
15385 .mod = .{ .rm = .{ .size = .qword } },
15386 }),
15387 .call => try self.asmImmediate(.{ ._, .call }, Immediate.rel(reloc)),
15388 else => unreachable,
15389 }
15415 } else switch (tag) {
15416 .lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{
15417 .base = .{ .reloc = sym_index },
15418 .mod = .{ .rm = .{ .size = .qword } },
15419 }),
15420 .call => try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index })),
15421 else => unreachable,
1539015422 }
1539115423 } else if (self.bin_file.cast(.plan9)) |p9_file| {
1539215424 const atom_index = p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
......@@ -15436,10 +15468,10 @@ fn genLazySymbolRef(
1543615468 const sym = zo.symbols.items[sym_index];
1543715469 switch (tag) {
1543815470 .lea, .call => try self.genSetReg(reg, Type.usize, .{
15439 .lea_symbol = .{ .sym = sym.nlist_idx },
15471 .lea_symbol = .{ .sym_index = sym.nlist_idx },
1544015472 }, .{}),
1544115473 .mov => try self.genSetReg(reg, Type.usize, .{
15442 .load_symbol = .{ .sym = sym.nlist_idx },
15474 .load_symbol = .{ .sym_index = sym.nlist_idx },
1544315475 }, .{}),
1544415476 else => unreachable,
1544515477 }
......@@ -18784,7 +18816,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
1878418816 .{ .frame = frame_index },
1878518817 0,
1878618818 Type.usize,
18787 .{ .lea_symbol = .{ .sym = tlv_sym } },
18819 .{ .lea_symbol = .{ .sym_index = tlv_sym } },
1878818820 .{},
1878918821 );
1879018822 break :init .{ .load_frame = .{ .index = frame_index } };
......@@ -18840,8 +18872,8 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
1884018872 .undef => .undef,
1884118873 .immediate => |imm| .{ .immediate = imm },
1884218874 .memory => |addr| .{ .memory = addr },
18843 .load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },
18844 .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym = sym_index } },
18875 .load_symbol => |sym_index| .{ .load_symbol = .{ .sym_index = sym_index } },
18876 .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index } },
1884518877 .load_direct => |sym_index| .{ .load_direct = sym_index },
1884618878 .lea_direct => |sym_index| .{ .lea_direct = sym_index },
1884718879 .load_got => |sym_index| .{ .lea_got = sym_index },
src/arch/x86_64/Emit.zig+108-49
......@@ -2,6 +2,7 @@
22
33air: Air,
44lower: Lower,
5atom_index: u32,
56debug_output: DebugInfoOutput,
67code: *std.ArrayList(u8),
78
......@@ -37,83 +38,84 @@ pub fn emitMir(emit: *Emit) Error!void {
3738 }) switch (lowered_relocs[0].target) {
3839 .inst => |target| try emit.relocs.append(emit.lower.allocator, .{
3940 .source = start_offset,
41 .source_offset = end_offset - 4,
4042 .target = target,
41 .offset = end_offset - 4,
43 .target_offset = lowered_relocs[0].off,
4244 .length = @intCast(end_offset - start_offset),
4345 }),
44 .linker_extern_fn => |symbol| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
46 .linker_extern_fn => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
4547 // Add relocation to the decl.
4648 const zo = elf_file.zigObjectPtr().?;
47 const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?;
49 const atom_ptr = zo.symbol(emit.atom_index).atom(elf_file).?;
4850 const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);
4951 try atom_ptr.addReloc(elf_file, .{
5052 .r_offset = end_offset - 4,
51 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,
52 .r_addend = -4,
53 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
54 .r_addend = lowered_relocs[0].off - 4,
5355 });
5456 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
5557 // Add relocation to the decl.
5658 const zo = macho_file.getZigObject().?;
57 const atom = zo.symbols.items[symbol.atom_index].getAtom(macho_file).?;
59 const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
5860 try atom.addReloc(macho_file, .{
5961 .tag = .@"extern",
6062 .offset = end_offset - 4,
61 .target = symbol.sym_index,
62 .addend = 0,
63 .target = sym_index,
64 .addend = lowered_relocs[0].off,
6365 .type = .branch,
6466 .meta = .{
6567 .pcrel = true,
6668 .has_subtractor = false,
6769 .length = 2,
68 .symbolnum = @intCast(symbol.sym_index),
70 .symbolnum = @intCast(sym_index),
6971 },
7072 });
7173 } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
7274 // Add relocation to the decl.
7375 const atom_index = coff_file.getAtomIndexForSymbol(
74 .{ .sym_index = symbol.atom_index, .file = null },
76 .{ .sym_index = emit.atom_index, .file = null },
7577 ).?;
76 const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)
77 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)
78 const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
79 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
7880 else
79 link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };
81 link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
8082 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
8183 .type = .direct,
8284 .target = target,
8385 .offset = end_offset - 4,
84 .addend = 0,
86 .addend = @intCast(lowered_relocs[0].off),
8587 .pcrel = true,
8688 .length = 2,
8789 });
8890 } else return emit.fail("TODO implement extern reloc for {s}", .{
8991 @tagName(emit.lower.bin_file.tag),
9092 }),
91 .linker_tlsld => |data| {
93 .linker_tlsld => |sym_index| {
9294 const elf_file = emit.lower.bin_file.cast(.elf).?;
9395 const zo = elf_file.zigObjectPtr().?;
94 const atom = zo.symbol(data.atom_index).atom(elf_file).?;
96 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
9597 const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);
9698 try atom.addReloc(elf_file, .{
9799 .r_offset = end_offset - 4,
98 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
99 .r_addend = -4,
100 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
101 .r_addend = lowered_relocs[0].off - 4,
100102 });
101103 },
102 .linker_dtpoff => |data| {
104 .linker_dtpoff => |sym_index| {
103105 const elf_file = emit.lower.bin_file.cast(.elf).?;
104106 const zo = elf_file.zigObjectPtr().?;
105 const atom = zo.symbol(data.atom_index).atom(elf_file).?;
107 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
106108 const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);
107109 try atom.addReloc(elf_file, .{
108110 .r_offset = end_offset - 4,
109 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
110 .r_addend = 0,
111 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
112 .r_addend = lowered_relocs[0].off,
111113 });
112114 },
113 .linker_reloc => |data| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
115 .linker_reloc => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
114116 const zo = elf_file.zigObjectPtr().?;
115 const atom = zo.symbol(data.atom_index).atom(elf_file).?;
116 const sym = zo.symbol(data.sym_index);
117 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
118 const sym = zo.symbol(sym_index);
117119 if (emit.lower.pic) {
118120 const r_type: u32 = if (sym.flags.is_extern_ptr)
119121 @intFromEnum(std.elf.R_X86_64.GOTPCREL)
......@@ -121,8 +123,8 @@ pub fn emitMir(emit: *Emit) Error!void {
121123 @intFromEnum(std.elf.R_X86_64.PC32);
122124 try atom.addReloc(elf_file, .{
123125 .r_offset = end_offset - 4,
124 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
125 .r_addend = -4,
126 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
127 .r_addend = lowered_relocs[0].off - 4,
126128 });
127129 } else {
128130 const r_type: u32 = if (sym.flags.is_tls)
......@@ -131,14 +133,14 @@ pub fn emitMir(emit: *Emit) Error!void {
131133 @intFromEnum(std.elf.R_X86_64.@"32");
132134 try atom.addReloc(elf_file, .{
133135 .r_offset = end_offset - 4,
134 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
135 .r_addend = 0,
136 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
137 .r_addend = lowered_relocs[0].off,
136138 });
137139 }
138140 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
139141 const zo = macho_file.getZigObject().?;
140 const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?;
141 const sym = &zo.symbols.items[data.sym_index];
142 const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
143 const sym = &zo.symbols.items[sym_index];
142144 const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr)
143145 .got_load
144146 else if (sym.flags.tlv)
......@@ -148,33 +150,33 @@ pub fn emitMir(emit: *Emit) Error!void {
148150 try atom.addReloc(macho_file, .{
149151 .tag = .@"extern",
150152 .offset = @intCast(end_offset - 4),
151 .target = data.sym_index,
152 .addend = 0,
153 .target = sym_index,
154 .addend = lowered_relocs[0].off,
153155 .type = @"type",
154156 .meta = .{
155157 .pcrel = true,
156158 .has_subtractor = false,
157159 .length = 2,
158 .symbolnum = @intCast(data.sym_index),
160 .symbolnum = @intCast(sym_index),
159161 },
160162 });
161163 } else unreachable,
162164 .linker_got,
163165 .linker_direct,
164166 .linker_import,
165 => |symbol| if (emit.lower.bin_file.cast(.elf)) |_| {
167 => |sym_index| if (emit.lower.bin_file.cast(.elf)) |_| {
166168 unreachable;
167169 } else if (emit.lower.bin_file.cast(.macho)) |_| {
168170 unreachable;
169171 } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
170172 const atom_index = coff_file.getAtomIndexForSymbol(.{
171 .sym_index = symbol.atom_index,
173 .sym_index = emit.atom_index,
172174 .file = null,
173175 }).?;
174 const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)
175 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)
176 const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
177 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
176178 else
177 link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };
179 link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
178180 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
179181 .type = switch (lowered_relocs[0].target) {
180182 .linker_got => .got,
......@@ -184,16 +186,15 @@ pub fn emitMir(emit: *Emit) Error!void {
184186 },
185187 .target = target,
186188 .offset = @intCast(end_offset - 4),
187 .addend = 0,
189 .addend = @intCast(lowered_relocs[0].off),
188190 .pcrel = true,
189191 .length = 2,
190192 });
191193 } else if (emit.lower.bin_file.cast(.plan9)) |p9_file| {
192 const atom_index = symbol.atom_index;
193 try p9_file.addReloc(atom_index, .{ // TODO we may need to add a .type field to the relocs if they are .linker_got instead of just .linker_direct
194 .target = symbol.sym_index, // we set sym_index to just be the atom index
194 try p9_file.addReloc(emit.atom_index, .{ // TODO we may need to add a .type field to the relocs if they are .linker_got instead of just .linker_direct
195 .target = sym_index, // we set sym_index to just be the atom index
195196 .offset = @intCast(end_offset - 4),
196 .addend = 0,
197 .addend = @intCast(lowered_relocs[0].off),
197198 .type = .pcrel,
198199 });
199200 } else return emit.fail("TODO implement linker reloc for {s}", .{
......@@ -261,6 +262,10 @@ pub fn emitMir(emit: *Emit) Error!void {
261262 .pseudo_dbg_local_ai_s,
262263 .pseudo_dbg_local_ai_u,
263264 .pseudo_dbg_local_ai_64,
265 .pseudo_dbg_local_as,
266 .pseudo_dbg_local_aso,
267 .pseudo_dbg_local_aro,
268 .pseudo_dbg_local_af,
264269 .pseudo_dbg_local_am,
265270 => {
266271 switch (emit.debug_output) {
......@@ -279,6 +284,57 @@ pub fn emitMir(emit: *Emit) Error!void {
279284 };
280285 break :stack_value &loc_buf[0];
281286 } } },
287 .pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{ .addr = .{
288 .sym = mir_inst.data.as.sym_index,
289 } } },
290 .pseudo_dbg_local_aso => loc: {
291 const sym_off = emit.lower.mir.extraData(
292 bits.SymbolOffset,
293 mir_inst.data.ax.payload,
294 ).data;
295 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
296 sym: {
297 loc_buf[0] = .{ .addr = .{ .sym = sym_off.sym_index } };
298 break :sym &loc_buf[0];
299 },
300 off: {
301 loc_buf[1] = .{ .consts = sym_off.off };
302 break :off &loc_buf[1];
303 },
304 } } };
305 },
306 .pseudo_dbg_local_aro => loc: {
307 const air_off = emit.lower.mir.extraData(
308 Mir.AirOffset,
309 mir_inst.data.rx.payload,
310 ).data;
311 break :loc .{ air_off.air_inst, .{ .plus = .{
312 reg: {
313 loc_buf[0] = .{ .breg = mir_inst.data.rx.r1.dwarfNum() };
314 break :reg &loc_buf[0];
315 },
316 off: {
317 loc_buf[1] = .{ .consts = air_off.off };
318 break :off &loc_buf[1];
319 },
320 } } };
321 },
322 .pseudo_dbg_local_af => loc: {
323 const reg_off = emit.lower.mir.resolveFrameAddr(emit.lower.mir.extraData(
324 bits.FrameAddr,
325 mir_inst.data.ax.payload,
326 ).data);
327 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
328 reg: {
329 loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() };
330 break :reg &loc_buf[0];
331 },
332 off: {
333 loc_buf[1] = .{ .consts = reg_off.off };
334 break :off &loc_buf[1];
335 },
336 } } };
337 },
282338 .pseudo_dbg_local_am => loc: {
283339 const mem = emit.lower.mem(mir_inst.data.ax.payload);
284340 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
......@@ -287,7 +343,7 @@ pub fn emitMir(emit: *Emit) Error!void {
287343 .none => .{ .constu = 0 },
288344 .reg => |reg| .{ .breg = reg.dwarfNum() },
289345 .frame => unreachable,
290 .reloc => |reloc| .{ .addr = .{ .sym = reloc.sym_index } },
346 .reloc => |sym_index| .{ .addr = .{ .sym = sym_index } },
291347 };
292348 break :base &loc_buf[0];
293349 },
......@@ -352,10 +408,12 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {
352408const Reloc = struct {
353409 /// Offset of the instruction.
354410 source: usize,
411 /// Offset of the relocation within the instruction.
412 source_offset: u32,
355413 /// Target of the relocation.
356414 target: Mir.Inst.Index,
357 /// Offset of the relocation within the instruction.
358 offset: u32,
415 /// Offset from the target instruction.
416 target_offset: i32,
359417 /// Length of the instruction.
360418 length: u5,
361419};
......@@ -368,8 +426,8 @@ fn fixupRelocs(emit: *Emit) Error!void {
368426 for (emit.relocs.items) |reloc| {
369427 const target = emit.code_offset_mapping.get(reloc.target) orelse
370428 return emit.fail("JMP/CALL relocation target not found!", .{});
371 const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length));
372 std.mem.writeInt(i32, emit.code.items[reloc.offset..][0..4], @intCast(disp), .little);
429 const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length)) + reloc.target_offset;
430 std.mem.writeInt(i32, emit.code.items[reloc.source_offset..][0..4], @intCast(disp), .little);
373431 }
374432}
375433
......@@ -422,6 +480,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
422480 }
423481}
424482
483const bits = @import("bits.zig");
425484const link = @import("../../link.zig");
426485const log = std.log.scoped(.emit);
427486const std = @import("std");
src/arch/x86_64/Lower.zig+40-35
......@@ -52,16 +52,17 @@ pub const Error = error{
5252pub const Reloc = struct {
5353 lowered_inst_index: u8,
5454 target: Target,
55 off: i32,
5556
5657 const Target = union(enum) {
5758 inst: Mir.Inst.Index,
58 linker_reloc: bits.Symbol,
59 linker_tlsld: bits.Symbol,
60 linker_dtpoff: bits.Symbol,
61 linker_extern_fn: bits.Symbol,
62 linker_got: bits.Symbol,
63 linker_direct: bits.Symbol,
64 linker_import: bits.Symbol,
59 linker_reloc: u32,
60 linker_tlsld: u32,
61 linker_dtpoff: u32,
62 linker_extern_fn: u32,
63 linker_got: u32,
64 linker_direct: u32,
65 linker_import: u32,
6566 };
6667};
6768
......@@ -173,19 +174,19 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
173174 .pseudo_j_z_and_np_inst => {
174175 assert(inst.data.inst.fixes == ._);
175176 try lower.emit(.none, .jnz, &.{
176 .{ .imm = lower.reloc(.{ .inst = index + 1 }) },
177 .{ .imm = lower.reloc(.{ .inst = index + 1 }, 0) },
177178 });
178179 try lower.emit(.none, .jnp, &.{
179 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },
180 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
180181 });
181182 },
182183 .pseudo_j_nz_or_p_inst => {
183184 assert(inst.data.inst.fixes == ._);
184185 try lower.emit(.none, .jnz, &.{
185 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },
186 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
186187 });
187188 try lower.emit(.none, .jp, &.{
188 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },
189 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
189190 });
190191 },
191192
......@@ -195,7 +196,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
195196 .{ .imm = Immediate.s(@bitCast(inst.data.ri.i)) },
196197 });
197198 try lower.emit(.none, .jz, &.{
198 .{ .imm = lower.reloc(.{ .inst = index + 1 }) },
199 .{ .imm = lower.reloc(.{ .inst = index + 1 }, 0) },
199200 });
200201 try lower.emit(.none, .lea, &.{
201202 .{ .reg = inst.data.ri.r1 },
......@@ -211,7 +212,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
211212 .{ .reg = inst.data.ri.r1.to32() },
212213 });
213214 try lower.emit(.none, .jmp, &.{
214 .{ .imm = lower.reloc(.{ .inst = index }) },
215 .{ .imm = lower.reloc(.{ .inst = index }, 0) },
215216 });
216217 assert(lower.result_insts_len == pseudo_probe_align_insts);
217218 },
......@@ -257,7 +258,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
257258 .{ .imm = Immediate.s(page_size) },
258259 });
259260 try lower.emit(.none, .jae, &.{
260 .{ .imm = lower.reloc(.{ .inst = index }) },
261 .{ .imm = lower.reloc(.{ .inst = index }, 0) },
261262 });
262263 assert(lower.result_insts_len == pseudo_probe_adjust_loop_insts);
263264 },
......@@ -273,6 +274,10 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
273274 .pseudo_dbg_local_ai_s,
274275 .pseudo_dbg_local_ai_u,
275276 .pseudo_dbg_local_ai_64,
277 .pseudo_dbg_local_as,
278 .pseudo_dbg_local_aso,
279 .pseudo_dbg_local_aro,
280 .pseudo_dbg_local_af,
276281 .pseudo_dbg_local_am,
277282 .pseudo_dead_none,
278283 => {},
......@@ -328,10 +333,11 @@ pub fn mem(lower: Lower, payload: u32) Memory {
328333 return lower.mir.resolveFrameLoc(lower.mir.extraData(Mir.Memory, payload).data).decode();
329334}
330335
331fn reloc(lower: *Lower, target: Reloc.Target) Immediate {
336fn reloc(lower: *Lower, target: Reloc.Target, off: i32) Immediate {
332337 lower.result_relocs[lower.result_relocs_len] = .{
333338 .lowered_inst_index = lower.result_insts_len,
334339 .target = target,
340 .off = off,
335341 };
336342 lower.result_relocs_len += 1;
337343 return Immediate.s(0);
......@@ -347,37 +353,36 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
347353 else => op,
348354 .mem => |mem_op| switch (mem_op.base()) {
349355 else => op,
350 .reloc => |sym| op: {
356 .reloc => |sym_index| op: {
351357 assert(prefix == .none);
352358 assert(mem_op.sib.disp == 0);
353359 assert(mem_op.sib.scale_index.scale == 0);
354360
355361 if (lower.bin_file.cast(.elf)) |elf_file| {
356362 const zo = elf_file.zigObjectPtr().?;
357 const elf_sym = zo.symbol(sym.sym_index);
363 const elf_sym = zo.symbol(sym_index);
358364
359365 if (elf_sym.flags.is_tls) {
360366 // TODO handle extern TLS vars, i.e., emit GD model
361367 if (lower.pic) {
362368 // Here, we currently assume local dynamic TLS vars, and so
363369 // we emit LD model.
364 _ = lower.reloc(.{ .linker_tlsld = sym });
370 _ = lower.reloc(.{ .linker_tlsld = sym_index }, 0);
365371 lower.result_insts[lower.result_insts_len] =
366372 try Instruction.new(.none, .lea, &[_]Operand{
367373 .{ .reg = .rdi },
368374 .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },
369375 });
370376 lower.result_insts_len += 1;
371 _ = lower.reloc(.{ .linker_extern_fn = .{
372 .atom_index = sym.atom_index,
373 .sym_index = try elf_file.getGlobalSymbol("__tls_get_addr", null),
374 } });
377 _ = lower.reloc(.{
378 .linker_extern_fn = try elf_file.getGlobalSymbol("__tls_get_addr", null),
379 }, 0);
375380 lower.result_insts[lower.result_insts_len] =
376381 try Instruction.new(.none, .call, &[_]Operand{
377382 .{ .imm = Immediate.s(0) },
378383 });
379384 lower.result_insts_len += 1;
380 _ = lower.reloc(.{ .linker_dtpoff = sym });
385 _ = lower.reloc(.{ .linker_dtpoff = sym_index }, 0);
381386 emit_mnemonic = .lea;
382387 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
383388 .base = .{ .reg = .rax },
......@@ -391,7 +396,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
391396 .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },
392397 });
393398 lower.result_insts_len += 1;
394 _ = lower.reloc(.{ .linker_reloc = sym });
399 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
395400 emit_mnemonic = .lea;
396401 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
397402 .base = .{ .reg = .rax },
......@@ -400,7 +405,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
400405 }
401406 }
402407
403 _ = lower.reloc(.{ .linker_reloc = sym });
408 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
404409 if (lower.pic) switch (mnemonic) {
405410 .lea => {
406411 if (elf_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
......@@ -437,10 +442,10 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
437442 }
438443 } else if (lower.bin_file.cast(.macho)) |macho_file| {
439444 const zo = macho_file.getZigObject().?;
440 const macho_sym = zo.symbols.items[sym.sym_index];
445 const macho_sym = zo.symbols.items[sym_index];
441446
442447 if (macho_sym.flags.tlv) {
443 _ = lower.reloc(.{ .linker_reloc = sym });
448 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
444449 lower.result_insts[lower.result_insts_len] =
445450 try Instruction.new(.none, .mov, &[_]Operand{
446451 .{ .reg = .rdi },
......@@ -456,7 +461,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
456461 break :op .{ .reg = .rax };
457462 }
458463
459 _ = lower.reloc(.{ .linker_reloc = sym });
464 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
460465 break :op switch (mnemonic) {
461466 .lea => {
462467 if (macho_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
......@@ -535,7 +540,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
535540 }, switch (inst.ops) {
536541 .none => &.{},
537542 .inst => &.{
538 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },
543 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
539544 },
540545 .i_s, .i_u => &.{
541546 .{ .imm = lower.imm(inst.ops, inst.data.i.i) },
......@@ -637,17 +642,17 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
637642 .{ .imm = lower.imm(inst.ops, inst.data.rrix.i) },
638643 },
639644 .extern_fn_reloc, .rel => &.{
640 .{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc }) },
645 .{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc.sym_index }, inst.data.reloc.off) },
641646 },
642647 .got_reloc, .direct_reloc, .import_reloc => ops: {
643648 const reg = inst.data.rx.r1;
644 const extra = lower.mir.extraData(bits.Symbol, inst.data.rx.payload).data;
649 const extra = lower.mir.extraData(bits.SymbolOffset, inst.data.rx.payload).data;
645650 _ = lower.reloc(switch (inst.ops) {
646 .got_reloc => .{ .linker_got = extra },
647 .direct_reloc => .{ .linker_direct = extra },
648 .import_reloc => .{ .linker_import = extra },
651 .got_reloc => .{ .linker_got = extra.sym_index },
652 .direct_reloc => .{ .linker_direct = extra.sym_index },
653 .import_reloc => .{ .linker_import = extra.sym_index },
649654 else => unreachable,
650 });
655 }, extra.off);
651656 break :ops &.{
652657 .{ .reg = reg },
653658 .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
src/arch/x86_64/Mir.zig+37-12
......@@ -820,16 +820,16 @@ pub const Inst = struct {
820820 /// Uses `reloc` payload.
821821 extern_fn_reloc,
822822 /// Linker relocation - GOT indirection.
823 /// Uses `rx` payload with extra data of type `bits.Symbol`.
823 /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
824824 got_reloc,
825825 /// Linker relocation - direct reference.
826 /// Uses `rx` payload with extra data of type `bits.Symbol`.
826 /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
827827 direct_reloc,
828828 /// Linker relocation - imports table indirection (binding).
829 /// Uses `rx` payload with extra data of type `bits.Symbol`.
829 /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
830830 import_reloc,
831831 /// Linker relocation - threadlocal variable via GOT indirection.
832 /// Uses `rx` payload with extra data of type `bits.Symbol`.
832 /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
833833 tlv_reloc,
834834
835835 // Pseudo instructions:
......@@ -907,9 +907,21 @@ pub const Inst = struct {
907907 /// Uses `ai` payload.
908908 pseudo_dbg_local_ai_u,
909909 /// Local argument or variable.
910 /// Uses `ax` payload with extra data of type `Imm64`.
910 /// Uses `ai` payload with extra data of type `Imm64`.
911911 pseudo_dbg_local_ai_64,
912912 /// Local argument or variable.
913 /// Uses `as` payload.
914 pseudo_dbg_local_as,
915 /// Local argument or variable.
916 /// Uses `ax` payload with extra data of type `bits.SymbolOffset`.
917 pseudo_dbg_local_aso,
918 /// Local argument or variable.
919 /// Uses `rx` payload with extra data of type `AirOffset`.
920 pseudo_dbg_local_aro,
921 /// Local argument or variable.
922 /// Uses `ax` payload with extra data of type `bits.FrameAddr`.
923 pseudo_dbg_local_af,
924 /// Local argument or variable.
913925 /// Uses `ax` payload with extra data of type `Memory`.
914926 pseudo_dbg_local_am,
915927
......@@ -1014,6 +1026,9 @@ pub const Inst = struct {
10141026 fixes: Fixes = ._,
10151027 payload: u32,
10161028 },
1029 ix: struct {
1030 payload: u32,
1031 },
10171032 a: struct {
10181033 air_inst: Air.Inst.Index,
10191034 },
......@@ -1021,14 +1036,18 @@ pub const Inst = struct {
10211036 air_inst: Air.Inst.Index,
10221037 i: u32,
10231038 },
1039 as: struct {
1040 air_inst: Air.Inst.Index,
1041 sym_index: u32,
1042 },
10241043 ax: struct {
10251044 air_inst: Air.Inst.Index,
10261045 payload: u32,
10271046 },
10281047 /// Relocation for the linker where:
1029 /// * `atom_index` is the index of the source
10301048 /// * `sym_index` is the index of the target
1031 reloc: bits.Symbol,
1049 /// * `off` is the offset from the target
1050 reloc: bits.SymbolOffset,
10321051 /// Debug line and column position
10331052 line_column: struct {
10341053 line: u32,
......@@ -1048,6 +1067,8 @@ pub const Inst = struct {
10481067 }
10491068};
10501069
1070pub const AirOffset = struct { air_inst: Air.Inst.Index, off: i32 };
1071
10511072/// Used in conjunction with payload to transfer a list of used registers in a compact manner.
10521073pub const RegisterList = struct {
10531074 bitset: BitSet = BitSet.initEmpty(),
......@@ -1146,15 +1167,13 @@ pub const Memory = struct {
11461167 .none => undefined,
11471168 .reg => |reg| @intFromEnum(reg),
11481169 .frame => |frame_index| @intFromEnum(frame_index),
1149 .reloc => |symbol| symbol.sym_index,
1170 .reloc => |sym_index| sym_index,
11501171 },
11511172 .off = switch (mem.mod) {
11521173 .rm => |rm| @bitCast(rm.disp),
11531174 .off => |off| @truncate(off),
11541175 },
1155 .extra = if (mem.base == .reloc)
1156 mem.base.reloc.atom_index
1157 else if (mem.mod == .off)
1176 .extra = if (mem.mod == .off)
11581177 @intCast(mem.mod.off >> 32)
11591178 else
11601179 undefined,
......@@ -1174,7 +1193,7 @@ pub const Memory = struct {
11741193 .none => .none,
11751194 .reg => .{ .reg = @enumFromInt(mem.base) },
11761195 .frame => .{ .frame = @enumFromInt(mem.base) },
1177 .reloc => .{ .reloc = .{ .atom_index = mem.extra, .sym_index = mem.base } },
1196 .reloc => .{ .reloc = mem.base },
11781197 },
11791198 .scale_index = switch (mem.info.index) {
11801199 .none => null,
......@@ -1214,6 +1233,7 @@ pub fn extraData(mir: Mir, comptime T: type, index: u32) struct { data: T, end:
12141233 @field(result, field.name) = switch (field.type) {
12151234 u32 => mir.extra[i],
12161235 i32, Memory.Info => @bitCast(mir.extra[i]),
1236 bits.FrameIndex, Air.Inst.Index => @enumFromInt(mir.extra[i]),
12171237 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
12181238 };
12191239 i += 1;
......@@ -1229,6 +1249,11 @@ pub const FrameLoc = struct {
12291249 disp: i32,
12301250};
12311251
1252pub fn resolveFrameAddr(mir: Mir, frame_addr: bits.FrameAddr) bits.RegisterOffset {
1253 const frame_loc = mir.frame_locs.get(@intFromEnum(frame_addr.index));
1254 return .{ .reg = frame_loc.base, .off = frame_loc.disp + frame_addr.off };
1255}
1256
12321257pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {
12331258 return switch (mem.info.base) {
12341259 .none, .reg, .reloc => mem,
src/arch/x86_64/bits.zig+12-27
......@@ -447,26 +447,11 @@ pub const FrameIndex = enum(u32) {
447447 }
448448};
449449
450/// A linker symbol not yet allocated in VM.
451pub const Symbol = struct {
452 /// Index of the containing atom.
453 atom_index: u32,
454 /// Index into the linker's symbol table.
455 sym_index: u32,
450pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
456451
457 pub fn format(
458 sym: Symbol,
459 comptime fmt: []const u8,
460 options: std.fmt.FormatOptions,
461 writer: anytype,
462 ) @TypeOf(writer).Error!void {
463 try writer.writeAll("Symbol(");
464 try std.fmt.formatType(sym.atom_index, fmt, options, writer, 0);
465 try writer.writeAll(", ");
466 try std.fmt.formatType(sym.sym_index, fmt, options, writer, 0);
467 try writer.writeByte(')');
468 }
469};
452pub const RegisterOffset = struct { reg: Register, off: i32 = 0 };
453
454pub const SymbolOffset = struct { sym_index: u32, off: i32 = 0 };
470455
471456pub const Memory = struct {
472457 base: Base,
......@@ -476,7 +461,7 @@ pub const Memory = struct {
476461 none,
477462 reg: Register,
478463 frame: FrameIndex,
479 reloc: Symbol,
464 reloc: u32,
480465
481466 pub const Tag = @typeInfo(Base).Union.tag_type.?;
482467
......@@ -568,7 +553,7 @@ pub const Memory = struct {
568553pub const Immediate = union(enum) {
569554 signed: i32,
570555 unsigned: u64,
571 reloc: Symbol,
556 reloc: SymbolOffset,
572557
573558 pub fn u(x: u64) Immediate {
574559 return .{ .unsigned = x };
......@@ -578,19 +563,19 @@ pub const Immediate = union(enum) {
578563 return .{ .signed = x };
579564 }
580565
581 pub fn rel(symbol: Symbol) Immediate {
582 return .{ .reloc = symbol };
566 pub fn rel(sym_off: SymbolOffset) Immediate {
567 return .{ .reloc = sym_off };
583568 }
584569
585570 pub fn format(
586571 imm: Immediate,
587 comptime fmt: []const u8,
588 options: std.fmt.FormatOptions,
572 comptime _: []const u8,
573 _: std.fmt.FormatOptions,
589574 writer: anytype,
590575 ) @TypeOf(writer).Error!void {
591576 switch (imm) {
592 .reloc => |x| try std.fmt.formatType(x, fmt, options, writer, 0),
593 inline else => |x| try writer.print("{d}", .{x}),
577 inline else => |int| try writer.print("{d}", .{int}),
578 .reloc => |sym_off| try writer.print("Symbol({[sym_index]d}) + {[off]d}", sym_off),
594579 }
595580 }
596581};
src/arch/x86_64/encoder.zig+5-10
......@@ -266,17 +266,12 @@ pub const Instruction = struct {
266266
267267 try writer.writeByte('[');
268268
269 var any = false;
269 var any = true;
270270 switch (sib.base) {
271 .none => {},
272 .reg => |reg| {
273 try writer.print("{s}", .{@tagName(reg)});
274 any = true;
275 },
276 inline .frame, .reloc => |payload| {
277 try writer.print("{}", .{payload});
278 any = true;
279 },
271 .none => any = false,
272 .reg => |reg| try writer.print("{s}", .{@tagName(reg)}),
273 .frame => |frame_index| try writer.print("{}", .{frame_index}),
274 .reloc => |sym_index| try writer.print("Symbol({d})", .{sym_index}),
280275 }
281276 if (mem.scaleIndex()) |si| {
282277 if (any) try writer.writeAll(" + ");