| author | |
| committer | |
| log | 55864e98e08c9d44ee2ea6fc1f3a3c2a98042310 |
| tree | 78344089f8c4cc2bdc07ea74f0a47b8f500d2fcb |
| parent | eaa227449c894a9205d63c2e963b967d13446591 |
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, |
| 110 | 110 | ||
| 111 | const air_bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {}; | 111 | const air_bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {}; |
| 112 | 112 | ||
| 113 | const FrameAddr = struct { index: FrameIndex, off: i32 = 0 }; | ||
| 114 | const RegisterOffset = struct { reg: Register, off: i32 = 0 }; | ||
| 115 | const SymbolOffset = struct { sym: u32, off: i32 = 0 }; | ||
| 116 | |||
| 117 | const Owner = union(enum) { | 113 | const 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 index | 201 | /// 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 index | 204 | /// 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 abi | 207 | /// 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 yet | 1031 | .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 | } |
| 1359 | 1367 | ||
| 1360 | fn asmAirImmediate(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, imm: Immediate) !void { | 1368 | fn 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 | else | 1385 | .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 | |||
| 1421 | fn 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 | |||
| 1443 | fn 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 | } |
| 2517 | 2593 | ||
| 2518 | fn getFrameAddrAlignment(self: *Self, frame_addr: FrameAddr) Alignment { | 2594 | fn 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 | } |
| 2522 | 2598 | ||
| 2523 | fn getFrameAddrSize(self: *Self, frame_addr: FrameAddr) u32 { | 2599 | fn 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 | } |
| 2526 | 2602 | ||
| ... | @@ -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 this | 15106 | .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 @@ |
| 2 | 2 | ||
| 3 | air: Air, | 3 | air: Air, |
| 4 | lower: Lower, | 4 | lower: Lower, |
| 5 | atom_index: u32, | ||
| 5 | debug_output: DebugInfoOutput, | 6 | debug_output: DebugInfoOutput, |
| 6 | code: *std.ArrayList(u8), | 7 | code: *std.ArrayList(u8), |
| 7 | 8 | ||
| ... | @@ -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 | else | 80 | 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_load | 145 | .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 | else | 178 | 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_direct | 195 | .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 { |
| 352 | const Reloc = struct { | 408 | const 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) orelse | 427 | 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 | } |
| 375 | 433 | ||
| ... | @@ -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 | } |
| 424 | 482 | ||
| 483 | const bits = @import("bits.zig"); | ||
| 425 | const link = @import("../../link.zig"); | 484 | const link = @import("../../link.zig"); |
| 426 | const log = std.log.scoped(.emit); | 485 | const log = std.log.scoped(.emit); |
| 427 | const std = @import("std"); | 486 | const 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{ |
| 52 | pub const Reloc = struct { | 52 | pub const Reloc = struct { |
| 53 | lowered_inst_index: u8, | 53 | lowered_inst_index: u8, |
| 54 | target: Target, | 54 | target: Target, |
| 55 | off: i32, | ||
| 55 | 56 | ||
| 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 | }; |
| 67 | 68 | ||
| ... | @@ -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 | }, |
| 191 | 192 | ||
| ... | @@ -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 | } |
| 330 | 335 | ||
| 331 | fn reloc(lower: *Lower, target: Reloc.Target) Immediate { | 336 | fn 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); |
| 354 | 360 | ||
| 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); |
| 358 | 364 | ||
| 359 | if (elf_sym.flags.is_tls) { | 365 | if (elf_sym.flags.is_tls) { |
| 360 | // TODO handle extern TLS vars, i.e., emit GD model | 366 | // 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 so | 368 | // 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 | } |
| 402 | 407 | ||
| 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]; |
| 441 | 446 | ||
| 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 | } |
| 458 | 463 | ||
| 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, |
| 834 | 834 | ||
| 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, |
| 915 | 927 | ||
| ... | @@ -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 target | 1048 | /// * `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 position | 1051 | /// 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 | }; |
| 1050 | 1069 | ||
| 1070 | pub 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. |
| 1052 | pub const RegisterList = struct { | 1073 | pub 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 | else | 1178 | 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 | }; |
| 1231 | 1251 | ||
| 1252 | pub 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 | |||
| 1232 | pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory { | 1257 | pub 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 | }; |
| 449 | 449 | ||
| 450 | /// A linker symbol not yet allocated in VM. | 450 | pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 }; |
| 451 | pub 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, | ||
| 456 | 451 | ||
| 457 | pub fn format( | 452 | pub const RegisterOffset = struct { reg: Register, off: i32 = 0 }; |
| 458 | sym: Symbol, | 453 | |
| 459 | comptime fmt: []const u8, | 454 | pub 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 | }; | ||
| 470 | 455 | ||
| 471 | pub const Memory = struct { | 456 | pub 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, |
| 480 | 465 | ||
| 481 | pub const Tag = @typeInfo(Base).Union.tag_type.?; | 466 | pub const Tag = @typeInfo(Base).Union.tag_type.?; |
| 482 | 467 | ||
| ... | @@ -568,7 +553,7 @@ pub const Memory = struct { | ... | @@ -568,7 +553,7 @@ pub const Memory = struct { |
| 568 | pub const Immediate = union(enum) { | 553 | pub const Immediate = union(enum) { |
| 569 | signed: i32, | 554 | signed: i32, |
| 570 | unsigned: u64, | 555 | unsigned: u64, |
| 571 | reloc: Symbol, | 556 | reloc: SymbolOffset, |
| 572 | 557 | ||
| 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 | } |
| 580 | 565 | ||
| 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 | } |
| 584 | 569 | ||
| 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 { |
| 266 | 266 | ||
| 267 | try writer.writeByte('['); | 267 | try writer.writeByte('['); |
| 268 | 268 | ||
| 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(" + "); |