Commit 55864e98e0
Changed files (6)
src
src/arch/x86_64/bits.zig
@@ -447,26 +447,11 @@ pub const FrameIndex = enum(u32) {
}
};
-/// A linker symbol not yet allocated in VM.
-pub const Symbol = struct {
- /// Index of the containing atom.
- atom_index: u32,
- /// Index into the linker's symbol table.
- sym_index: u32,
+pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
- pub fn format(
- sym: Symbol,
- comptime fmt: []const u8,
- options: std.fmt.FormatOptions,
- writer: anytype,
- ) @TypeOf(writer).Error!void {
- try writer.writeAll("Symbol(");
- try std.fmt.formatType(sym.atom_index, fmt, options, writer, 0);
- try writer.writeAll(", ");
- try std.fmt.formatType(sym.sym_index, fmt, options, writer, 0);
- try writer.writeByte(')');
- }
-};
+pub const RegisterOffset = struct { reg: Register, off: i32 = 0 };
+
+pub const SymbolOffset = struct { sym_index: u32, off: i32 = 0 };
pub const Memory = struct {
base: Base,
@@ -476,7 +461,7 @@ pub const Memory = struct {
none,
reg: Register,
frame: FrameIndex,
- reloc: Symbol,
+ reloc: u32,
pub const Tag = @typeInfo(Base).Union.tag_type.?;
@@ -568,7 +553,7 @@ pub const Memory = struct {
pub const Immediate = union(enum) {
signed: i32,
unsigned: u64,
- reloc: Symbol,
+ reloc: SymbolOffset,
pub fn u(x: u64) Immediate {
return .{ .unsigned = x };
@@ -578,19 +563,19 @@ pub const Immediate = union(enum) {
return .{ .signed = x };
}
- pub fn rel(symbol: Symbol) Immediate {
- return .{ .reloc = symbol };
+ pub fn rel(sym_off: SymbolOffset) Immediate {
+ return .{ .reloc = sym_off };
}
pub fn format(
imm: Immediate,
- comptime fmt: []const u8,
- options: std.fmt.FormatOptions,
+ comptime _: []const u8,
+ _: std.fmt.FormatOptions,
writer: anytype,
) @TypeOf(writer).Error!void {
switch (imm) {
- .reloc => |x| try std.fmt.formatType(x, fmt, options, writer, 0),
- inline else => |x| try writer.print("{d}", .{x}),
+ inline else => |int| try writer.print("{d}", .{int}),
+ .reloc => |sym_off| try writer.print("Symbol({[sym_index]d}) + {[off]d}", sym_off),
}
}
};
src/arch/x86_64/CodeGen.zig
@@ -64,8 +64,8 @@ va_info: union {
sysv: struct {
gp_count: u32,
fp_count: u32,
- overflow_arg_area: FrameAddr,
- reg_save_area: FrameAddr,
+ overflow_arg_area: bits.FrameAddr,
+ reg_save_area: bits.FrameAddr,
},
win64: struct {},
},
@@ -110,10 +110,6 @@ air_bookkeeping: @TypeOf(air_bookkeeping_init) = air_bookkeeping_init,
const air_bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {};
-const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
-const RegisterOffset = struct { reg: Register, off: i32 = 0 };
-const SymbolOffset = struct { sym: u32, off: i32 = 0 };
-
const Owner = union(enum) {
nav_index: InternPool.Nav.Index,
lazy_sym: link.File.LazySymbol,
@@ -171,7 +167,7 @@ pub const MCValue = union(enum) {
/// The value is split across two registers.
register_pair: [2]Register,
/// The value is a constant offset from the value in a register.
- register_offset: RegisterOffset,
+ register_offset: bits.RegisterOffset,
/// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.
register_overflow: struct { reg: Register, eflags: Condition },
/// The value is in memory at a hard-coded address.
@@ -179,11 +175,11 @@ pub const MCValue = union(enum) {
memory: u64,
/// The value is in memory at an address not-yet-allocated by the linker.
/// This traditionally corresponds to a relocation emitted in a relocatable object file.
- load_symbol: SymbolOffset,
+ load_symbol: bits.SymbolOffset,
/// The address of the memory location not-yet-allocated by the linker.
- lea_symbol: SymbolOffset,
+ lea_symbol: bits.SymbolOffset,
/// The value is in memory at a constant offset from the address in a register.
- indirect: RegisterOffset,
+ indirect: bits.RegisterOffset,
/// The value is in memory.
/// Payload is a symbol index.
load_direct: u32,
@@ -204,10 +200,10 @@ pub const MCValue = union(enum) {
lea_tlv: u32,
/// The value stored at an offset from a frame index
/// Payload is a frame address.
- load_frame: FrameAddr,
+ load_frame: bits.FrameAddr,
/// The address of an offset from a frame index
/// Payload is a frame address.
- lea_frame: FrameAddr,
+ lea_frame: bits.FrameAddr,
/// Supports integer_per_element abi
elementwise_regs_then_frame: packed struct { regs: u3 = 0, frame_off: i29 = 0, frame_index: FrameIndex },
/// This indicates that we have already allocated a frame index for this instruction,
@@ -423,10 +419,7 @@ pub const MCValue = union(enum) {
.load_symbol => |sym_off| {
assert(sym_off.off == 0);
return .{
- .base = .{ .reloc = .{
- .atom_index = try function.owner.getSymbolIndex(function),
- .sym_index = sym_off.sym,
- } },
+ .base = .{ .reloc = sym_off.sym_index },
.mod = .{ .rm = .{
.size = size,
.disp = sym_off.off,
@@ -453,8 +446,8 @@ pub const MCValue = union(enum) {
.register_overflow => |pl| try writer.print("{s}:{s}", .{
@tagName(pl.eflags), @tagName(pl.reg),
}),
- .load_symbol => |pl| try writer.print("[{} + 0x{x}]", .{ pl.sym, pl.off }),
- .lea_symbol => |pl| try writer.print("{} + 0x{x}", .{ pl.sym, pl.off }),
+ .load_symbol => |pl| try writer.print("[{} + 0x{x}]", .{ pl.sym_index, pl.off }),
+ .lea_symbol => |pl| try writer.print("{} + 0x{x}", .{ pl.sym_index, pl.off }),
.indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
.load_direct => |pl| try writer.print("[direct:{d}]", .{pl}),
.lea_direct => |pl| try writer.print("direct:{d}", .{pl}),
@@ -921,6 +914,13 @@ pub fn generate(
.link_mode = comp.config.link_mode,
.pic = mod.pic,
},
+ .atom_index = function.owner.getSymbolIndex(&function) catch |err| switch (err) {
+ error.CodegenFail => return Result{ .fail = function.err_msg.? },
+ error.OutOfRegisters => return Result{
+ .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
+ },
+ else => |e| return e,
+ },
.debug_output = debug_output,
.code = code,
.prev_di_pc = 0,
@@ -1019,6 +1019,13 @@ pub fn generateLazy(
.link_mode = comp.config.link_mode,
.pic = mod.pic,
},
+ .atom_index = function.owner.getSymbolIndex(&function) catch |err| switch (err) {
+ error.CodegenFail => return Result{ .fail = function.err_msg.? },
+ error.OutOfRegisters => return Result{
+ .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
+ },
+ else => |e| return e,
+ },
.debug_output = debug_output,
.code = code,
.prev_di_pc = undefined, // no debug info yet
@@ -1192,6 +1199,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
self.mir_extra.appendAssumeCapacity(switch (field.type) {
u32 => @field(extra, field.name),
i32, Mir.Memory.Info => @bitCast(@field(extra, field.name)),
+ bits.FrameIndex => @intFromEnum(@field(extra, field.name)),
else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
});
}
@@ -1358,26 +1366,94 @@ fn asmAir(self: *Self, tag: MirTagAir, inst: Air.Inst.Index) !void {
}
fn asmAirImmediate(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, imm: Immediate) !void {
- const ops: Mir.Inst.Ops, const i: u32 = switch (imm) {
- .signed => |s| .{ switch (tag) {
- .dbg_local => .pseudo_dbg_local_ai_s,
- }, @bitCast(s) },
- .unsigned => |u| if (math.cast(u32, u)) |small|
- .{ switch (tag) {
+ switch (imm) {
+ .signed => |s| _ = try self.addInst(.{
+ .tag = .pseudo,
+ .ops = switch (tag) {
+ .dbg_local => .pseudo_dbg_local_ai_s,
+ },
+ .data = .{ .ai = .{
+ .air_inst = inst,
+ .i = @bitCast(s),
+ } },
+ }),
+ .unsigned => |u| _ = if (math.cast(u32, u)) |small| try self.addInst(.{
+ .tag = .pseudo,
+ .ops = switch (tag) {
.dbg_local => .pseudo_dbg_local_ai_u,
- }, small }
- else
- .{ switch (tag) {
+ },
+ .data = .{ .ai = .{
+ .air_inst = inst,
+ .i = small,
+ } },
+ }) else try self.addInst(.{
+ .tag = .pseudo,
+ .ops = switch (tag) {
.dbg_local => .pseudo_dbg_local_ai_64,
- }, try self.addExtra(Mir.Imm64.encode(u)) },
- .reloc => unreachable,
- };
+ },
+ .data = .{ .ai = .{
+ .air_inst = inst,
+ .i = try self.addExtra(Mir.Imm64.encode(u)),
+ } },
+ }),
+ .reloc => |sym_off| _ = if (sym_off.off == 0) try self.addInst(.{
+ .tag = .pseudo,
+ .ops = switch (tag) {
+ .dbg_local => .pseudo_dbg_local_as,
+ },
+ .data = .{ .as = .{
+ .air_inst = inst,
+ .sym_index = sym_off.sym_index,
+ } },
+ }) else try self.addInst(.{
+ .tag = .pseudo,
+ .ops = switch (tag) {
+ .dbg_local => .pseudo_dbg_local_aso,
+ },
+ .data = .{ .ax = .{
+ .air_inst = inst,
+ .payload = try self.addExtra(sym_off),
+ } },
+ }),
+ }
+}
+
+fn asmAirRegisterImmediate(
+ self: *Self,
+ tag: MirTagAir,
+ inst: Air.Inst.Index,
+ reg: Register,
+ imm: Immediate,
+) !void {
_ = try self.addInst(.{
.tag = .pseudo,
- .ops = ops,
- .data = .{ .ai = .{
+ .ops = switch (tag) {
+ .dbg_local => .pseudo_dbg_local_aro,
+ },
+ .data = .{ .rx = .{
+ .r1 = reg,
+ .payload = try self.addExtra(Mir.AirOffset{
+ .air_inst = inst,
+ .off = imm.signed,
+ }),
+ } },
+ });
+}
+
+fn asmAirFrameAddress(
+ self: *Self,
+ tag: MirTagAir,
+ inst: Air.Inst.Index,
+ frame_addr: bits.FrameAddr,
+) !void {
+ _ = try self.addInst(.{
+ .tag = .pseudo,
+ .ops = switch (tag) {
+ .dbg_local => .pseudo_dbg_local_af,
+ },
+ .data = .{ .ax = .{
.air_inst = inst,
- .i = i,
+ .payload = try self.addExtra(frame_addr),
} },
});
}
@@ -1433,9 +1509,9 @@ fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void {
.reloc => .rel,
},
.data = switch (imm) {
- .reloc => |x| reloc: {
+ .reloc => |sym_off| reloc: {
assert(tag[0] == ._);
- break :reloc .{ .reloc = x };
+ break :reloc .{ .reloc = sym_off };
},
.signed, .unsigned => .{ .i = .{
.fixes = tag[0],
@@ -2515,12 +2591,12 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo
};
}
-fn getFrameAddrAlignment(self: *Self, frame_addr: FrameAddr) Alignment {
+fn getFrameAddrAlignment(self: *Self, frame_addr: bits.FrameAddr) Alignment {
const alloc_align = self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_align;
return @enumFromInt(@min(@intFromEnum(alloc_align), @ctz(frame_addr.off)));
}
-fn getFrameAddrSize(self: *Self, frame_addr: FrameAddr) u32 {
+fn getFrameAddrSize(self: *Self, frame_addr: bits.FrameAddr) u32 {
return self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_size - @as(u31, @intCast(frame_addr.off));
}
@@ -11999,6 +12075,8 @@ fn genLocalDebugInfo(
.none => try self.asmAir(.dbg_local, inst),
.unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
.immediate => |imm| try self.asmAirImmediate(.dbg_local, inst, Immediate.u(imm)),
+ .lea_frame => |frame_addr| try self.asmAirFrameAddress(.dbg_local, inst, frame_addr),
+ .lea_symbol => |sym_off| try self.asmAirImmediate(.dbg_local, inst, Immediate.rel(sym_off)),
else => {
const ty = switch (tag) {
else => unreachable,
@@ -12027,14 +12105,14 @@ fn genLocalDebugInfo(
} },
}),
.lea_symbol => |sym_off| try self.asmAirMemory(.dbg_local, inst, .{
- .base = .{ .reloc = .{ .atom_index = undefined, .sym_index = sym_off.sym } },
+ .base = .{ .reloc = sym_off.sym_index },
.mod = .{ .rm = .{
.size = .qword,
.disp = sym_off.off,
} },
}),
- .lea_direct, .lea_got, .lea_tlv => |sym| try self.asmAirMemory(.dbg_local, inst, .{
- .base = .{ .reloc = .{ .atom_index = undefined, .sym_index = sym } },
+ .lea_direct, .lea_got, .lea_tlv => |sym_index| try self.asmAirMemory(.dbg_local, inst, .{
+ .base = .{ .reloc = sym_index },
.mod = .{ .rm = .{ .size = .qword } },
}),
},
@@ -12357,10 +12435,7 @@ fn genCall(self: *Self, info: union(enum) {
if (self.bin_file.cast(.elf)) |elf_file| {
const zo = elf_file.zigObjectPtr().?;
const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
- try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
- .atom_index = try self.owner.getSymbolIndex(self),
- .sym_index = sym_index,
- }));
+ try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index }));
} else if (self.bin_file.cast(.coff)) |coff_file| {
const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
@@ -12370,10 +12445,7 @@ fn genCall(self: *Self, info: union(enum) {
const zo = macho_file.getZigObject().?;
const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);
const sym = zo.symbols.items[sym_index];
- try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
- .atom_index = try self.owner.getSymbolIndex(self),
- .sym_index = sym.nlist_idx,
- }));
+ try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym.nlist_idx }));
} else if (self.bin_file.cast(.plan9)) |p9| {
const atom_index = try p9.seeNav(pt, func.owner_nav);
const atom = p9.getAtom(atom_index);
@@ -12391,19 +12463,13 @@ fn genCall(self: *Self, info: union(enum) {
@"extern".name.toSlice(ip),
@"extern".lib_name.toSlice(ip),
);
- try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
- .atom_index = try self.owner.getSymbolIndex(self),
- .sym_index = target_sym_index,
- }));
+ try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
} else if (self.bin_file.cast(.macho)) |macho_file| {
const target_sym_index = try macho_file.getGlobalSymbol(
@"extern".name.toSlice(ip),
@"extern".lib_name.toSlice(ip),
);
- try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
- .atom_index = try self.owner.getSymbolIndex(self),
- .sym_index = target_sym_index,
- }));
+ try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
} else try self.genExternSymbolRef(
.call,
@"extern".lib_name.toSlice(ip),
@@ -12418,16 +12484,10 @@ fn genCall(self: *Self, info: union(enum) {
},
.lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {
const target_sym_index = try elf_file.getGlobalSymbol(lib.callee, lib.lib);
- try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
- .atom_index = try self.owner.getSymbolIndex(self),
- .sym_index = target_sym_index,
- }));
+ try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
} else if (self.bin_file.cast(.macho)) |macho_file| {
const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib);
- try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
- .atom_index = try self.owner.getSymbolIndex(self),
- .sym_index = target_sym_index,
- }));
+ try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
} else try self.genExternSymbolRef(.call, lib.lib, lib.callee),
}
return call_info.return_value.short;
@@ -14968,10 +15028,7 @@ fn genSetReg(
.general_purpose => {
assert(sym_off.off == 0);
try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(dst_reg, abi_size), .{
- .base = .{ .reloc = .{
- .atom_index = try self.owner.getSymbolIndex(self),
- .sym_index = sym_off.sym,
- } },
+ .base = .{ .reloc = sym_off.sym_index },
.mod = .{ .rm = .{
.size = self.memSize(ty),
.disp = sym_off.off,
@@ -14989,10 +15046,7 @@ fn genSetReg(
.ops = .direct_reloc,
.data = .{ .rx = .{
.r1 = registerAlias(dst_reg, abi_size),
- .payload = try self.addExtra(bits.Symbol{
- .atom_index = try self.owner.getSymbolIndex(self),
- .sym_index = sym_index,
- }),
+ .payload = try self.addExtra(bits.SymbolOffset{ .sym_index = sym_index }),
} },
});
return;
@@ -15017,52 +15071,38 @@ fn genSetReg(
},
);
},
- .lea_symbol => |sym_index| {
- const atom_index = try self.owner.getSymbolIndex(self);
- switch (self.bin_file.tag) {
- .elf, .macho => {
- try self.asmRegisterMemory(
- .{ ._, .lea },
- dst_reg.to64(),
- .{
- .base = .{ .reloc = .{
- .atom_index = atom_index,
- .sym_index = sym_index.sym,
- } },
- .mod = .{ .rm = .{
- .size = .qword,
- .disp = sym_index.off,
- } },
- },
- );
- },
- else => return self.fail("TODO emit symbol sequence on {s}", .{
- @tagName(self.bin_file.tag),
- }),
- }
- },
- .lea_direct, .lea_got => |sym_index| {
- const atom_index = try self.owner.getSymbolIndex(self);
- _ = try self.addInst(.{
- .tag = switch (src_mcv) {
- .lea_direct => .lea,
- .lea_got => .mov,
- else => unreachable,
- },
- .ops = switch (src_mcv) {
- .lea_direct => .direct_reloc,
- .lea_got => .got_reloc,
- else => unreachable,
+ .lea_symbol => |sym_off| switch (self.bin_file.tag) {
+ .elf, .macho => try self.asmRegisterMemory(
+ .{ ._, .lea },
+ dst_reg.to64(),
+ .{
+ .base = .{ .reloc = sym_off.sym_index },
+ .mod = .{ .rm = .{
+ .size = .qword,
+ .disp = sym_off.off,
+ } },
},
- .data = .{ .rx = .{
- .r1 = dst_reg.to64(),
- .payload = try self.addExtra(bits.Symbol{
- .atom_index = atom_index,
- .sym_index = sym_index,
- }),
- } },
- });
+ ),
+ else => return self.fail("TODO emit symbol sequence on {s}", .{
+ @tagName(self.bin_file.tag),
+ }),
},
+ .lea_direct, .lea_got => |sym_index| _ = try self.addInst(.{
+ .tag = switch (src_mcv) {
+ .lea_direct => .lea,
+ .lea_got => .mov,
+ else => unreachable,
+ },
+ .ops = switch (src_mcv) {
+ .lea_direct => .direct_reloc,
+ .lea_got => .got_reloc,
+ else => unreachable,
+ },
+ .data = .{ .rx = .{
+ .r1 = dst_reg.to64(),
+ .payload = try self.addExtra(bits.SymbolOffset{ .sym_index = sym_index }),
+ } },
+ }),
.lea_tlv => unreachable, // TODO: remove this
.air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref), opts),
}
@@ -15083,7 +15123,7 @@ fn genSetMem(
.none => .{ .immediate = @bitCast(@as(i64, disp)) },
.reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
.frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },
- .reloc => |base_symbol| .{ .lea_symbol = .{ .sym = base_symbol.sym_index, .off = disp } },
+ .reloc => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index, .off = disp } },
};
switch (src_mcv) {
.none,
@@ -15326,7 +15366,6 @@ fn genExternSymbolRef(
lib: ?[]const u8,
callee: []const u8,
) InnerError!void {
- const atom_index = try self.owner.getSymbolIndex(self);
if (self.bin_file.cast(.coff)) |coff_file| {
const global_index = try coff_file.getGlobalSymbol(callee, lib);
_ = try self.addInst(.{
@@ -15334,8 +15373,7 @@ fn genExternSymbolRef(
.ops = .import_reloc,
.data = .{ .rx = .{
.r1 = .rax,
- .payload = try self.addExtra(bits.Symbol{
- .atom_index = atom_index,
+ .payload = try self.addExtra(bits.SymbolOffset{
.sym_index = link.File.Coff.global_symbol_bit | global_index,
}),
} },
@@ -15362,10 +15400,10 @@ fn genLazySymbolRef(
if (self.mod.pic) {
switch (tag) {
.lea, .call => try self.genSetReg(reg, Type.usize, .{
- .lea_symbol = .{ .sym = sym_index },
+ .lea_symbol = .{ .sym_index = sym_index },
}, .{}),
.mov => try self.genSetReg(reg, Type.usize, .{
- .load_symbol = .{ .sym = sym_index },
+ .load_symbol = .{ .sym_index = sym_index },
}, .{}),
else => unreachable,
}
@@ -15374,19 +15412,13 @@ fn genLazySymbolRef(
.call => try self.asmRegister(.{ ._, .call }, reg),
else => unreachable,
}
- } else {
- const reloc = bits.Symbol{
- .atom_index = try self.owner.getSymbolIndex(self),
- .sym_index = sym_index,
- };
- switch (tag) {
- .lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{
- .base = .{ .reloc = reloc },
- .mod = .{ .rm = .{ .size = .qword } },
- }),
- .call => try self.asmImmediate(.{ ._, .call }, Immediate.rel(reloc)),
- else => unreachable,
- }
+ } else switch (tag) {
+ .lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{
+ .base = .{ .reloc = sym_index },
+ .mod = .{ .rm = .{ .size = .qword } },
+ }),
+ .call => try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index })),
+ else => unreachable,
}
} else if (self.bin_file.cast(.plan9)) |p9_file| {
const atom_index = p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
@@ -15436,10 +15468,10 @@ fn genLazySymbolRef(
const sym = zo.symbols.items[sym_index];
switch (tag) {
.lea, .call => try self.genSetReg(reg, Type.usize, .{
- .lea_symbol = .{ .sym = sym.nlist_idx },
+ .lea_symbol = .{ .sym_index = sym.nlist_idx },
}, .{}),
.mov => try self.genSetReg(reg, Type.usize, .{
- .load_symbol = .{ .sym = sym.nlist_idx },
+ .load_symbol = .{ .sym_index = sym.nlist_idx },
}, .{}),
else => unreachable,
}
@@ -18784,7 +18816,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
.{ .frame = frame_index },
0,
Type.usize,
- .{ .lea_symbol = .{ .sym = tlv_sym } },
+ .{ .lea_symbol = .{ .sym_index = tlv_sym } },
.{},
);
break :init .{ .load_frame = .{ .index = frame_index } };
@@ -18840,8 +18872,8 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
.undef => .undef,
.immediate => |imm| .{ .immediate = imm },
.memory => |addr| .{ .memory = addr },
- .load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },
- .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym = sym_index } },
+ .load_symbol => |sym_index| .{ .load_symbol = .{ .sym_index = sym_index } },
+ .lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index } },
.load_direct => |sym_index| .{ .load_direct = sym_index },
.lea_direct => |sym_index| .{ .lea_direct = sym_index },
.load_got => |sym_index| .{ .lea_got = sym_index },
src/arch/x86_64/Emit.zig
@@ -2,6 +2,7 @@
air: Air,
lower: Lower,
+atom_index: u32,
debug_output: DebugInfoOutput,
code: *std.ArrayList(u8),
@@ -37,83 +38,84 @@ pub fn emitMir(emit: *Emit) Error!void {
}) switch (lowered_relocs[0].target) {
.inst => |target| try emit.relocs.append(emit.lower.allocator, .{
.source = start_offset,
+ .source_offset = end_offset - 4,
.target = target,
- .offset = end_offset - 4,
+ .target_offset = lowered_relocs[0].off,
.length = @intCast(end_offset - start_offset),
}),
- .linker_extern_fn => |symbol| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
+ .linker_extern_fn => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
// Add relocation to the decl.
const zo = elf_file.zigObjectPtr().?;
- const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?;
+ const atom_ptr = zo.symbol(emit.atom_index).atom(elf_file).?;
const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);
try atom_ptr.addReloc(elf_file, .{
.r_offset = end_offset - 4,
- .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,
- .r_addend = -4,
+ .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
+ .r_addend = lowered_relocs[0].off - 4,
});
} else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
// Add relocation to the decl.
const zo = macho_file.getZigObject().?;
- const atom = zo.symbols.items[symbol.atom_index].getAtom(macho_file).?;
+ const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
try atom.addReloc(macho_file, .{
.tag = .@"extern",
.offset = end_offset - 4,
- .target = symbol.sym_index,
- .addend = 0,
+ .target = sym_index,
+ .addend = lowered_relocs[0].off,
.type = .branch,
.meta = .{
.pcrel = true,
.has_subtractor = false,
.length = 2,
- .symbolnum = @intCast(symbol.sym_index),
+ .symbolnum = @intCast(sym_index),
},
});
} else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
// Add relocation to the decl.
const atom_index = coff_file.getAtomIndexForSymbol(
- .{ .sym_index = symbol.atom_index, .file = null },
+ .{ .sym_index = emit.atom_index, .file = null },
).?;
- const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)
- coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)
+ const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
+ coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
else
- link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };
+ link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
.type = .direct,
.target = target,
.offset = end_offset - 4,
- .addend = 0,
+ .addend = @intCast(lowered_relocs[0].off),
.pcrel = true,
.length = 2,
});
} else return emit.fail("TODO implement extern reloc for {s}", .{
@tagName(emit.lower.bin_file.tag),
}),
- .linker_tlsld => |data| {
+ .linker_tlsld => |sym_index| {
const elf_file = emit.lower.bin_file.cast(.elf).?;
const zo = elf_file.zigObjectPtr().?;
- const atom = zo.symbol(data.atom_index).atom(elf_file).?;
+ const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);
try atom.addReloc(elf_file, .{
.r_offset = end_offset - 4,
- .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
- .r_addend = -4,
+ .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
+ .r_addend = lowered_relocs[0].off - 4,
});
},
- .linker_dtpoff => |data| {
+ .linker_dtpoff => |sym_index| {
const elf_file = emit.lower.bin_file.cast(.elf).?;
const zo = elf_file.zigObjectPtr().?;
- const atom = zo.symbol(data.atom_index).atom(elf_file).?;
+ const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);
try atom.addReloc(elf_file, .{
.r_offset = end_offset - 4,
- .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
- .r_addend = 0,
+ .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
+ .r_addend = lowered_relocs[0].off,
});
},
- .linker_reloc => |data| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
+ .linker_reloc => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
const zo = elf_file.zigObjectPtr().?;
- const atom = zo.symbol(data.atom_index).atom(elf_file).?;
- const sym = zo.symbol(data.sym_index);
+ const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
+ const sym = zo.symbol(sym_index);
if (emit.lower.pic) {
const r_type: u32 = if (sym.flags.is_extern_ptr)
@intFromEnum(std.elf.R_X86_64.GOTPCREL)
@@ -121,8 +123,8 @@ pub fn emitMir(emit: *Emit) Error!void {
@intFromEnum(std.elf.R_X86_64.PC32);
try atom.addReloc(elf_file, .{
.r_offset = end_offset - 4,
- .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
- .r_addend = -4,
+ .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
+ .r_addend = lowered_relocs[0].off - 4,
});
} else {
const r_type: u32 = if (sym.flags.is_tls)
@@ -131,14 +133,14 @@ pub fn emitMir(emit: *Emit) Error!void {
@intFromEnum(std.elf.R_X86_64.@"32");
try atom.addReloc(elf_file, .{
.r_offset = end_offset - 4,
- .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
- .r_addend = 0,
+ .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
+ .r_addend = lowered_relocs[0].off,
});
}
} else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
const zo = macho_file.getZigObject().?;
- const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?;
- const sym = &zo.symbols.items[data.sym_index];
+ const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
+ const sym = &zo.symbols.items[sym_index];
const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr)
.got_load
else if (sym.flags.tlv)
@@ -148,33 +150,33 @@ pub fn emitMir(emit: *Emit) Error!void {
try atom.addReloc(macho_file, .{
.tag = .@"extern",
.offset = @intCast(end_offset - 4),
- .target = data.sym_index,
- .addend = 0,
+ .target = sym_index,
+ .addend = lowered_relocs[0].off,
.type = @"type",
.meta = .{
.pcrel = true,
.has_subtractor = false,
.length = 2,
- .symbolnum = @intCast(data.sym_index),
+ .symbolnum = @intCast(sym_index),
},
});
} else unreachable,
.linker_got,
.linker_direct,
.linker_import,
- => |symbol| if (emit.lower.bin_file.cast(.elf)) |_| {
+ => |sym_index| if (emit.lower.bin_file.cast(.elf)) |_| {
unreachable;
} else if (emit.lower.bin_file.cast(.macho)) |_| {
unreachable;
} else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
const atom_index = coff_file.getAtomIndexForSymbol(.{
- .sym_index = symbol.atom_index,
+ .sym_index = emit.atom_index,
.file = null,
}).?;
- const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)
- coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)
+ const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
+ coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
else
- link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };
+ link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
.type = switch (lowered_relocs[0].target) {
.linker_got => .got,
@@ -184,16 +186,15 @@ pub fn emitMir(emit: *Emit) Error!void {
},
.target = target,
.offset = @intCast(end_offset - 4),
- .addend = 0,
+ .addend = @intCast(lowered_relocs[0].off),
.pcrel = true,
.length = 2,
});
} else if (emit.lower.bin_file.cast(.plan9)) |p9_file| {
- const atom_index = symbol.atom_index;
- 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
- .target = symbol.sym_index, // we set sym_index to just be the atom index
+ 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
+ .target = sym_index, // we set sym_index to just be the atom index
.offset = @intCast(end_offset - 4),
- .addend = 0,
+ .addend = @intCast(lowered_relocs[0].off),
.type = .pcrel,
});
} else return emit.fail("TODO implement linker reloc for {s}", .{
@@ -261,6 +262,10 @@ pub fn emitMir(emit: *Emit) Error!void {
.pseudo_dbg_local_ai_s,
.pseudo_dbg_local_ai_u,
.pseudo_dbg_local_ai_64,
+ .pseudo_dbg_local_as,
+ .pseudo_dbg_local_aso,
+ .pseudo_dbg_local_aro,
+ .pseudo_dbg_local_af,
.pseudo_dbg_local_am,
=> {
switch (emit.debug_output) {
@@ -279,6 +284,57 @@ pub fn emitMir(emit: *Emit) Error!void {
};
break :stack_value &loc_buf[0];
} } },
+ .pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{ .addr = .{
+ .sym = mir_inst.data.as.sym_index,
+ } } },
+ .pseudo_dbg_local_aso => loc: {
+ const sym_off = emit.lower.mir.extraData(
+ bits.SymbolOffset,
+ mir_inst.data.ax.payload,
+ ).data;
+ break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
+ sym: {
+ loc_buf[0] = .{ .addr = .{ .sym = sym_off.sym_index } };
+ break :sym &loc_buf[0];
+ },
+ off: {
+ loc_buf[1] = .{ .consts = sym_off.off };
+ break :off &loc_buf[1];
+ },
+ } } };
+ },
+ .pseudo_dbg_local_aro => loc: {
+ const air_off = emit.lower.mir.extraData(
+ Mir.AirOffset,
+ mir_inst.data.rx.payload,
+ ).data;
+ break :loc .{ air_off.air_inst, .{ .plus = .{
+ reg: {
+ loc_buf[0] = .{ .breg = mir_inst.data.rx.r1.dwarfNum() };
+ break :reg &loc_buf[0];
+ },
+ off: {
+ loc_buf[1] = .{ .consts = air_off.off };
+ break :off &loc_buf[1];
+ },
+ } } };
+ },
+ .pseudo_dbg_local_af => loc: {
+ const reg_off = emit.lower.mir.resolveFrameAddr(emit.lower.mir.extraData(
+ bits.FrameAddr,
+ mir_inst.data.ax.payload,
+ ).data);
+ break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
+ reg: {
+ loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() };
+ break :reg &loc_buf[0];
+ },
+ off: {
+ loc_buf[1] = .{ .consts = reg_off.off };
+ break :off &loc_buf[1];
+ },
+ } } };
+ },
.pseudo_dbg_local_am => loc: {
const mem = emit.lower.mem(mir_inst.data.ax.payload);
break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
@@ -287,7 +343,7 @@ pub fn emitMir(emit: *Emit) Error!void {
.none => .{ .constu = 0 },
.reg => |reg| .{ .breg = reg.dwarfNum() },
.frame => unreachable,
- .reloc => |reloc| .{ .addr = .{ .sym = reloc.sym_index } },
+ .reloc => |sym_index| .{ .addr = .{ .sym = sym_index } },
};
break :base &loc_buf[0];
},
@@ -352,10 +408,12 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {
const Reloc = struct {
/// Offset of the instruction.
source: usize,
+ /// Offset of the relocation within the instruction.
+ source_offset: u32,
/// Target of the relocation.
target: Mir.Inst.Index,
- /// Offset of the relocation within the instruction.
- offset: u32,
+ /// Offset from the target instruction.
+ target_offset: i32,
/// Length of the instruction.
length: u5,
};
@@ -368,8 +426,8 @@ fn fixupRelocs(emit: *Emit) Error!void {
for (emit.relocs.items) |reloc| {
const target = emit.code_offset_mapping.get(reloc.target) orelse
return emit.fail("JMP/CALL relocation target not found!", .{});
- const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length));
- std.mem.writeInt(i32, emit.code.items[reloc.offset..][0..4], @intCast(disp), .little);
+ const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length)) + reloc.target_offset;
+ std.mem.writeInt(i32, emit.code.items[reloc.source_offset..][0..4], @intCast(disp), .little);
}
}
@@ -422,6 +480,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
}
}
+const bits = @import("bits.zig");
const link = @import("../../link.zig");
const log = std.log.scoped(.emit);
const std = @import("std");
src/arch/x86_64/encoder.zig
@@ -266,17 +266,12 @@ pub const Instruction = struct {
try writer.writeByte('[');
- var any = false;
+ var any = true;
switch (sib.base) {
- .none => {},
- .reg => |reg| {
- try writer.print("{s}", .{@tagName(reg)});
- any = true;
- },
- inline .frame, .reloc => |payload| {
- try writer.print("{}", .{payload});
- any = true;
- },
+ .none => any = false,
+ .reg => |reg| try writer.print("{s}", .{@tagName(reg)}),
+ .frame => |frame_index| try writer.print("{}", .{frame_index}),
+ .reloc => |sym_index| try writer.print("Symbol({d})", .{sym_index}),
}
if (mem.scaleIndex()) |si| {
if (any) try writer.writeAll(" + ");
src/arch/x86_64/Lower.zig
@@ -52,16 +52,17 @@ pub const Error = error{
pub const Reloc = struct {
lowered_inst_index: u8,
target: Target,
+ off: i32,
const Target = union(enum) {
inst: Mir.Inst.Index,
- linker_reloc: bits.Symbol,
- linker_tlsld: bits.Symbol,
- linker_dtpoff: bits.Symbol,
- linker_extern_fn: bits.Symbol,
- linker_got: bits.Symbol,
- linker_direct: bits.Symbol,
- linker_import: bits.Symbol,
+ linker_reloc: u32,
+ linker_tlsld: u32,
+ linker_dtpoff: u32,
+ linker_extern_fn: u32,
+ linker_got: u32,
+ linker_direct: u32,
+ linker_import: u32,
};
};
@@ -173,19 +174,19 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.pseudo_j_z_and_np_inst => {
assert(inst.data.inst.fixes == ._);
try lower.emit(.none, .jnz, &.{
- .{ .imm = lower.reloc(.{ .inst = index + 1 }) },
+ .{ .imm = lower.reloc(.{ .inst = index + 1 }, 0) },
});
try lower.emit(.none, .jnp, &.{
- .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },
+ .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
});
},
.pseudo_j_nz_or_p_inst => {
assert(inst.data.inst.fixes == ._);
try lower.emit(.none, .jnz, &.{
- .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },
+ .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
});
try lower.emit(.none, .jp, &.{
- .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },
+ .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
});
},
@@ -195,7 +196,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.{ .imm = Immediate.s(@bitCast(inst.data.ri.i)) },
});
try lower.emit(.none, .jz, &.{
- .{ .imm = lower.reloc(.{ .inst = index + 1 }) },
+ .{ .imm = lower.reloc(.{ .inst = index + 1 }, 0) },
});
try lower.emit(.none, .lea, &.{
.{ .reg = inst.data.ri.r1 },
@@ -211,7 +212,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.{ .reg = inst.data.ri.r1.to32() },
});
try lower.emit(.none, .jmp, &.{
- .{ .imm = lower.reloc(.{ .inst = index }) },
+ .{ .imm = lower.reloc(.{ .inst = index }, 0) },
});
assert(lower.result_insts_len == pseudo_probe_align_insts);
},
@@ -257,7 +258,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.{ .imm = Immediate.s(page_size) },
});
try lower.emit(.none, .jae, &.{
- .{ .imm = lower.reloc(.{ .inst = index }) },
+ .{ .imm = lower.reloc(.{ .inst = index }, 0) },
});
assert(lower.result_insts_len == pseudo_probe_adjust_loop_insts);
},
@@ -273,6 +274,10 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
.pseudo_dbg_local_ai_s,
.pseudo_dbg_local_ai_u,
.pseudo_dbg_local_ai_64,
+ .pseudo_dbg_local_as,
+ .pseudo_dbg_local_aso,
+ .pseudo_dbg_local_aro,
+ .pseudo_dbg_local_af,
.pseudo_dbg_local_am,
.pseudo_dead_none,
=> {},
@@ -328,10 +333,11 @@ pub fn mem(lower: Lower, payload: u32) Memory {
return lower.mir.resolveFrameLoc(lower.mir.extraData(Mir.Memory, payload).data).decode();
}
-fn reloc(lower: *Lower, target: Reloc.Target) Immediate {
+fn reloc(lower: *Lower, target: Reloc.Target, off: i32) Immediate {
lower.result_relocs[lower.result_relocs_len] = .{
.lowered_inst_index = lower.result_insts_len,
.target = target,
+ .off = off,
};
lower.result_relocs_len += 1;
return Immediate.s(0);
@@ -347,37 +353,36 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
else => op,
.mem => |mem_op| switch (mem_op.base()) {
else => op,
- .reloc => |sym| op: {
+ .reloc => |sym_index| op: {
assert(prefix == .none);
assert(mem_op.sib.disp == 0);
assert(mem_op.sib.scale_index.scale == 0);
if (lower.bin_file.cast(.elf)) |elf_file| {
const zo = elf_file.zigObjectPtr().?;
- const elf_sym = zo.symbol(sym.sym_index);
+ const elf_sym = zo.symbol(sym_index);
if (elf_sym.flags.is_tls) {
// TODO handle extern TLS vars, i.e., emit GD model
if (lower.pic) {
// Here, we currently assume local dynamic TLS vars, and so
// we emit LD model.
- _ = lower.reloc(.{ .linker_tlsld = sym });
+ _ = lower.reloc(.{ .linker_tlsld = sym_index }, 0);
lower.result_insts[lower.result_insts_len] =
try Instruction.new(.none, .lea, &[_]Operand{
.{ .reg = .rdi },
.{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },
});
lower.result_insts_len += 1;
- _ = lower.reloc(.{ .linker_extern_fn = .{
- .atom_index = sym.atom_index,
- .sym_index = try elf_file.getGlobalSymbol("__tls_get_addr", null),
- } });
+ _ = lower.reloc(.{
+ .linker_extern_fn = try elf_file.getGlobalSymbol("__tls_get_addr", null),
+ }, 0);
lower.result_insts[lower.result_insts_len] =
try Instruction.new(.none, .call, &[_]Operand{
.{ .imm = Immediate.s(0) },
});
lower.result_insts_len += 1;
- _ = lower.reloc(.{ .linker_dtpoff = sym });
+ _ = lower.reloc(.{ .linker_dtpoff = sym_index }, 0);
emit_mnemonic = .lea;
break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
.base = .{ .reg = .rax },
@@ -391,7 +396,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
.{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },
});
lower.result_insts_len += 1;
- _ = lower.reloc(.{ .linker_reloc = sym });
+ _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
emit_mnemonic = .lea;
break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
.base = .{ .reg = .rax },
@@ -400,7 +405,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
}
}
- _ = lower.reloc(.{ .linker_reloc = sym });
+ _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
if (lower.pic) switch (mnemonic) {
.lea => {
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)
}
} else if (lower.bin_file.cast(.macho)) |macho_file| {
const zo = macho_file.getZigObject().?;
- const macho_sym = zo.symbols.items[sym.sym_index];
+ const macho_sym = zo.symbols.items[sym_index];
if (macho_sym.flags.tlv) {
- _ = lower.reloc(.{ .linker_reloc = sym });
+ _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
lower.result_insts[lower.result_insts_len] =
try Instruction.new(.none, .mov, &[_]Operand{
.{ .reg = .rdi },
@@ -456,7 +461,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
break :op .{ .reg = .rax };
}
- _ = lower.reloc(.{ .linker_reloc = sym });
+ _ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
break :op switch (mnemonic) {
.lea => {
if (macho_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
@@ -535,7 +540,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
}, switch (inst.ops) {
.none => &.{},
.inst => &.{
- .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },
+ .{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
},
.i_s, .i_u => &.{
.{ .imm = lower.imm(inst.ops, inst.data.i.i) },
@@ -637,17 +642,17 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
.{ .imm = lower.imm(inst.ops, inst.data.rrix.i) },
},
.extern_fn_reloc, .rel => &.{
- .{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc }) },
+ .{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc.sym_index }, inst.data.reloc.off) },
},
.got_reloc, .direct_reloc, .import_reloc => ops: {
const reg = inst.data.rx.r1;
- const extra = lower.mir.extraData(bits.Symbol, inst.data.rx.payload).data;
+ const extra = lower.mir.extraData(bits.SymbolOffset, inst.data.rx.payload).data;
_ = lower.reloc(switch (inst.ops) {
- .got_reloc => .{ .linker_got = extra },
- .direct_reloc => .{ .linker_direct = extra },
- .import_reloc => .{ .linker_import = extra },
+ .got_reloc => .{ .linker_got = extra.sym_index },
+ .direct_reloc => .{ .linker_direct = extra.sym_index },
+ .import_reloc => .{ .linker_import = extra.sym_index },
else => unreachable,
- });
+ }, extra.off);
break :ops &.{
.{ .reg = reg },
.{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
src/arch/x86_64/Mir.zig
@@ -820,16 +820,16 @@ pub const Inst = struct {
/// Uses `reloc` payload.
extern_fn_reloc,
/// Linker relocation - GOT indirection.
- /// Uses `rx` payload with extra data of type `bits.Symbol`.
+ /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
got_reloc,
/// Linker relocation - direct reference.
- /// Uses `rx` payload with extra data of type `bits.Symbol`.
+ /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
direct_reloc,
/// Linker relocation - imports table indirection (binding).
- /// Uses `rx` payload with extra data of type `bits.Symbol`.
+ /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
import_reloc,
/// Linker relocation - threadlocal variable via GOT indirection.
- /// Uses `rx` payload with extra data of type `bits.Symbol`.
+ /// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
tlv_reloc,
// Pseudo instructions:
@@ -907,9 +907,21 @@ pub const Inst = struct {
/// Uses `ai` payload.
pseudo_dbg_local_ai_u,
/// Local argument or variable.
- /// Uses `ax` payload with extra data of type `Imm64`.
+ /// Uses `ai` payload with extra data of type `Imm64`.
pseudo_dbg_local_ai_64,
/// Local argument or variable.
+ /// Uses `as` payload.
+ pseudo_dbg_local_as,
+ /// Local argument or variable.
+ /// Uses `ax` payload with extra data of type `bits.SymbolOffset`.
+ pseudo_dbg_local_aso,
+ /// Local argument or variable.
+ /// Uses `rx` payload with extra data of type `AirOffset`.
+ pseudo_dbg_local_aro,
+ /// Local argument or variable.
+ /// Uses `ax` payload with extra data of type `bits.FrameAddr`.
+ pseudo_dbg_local_af,
+ /// Local argument or variable.
/// Uses `ax` payload with extra data of type `Memory`.
pseudo_dbg_local_am,
@@ -1014,6 +1026,9 @@ pub const Inst = struct {
fixes: Fixes = ._,
payload: u32,
},
+ ix: struct {
+ payload: u32,
+ },
a: struct {
air_inst: Air.Inst.Index,
},
@@ -1021,14 +1036,18 @@ pub const Inst = struct {
air_inst: Air.Inst.Index,
i: u32,
},
+ as: struct {
+ air_inst: Air.Inst.Index,
+ sym_index: u32,
+ },
ax: struct {
air_inst: Air.Inst.Index,
payload: u32,
},
/// Relocation for the linker where:
- /// * `atom_index` is the index of the source
/// * `sym_index` is the index of the target
- reloc: bits.Symbol,
+ /// * `off` is the offset from the target
+ reloc: bits.SymbolOffset,
/// Debug line and column position
line_column: struct {
line: u32,
@@ -1048,6 +1067,8 @@ pub const Inst = struct {
}
};
+pub const AirOffset = struct { air_inst: Air.Inst.Index, off: i32 };
+
/// Used in conjunction with payload to transfer a list of used registers in a compact manner.
pub const RegisterList = struct {
bitset: BitSet = BitSet.initEmpty(),
@@ -1146,15 +1167,13 @@ pub const Memory = struct {
.none => undefined,
.reg => |reg| @intFromEnum(reg),
.frame => |frame_index| @intFromEnum(frame_index),
- .reloc => |symbol| symbol.sym_index,
+ .reloc => |sym_index| sym_index,
},
.off = switch (mem.mod) {
.rm => |rm| @bitCast(rm.disp),
.off => |off| @truncate(off),
},
- .extra = if (mem.base == .reloc)
- mem.base.reloc.atom_index
- else if (mem.mod == .off)
+ .extra = if (mem.mod == .off)
@intCast(mem.mod.off >> 32)
else
undefined,
@@ -1174,7 +1193,7 @@ pub const Memory = struct {
.none => .none,
.reg => .{ .reg = @enumFromInt(mem.base) },
.frame => .{ .frame = @enumFromInt(mem.base) },
- .reloc => .{ .reloc = .{ .atom_index = mem.extra, .sym_index = mem.base } },
+ .reloc => .{ .reloc = mem.base },
},
.scale_index = switch (mem.info.index) {
.none => null,
@@ -1214,6 +1233,7 @@ pub fn extraData(mir: Mir, comptime T: type, index: u32) struct { data: T, end:
@field(result, field.name) = switch (field.type) {
u32 => mir.extra[i],
i32, Memory.Info => @bitCast(mir.extra[i]),
+ bits.FrameIndex, Air.Inst.Index => @enumFromInt(mir.extra[i]),
else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
};
i += 1;
@@ -1229,6 +1249,11 @@ pub const FrameLoc = struct {
disp: i32,
};
+pub fn resolveFrameAddr(mir: Mir, frame_addr: bits.FrameAddr) bits.RegisterOffset {
+ const frame_loc = mir.frame_locs.get(@intFromEnum(frame_addr.index));
+ return .{ .reg = frame_loc.base, .off = frame_loc.disp + frame_addr.off };
+}
+
pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {
return switch (mem.info.base) {
.none, .reg, .reloc => mem,