x86_64: get something going for the local exec model
This commit is contained in:
@@ -120,6 +120,8 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
link.File.Elf.R_X86_64_ZIG_GOT32
|
||||
else if (sym.flags.needs_got)
|
||||
std.elf.R_X86_64_GOT32
|
||||
else if (sym.isTls(elf_file))
|
||||
std.elf.R_X86_64_TPOFF32
|
||||
else
|
||||
std.elf.R_X86_64_32;
|
||||
try atom.addReloc(elf_file, .{
|
||||
|
||||
@@ -319,20 +319,25 @@ fn reloc(lower: *Lower, target: Reloc.Target) Immediate {
|
||||
return Immediate.s(0);
|
||||
}
|
||||
|
||||
fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
|
||||
const needsZigGot = struct {
|
||||
fn needsZigGot(sym: bits.Symbol, ctx: *link.File) bool {
|
||||
const elf_file = ctx.cast(link.File.Elf).?;
|
||||
const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
|
||||
return elf_file.symbol(sym_index).flags.needs_zig_got;
|
||||
}
|
||||
}.needsZigGot;
|
||||
fn needsZigGot(sym: bits.Symbol, ctx: *link.File) bool {
|
||||
const elf_file = ctx.cast(link.File.Elf).?;
|
||||
const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
|
||||
return elf_file.symbol(sym_index).flags.needs_zig_got;
|
||||
}
|
||||
|
||||
fn isTls(sym: bits.Symbol, ctx: *link.File) bool {
|
||||
const elf_file = ctx.cast(link.File.Elf).?;
|
||||
const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
|
||||
return elf_file.symbol(sym_index).isTls(elf_file);
|
||||
}
|
||||
|
||||
fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
|
||||
const is_obj_or_static_lib = switch (lower.bin_file.options.output_mode) {
|
||||
.Exe => false,
|
||||
.Obj => true,
|
||||
.Lib => lower.bin_file.options.link_mode == .Static,
|
||||
};
|
||||
|
||||
var emit_prefix = prefix;
|
||||
var emit_mnemonic = mnemonic;
|
||||
var emit_ops_storage: [4]Operand = undefined;
|
||||
@@ -346,6 +351,29 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
|
||||
assert(prefix == .none);
|
||||
assert(mem_op.sib.disp == 0);
|
||||
assert(mem_op.sib.scale_index.scale == 0);
|
||||
|
||||
if (isTls(sym, lower.bin_file)) {
|
||||
lower.result_insts[lower.result_insts_len] =
|
||||
try Instruction.new(.none, .mov, &[_]Operand{
|
||||
.{ .reg = ops[0].reg.to64() },
|
||||
.{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },
|
||||
});
|
||||
lower.result_insts_len += 1;
|
||||
_ = lower.reloc(.{ .linker_reloc = sym });
|
||||
if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
|
||||
elf_file.symbol(sym_index).flags.needs_zig_got = false;
|
||||
}
|
||||
emit_mnemonic = .lea;
|
||||
switch (mnemonic) {
|
||||
.lea, .mov => break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
|
||||
.base = .{ .reg = ops[0].reg.to64() },
|
||||
.disp = undefined,
|
||||
}) },
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
_ = lower.reloc(.{ .linker_reloc = sym });
|
||||
break :op if (lower.bin_file.options.pic) switch (mnemonic) {
|
||||
.lea => {
|
||||
|
||||
@@ -51,6 +51,13 @@ pub fn isIFunc(symbol: Symbol, elf_file: *Elf) bool {
|
||||
return symbol.type(elf_file) == elf.STT_GNU_IFUNC;
|
||||
}
|
||||
|
||||
// TODO this check is enough for ZigObject emitted TLS vars but what about those emitted
|
||||
// by different backends/compilers?
|
||||
pub fn isTls(symbol: Symbol, elf_file: *Elf) bool {
|
||||
if (symbol.file(elf_file) == null) return false;
|
||||
return symbol.type(elf_file) == elf.STT_TLS;
|
||||
}
|
||||
|
||||
pub fn @"type"(symbol: Symbol, elf_file: *Elf) u4 {
|
||||
const esym = symbol.elfSym(elf_file);
|
||||
const file_ptr = symbol.file(elf_file).?;
|
||||
|
||||
@@ -723,7 +723,18 @@ pub fn getOrCreateMetadataForDecl(
|
||||
) !Symbol.Index {
|
||||
const gop = try self.decls.getOrPut(elf_file.base.allocator, decl_index);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = .{ .symbol_index = try self.addAtom(elf_file) };
|
||||
const symbol_index = try self.addAtom(elf_file);
|
||||
const mod = elf_file.base.options.module.?;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const single_threaded = elf_file.base.options.single_threaded;
|
||||
if (decl.getOwnedVariable(mod)) |variable| {
|
||||
if (variable.is_threadlocal and !single_threaded) {
|
||||
const sym = elf_file.symbol(symbol_index);
|
||||
self.elfSym(sym.esym_index).st_info = elf.STT_TLS;
|
||||
}
|
||||
}
|
||||
|
||||
gop.value_ptr.* = .{ .symbol_index = symbol_index };
|
||||
}
|
||||
return gop.value_ptr.symbol_index;
|
||||
}
|
||||
@@ -891,7 +902,7 @@ fn updateTlv(
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
|
||||
|
||||
log.debug("updateTlv {s}{*}", .{ decl_name, decl });
|
||||
log.debug("updateTlv {s} ({*})", .{ decl_name, decl });
|
||||
|
||||
const required_alignment = decl.getAlignment(mod);
|
||||
|
||||
@@ -906,7 +917,7 @@ fn updateTlv(
|
||||
atom_ptr.flags.alive = true;
|
||||
atom_ptr.name_offset = sym.name_offset;
|
||||
esym.st_name = sym.name_offset;
|
||||
esym.st_info |= elf.STT_TLS;
|
||||
esym.st_info = elf.STT_TLS;
|
||||
esym.st_size = code.len;
|
||||
|
||||
atom_ptr.alignment = required_alignment;
|
||||
|
||||
Reference in New Issue
Block a user