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 {...@@ -64,8 +64,8 @@ va_info: union {
64 sysv: struct {64 sysv: struct {
65 gp_count: u32,65 gp_count: u32,
66 fp_count: u32,66 fp_count: u32,
67 overflow_arg_area: FrameAddr,67 overflow_arg_area: bits.FrameAddr,
68 reg_save_area: FrameAddr,68 reg_save_area: bits.FrameAddr,
69 },69 },
70 win64: struct {},70 win64: struct {},
71},71},
...@@ -110,10 +110,6 @@ air_bookkeeping: @TypeOf(air_bookkeeping_init) = air_bookkeeping_init,...@@ -110,10 +110,6 @@ air_bookkeeping: @TypeOf(air_bookkeeping_init) = air_bookkeeping_init,
110110
111const air_bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {};111const 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
117const Owner = union(enum) {113const Owner = union(enum) {
118 nav_index: InternPool.Nav.Index,114 nav_index: InternPool.Nav.Index,
119 lazy_sym: link.File.LazySymbol,115 lazy_sym: link.File.LazySymbol,
...@@ -171,7 +167,7 @@ pub const MCValue = union(enum) {...@@ -171,7 +167,7 @@ pub const MCValue = union(enum) {
171 /// The value is split across two registers.167 /// The value is split across two registers.
172 register_pair: [2]Register,168 register_pair: [2]Register,
173 /// The value is a constant offset from the value in a register.169 /// The value is a constant offset from the value in a register.
174 register_offset: RegisterOffset,170 register_offset: bits.RegisterOffset,
175 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.171 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.
176 register_overflow: struct { reg: Register, eflags: Condition },172 register_overflow: struct { reg: Register, eflags: Condition },
177 /// The value is in memory at a hard-coded address.173 /// The value is in memory at a hard-coded address.
...@@ -179,11 +175,11 @@ pub const MCValue = union(enum) {...@@ -179,11 +175,11 @@ pub const MCValue = union(enum) {
179 memory: u64,175 memory: u64,
180 /// The value is in memory at an address not-yet-allocated by the linker.176 /// The value is in memory at an address not-yet-allocated by the linker.
181 /// This traditionally corresponds to a relocation emitted in a relocatable object file.177 /// This traditionally corresponds to a relocation emitted in a relocatable object file.
182 load_symbol: SymbolOffset,178 load_symbol: bits.SymbolOffset,
183 /// The address of the memory location not-yet-allocated by the linker.179 /// The address of the memory location not-yet-allocated by the linker.
184 lea_symbol: SymbolOffset,180 lea_symbol: bits.SymbolOffset,
185 /// The value is in memory at a constant offset from the address in a register.181 /// The value is in memory at a constant offset from the address in a register.
186 indirect: RegisterOffset,182 indirect: bits.RegisterOffset,
187 /// The value is in memory.183 /// The value is in memory.
188 /// Payload is a symbol index.184 /// Payload is a symbol index.
189 load_direct: u32,185 load_direct: u32,
...@@ -204,10 +200,10 @@ pub const MCValue = union(enum) {...@@ -204,10 +200,10 @@ pub const MCValue = union(enum) {
204 lea_tlv: u32,200 lea_tlv: u32,
205 /// The value stored at an offset from a frame index201 /// The value stored at an offset from a frame index
206 /// Payload is a frame address.202 /// Payload is a frame address.
207 load_frame: FrameAddr,203 load_frame: bits.FrameAddr,
208 /// The address of an offset from a frame index204 /// The address of an offset from a frame index
209 /// Payload is a frame address.205 /// Payload is a frame address.
210 lea_frame: FrameAddr,206 lea_frame: bits.FrameAddr,
211 /// Supports integer_per_element abi207 /// Supports integer_per_element abi
212 elementwise_regs_then_frame: packed struct { regs: u3 = 0, frame_off: i29 = 0, frame_index: FrameIndex },208 elementwise_regs_then_frame: packed struct { regs: u3 = 0, frame_off: i29 = 0, frame_index: FrameIndex },
213 /// This indicates that we have already allocated a frame index for this instruction,209 /// This indicates that we have already allocated a frame index for this instruction,
...@@ -423,10 +419,7 @@ pub const MCValue = union(enum) {...@@ -423,10 +419,7 @@ pub const MCValue = union(enum) {
423 .load_symbol => |sym_off| {419 .load_symbol => |sym_off| {
424 assert(sym_off.off == 0);420 assert(sym_off.off == 0);
425 return .{421 return .{
426 .base = .{ .reloc = .{422 .base = .{ .reloc = sym_off.sym_index },
427 .atom_index = try function.owner.getSymbolIndex(function),
428 .sym_index = sym_off.sym,
429 } },
430 .mod = .{ .rm = .{423 .mod = .{ .rm = .{
431 .size = size,424 .size = size,
432 .disp = sym_off.off,425 .disp = sym_off.off,
...@@ -453,8 +446,8 @@ pub const MCValue = union(enum) {...@@ -453,8 +446,8 @@ pub const MCValue = union(enum) {
453 .register_overflow => |pl| try writer.print("{s}:{s}", .{446 .register_overflow => |pl| try writer.print("{s}:{s}", .{
454 @tagName(pl.eflags), @tagName(pl.reg),447 @tagName(pl.eflags), @tagName(pl.reg),
455 }),448 }),
456 .load_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 }),
457 .lea_symbol => |pl| try writer.print("{} + 0x{x}", .{ pl.sym, pl.off }),450 .lea_symbol => |pl| try writer.print("{} + 0x{x}", .{ pl.sym_index, pl.off }),
458 .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),451 .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
459 .load_direct => |pl| try writer.print("[direct:{d}]", .{pl}),452 .load_direct => |pl| try writer.print("[direct:{d}]", .{pl}),
460 .lea_direct => |pl| try writer.print("direct:{d}", .{pl}),453 .lea_direct => |pl| try writer.print("direct:{d}", .{pl}),
...@@ -921,6 +914,13 @@ pub fn generate(...@@ -921,6 +914,13 @@ pub fn generate(
921 .link_mode = comp.config.link_mode,914 .link_mode = comp.config.link_mode,
922 .pic = mod.pic,915 .pic = mod.pic,
923 },916 },
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 },
924 .debug_output = debug_output,924 .debug_output = debug_output,
925 .code = code,925 .code = code,
926 .prev_di_pc = 0,926 .prev_di_pc = 0,
...@@ -1019,6 +1019,13 @@ pub fn generateLazy(...@@ -1019,6 +1019,13 @@ pub fn generateLazy(
1019 .link_mode = comp.config.link_mode,1019 .link_mode = comp.config.link_mode,
1020 .pic = mod.pic,1020 .pic = mod.pic,
1021 },1021 },
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 },
1022 .debug_output = debug_output,1029 .debug_output = debug_output,
1023 .code = code,1030 .code = code,
1024 .prev_di_pc = undefined, // no debug info yet1031 .prev_di_pc = undefined, // no debug info yet
...@@ -1192,6 +1199,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {...@@ -1192,6 +1199,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
1192 self.mir_extra.appendAssumeCapacity(switch (field.type) {1199 self.mir_extra.appendAssumeCapacity(switch (field.type) {
1193 u32 => @field(extra, field.name),1200 u32 => @field(extra, field.name),
1194 i32, Mir.Memory.Info => @bitCast(@field(extra, field.name)),1201 i32, Mir.Memory.Info => @bitCast(@field(extra, field.name)),
1202 bits.FrameIndex => @intFromEnum(@field(extra, field.name)),
1195 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),1203 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
1196 });1204 });
1197 }1205 }
...@@ -1358,26 +1366,94 @@ fn asmAir(self: *Self, tag: MirTagAir, inst: Air.Inst.Index) !void {...@@ -1358,26 +1366,94 @@ fn asmAir(self: *Self, tag: MirTagAir, inst: Air.Inst.Index) !void {
1358}1366}
13591367
1360fn asmAirImmediate(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, imm: Immediate) !void {1368fn asmAirImmediate(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, imm: Immediate) !void {
1361 const ops: Mir.Inst.Ops, const i: u32 = switch (imm) {1369 switch (imm) {
1362 .signed => |s| .{ switch (tag) {1370 .signed => |s| _ = try self.addInst(.{
1363 .dbg_local => .pseudo_dbg_local_ai_s,1371 .tag = .pseudo,
1364 }, @bitCast(s) },1372 .ops = switch (tag) {
1365 .unsigned => |u| if (math.cast(u32, u)) |small|1373 .dbg_local => .pseudo_dbg_local_ai_s,
1366 .{ switch (tag) {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) {
1367 .dbg_local => .pseudo_dbg_local_ai_u,1383 .dbg_local => .pseudo_dbg_local_ai_u,
1368 }, small }1384 },
1369 else1385 .data = .{ .ai = .{
1370 .{ switch (tag) {1386 .air_inst = inst,
1387 .i = small,
1388 } },
1389 }) else try self.addInst(.{
1390 .tag = .pseudo,
1391 .ops = switch (tag) {
1371 .dbg_local => .pseudo_dbg_local_ai_64,1392 .dbg_local => .pseudo_dbg_local_ai_64,
1372 }, try self.addExtra(Mir.Imm64.encode(u)) },1393 },
1373 .reloc => unreachable,1394 .data = .{ .ai = .{
1374 };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 {
1375 _ = try self.addInst(.{1428 _ = try self.addInst(.{
1376 .tag = .pseudo,1429 .tag = .pseudo,
1377 .ops = ops,1430 .ops = switch (tag) {
1378 .data = .{ .ai = .{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 = .{
1379 .air_inst = inst,1455 .air_inst = inst,
1380 .i = i,1456 .payload = try self.addExtra(frame_addr),
1381 } },1457 } },
1382 });1458 });
1383}1459}
...@@ -1433,9 +1509,9 @@ fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void {...@@ -1433,9 +1509,9 @@ fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void {
1433 .reloc => .rel,1509 .reloc => .rel,
1434 },1510 },
1435 .data = switch (imm) {1511 .data = switch (imm) {
1436 .reloc => |x| reloc: {1512 .reloc => |sym_off| reloc: {
1437 assert(tag[0] == ._);1513 assert(tag[0] == ._);
1438 break :reloc .{ .reloc = x };1514 break :reloc .{ .reloc = sym_off };
1439 },1515 },
1440 .signed, .unsigned => .{ .i = .{1516 .signed, .unsigned => .{ .i = .{
1441 .fixes = tag[0],1517 .fixes = tag[0],
...@@ -2515,12 +2591,12 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo...@@ -2515,12 +2591,12 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo
2515 };2591 };
2516}2592}
25172593
2518fn getFrameAddrAlignment(self: *Self, frame_addr: FrameAddr) Alignment {2594fn getFrameAddrAlignment(self: *Self, frame_addr: bits.FrameAddr) Alignment {
2519 const alloc_align = self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_align;2595 const alloc_align = self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_align;
2520 return @enumFromInt(@min(@intFromEnum(alloc_align), @ctz(frame_addr.off)));2596 return @enumFromInt(@min(@intFromEnum(alloc_align), @ctz(frame_addr.off)));
2521}2597}
25222598
2523fn getFrameAddrSize(self: *Self, frame_addr: FrameAddr) u32 {2599fn getFrameAddrSize(self: *Self, frame_addr: bits.FrameAddr) u32 {
2524 return self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_size - @as(u31, @intCast(frame_addr.off));2600 return self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_size - @as(u31, @intCast(frame_addr.off));
2525}2601}
25262602
...@@ -11999,6 +12075,8 @@ fn genLocalDebugInfo(...@@ -11999,6 +12075,8 @@ fn genLocalDebugInfo(
11999 .none => try self.asmAir(.dbg_local, inst),12075 .none => try self.asmAir(.dbg_local, inst),
12000 .unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,12076 .unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
12001 .immediate => |imm| try self.asmAirImmediate(.dbg_local, inst, Immediate.u(imm)),12077 .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)),
12002 else => {12080 else => {
12003 const ty = switch (tag) {12081 const ty = switch (tag) {
12004 else => unreachable,12082 else => unreachable,
...@@ -12027,14 +12105,14 @@ fn genLocalDebugInfo(...@@ -12027,14 +12105,14 @@ fn genLocalDebugInfo(
12027 } },12105 } },
12028 }),12106 }),
12029 .lea_symbol => |sym_off| try self.asmAirMemory(.dbg_local, inst, .{12107 .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 },
12031 .mod = .{ .rm = .{12109 .mod = .{ .rm = .{
12032 .size = .qword,12110 .size = .qword,
12033 .disp = sym_off.off,12111 .disp = sym_off.off,
12034 } },12112 } },
12035 }),12113 }),
12036 .lea_direct, .lea_got, .lea_tlv => |sym| try self.asmAirMemory(.dbg_local, inst, .{12114 .lea_direct, .lea_got, .lea_tlv => |sym_index| try self.asmAirMemory(.dbg_local, inst, .{
12037 .base = .{ .reloc = .{ .atom_index = undefined, .sym_index = sym } },12115 .base = .{ .reloc = sym_index },
12038 .mod = .{ .rm = .{ .size = .qword } },12116 .mod = .{ .rm = .{ .size = .qword } },
12039 }),12117 }),
12040 },12118 },
...@@ -12357,10 +12435,7 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12357,10 +12435,7 @@ fn genCall(self: *Self, info: union(enum) {
12357 if (self.bin_file.cast(.elf)) |elf_file| {12435 if (self.bin_file.cast(.elf)) |elf_file| {
12358 const zo = elf_file.zigObjectPtr().?;12436 const zo = elf_file.zigObjectPtr().?;
12359 const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);12437 const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
12360 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{12438 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index }));
12361 .atom_index = try self.owner.getSymbolIndex(self),
12362 .sym_index = sym_index,
12363 }));
12364 } else if (self.bin_file.cast(.coff)) |coff_file| {12439 } else if (self.bin_file.cast(.coff)) |coff_file| {
12365 const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);12440 const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
12366 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;12441 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
...@@ -12370,10 +12445,7 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12370,10 +12445,7 @@ fn genCall(self: *Self, info: union(enum) {
12370 const zo = macho_file.getZigObject().?;12445 const zo = macho_file.getZigObject().?;
12371 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);12446 const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);
12372 const sym = zo.symbols.items[sym_index];12447 const sym = zo.symbols.items[sym_index];
12373 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{12448 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym.nlist_idx }));
12374 .atom_index = try self.owner.getSymbolIndex(self),
12375 .sym_index = sym.nlist_idx,
12376 }));
12377 } else if (self.bin_file.cast(.plan9)) |p9| {12449 } else if (self.bin_file.cast(.plan9)) |p9| {
12378 const atom_index = try p9.seeNav(pt, func.owner_nav);12450 const atom_index = try p9.seeNav(pt, func.owner_nav);
12379 const atom = p9.getAtom(atom_index);12451 const atom = p9.getAtom(atom_index);
...@@ -12391,19 +12463,13 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12391,19 +12463,13 @@ fn genCall(self: *Self, info: union(enum) {
12391 @"extern".name.toSlice(ip),12463 @"extern".name.toSlice(ip),
12392 @"extern".lib_name.toSlice(ip),12464 @"extern".lib_name.toSlice(ip),
12393 );12465 );
12394 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{12466 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
12395 .atom_index = try self.owner.getSymbolIndex(self),
12396 .sym_index = target_sym_index,
12397 }));
12398 } else if (self.bin_file.cast(.macho)) |macho_file| {12467 } else if (self.bin_file.cast(.macho)) |macho_file| {
12399 const target_sym_index = try macho_file.getGlobalSymbol(12468 const target_sym_index = try macho_file.getGlobalSymbol(
12400 @"extern".name.toSlice(ip),12469 @"extern".name.toSlice(ip),
12401 @"extern".lib_name.toSlice(ip),12470 @"extern".lib_name.toSlice(ip),
12402 );12471 );
12403 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{12472 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
12404 .atom_index = try self.owner.getSymbolIndex(self),
12405 .sym_index = target_sym_index,
12406 }));
12407 } else try self.genExternSymbolRef(12473 } else try self.genExternSymbolRef(
12408 .call,12474 .call,
12409 @"extern".lib_name.toSlice(ip),12475 @"extern".lib_name.toSlice(ip),
...@@ -12418,16 +12484,10 @@ fn genCall(self: *Self, info: union(enum) {...@@ -12418,16 +12484,10 @@ fn genCall(self: *Self, info: union(enum) {
12418 },12484 },
12419 .lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {12485 .lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {
12420 const target_sym_index = try elf_file.getGlobalSymbol(lib.callee, lib.lib);12486 const target_sym_index = try elf_file.getGlobalSymbol(lib.callee, lib.lib);
12421 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{12487 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
12422 .atom_index = try self.owner.getSymbolIndex(self),
12423 .sym_index = target_sym_index,
12424 }));
12425 } else if (self.bin_file.cast(.macho)) |macho_file| {12488 } else if (self.bin_file.cast(.macho)) |macho_file| {
12426 const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib);12489 const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib);
12427 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{12490 try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
12428 .atom_index = try self.owner.getSymbolIndex(self),
12429 .sym_index = target_sym_index,
12430 }));
12431 } else try self.genExternSymbolRef(.call, lib.lib, lib.callee),12491 } else try self.genExternSymbolRef(.call, lib.lib, lib.callee),
12432 }12492 }
12433 return call_info.return_value.short;12493 return call_info.return_value.short;
...@@ -14968,10 +15028,7 @@ fn genSetReg(...@@ -14968,10 +15028,7 @@ fn genSetReg(
14968 .general_purpose => {15028 .general_purpose => {
14969 assert(sym_off.off == 0);15029 assert(sym_off.off == 0);
14970 try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(dst_reg, abi_size), .{15030 try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(dst_reg, abi_size), .{
14971 .base = .{ .reloc = .{15031 .base = .{ .reloc = sym_off.sym_index },
14972 .atom_index = try self.owner.getSymbolIndex(self),
14973 .sym_index = sym_off.sym,
14974 } },
14975 .mod = .{ .rm = .{15032 .mod = .{ .rm = .{
14976 .size = self.memSize(ty),15033 .size = self.memSize(ty),
14977 .disp = sym_off.off,15034 .disp = sym_off.off,
...@@ -14989,10 +15046,7 @@ fn genSetReg(...@@ -14989,10 +15046,7 @@ fn genSetReg(
14989 .ops = .direct_reloc,15046 .ops = .direct_reloc,
14990 .data = .{ .rx = .{15047 .data = .{ .rx = .{
14991 .r1 = registerAlias(dst_reg, abi_size),15048 .r1 = registerAlias(dst_reg, abi_size),
14992 .payload = try self.addExtra(bits.Symbol{15049 .payload = try self.addExtra(bits.SymbolOffset{ .sym_index = sym_index }),
14993 .atom_index = try self.owner.getSymbolIndex(self),
14994 .sym_index = sym_index,
14995 }),
14996 } },15050 } },
14997 });15051 });
14998 return;15052 return;
...@@ -15017,52 +15071,38 @@ fn genSetReg(...@@ -15017,52 +15071,38 @@ fn genSetReg(
15017 },15071 },
15018 );15072 );
15019 },15073 },
15020 .lea_symbol => |sym_index| {15074 .lea_symbol => |sym_off| switch (self.bin_file.tag) {
15021 const atom_index = try self.owner.getSymbolIndex(self);15075 .elf, .macho => try self.asmRegisterMemory(
15022 switch (self.bin_file.tag) {15076 .{ ._, .lea },
15023 .elf, .macho => {15077 dst_reg.to64(),
15024 try self.asmRegisterMemory(15078 .{
15025 .{ ._, .lea },15079 .base = .{ .reloc = sym_off.sym_index },
15026 dst_reg.to64(),15080 .mod = .{ .rm = .{
15027 .{15081 .size = .qword,
15028 .base = .{ .reloc = .{15082 .disp = sym_off.off,
15029 .atom_index = atom_index,15083 } },
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,
15056 },15084 },
15057 .data = .{ .rx = .{15085 ),
15058 .r1 = dst_reg.to64(),15086 else => return self.fail("TODO emit symbol sequence on {s}", .{
15059 .payload = try self.addExtra(bits.Symbol{15087 @tagName(self.bin_file.tag),
15060 .atom_index = atom_index,15088 }),
15061 .sym_index = sym_index,
15062 }),
15063 } },
15064 });
15065 },15089 },
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 }),
15066 .lea_tlv => unreachable, // TODO: remove this15106 .lea_tlv => unreachable, // TODO: remove this
15067 .air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref), opts),15107 .air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref), opts),
15068 }15108 }
...@@ -15083,7 +15123,7 @@ fn genSetMem(...@@ -15083,7 +15123,7 @@ fn genSetMem(
15083 .none => .{ .immediate = @bitCast(@as(i64, disp)) },15123 .none => .{ .immediate = @bitCast(@as(i64, disp)) },
15084 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },15124 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
15085 .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },15125 .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 } },
15087 };15127 };
15088 switch (src_mcv) {15128 switch (src_mcv) {
15089 .none,15129 .none,
...@@ -15326,7 +15366,6 @@ fn genExternSymbolRef(...@@ -15326,7 +15366,6 @@ fn genExternSymbolRef(
15326 lib: ?[]const u8,15366 lib: ?[]const u8,
15327 callee: []const u8,15367 callee: []const u8,
15328) InnerError!void {15368) InnerError!void {
15329 const atom_index = try self.owner.getSymbolIndex(self);
15330 if (self.bin_file.cast(.coff)) |coff_file| {15369 if (self.bin_file.cast(.coff)) |coff_file| {
15331 const global_index = try coff_file.getGlobalSymbol(callee, lib);15370 const global_index = try coff_file.getGlobalSymbol(callee, lib);
15332 _ = try self.addInst(.{15371 _ = try self.addInst(.{
...@@ -15334,8 +15373,7 @@ fn genExternSymbolRef(...@@ -15334,8 +15373,7 @@ fn genExternSymbolRef(
15334 .ops = .import_reloc,15373 .ops = .import_reloc,
15335 .data = .{ .rx = .{15374 .data = .{ .rx = .{
15336 .r1 = .rax,15375 .r1 = .rax,
15337 .payload = try self.addExtra(bits.Symbol{15376 .payload = try self.addExtra(bits.SymbolOffset{
15338 .atom_index = atom_index,
15339 .sym_index = link.File.Coff.global_symbol_bit | global_index,15377 .sym_index = link.File.Coff.global_symbol_bit | global_index,
15340 }),15378 }),
15341 } },15379 } },
...@@ -15362,10 +15400,10 @@ fn genLazySymbolRef(...@@ -15362,10 +15400,10 @@ fn genLazySymbolRef(
15362 if (self.mod.pic) {15400 if (self.mod.pic) {
15363 switch (tag) {15401 switch (tag) {
15364 .lea, .call => try self.genSetReg(reg, Type.usize, .{15402 .lea, .call => try self.genSetReg(reg, Type.usize, .{
15365 .lea_symbol = .{ .sym = sym_index },15403 .lea_symbol = .{ .sym_index = sym_index },
15366 }, .{}),15404 }, .{}),
15367 .mov => try self.genSetReg(reg, Type.usize, .{15405 .mov => try self.genSetReg(reg, Type.usize, .{
15368 .load_symbol = .{ .sym = sym_index },15406 .load_symbol = .{ .sym_index = sym_index },
15369 }, .{}),15407 }, .{}),
15370 else => unreachable,15408 else => unreachable,
15371 }15409 }
...@@ -15374,19 +15412,13 @@ fn genLazySymbolRef(...@@ -15374,19 +15412,13 @@ fn genLazySymbolRef(
15374 .call => try self.asmRegister(.{ ._, .call }, reg),15412 .call => try self.asmRegister(.{ ._, .call }, reg),
15375 else => unreachable,15413 else => unreachable,
15376 }15414 }
15377 } else {15415 } else switch (tag) {
15378 const reloc = bits.Symbol{15416 .lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{
15379 .atom_index = try self.owner.getSymbolIndex(self),15417 .base = .{ .reloc = sym_index },
15380 .sym_index = sym_index,15418 .mod = .{ .rm = .{ .size = .qword } },
15381 };15419 }),
15382 switch (tag) {15420 .call => try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index })),
15383 .lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{15421 else => unreachable,
15384 .base = .{ .reloc = reloc },
15385 .mod = .{ .rm = .{ .size = .qword } },
15386 }),
15387 .call => try self.asmImmediate(.{ ._, .call }, Immediate.rel(reloc)),
15388 else => unreachable,
15389 }
15390 }15422 }
15391 } else if (self.bin_file.cast(.plan9)) |p9_file| {15423 } else if (self.bin_file.cast(.plan9)) |p9_file| {
15392 const atom_index = p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|15424 const atom_index = p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
...@@ -15436,10 +15468,10 @@ fn genLazySymbolRef(...@@ -15436,10 +15468,10 @@ fn genLazySymbolRef(
15436 const sym = zo.symbols.items[sym_index];15468 const sym = zo.symbols.items[sym_index];
15437 switch (tag) {15469 switch (tag) {
15438 .lea, .call => try self.genSetReg(reg, Type.usize, .{15470 .lea, .call => try self.genSetReg(reg, Type.usize, .{
15439 .lea_symbol = .{ .sym = sym.nlist_idx },15471 .lea_symbol = .{ .sym_index = sym.nlist_idx },
15440 }, .{}),15472 }, .{}),
15441 .mov => try self.genSetReg(reg, Type.usize, .{15473 .mov => try self.genSetReg(reg, Type.usize, .{
15442 .load_symbol = .{ .sym = sym.nlist_idx },15474 .load_symbol = .{ .sym_index = sym.nlist_idx },
15443 }, .{}),15475 }, .{}),
15444 else => unreachable,15476 else => unreachable,
15445 }15477 }
...@@ -18784,7 +18816,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {...@@ -18784,7 +18816,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
18784 .{ .frame = frame_index },18816 .{ .frame = frame_index },
18785 0,18817 0,
18786 Type.usize,18818 Type.usize,
18787 .{ .lea_symbol = .{ .sym = tlv_sym } },18819 .{ .lea_symbol = .{ .sym_index = tlv_sym } },
18788 .{},18820 .{},
18789 );18821 );
18790 break :init .{ .load_frame = .{ .index = frame_index } };18822 break :init .{ .load_frame = .{ .index = frame_index } };
...@@ -18840,8 +18872,8 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {...@@ -18840,8 +18872,8 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
18840 .undef => .undef,18872 .undef => .undef,
18841 .immediate => |imm| .{ .immediate = imm },18873 .immediate => |imm| .{ .immediate = imm },
18842 .memory => |addr| .{ .memory = addr },18874 .memory => |addr| .{ .memory = addr },
18843 .load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },18875 .load_symbol => |sym_index| .{ .load_symbol = .{ .sym_index = sym_index } },
18844 .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym = sym_index } },18876 .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index } },
18845 .load_direct => |sym_index| .{ .load_direct = sym_index },18877 .load_direct => |sym_index| .{ .load_direct = sym_index },
18846 .lea_direct => |sym_index| .{ .lea_direct = sym_index },18878 .lea_direct => |sym_index| .{ .lea_direct = sym_index },
18847 .load_got => |sym_index| .{ .lea_got = sym_index },18879 .load_got => |sym_index| .{ .lea_got = sym_index },
src/arch/x86_64/Emit.zig+108-49
...@@ -2,6 +2,7 @@...@@ -2,6 +2,7 @@
22
3air: Air,3air: Air,
4lower: Lower,4lower: Lower,
5atom_index: u32,
5debug_output: DebugInfoOutput,6debug_output: DebugInfoOutput,
6code: *std.ArrayList(u8),7code: *std.ArrayList(u8),
78
...@@ -37,83 +38,84 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -37,83 +38,84 @@ pub fn emitMir(emit: *Emit) Error!void {
37 }) switch (lowered_relocs[0].target) {38 }) switch (lowered_relocs[0].target) {
38 .inst => |target| try emit.relocs.append(emit.lower.allocator, .{39 .inst => |target| try emit.relocs.append(emit.lower.allocator, .{
39 .source = start_offset,40 .source = start_offset,
41 .source_offset = end_offset - 4,
40 .target = target,42 .target = target,
41 .offset = end_offset - 4,43 .target_offset = lowered_relocs[0].off,
42 .length = @intCast(end_offset - start_offset),44 .length = @intCast(end_offset - start_offset),
43 }),45 }),
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| {
45 // Add relocation to the decl.47 // Add relocation to the decl.
46 const zo = elf_file.zigObjectPtr().?;48 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).?;
48 const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);50 const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);
49 try atom_ptr.addReloc(elf_file, .{51 try atom_ptr.addReloc(elf_file, .{
50 .r_offset = end_offset - 4,52 .r_offset = end_offset - 4,
51 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,53 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
52 .r_addend = -4,54 .r_addend = lowered_relocs[0].off - 4,
53 });55 });
54 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {56 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
55 // Add relocation to the decl.57 // Add relocation to the decl.
56 const zo = macho_file.getZigObject().?;58 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).?;
58 try atom.addReloc(macho_file, .{60 try atom.addReloc(macho_file, .{
59 .tag = .@"extern",61 .tag = .@"extern",
60 .offset = end_offset - 4,62 .offset = end_offset - 4,
61 .target = symbol.sym_index,63 .target = sym_index,
62 .addend = 0,64 .addend = lowered_relocs[0].off,
63 .type = .branch,65 .type = .branch,
64 .meta = .{66 .meta = .{
65 .pcrel = true,67 .pcrel = true,
66 .has_subtractor = false,68 .has_subtractor = false,
67 .length = 2,69 .length = 2,
68 .symbolnum = @intCast(symbol.sym_index),70 .symbolnum = @intCast(sym_index),
69 },71 },
70 });72 });
71 } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {73 } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
72 // Add relocation to the decl.74 // Add relocation to the decl.
73 const atom_index = coff_file.getAtomIndexForSymbol(75 const atom_index = coff_file.getAtomIndexForSymbol(
74 .{ .sym_index = symbol.atom_index, .file = null },76 .{ .sym_index = emit.atom_index, .file = null },
75 ).?;77 ).?;
76 const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)78 const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
77 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)79 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
78 else80 else
79 link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };81 link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
80 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{82 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
81 .type = .direct,83 .type = .direct,
82 .target = target,84 .target = target,
83 .offset = end_offset - 4,85 .offset = end_offset - 4,
84 .addend = 0,86 .addend = @intCast(lowered_relocs[0].off),
85 .pcrel = true,87 .pcrel = true,
86 .length = 2,88 .length = 2,
87 });89 });
88 } else return emit.fail("TODO implement extern reloc for {s}", .{90 } else return emit.fail("TODO implement extern reloc for {s}", .{
89 @tagName(emit.lower.bin_file.tag),91 @tagName(emit.lower.bin_file.tag),
90 }),92 }),
91 .linker_tlsld => |data| {93 .linker_tlsld => |sym_index| {
92 const elf_file = emit.lower.bin_file.cast(.elf).?;94 const elf_file = emit.lower.bin_file.cast(.elf).?;
93 const zo = elf_file.zigObjectPtr().?;95 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).?;
95 const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);97 const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);
96 try atom.addReloc(elf_file, .{98 try atom.addReloc(elf_file, .{
97 .r_offset = end_offset - 4,99 .r_offset = end_offset - 4,
98 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,100 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
99 .r_addend = -4,101 .r_addend = lowered_relocs[0].off - 4,
100 });102 });
101 },103 },
102 .linker_dtpoff => |data| {104 .linker_dtpoff => |sym_index| {
103 const elf_file = emit.lower.bin_file.cast(.elf).?;105 const elf_file = emit.lower.bin_file.cast(.elf).?;
104 const zo = elf_file.zigObjectPtr().?;106 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).?;
106 const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);108 const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);
107 try atom.addReloc(elf_file, .{109 try atom.addReloc(elf_file, .{
108 .r_offset = end_offset - 4,110 .r_offset = end_offset - 4,
109 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,111 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
110 .r_addend = 0,112 .r_addend = lowered_relocs[0].off,
111 });113 });
112 },114 },
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| {
114 const zo = elf_file.zigObjectPtr().?;116 const zo = elf_file.zigObjectPtr().?;
115 const atom = zo.symbol(data.atom_index).atom(elf_file).?;117 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
116 const sym = zo.symbol(data.sym_index);118 const sym = zo.symbol(sym_index);
117 if (emit.lower.pic) {119 if (emit.lower.pic) {
118 const r_type: u32 = if (sym.flags.is_extern_ptr)120 const r_type: u32 = if (sym.flags.is_extern_ptr)
119 @intFromEnum(std.elf.R_X86_64.GOTPCREL)121 @intFromEnum(std.elf.R_X86_64.GOTPCREL)
...@@ -121,8 +123,8 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -121,8 +123,8 @@ pub fn emitMir(emit: *Emit) Error!void {
121 @intFromEnum(std.elf.R_X86_64.PC32);123 @intFromEnum(std.elf.R_X86_64.PC32);
122 try atom.addReloc(elf_file, .{124 try atom.addReloc(elf_file, .{
123 .r_offset = end_offset - 4,125 .r_offset = end_offset - 4,
124 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,126 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
125 .r_addend = -4,127 .r_addend = lowered_relocs[0].off - 4,
126 });128 });
127 } else {129 } else {
128 const r_type: u32 = if (sym.flags.is_tls)130 const r_type: u32 = if (sym.flags.is_tls)
...@@ -131,14 +133,14 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -131,14 +133,14 @@ pub fn emitMir(emit: *Emit) Error!void {
131 @intFromEnum(std.elf.R_X86_64.@"32");133 @intFromEnum(std.elf.R_X86_64.@"32");
132 try atom.addReloc(elf_file, .{134 try atom.addReloc(elf_file, .{
133 .r_offset = end_offset - 4,135 .r_offset = end_offset - 4,
134 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,136 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
135 .r_addend = 0,137 .r_addend = lowered_relocs[0].off,
136 });138 });
137 }139 }
138 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {140 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
139 const zo = macho_file.getZigObject().?;141 const zo = macho_file.getZigObject().?;
140 const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?;142 const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
141 const sym = &zo.symbols.items[data.sym_index];143 const sym = &zo.symbols.items[sym_index];
142 const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr)144 const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr)
143 .got_load145 .got_load
144 else if (sym.flags.tlv)146 else if (sym.flags.tlv)
...@@ -148,33 +150,33 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -148,33 +150,33 @@ pub fn emitMir(emit: *Emit) Error!void {
148 try atom.addReloc(macho_file, .{150 try atom.addReloc(macho_file, .{
149 .tag = .@"extern",151 .tag = .@"extern",
150 .offset = @intCast(end_offset - 4),152 .offset = @intCast(end_offset - 4),
151 .target = data.sym_index,153 .target = sym_index,
152 .addend = 0,154 .addend = lowered_relocs[0].off,
153 .type = @"type",155 .type = @"type",
154 .meta = .{156 .meta = .{
155 .pcrel = true,157 .pcrel = true,
156 .has_subtractor = false,158 .has_subtractor = false,
157 .length = 2,159 .length = 2,
158 .symbolnum = @intCast(data.sym_index),160 .symbolnum = @intCast(sym_index),
159 },161 },
160 });162 });
161 } else unreachable,163 } else unreachable,
162 .linker_got,164 .linker_got,
163 .linker_direct,165 .linker_direct,
164 .linker_import,166 .linker_import,
165 => |symbol| if (emit.lower.bin_file.cast(.elf)) |_| {167 => |sym_index| if (emit.lower.bin_file.cast(.elf)) |_| {
166 unreachable;168 unreachable;
167 } else if (emit.lower.bin_file.cast(.macho)) |_| {169 } else if (emit.lower.bin_file.cast(.macho)) |_| {
168 unreachable;170 unreachable;
169 } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {171 } else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
170 const atom_index = coff_file.getAtomIndexForSymbol(.{172 const atom_index = coff_file.getAtomIndexForSymbol(.{
171 .sym_index = symbol.atom_index,173 .sym_index = emit.atom_index,
172 .file = null,174 .file = null,
173 }).?;175 }).?;
174 const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)176 const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
175 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)177 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
176 else178 else
177 link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };179 link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
178 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{180 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
179 .type = switch (lowered_relocs[0].target) {181 .type = switch (lowered_relocs[0].target) {
180 .linker_got => .got,182 .linker_got => .got,
...@@ -184,16 +186,15 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -184,16 +186,15 @@ pub fn emitMir(emit: *Emit) Error!void {
184 },186 },
185 .target = target,187 .target = target,
186 .offset = @intCast(end_offset - 4),188 .offset = @intCast(end_offset - 4),
187 .addend = 0,189 .addend = @intCast(lowered_relocs[0].off),
188 .pcrel = true,190 .pcrel = true,
189 .length = 2,191 .length = 2,
190 });192 });
191 } else if (emit.lower.bin_file.cast(.plan9)) |p9_file| {193 } else if (emit.lower.bin_file.cast(.plan9)) |p9_file| {
192 const atom_index = symbol.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
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_direct195 .target = sym_index, // we set sym_index to just be the atom index
194 .target = symbol.sym_index, // we set sym_index to just be the atom index
195 .offset = @intCast(end_offset - 4),196 .offset = @intCast(end_offset - 4),
196 .addend = 0,197 .addend = @intCast(lowered_relocs[0].off),
197 .type = .pcrel,198 .type = .pcrel,
198 });199 });
199 } else return emit.fail("TODO implement linker reloc for {s}", .{200 } else return emit.fail("TODO implement linker reloc for {s}", .{
...@@ -261,6 +262,10 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -261,6 +262,10 @@ pub fn emitMir(emit: *Emit) Error!void {
261 .pseudo_dbg_local_ai_s,262 .pseudo_dbg_local_ai_s,
262 .pseudo_dbg_local_ai_u,263 .pseudo_dbg_local_ai_u,
263 .pseudo_dbg_local_ai_64,264 .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,
264 .pseudo_dbg_local_am,269 .pseudo_dbg_local_am,
265 => {270 => {
266 switch (emit.debug_output) {271 switch (emit.debug_output) {
...@@ -279,6 +284,57 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -279,6 +284,57 @@ pub fn emitMir(emit: *Emit) Error!void {
279 };284 };
280 break :stack_value &loc_buf[0];285 break :stack_value &loc_buf[0];
281 } } },286 } } },
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 },
282 .pseudo_dbg_local_am => loc: {338 .pseudo_dbg_local_am => loc: {
283 const mem = emit.lower.mem(mir_inst.data.ax.payload);339 const mem = emit.lower.mem(mir_inst.data.ax.payload);
284 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{340 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
...@@ -287,7 +343,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -287,7 +343,7 @@ pub fn emitMir(emit: *Emit) Error!void {
287 .none => .{ .constu = 0 },343 .none => .{ .constu = 0 },
288 .reg => |reg| .{ .breg = reg.dwarfNum() },344 .reg => |reg| .{ .breg = reg.dwarfNum() },
289 .frame => unreachable,345 .frame => unreachable,
290 .reloc => |reloc| .{ .addr = .{ .sym = reloc.sym_index } },346 .reloc => |sym_index| .{ .addr = .{ .sym = sym_index } },
291 };347 };
292 break :base &loc_buf[0];348 break :base &loc_buf[0];
293 },349 },
...@@ -352,10 +408,12 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {...@@ -352,10 +408,12 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {
352const Reloc = struct {408const Reloc = struct {
353 /// Offset of the instruction.409 /// Offset of the instruction.
354 source: usize,410 source: usize,
411 /// Offset of the relocation within the instruction.
412 source_offset: u32,
355 /// Target of the relocation.413 /// Target of the relocation.
356 target: Mir.Inst.Index,414 target: Mir.Inst.Index,
357 /// Offset of the relocation within the instruction.415 /// Offset from the target instruction.
358 offset: u32,416 target_offset: i32,
359 /// Length of the instruction.417 /// Length of the instruction.
360 length: u5,418 length: u5,
361};419};
...@@ -368,8 +426,8 @@ fn fixupRelocs(emit: *Emit) Error!void {...@@ -368,8 +426,8 @@ fn fixupRelocs(emit: *Emit) Error!void {
368 for (emit.relocs.items) |reloc| {426 for (emit.relocs.items) |reloc| {
369 const target = emit.code_offset_mapping.get(reloc.target) orelse427 const target = emit.code_offset_mapping.get(reloc.target) orelse
370 return emit.fail("JMP/CALL relocation target not found!", .{});428 return emit.fail("JMP/CALL relocation target not found!", .{});
371 const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length));429 const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length)) + reloc.target_offset;
372 std.mem.writeInt(i32, emit.code.items[reloc.offset..][0..4], @intCast(disp), .little);430 std.mem.writeInt(i32, emit.code.items[reloc.source_offset..][0..4], @intCast(disp), .little);
373 }431 }
374}432}
375433
...@@ -422,6 +480,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {...@@ -422,6 +480,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
422 }480 }
423}481}
424482
483const bits = @import("bits.zig");
425const link = @import("../../link.zig");484const link = @import("../../link.zig");
426const log = std.log.scoped(.emit);485const log = std.log.scoped(.emit);
427const std = @import("std");486const std = @import("std");
src/arch/x86_64/Lower.zig+40-35
...@@ -52,16 +52,17 @@ pub const Error = error{...@@ -52,16 +52,17 @@ pub const Error = error{
52pub const Reloc = struct {52pub const Reloc = struct {
53 lowered_inst_index: u8,53 lowered_inst_index: u8,
54 target: Target,54 target: Target,
55 off: i32,
5556
56 const Target = union(enum) {57 const Target = union(enum) {
57 inst: Mir.Inst.Index,58 inst: Mir.Inst.Index,
58 linker_reloc: bits.Symbol,59 linker_reloc: u32,
59 linker_tlsld: bits.Symbol,60 linker_tlsld: u32,
60 linker_dtpoff: bits.Symbol,61 linker_dtpoff: u32,
61 linker_extern_fn: bits.Symbol,62 linker_extern_fn: u32,
62 linker_got: bits.Symbol,63 linker_got: u32,
63 linker_direct: bits.Symbol,64 linker_direct: u32,
64 linker_import: bits.Symbol,65 linker_import: u32,
65 };66 };
66};67};
6768
...@@ -173,19 +174,19 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -173,19 +174,19 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
173 .pseudo_j_z_and_np_inst => {174 .pseudo_j_z_and_np_inst => {
174 assert(inst.data.inst.fixes == ._);175 assert(inst.data.inst.fixes == ._);
175 try lower.emit(.none, .jnz, &.{176 try lower.emit(.none, .jnz, &.{
176 .{ .imm = lower.reloc(.{ .inst = index + 1 }) },177 .{ .imm = lower.reloc(.{ .inst = index + 1 }, 0) },
177 });178 });
178 try lower.emit(.none, .jnp, &.{179 try lower.emit(.none, .jnp, &.{
179 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },180 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
180 });181 });
181 },182 },
182 .pseudo_j_nz_or_p_inst => {183 .pseudo_j_nz_or_p_inst => {
183 assert(inst.data.inst.fixes == ._);184 assert(inst.data.inst.fixes == ._);
184 try lower.emit(.none, .jnz, &.{185 try lower.emit(.none, .jnz, &.{
185 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },186 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
186 });187 });
187 try lower.emit(.none, .jp, &.{188 try lower.emit(.none, .jp, &.{
188 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },189 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
189 });190 });
190 },191 },
191192
...@@ -195,7 +196,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -195,7 +196,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
195 .{ .imm = Immediate.s(@bitCast(inst.data.ri.i)) },196 .{ .imm = Immediate.s(@bitCast(inst.data.ri.i)) },
196 });197 });
197 try lower.emit(.none, .jz, &.{198 try lower.emit(.none, .jz, &.{
198 .{ .imm = lower.reloc(.{ .inst = index + 1 }) },199 .{ .imm = lower.reloc(.{ .inst = index + 1 }, 0) },
199 });200 });
200 try lower.emit(.none, .lea, &.{201 try lower.emit(.none, .lea, &.{
201 .{ .reg = inst.data.ri.r1 },202 .{ .reg = inst.data.ri.r1 },
...@@ -211,7 +212,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -211,7 +212,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
211 .{ .reg = inst.data.ri.r1.to32() },212 .{ .reg = inst.data.ri.r1.to32() },
212 });213 });
213 try lower.emit(.none, .jmp, &.{214 try lower.emit(.none, .jmp, &.{
214 .{ .imm = lower.reloc(.{ .inst = index }) },215 .{ .imm = lower.reloc(.{ .inst = index }, 0) },
215 });216 });
216 assert(lower.result_insts_len == pseudo_probe_align_insts);217 assert(lower.result_insts_len == pseudo_probe_align_insts);
217 },218 },
...@@ -257,7 +258,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -257,7 +258,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
257 .{ .imm = Immediate.s(page_size) },258 .{ .imm = Immediate.s(page_size) },
258 });259 });
259 try lower.emit(.none, .jae, &.{260 try lower.emit(.none, .jae, &.{
260 .{ .imm = lower.reloc(.{ .inst = index }) },261 .{ .imm = lower.reloc(.{ .inst = index }, 0) },
261 });262 });
262 assert(lower.result_insts_len == pseudo_probe_adjust_loop_insts);263 assert(lower.result_insts_len == pseudo_probe_adjust_loop_insts);
263 },264 },
...@@ -273,6 +274,10 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -273,6 +274,10 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
273 .pseudo_dbg_local_ai_s,274 .pseudo_dbg_local_ai_s,
274 .pseudo_dbg_local_ai_u,275 .pseudo_dbg_local_ai_u,
275 .pseudo_dbg_local_ai_64,276 .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,
276 .pseudo_dbg_local_am,281 .pseudo_dbg_local_am,
277 .pseudo_dead_none,282 .pseudo_dead_none,
278 => {},283 => {},
...@@ -328,10 +333,11 @@ pub fn mem(lower: Lower, payload: u32) Memory {...@@ -328,10 +333,11 @@ pub fn mem(lower: Lower, payload: u32) Memory {
328 return lower.mir.resolveFrameLoc(lower.mir.extraData(Mir.Memory, payload).data).decode();333 return lower.mir.resolveFrameLoc(lower.mir.extraData(Mir.Memory, payload).data).decode();
329}334}
330335
331fn reloc(lower: *Lower, target: Reloc.Target) Immediate {336fn reloc(lower: *Lower, target: Reloc.Target, off: i32) Immediate {
332 lower.result_relocs[lower.result_relocs_len] = .{337 lower.result_relocs[lower.result_relocs_len] = .{
333 .lowered_inst_index = lower.result_insts_len,338 .lowered_inst_index = lower.result_insts_len,
334 .target = target,339 .target = target,
340 .off = off,
335 };341 };
336 lower.result_relocs_len += 1;342 lower.result_relocs_len += 1;
337 return Immediate.s(0);343 return Immediate.s(0);
...@@ -347,37 +353,36 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -347,37 +353,36 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
347 else => op,353 else => op,
348 .mem => |mem_op| switch (mem_op.base()) {354 .mem => |mem_op| switch (mem_op.base()) {
349 else => op,355 else => op,
350 .reloc => |sym| op: {356 .reloc => |sym_index| op: {
351 assert(prefix == .none);357 assert(prefix == .none);
352 assert(mem_op.sib.disp == 0);358 assert(mem_op.sib.disp == 0);
353 assert(mem_op.sib.scale_index.scale == 0);359 assert(mem_op.sib.scale_index.scale == 0);
354360
355 if (lower.bin_file.cast(.elf)) |elf_file| {361 if (lower.bin_file.cast(.elf)) |elf_file| {
356 const zo = elf_file.zigObjectPtr().?;362 const zo = elf_file.zigObjectPtr().?;
357 const elf_sym = zo.symbol(sym.sym_index);363 const elf_sym = zo.symbol(sym_index);
358364
359 if (elf_sym.flags.is_tls) {365 if (elf_sym.flags.is_tls) {
360 // TODO handle extern TLS vars, i.e., emit GD model366 // TODO handle extern TLS vars, i.e., emit GD model
361 if (lower.pic) {367 if (lower.pic) {
362 // Here, we currently assume local dynamic TLS vars, and so368 // Here, we currently assume local dynamic TLS vars, and so
363 // we emit LD model.369 // we emit LD model.
364 _ = lower.reloc(.{ .linker_tlsld = sym });370 _ = lower.reloc(.{ .linker_tlsld = sym_index }, 0);
365 lower.result_insts[lower.result_insts_len] =371 lower.result_insts[lower.result_insts_len] =
366 try Instruction.new(.none, .lea, &[_]Operand{372 try Instruction.new(.none, .lea, &[_]Operand{
367 .{ .reg = .rdi },373 .{ .reg = .rdi },
368 .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },374 .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },
369 });375 });
370 lower.result_insts_len += 1;376 lower.result_insts_len += 1;
371 _ = lower.reloc(.{ .linker_extern_fn = .{377 _ = lower.reloc(.{
372 .atom_index = sym.atom_index,378 .linker_extern_fn = try elf_file.getGlobalSymbol("__tls_get_addr", null),
373 .sym_index = try elf_file.getGlobalSymbol("__tls_get_addr", null),379 }, 0);
374 } });
375 lower.result_insts[lower.result_insts_len] =380 lower.result_insts[lower.result_insts_len] =
376 try Instruction.new(.none, .call, &[_]Operand{381 try Instruction.new(.none, .call, &[_]Operand{
377 .{ .imm = Immediate.s(0) },382 .{ .imm = Immediate.s(0) },
378 });383 });
379 lower.result_insts_len += 1;384 lower.result_insts_len += 1;
380 _ = lower.reloc(.{ .linker_dtpoff = sym });385 _ = lower.reloc(.{ .linker_dtpoff = sym_index }, 0);
381 emit_mnemonic = .lea;386 emit_mnemonic = .lea;
382 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{387 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
383 .base = .{ .reg = .rax },388 .base = .{ .reg = .rax },
...@@ -391,7 +396,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -391,7 +396,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
391 .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },396 .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },
392 });397 });
393 lower.result_insts_len += 1;398 lower.result_insts_len += 1;
394 _ = lower.reloc(.{ .linker_reloc = sym });399 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
395 emit_mnemonic = .lea;400 emit_mnemonic = .lea;
396 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{401 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
397 .base = .{ .reg = .rax },402 .base = .{ .reg = .rax },
...@@ -400,7 +405,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -400,7 +405,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
400 }405 }
401 }406 }
402407
403 _ = lower.reloc(.{ .linker_reloc = sym });408 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
404 if (lower.pic) switch (mnemonic) {409 if (lower.pic) switch (mnemonic) {
405 .lea => {410 .lea => {
406 if (elf_sym.flags.is_extern_ptr) emit_mnemonic = .mov;411 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)...@@ -437,10 +442,10 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
437 }442 }
438 } else if (lower.bin_file.cast(.macho)) |macho_file| {443 } else if (lower.bin_file.cast(.macho)) |macho_file| {
439 const zo = macho_file.getZigObject().?;444 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
442 if (macho_sym.flags.tlv) {447 if (macho_sym.flags.tlv) {
443 _ = lower.reloc(.{ .linker_reloc = sym });448 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
444 lower.result_insts[lower.result_insts_len] =449 lower.result_insts[lower.result_insts_len] =
445 try Instruction.new(.none, .mov, &[_]Operand{450 try Instruction.new(.none, .mov, &[_]Operand{
446 .{ .reg = .rdi },451 .{ .reg = .rdi },
...@@ -456,7 +461,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -456,7 +461,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
456 break :op .{ .reg = .rax };461 break :op .{ .reg = .rax };
457 }462 }
458463
459 _ = lower.reloc(.{ .linker_reloc = sym });464 _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
460 break :op switch (mnemonic) {465 break :op switch (mnemonic) {
461 .lea => {466 .lea => {
462 if (macho_sym.flags.is_extern_ptr) emit_mnemonic = .mov;467 if (macho_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
...@@ -535,7 +540,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -535,7 +540,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
535 }, switch (inst.ops) {540 }, switch (inst.ops) {
536 .none => &.{},541 .none => &.{},
537 .inst => &.{542 .inst => &.{
538 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },543 .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
539 },544 },
540 .i_s, .i_u => &.{545 .i_s, .i_u => &.{
541 .{ .imm = lower.imm(inst.ops, inst.data.i.i) },546 .{ .imm = lower.imm(inst.ops, inst.data.i.i) },
...@@ -637,17 +642,17 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -637,17 +642,17 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
637 .{ .imm = lower.imm(inst.ops, inst.data.rrix.i) },642 .{ .imm = lower.imm(inst.ops, inst.data.rrix.i) },
638 },643 },
639 .extern_fn_reloc, .rel => &.{644 .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) },
641 },646 },
642 .got_reloc, .direct_reloc, .import_reloc => ops: {647 .got_reloc, .direct_reloc, .import_reloc => ops: {
643 const reg = inst.data.rx.r1;648 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;
645 _ = lower.reloc(switch (inst.ops) {650 _ = lower.reloc(switch (inst.ops) {
646 .got_reloc => .{ .linker_got = extra },651 .got_reloc => .{ .linker_got = extra.sym_index },
647 .direct_reloc => .{ .linker_direct = extra },652 .direct_reloc => .{ .linker_direct = extra.sym_index },
648 .import_reloc => .{ .linker_import = extra },653 .import_reloc => .{ .linker_import = extra.sym_index },
649 else => unreachable,654 else => unreachable,
650 });655 }, extra.off);
651 break :ops &.{656 break :ops &.{
652 .{ .reg = reg },657 .{ .reg = reg },
653 .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },658 .{ .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 {...@@ -820,16 +820,16 @@ pub const Inst = struct {
820 /// Uses `reloc` payload.820 /// Uses `reloc` payload.
821 extern_fn_reloc,821 extern_fn_reloc,
822 /// Linker relocation - GOT indirection.822 /// 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`.
824 got_reloc,824 got_reloc,
825 /// Linker relocation - direct reference.825 /// 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`.
827 direct_reloc,827 direct_reloc,
828 /// Linker relocation - imports table indirection (binding).828 /// 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`.
830 import_reloc,830 import_reloc,
831 /// Linker relocation - threadlocal variable via GOT indirection.831 /// 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`.
833 tlv_reloc,833 tlv_reloc,
834834
835 // Pseudo instructions:835 // Pseudo instructions:
...@@ -907,9 +907,21 @@ pub const Inst = struct {...@@ -907,9 +907,21 @@ pub const Inst = struct {
907 /// Uses `ai` payload.907 /// Uses `ai` payload.
908 pseudo_dbg_local_ai_u,908 pseudo_dbg_local_ai_u,
909 /// Local argument or variable.909 /// Local argument or variable.
910 /// Uses `ax` payload with extra data of type `Imm64`.910 /// Uses `ai` payload with extra data of type `Imm64`.
911 pseudo_dbg_local_ai_64,911 pseudo_dbg_local_ai_64,
912 /// Local argument or variable.912 /// 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.
913 /// Uses `ax` payload with extra data of type `Memory`.925 /// Uses `ax` payload with extra data of type `Memory`.
914 pseudo_dbg_local_am,926 pseudo_dbg_local_am,
915927
...@@ -1014,6 +1026,9 @@ pub const Inst = struct {...@@ -1014,6 +1026,9 @@ pub const Inst = struct {
1014 fixes: Fixes = ._,1026 fixes: Fixes = ._,
1015 payload: u32,1027 payload: u32,
1016 },1028 },
1029 ix: struct {
1030 payload: u32,
1031 },
1017 a: struct {1032 a: struct {
1018 air_inst: Air.Inst.Index,1033 air_inst: Air.Inst.Index,
1019 },1034 },
...@@ -1021,14 +1036,18 @@ pub const Inst = struct {...@@ -1021,14 +1036,18 @@ pub const Inst = struct {
1021 air_inst: Air.Inst.Index,1036 air_inst: Air.Inst.Index,
1022 i: u32,1037 i: u32,
1023 },1038 },
1039 as: struct {
1040 air_inst: Air.Inst.Index,
1041 sym_index: u32,
1042 },
1024 ax: struct {1043 ax: struct {
1025 air_inst: Air.Inst.Index,1044 air_inst: Air.Inst.Index,
1026 payload: u32,1045 payload: u32,
1027 },1046 },
1028 /// Relocation for the linker where:1047 /// Relocation for the linker where:
1029 /// * `atom_index` is the index of the source
1030 /// * `sym_index` is the index of the target1048 /// * `sym_index` is the index of the target
1031 reloc: bits.Symbol,1049 /// * `off` is the offset from the target
1050 reloc: bits.SymbolOffset,
1032 /// Debug line and column position1051 /// Debug line and column position
1033 line_column: struct {1052 line_column: struct {
1034 line: u32,1053 line: u32,
...@@ -1048,6 +1067,8 @@ pub const Inst = struct {...@@ -1048,6 +1067,8 @@ pub const Inst = struct {
1048 }1067 }
1049};1068};
10501069
1070pub const AirOffset = struct { air_inst: Air.Inst.Index, off: i32 };
1071
1051/// Used in conjunction with payload to transfer a list of used registers in a compact manner.1072/// Used in conjunction with payload to transfer a list of used registers in a compact manner.
1052pub const RegisterList = struct {1073pub const RegisterList = struct {
1053 bitset: BitSet = BitSet.initEmpty(),1074 bitset: BitSet = BitSet.initEmpty(),
...@@ -1146,15 +1167,13 @@ pub const Memory = struct {...@@ -1146,15 +1167,13 @@ pub const Memory = struct {
1146 .none => undefined,1167 .none => undefined,
1147 .reg => |reg| @intFromEnum(reg),1168 .reg => |reg| @intFromEnum(reg),
1148 .frame => |frame_index| @intFromEnum(frame_index),1169 .frame => |frame_index| @intFromEnum(frame_index),
1149 .reloc => |symbol| symbol.sym_index,1170 .reloc => |sym_index| sym_index,
1150 },1171 },
1151 .off = switch (mem.mod) {1172 .off = switch (mem.mod) {
1152 .rm => |rm| @bitCast(rm.disp),1173 .rm => |rm| @bitCast(rm.disp),
1153 .off => |off| @truncate(off),1174 .off => |off| @truncate(off),
1154 },1175 },
1155 .extra = if (mem.base == .reloc)1176 .extra = if (mem.mod == .off)
1156 mem.base.reloc.atom_index
1157 else if (mem.mod == .off)
1158 @intCast(mem.mod.off >> 32)1177 @intCast(mem.mod.off >> 32)
1159 else1178 else
1160 undefined,1179 undefined,
...@@ -1174,7 +1193,7 @@ pub const Memory = struct {...@@ -1174,7 +1193,7 @@ pub const Memory = struct {
1174 .none => .none,1193 .none => .none,
1175 .reg => .{ .reg = @enumFromInt(mem.base) },1194 .reg => .{ .reg = @enumFromInt(mem.base) },
1176 .frame => .{ .frame = @enumFromInt(mem.base) },1195 .frame => .{ .frame = @enumFromInt(mem.base) },
1177 .reloc => .{ .reloc = .{ .atom_index = mem.extra, .sym_index = mem.base } },1196 .reloc => .{ .reloc = mem.base },
1178 },1197 },
1179 .scale_index = switch (mem.info.index) {1198 .scale_index = switch (mem.info.index) {
1180 .none => null,1199 .none => null,
...@@ -1214,6 +1233,7 @@ pub fn extraData(mir: Mir, comptime T: type, index: u32) struct { data: T, end:...@@ -1214,6 +1233,7 @@ pub fn extraData(mir: Mir, comptime T: type, index: u32) struct { data: T, end:
1214 @field(result, field.name) = switch (field.type) {1233 @field(result, field.name) = switch (field.type) {
1215 u32 => mir.extra[i],1234 u32 => mir.extra[i],
1216 i32, Memory.Info => @bitCast(mir.extra[i]),1235 i32, Memory.Info => @bitCast(mir.extra[i]),
1236 bits.FrameIndex, Air.Inst.Index => @enumFromInt(mir.extra[i]),
1217 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),1237 else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
1218 };1238 };
1219 i += 1;1239 i += 1;
...@@ -1229,6 +1249,11 @@ pub const FrameLoc = struct {...@@ -1229,6 +1249,11 @@ pub const FrameLoc = struct {
1229 disp: i32,1249 disp: i32,
1230};1250};
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
1232pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {1257pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {
1233 return switch (mem.info.base) {1258 return switch (mem.info.base) {
1234 .none, .reg, .reloc => mem,1259 .none, .reg, .reloc => mem,
src/arch/x86_64/bits.zig+12-27
...@@ -447,26 +447,11 @@ pub const FrameIndex = enum(u32) {...@@ -447,26 +447,11 @@ pub const FrameIndex = enum(u32) {
447 }447 }
448};448};
449449
450/// A linker symbol not yet allocated in VM.450pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
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,
456451
457 pub fn format(452pub const RegisterOffset = struct { reg: Register, off: i32 = 0 };
458 sym: Symbol,453
459 comptime fmt: []const u8,454pub const SymbolOffset = struct { sym_index: u32, off: i32 = 0 };
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};
470455
471pub const Memory = struct {456pub const Memory = struct {
472 base: Base,457 base: Base,
...@@ -476,7 +461,7 @@ pub const Memory = struct {...@@ -476,7 +461,7 @@ pub const Memory = struct {
476 none,461 none,
477 reg: Register,462 reg: Register,
478 frame: FrameIndex,463 frame: FrameIndex,
479 reloc: Symbol,464 reloc: u32,
480465
481 pub const Tag = @typeInfo(Base).Union.tag_type.?;466 pub const Tag = @typeInfo(Base).Union.tag_type.?;
482467
...@@ -568,7 +553,7 @@ pub const Memory = struct {...@@ -568,7 +553,7 @@ pub const Memory = struct {
568pub const Immediate = union(enum) {553pub const Immediate = union(enum) {
569 signed: i32,554 signed: i32,
570 unsigned: u64,555 unsigned: u64,
571 reloc: Symbol,556 reloc: SymbolOffset,
572557
573 pub fn u(x: u64) Immediate {558 pub fn u(x: u64) Immediate {
574 return .{ .unsigned = x };559 return .{ .unsigned = x };
...@@ -578,19 +563,19 @@ pub const Immediate = union(enum) {...@@ -578,19 +563,19 @@ pub const Immediate = union(enum) {
578 return .{ .signed = x };563 return .{ .signed = x };
579 }564 }
580565
581 pub fn rel(symbol: Symbol) Immediate {566 pub fn rel(sym_off: SymbolOffset) Immediate {
582 return .{ .reloc = symbol };567 return .{ .reloc = sym_off };
583 }568 }
584569
585 pub fn format(570 pub fn format(
586 imm: Immediate,571 imm: Immediate,
587 comptime fmt: []const u8,572 comptime _: []const u8,
588 options: std.fmt.FormatOptions,573 _: std.fmt.FormatOptions,
589 writer: anytype,574 writer: anytype,
590 ) @TypeOf(writer).Error!void {575 ) @TypeOf(writer).Error!void {
591 switch (imm) {576 switch (imm) {
592 .reloc => |x| try std.fmt.formatType(x, fmt, options, writer, 0),577 inline else => |int| try writer.print("{d}", .{int}),
593 inline else => |x| try writer.print("{d}", .{x}),578 .reloc => |sym_off| try writer.print("Symbol({[sym_index]d}) + {[off]d}", sym_off),
594 }579 }
595 }580 }
596};581};
src/arch/x86_64/encoder.zig+5-10
...@@ -266,17 +266,12 @@ pub const Instruction = struct {...@@ -266,17 +266,12 @@ pub const Instruction = struct {
266266
267 try writer.writeByte('[');267 try writer.writeByte('[');
268268
269 var any = false;269 var any = true;
270 switch (sib.base) {270 switch (sib.base) {
271 .none => {},271 .none => any = false,
272 .reg => |reg| {272 .reg => |reg| try writer.print("{s}", .{@tagName(reg)}),
273 try writer.print("{s}", .{@tagName(reg)});273 .frame => |frame_index| try writer.print("{}", .{frame_index}),
274 any = true;274 .reloc => |sym_index| try writer.print("Symbol({d})", .{sym_index}),
275 },
276 inline .frame, .reloc => |payload| {
277 try writer.print("{}", .{payload});
278 any = true;
279 },
280 }275 }
281 if (mem.scaleIndex()) |si| {276 if (mem.scaleIndex()) |si| {
282 if (any) try writer.writeAll(" + ");277 if (any) try writer.writeAll(" + ");