mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 22:33:08 +00:00
x86_64: make TLV a separate MCValue
This commit is contained in:
parent
887da399eb
commit
3f35d6984f
@ -3982,7 +3982,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
|
|||||||
.got => .load_memory_ptr_got,
|
.got => .load_memory_ptr_got,
|
||||||
.direct => .load_memory_ptr_direct,
|
.direct => .load_memory_ptr_direct,
|
||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.tlv => @panic("TODO TLV support"),
|
|
||||||
};
|
};
|
||||||
const atom_index = switch (self.bin_file.tag) {
|
const atom_index = switch (self.bin_file.tag) {
|
||||||
.macho => blk: {
|
.macho => blk: {
|
||||||
@ -5511,7 +5510,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
|
|||||||
.got => .load_memory_ptr_got,
|
.got => .load_memory_ptr_got,
|
||||||
.direct => .load_memory_ptr_direct,
|
.direct => .load_memory_ptr_direct,
|
||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.tlv => @panic("TODO TLV support"),
|
|
||||||
};
|
};
|
||||||
const atom_index = switch (self.bin_file.tag) {
|
const atom_index = switch (self.bin_file.tag) {
|
||||||
.macho => blk: {
|
.macho => blk: {
|
||||||
@ -5632,7 +5630,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
|||||||
.got => .load_memory_got,
|
.got => .load_memory_got,
|
||||||
.direct => .load_memory_direct,
|
.direct => .load_memory_direct,
|
||||||
.import => .load_memory_import,
|
.import => .load_memory_import,
|
||||||
.tlv => @panic("TODO TLV support"),
|
|
||||||
};
|
};
|
||||||
const atom_index = switch (self.bin_file.tag) {
|
const atom_index = switch (self.bin_file.tag) {
|
||||||
.macho => blk: {
|
.macho => blk: {
|
||||||
@ -5833,7 +5830,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
|
|||||||
.got => .load_memory_ptr_got,
|
.got => .load_memory_ptr_got,
|
||||||
.direct => .load_memory_ptr_direct,
|
.direct => .load_memory_ptr_direct,
|
||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.tlv => @panic("TODO TLV support"),
|
|
||||||
};
|
};
|
||||||
const atom_index = switch (self.bin_file.tag) {
|
const atom_index = switch (self.bin_file.tag) {
|
||||||
.macho => blk: {
|
.macho => blk: {
|
||||||
@ -6175,6 +6171,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
|
|||||||
.linker_load => |ll| .{ .linker_load = ll },
|
.linker_load => |ll| .{ .linker_load = ll },
|
||||||
.immediate => |imm| .{ .immediate = imm },
|
.immediate => |imm| .{ .immediate = imm },
|
||||||
.memory => |addr| .{ .memory = addr },
|
.memory => |addr| .{ .memory = addr },
|
||||||
|
.tlv_reloc => unreachable, // TODO
|
||||||
},
|
},
|
||||||
.fail => |msg| {
|
.fail => |msg| {
|
||||||
self.err_msg = msg;
|
self.err_msg = msg;
|
||||||
|
|||||||
@ -6114,7 +6114,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
|
|||||||
.mcv => |mcv| switch (mcv) {
|
.mcv => |mcv| switch (mcv) {
|
||||||
.none => .none,
|
.none => .none,
|
||||||
.undef => .undef,
|
.undef => .undef,
|
||||||
.linker_load => unreachable, // TODO
|
.tlv_reloc, .linker_load => unreachable, // TODO
|
||||||
.immediate => |imm| .{ .immediate = @truncate(u32, imm) },
|
.immediate => |imm| .{ .immediate = @truncate(u32, imm) },
|
||||||
.memory => |addr| .{ .memory = addr },
|
.memory => |addr| .{ .memory = addr },
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2572,7 +2572,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
|
|||||||
.mcv => |mcv| switch (mcv) {
|
.mcv => |mcv| switch (mcv) {
|
||||||
.none => .none,
|
.none => .none,
|
||||||
.undef => .undef,
|
.undef => .undef,
|
||||||
.linker_load => unreachable, // TODO
|
.tlv_reloc, .linker_load => unreachable, // TODO
|
||||||
.immediate => |imm| .{ .immediate = imm },
|
.immediate => |imm| .{ .immediate = imm },
|
||||||
.memory => |addr| .{ .memory = addr },
|
.memory => |addr| .{ .memory = addr },
|
||||||
},
|
},
|
||||||
|
|||||||
@ -3931,7 +3931,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
|
|||||||
.mcv => |mcv| switch (mcv) {
|
.mcv => |mcv| switch (mcv) {
|
||||||
.none => .none,
|
.none => .none,
|
||||||
.undef => .undef,
|
.undef => .undef,
|
||||||
.linker_load => unreachable, // TODO
|
.tlv_reloc, .linker_load => unreachable, // TODO
|
||||||
.immediate => |imm| .{ .immediate = imm },
|
.immediate => |imm| .{ .immediate = imm },
|
||||||
.memory => |addr| .{ .memory = addr },
|
.memory => |addr| .{ .memory = addr },
|
||||||
},
|
},
|
||||||
|
|||||||
@ -132,6 +132,10 @@ pub const MCValue = union(enum) {
|
|||||||
memory: u64,
|
memory: u64,
|
||||||
/// The value is in memory but requires a linker relocation fixup.
|
/// The value is in memory but requires a linker relocation fixup.
|
||||||
linker_load: codegen.LinkerLoad,
|
linker_load: codegen.LinkerLoad,
|
||||||
|
/// Pointer to a threadlocal variable.
|
||||||
|
/// The address resolution will be deferred until the linker allocates everything in virtual memory.
|
||||||
|
/// Payload is a symbol index.
|
||||||
|
tlv_reloc: u32,
|
||||||
/// The value is one of the stack variables.
|
/// The value is one of the stack variables.
|
||||||
/// If the type is a pointer, it means the pointer address is in the stack at this offset.
|
/// If the type is a pointer, it means the pointer address is in the stack at this offset.
|
||||||
stack_offset: i32,
|
stack_offset: i32,
|
||||||
@ -146,6 +150,7 @@ pub const MCValue = union(enum) {
|
|||||||
.stack_offset,
|
.stack_offset,
|
||||||
.ptr_stack_offset,
|
.ptr_stack_offset,
|
||||||
.linker_load,
|
.linker_load,
|
||||||
|
.tlv_reloc,
|
||||||
=> true,
|
=> true,
|
||||||
else => false,
|
else => false,
|
||||||
};
|
};
|
||||||
@ -736,7 +741,6 @@ fn asmMovLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege
|
|||||||
.got => .got_reloc,
|
.got => .got_reloc,
|
||||||
.direct => .direct_reloc,
|
.direct => .direct_reloc,
|
||||||
.import => .import_reloc,
|
.import => .import_reloc,
|
||||||
.tlv => .tlv_reloc,
|
|
||||||
};
|
};
|
||||||
_ = try self.addInst(.{
|
_ = try self.addInst(.{
|
||||||
.tag = .mov_linker,
|
.tag = .mov_linker,
|
||||||
@ -754,7 +758,6 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege
|
|||||||
.got => .got_reloc,
|
.got => .got_reloc,
|
||||||
.direct => .direct_reloc,
|
.direct => .direct_reloc,
|
||||||
.import => .import_reloc,
|
.import => .import_reloc,
|
||||||
.tlv => .tlv_reloc,
|
|
||||||
};
|
};
|
||||||
_ = try self.addInst(.{
|
_ = try self.addInst(.{
|
||||||
.tag = .lea_linker,
|
.tag = .lea_linker,
|
||||||
@ -767,15 +770,6 @@ fn asmLeaLinker(self: *Self, reg: Register, atom_index: u32, linker_load: codege
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genTlvPtr(self: *Self, reg: Register, atom_index: u32, linker_load: codegen.LinkerLoad) !void {
|
|
||||||
assert(linker_load.type == .tlv);
|
|
||||||
if (self.bin_file.cast(link.File.MachO)) |_| {
|
|
||||||
try self.asmMovLinker(.rdi, atom_index, linker_load);
|
|
||||||
try self.asmMemory(.call, Memory.sib(.qword, .{ .base = .rdi }));
|
|
||||||
try self.genSetReg(Type.usize, reg, .{ .register = .rax });
|
|
||||||
} else return self.fail("TODO emit ptr-to-TLV sequence on {s}", .{@tagName(self.bin_file.tag)});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gen(self: *Self) InnerError!void {
|
fn gen(self: *Self) InnerError!void {
|
||||||
const cc = self.fn_type.fnCallingConvention();
|
const cc = self.fn_type.fnCallingConvention();
|
||||||
if (cc != .Naked) {
|
if (cc != .Naked) {
|
||||||
@ -2929,6 +2923,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
.memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),
|
.memory => |addr| try self.genSetReg(Type.usize, addr_reg, .{ .immediate = addr }),
|
||||||
|
.tlv_reloc => try self.genSetReg(array_ty, addr_reg, array),
|
||||||
.linker_load => |load_struct| {
|
.linker_load => |load_struct| {
|
||||||
const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
|
const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
|
||||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||||
@ -2942,7 +2937,6 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
||||||
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
||||||
.tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
|
else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
|
||||||
@ -3656,7 +3650,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
|
|||||||
else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
|
else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.memory => {
|
.memory, .tlv_reloc => {
|
||||||
const reg = try self.copyToTmpRegister(ptr_ty, ptr);
|
const reg = try self.copyToTmpRegister(ptr_ty, ptr);
|
||||||
try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
|
try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
|
||||||
},
|
},
|
||||||
@ -3676,7 +3670,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
|
|||||||
switch (load_struct.type) {
|
switch (load_struct.type) {
|
||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
.got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
||||||
.tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try self.load(dst_mcv, .{ .register = addr_reg }, ptr_ty);
|
try self.load(dst_mcv, .{ .register = addr_reg }, ptr_ty);
|
||||||
@ -3838,7 +3831,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
|
|||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
||||||
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
||||||
.tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@ -3863,7 +3855,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
|
|||||||
.{ .immediate = abi_size },
|
.{ .immediate = abi_size },
|
||||||
.{},
|
.{},
|
||||||
),
|
),
|
||||||
.ptr_stack_offset => {
|
.ptr_stack_offset, .tlv_reloc => {
|
||||||
const tmp_reg = try self.copyToTmpRegister(value_ty, value);
|
const tmp_reg = try self.copyToTmpRegister(value_ty, value);
|
||||||
const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
|
const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
|
||||||
defer self.register_manager.unlockReg(tmp_lock);
|
defer self.register_manager.unlockReg(tmp_lock);
|
||||||
@ -3900,12 +3892,19 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
|
|||||||
switch (load_struct.type) {
|
switch (load_struct.type) {
|
||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
.got, .direct => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
||||||
.tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const new_ptr = MCValue{ .register = addr_reg };
|
||||||
|
try self.store(new_ptr, value, ptr_ty, value_ty);
|
||||||
|
},
|
||||||
|
.tlv_reloc => {
|
||||||
|
const addr_reg = try self.copyToTmpRegister(Type.usize, ptr);
|
||||||
|
const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
|
||||||
|
defer self.register_manager.unlockReg(addr_reg_lock);
|
||||||
|
|
||||||
const new_ptr = MCValue{ .register = addr_reg };
|
const new_ptr = MCValue{ .register = addr_reg };
|
||||||
try self.store(new_ptr, value, ptr_ty, value_ty);
|
try self.store(new_ptr, value, ptr_ty, value_ty);
|
||||||
},
|
},
|
||||||
@ -3954,7 +3953,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
|
|||||||
|
|
||||||
const dst_mcv: MCValue = result: {
|
const dst_mcv: MCValue = result: {
|
||||||
switch (mcv) {
|
switch (mcv) {
|
||||||
.stack_offset => {
|
.stack_offset, .tlv_reloc => {
|
||||||
const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
|
const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
|
||||||
.immediate = field_offset,
|
.immediate = field_offset,
|
||||||
});
|
});
|
||||||
@ -4236,6 +4235,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
.ptr_stack_offset => unreachable,
|
.ptr_stack_offset => unreachable,
|
||||||
|
.tlv_reloc => unreachable,
|
||||||
.memory, .linker_load => {
|
.memory, .linker_load => {
|
||||||
const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
|
const addr_reg = (try self.register_manager.allocReg(null, gp)).to64();
|
||||||
const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
|
const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
|
||||||
@ -4256,7 +4256,6 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue
|
|||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
||||||
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
||||||
.tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@ -4898,6 +4897,7 @@ fn genBinOp(
|
|||||||
.eflags,
|
.eflags,
|
||||||
.register_overflow,
|
.register_overflow,
|
||||||
.ptr_stack_offset,
|
.ptr_stack_offset,
|
||||||
|
.tlv_reloc,
|
||||||
=> unreachable,
|
=> unreachable,
|
||||||
.register => |src_reg| try self.asmCmovccRegisterRegister(
|
.register => |src_reg| try self.asmCmovccRegisterRegister(
|
||||||
registerAlias(tmp_reg, cmov_abi_size),
|
registerAlias(tmp_reg, cmov_abi_size),
|
||||||
@ -4932,7 +4932,6 @@ fn genBinOp(
|
|||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
||||||
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
||||||
.tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@ -4983,7 +4982,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
|
|||||||
.undef => unreachable,
|
.undef => unreachable,
|
||||||
.dead, .unreach => unreachable,
|
.dead, .unreach => unreachable,
|
||||||
.register_overflow => unreachable,
|
.register_overflow => unreachable,
|
||||||
.ptr_stack_offset => {
|
.ptr_stack_offset, .tlv_reloc => {
|
||||||
const dst_reg_lock = self.register_manager.lockReg(dst_reg);
|
const dst_reg_lock = self.register_manager.lockReg(dst_reg);
|
||||||
defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
|
defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
|
||||||
|
|
||||||
@ -5079,7 +5078,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
|
|||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got => try self.asmMovLinker(dst_addr_reg, atom_index, load_struct),
|
.got => try self.asmMovLinker(dst_addr_reg, atom_index, load_struct),
|
||||||
.direct => try self.asmLeaLinker(dst_addr_reg, atom_index, load_struct),
|
.direct => try self.asmLeaLinker(dst_addr_reg, atom_index, load_struct),
|
||||||
.tlv => try self.genTlvPtr(dst_addr_reg, atom_index, load_struct),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@ -5125,7 +5123,6 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
|
|||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got => try self.asmMovLinker(src_addr_reg, atom_index, load_struct),
|
.got => try self.asmMovLinker(src_addr_reg, atom_index, load_struct),
|
||||||
.direct => try self.asmLeaLinker(src_addr_reg, atom_index, load_struct),
|
.direct => try self.asmLeaLinker(src_addr_reg, atom_index, load_struct),
|
||||||
.tlv => try self.genTlvPtr(src_addr_reg, atom_index, load_struct),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@ -5236,7 +5233,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.memory, .linker_load => {
|
.memory, .linker_load, .tlv_reloc => {
|
||||||
try self.asmRegisterMemory(
|
try self.asmRegisterMemory(
|
||||||
.mov,
|
.mov,
|
||||||
registerAlias(src.?.limb_reg, limb_abi_size),
|
registerAlias(src.?.limb_reg, limb_abi_size),
|
||||||
@ -5275,6 +5272,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.ptr_stack_offset => unreachable,
|
.ptr_stack_offset => unreachable,
|
||||||
|
.tlv_reloc => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5288,6 +5286,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
|
|||||||
.dead, .unreach, .immediate => unreachable,
|
.dead, .unreach, .immediate => unreachable,
|
||||||
.eflags => unreachable,
|
.eflags => unreachable,
|
||||||
.ptr_stack_offset => unreachable,
|
.ptr_stack_offset => unreachable,
|
||||||
|
.tlv_reloc => unreachable,
|
||||||
.register_overflow => unreachable,
|
.register_overflow => unreachable,
|
||||||
.register => |dst_reg| {
|
.register => |dst_reg| {
|
||||||
const dst_alias = registerAlias(dst_reg, abi_size);
|
const dst_alias = registerAlias(dst_reg, abi_size);
|
||||||
@ -5299,6 +5298,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
|
|||||||
.undef => try self.genSetReg(dst_ty, dst_reg, .undef),
|
.undef => try self.genSetReg(dst_ty, dst_reg, .undef),
|
||||||
.dead, .unreach => unreachable,
|
.dead, .unreach => unreachable,
|
||||||
.ptr_stack_offset => unreachable,
|
.ptr_stack_offset => unreachable,
|
||||||
|
.tlv_reloc => unreachable,
|
||||||
.register_overflow => unreachable,
|
.register_overflow => unreachable,
|
||||||
.register => |src_reg| try self.asmRegisterRegister(
|
.register => |src_reg| try self.asmRegisterRegister(
|
||||||
.imul,
|
.imul,
|
||||||
@ -5342,6 +5342,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
|
|||||||
.undef => return self.genSetStack(dst_ty, off, .undef, .{}),
|
.undef => return self.genSetStack(dst_ty, off, .undef, .{}),
|
||||||
.dead, .unreach => unreachable,
|
.dead, .unreach => unreachable,
|
||||||
.ptr_stack_offset => unreachable,
|
.ptr_stack_offset => unreachable,
|
||||||
|
.tlv_reloc => unreachable,
|
||||||
.register_overflow => unreachable,
|
.register_overflow => unreachable,
|
||||||
.register => |src_reg| {
|
.register => |src_reg| {
|
||||||
// copy dst to a register
|
// copy dst to a register
|
||||||
@ -5564,6 +5565,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
|||||||
.linker_load => unreachable,
|
.linker_load => unreachable,
|
||||||
.eflags => unreachable,
|
.eflags => unreachable,
|
||||||
.register_overflow => unreachable,
|
.register_overflow => unreachable,
|
||||||
|
.tlv_reloc => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5602,6 +5604,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
|||||||
.linker_load => unreachable,
|
.linker_load => unreachable,
|
||||||
.eflags => unreachable,
|
.eflags => unreachable,
|
||||||
.register_overflow => unreachable,
|
.register_overflow => unreachable,
|
||||||
|
.tlv_reloc => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6123,6 +6126,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
|
|||||||
.register_overflow,
|
.register_overflow,
|
||||||
.ptr_stack_offset,
|
.ptr_stack_offset,
|
||||||
.eflags,
|
.eflags,
|
||||||
|
.tlv_reloc,
|
||||||
=> unreachable,
|
=> unreachable,
|
||||||
|
|
||||||
.register => |opt_reg| {
|
.register => |opt_reg| {
|
||||||
@ -6163,7 +6167,6 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
|
|||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
||||||
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
||||||
.tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@ -7121,7 +7124,6 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
|
|||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
||||||
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
||||||
.tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@ -7168,7 +7170,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.ptr_stack_offset => {
|
.ptr_stack_offset, .tlv_reloc => {
|
||||||
const reg = try self.copyToTmpRegister(ty, mcv);
|
const reg = try self.copyToTmpRegister(ty, mcv);
|
||||||
return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
|
return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
|
||||||
},
|
},
|
||||||
@ -7349,7 +7351,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
|
|||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
.got => try self.asmMovLinker(addr_reg, atom_index, load_struct),
|
||||||
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
.direct => try self.asmLeaLinker(addr_reg, atom_index, load_struct),
|
||||||
.tlv => try self.genTlvPtr(addr_reg, atom_index, load_struct),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@ -7374,7 +7375,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
|
|||||||
.{ .immediate = abi_size },
|
.{ .immediate = abi_size },
|
||||||
.{},
|
.{},
|
||||||
),
|
),
|
||||||
.ptr_stack_offset => {
|
.ptr_stack_offset, .tlv_reloc => {
|
||||||
const tmp_reg = try self.copyToTmpRegister(ty, mcv);
|
const tmp_reg = try self.copyToTmpRegister(ty, mcv);
|
||||||
const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
|
const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
|
||||||
defer self.register_manager.unlockReg(tmp_lock);
|
defer self.register_manager.unlockReg(tmp_lock);
|
||||||
@ -7481,13 +7482,9 @@ fn genInlineMemcpy(
|
|||||||
switch (load_struct.type) {
|
switch (load_struct.type) {
|
||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
|
.got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
|
||||||
.tlv => {
|
|
||||||
try self.genTlvPtr(.rdi, atom_index, load_struct);
|
|
||||||
// Load the pointer, which is stored in memory
|
|
||||||
try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi }));
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.tlv_reloc => try self.genSetReg(Type.usize, .rdi, dst_ptr),
|
||||||
.stack_offset, .ptr_stack_offset => |off| {
|
.stack_offset, .ptr_stack_offset => |off| {
|
||||||
try self.asmRegisterMemory(switch (dst_ptr) {
|
try self.asmRegisterMemory(switch (dst_ptr) {
|
||||||
.stack_offset => .mov,
|
.stack_offset => .mov,
|
||||||
@ -7528,13 +7525,9 @@ fn genInlineMemcpy(
|
|||||||
switch (load_struct.type) {
|
switch (load_struct.type) {
|
||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got, .direct => try self.asmMovLinker(.rsi, atom_index, load_struct),
|
.got, .direct => try self.asmMovLinker(.rsi, atom_index, load_struct),
|
||||||
.tlv => {
|
|
||||||
try self.genTlvPtr(.rsi, atom_index, load_struct);
|
|
||||||
// Load the pointer, which is stored in memory
|
|
||||||
try self.asmRegisterMemory(.mov, .rsi, Memory.sib(.qword, .{ .base = .rsi }));
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.tlv_reloc => try self.genSetReg(Type.usize, .rsi, src_ptr),
|
||||||
.stack_offset, .ptr_stack_offset => |off| {
|
.stack_offset, .ptr_stack_offset => |off| {
|
||||||
try self.asmRegisterMemory(switch (src_ptr) {
|
try self.asmRegisterMemory(switch (src_ptr) {
|
||||||
.stack_offset => .mov,
|
.stack_offset => .mov,
|
||||||
@ -7598,13 +7591,9 @@ fn genInlineMemset(
|
|||||||
switch (load_struct.type) {
|
switch (load_struct.type) {
|
||||||
.import => unreachable,
|
.import => unreachable,
|
||||||
.got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
|
.got, .direct => try self.asmMovLinker(.rdi, atom_index, load_struct),
|
||||||
.tlv => {
|
|
||||||
try self.genTlvPtr(.rdi, atom_index, load_struct);
|
|
||||||
// Load the pointer, which is stored in memory
|
|
||||||
try self.asmRegisterMemory(.mov, .rdi, Memory.sib(.qword, .{ .base = .rdi }));
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.tlv_reloc => try self.genSetReg(Type.usize, .rdi, dst_ptr),
|
||||||
.stack_offset, .ptr_stack_offset => |off| {
|
.stack_offset, .ptr_stack_offset => |off| {
|
||||||
try self.asmRegisterMemory(switch (dst_ptr) {
|
try self.asmRegisterMemory(switch (dst_ptr) {
|
||||||
.stack_offset => .mov,
|
.stack_offset => .mov,
|
||||||
@ -7780,6 +7769,30 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
.tlv_reloc => |sym_index| {
|
||||||
|
const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
|
||||||
|
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||||
|
break :blk macho_file.getAtom(atom).getSymbolIndex().?;
|
||||||
|
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| blk: {
|
||||||
|
const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||||
|
break :blk coff_file.getAtom(atom).getSymbolIndex().?;
|
||||||
|
} else unreachable;
|
||||||
|
|
||||||
|
if (self.bin_file.cast(link.File.MachO)) |_| {
|
||||||
|
_ = try self.addInst(.{
|
||||||
|
.tag = .mov_linker,
|
||||||
|
.ops = .tlv_reloc,
|
||||||
|
.data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{
|
||||||
|
.reg = @enumToInt(Register.rdi),
|
||||||
|
.atom_index = atom_index,
|
||||||
|
.sym_index = sym_index,
|
||||||
|
}) },
|
||||||
|
});
|
||||||
|
// TODO: spill registers before calling
|
||||||
|
try self.asmMemory(.call, Memory.sib(.qword, .{ .base = .rdi }));
|
||||||
|
try self.genSetReg(Type.usize, reg, .{ .register = .rax });
|
||||||
|
} else return self.fail("TODO emit ptr to TLV sequence on {s}", .{@tagName(self.bin_file.tag)});
|
||||||
|
},
|
||||||
.linker_load => |load_struct| {
|
.linker_load => |load_struct| {
|
||||||
const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
|
const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
|
||||||
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
|
||||||
@ -7792,10 +7805,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
|||||||
switch (ty.zigTypeTag()) {
|
switch (ty.zigTypeTag()) {
|
||||||
.Float => {
|
.Float => {
|
||||||
const base_reg = (try self.register_manager.allocReg(null, gp)).to64();
|
const base_reg = (try self.register_manager.allocReg(null, gp)).to64();
|
||||||
switch (load_struct.type) {
|
try self.asmLeaLinker(base_reg, atom_index, load_struct);
|
||||||
.tlv => try self.genTlvPtr(base_reg, atom_index, load_struct),
|
|
||||||
else => try self.asmLeaLinker(base_reg, atom_index, load_struct),
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intrinsicsAllowed(self.target.*, ty)) {
|
if (intrinsicsAllowed(self.target.*, ty)) {
|
||||||
return self.asmRegisterMemory(
|
return self.asmRegisterMemory(
|
||||||
@ -7813,17 +7823,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
|||||||
|
|
||||||
return self.fail("TODO genSetReg from memory for float with no intrinsics", .{});
|
return self.fail("TODO genSetReg from memory for float with no intrinsics", .{});
|
||||||
},
|
},
|
||||||
else => switch (load_struct.type) {
|
else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct),
|
||||||
.tlv => {
|
|
||||||
try self.genTlvPtr(reg.to64(), atom_index, load_struct);
|
|
||||||
try self.asmRegisterMemory(
|
|
||||||
.mov,
|
|
||||||
registerAlias(reg, abi_size),
|
|
||||||
Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg.to64() }),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
else => try self.asmMovLinker(registerAlias(reg, abi_size), atom_index, load_struct),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.stack_offset => |off| {
|
.stack_offset => |off| {
|
||||||
@ -8779,6 +8779,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
|
|||||||
.linker_load => |ll| .{ .linker_load = ll },
|
.linker_load => |ll| .{ .linker_load = ll },
|
||||||
.immediate => |imm| .{ .immediate = imm },
|
.immediate => |imm| .{ .immediate = imm },
|
||||||
.memory => |addr| .{ .memory = addr },
|
.memory => |addr| .{ .memory = addr },
|
||||||
|
.tlv_reloc => |sym_index| .{ .tlv_reloc = sym_index },
|
||||||
},
|
},
|
||||||
.fail => |msg| {
|
.fail => |msg| {
|
||||||
self.err_msg = msg;
|
self.err_msg = msg;
|
||||||
|
|||||||
@ -912,13 +912,11 @@ fn lowerDeclRef(
|
|||||||
/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
|
/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
|
||||||
/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
|
/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
|
||||||
/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
|
/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
|
||||||
/// * tlv - the value is a threadlocal variable referenced indirectly via GOT (the linker emits a got-type reloc)
|
|
||||||
pub const LinkerLoad = struct {
|
pub const LinkerLoad = struct {
|
||||||
type: enum {
|
type: enum {
|
||||||
got,
|
got,
|
||||||
direct,
|
direct,
|
||||||
import,
|
import,
|
||||||
tlv,
|
|
||||||
},
|
},
|
||||||
sym_index: u32,
|
sym_index: u32,
|
||||||
};
|
};
|
||||||
@ -934,6 +932,10 @@ pub const GenResult = union(enum) {
|
|||||||
/// such as ARM, the immediate will never exceed 32-bits.
|
/// such as ARM, the immediate will never exceed 32-bits.
|
||||||
immediate: u64,
|
immediate: u64,
|
||||||
linker_load: LinkerLoad,
|
linker_load: LinkerLoad,
|
||||||
|
/// Pointer to a threadlocal variable.
|
||||||
|
/// The address resolution will be deferred until the linker allocates everything in virtual memory.
|
||||||
|
/// Payload is a symbol index.
|
||||||
|
tlv_reloc: u32,
|
||||||
/// Direct by-address reference to memory location.
|
/// Direct by-address reference to memory location.
|
||||||
memory: u64,
|
memory: u64,
|
||||||
};
|
};
|
||||||
@ -1002,8 +1004,11 @@ fn genDeclRef(
|
|||||||
} else if (bin_file.cast(link.File.MachO)) |macho_file| {
|
} else if (bin_file.cast(link.File.MachO)) |macho_file| {
|
||||||
const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
|
const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
|
||||||
const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
|
const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
|
||||||
|
if (is_threadlocal) {
|
||||||
|
return GenResult.mcv(.{ .tlv_reloc = sym_index });
|
||||||
|
}
|
||||||
return GenResult.mcv(.{ .linker_load = .{
|
return GenResult.mcv(.{ .linker_load = .{
|
||||||
.type = if (is_threadlocal) .tlv else .got,
|
.type = .got,
|
||||||
.sym_index = sym_index,
|
.sym_index = sym_index,
|
||||||
} });
|
} });
|
||||||
} else if (bin_file.cast(link.File.Coff)) |coff_file| {
|
} else if (bin_file.cast(link.File.Coff)) |coff_file| {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user