mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 13:58:27 +00:00
codegen: make threadlocal logic consistent
This commit is contained in:
parent
56119699bf
commit
d312dfc1f2
@ -163354,7 +163354,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
|
||||
},
|
||||
.runtime_nav_ptr => {
|
||||
const ty_nav = air_datas[@intFromEnum(inst)].ty_nav;
|
||||
const is_threadlocal = ip.getNav(ty_nav.nav).isThreadlocal(ip);
|
||||
const nav = ip.getNav(ty_nav.nav);
|
||||
const is_threadlocal = zcu.comp.config.any_non_single_threaded and nav.isThreadlocal(ip);
|
||||
if (is_threadlocal) if (cg.mod.pic) {
|
||||
try cg.spillRegisters(&.{ .rdi, .rax });
|
||||
} else {
|
||||
|
||||
@ -21,7 +21,8 @@ pub const Error = Lower.Error || error{
|
||||
} || link.File.UpdateDebugInfoError;
|
||||
|
||||
pub fn emitMir(emit: *Emit) Error!void {
|
||||
const gpa = emit.bin_file.comp.gpa;
|
||||
const comp = emit.bin_file.comp;
|
||||
const gpa = comp.gpa;
|
||||
try emit.code_offset_mapping.resize(gpa, emit.lower.mir.instructions.len);
|
||||
emit.relocs.clearRetainingCapacity();
|
||||
emit.table_relocs.clearRetainingCapacity();
|
||||
@ -99,12 +100,10 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
.inst => |inst| .{ .index = inst, .is_extern = false, .type = .inst },
|
||||
.table => .{ .index = undefined, .is_extern = false, .type = .table },
|
||||
.nav => |nav| {
|
||||
const ip = &emit.pt.zcu.intern_pool;
|
||||
const sym_index = switch (try codegen.genNavRef(
|
||||
emit.bin_file,
|
||||
emit.pt,
|
||||
emit.lower.src_loc,
|
||||
.fromInterned(ip.getNav(nav).typeOf(ip)),
|
||||
nav,
|
||||
emit.lower.target.*,
|
||||
)) {
|
||||
@ -118,12 +117,13 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
return error.EmitFail;
|
||||
},
|
||||
};
|
||||
const ip = &emit.pt.zcu.intern_pool;
|
||||
break :target switch (ip.getNav(nav).status) {
|
||||
.unresolved => unreachable,
|
||||
.type_resolved => |type_resolved| .{
|
||||
.index = sym_index,
|
||||
.is_extern = false,
|
||||
.type = if (type_resolved.is_threadlocal) .tlv else .symbol,
|
||||
.type = if (type_resolved.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
|
||||
},
|
||||
.fully_resolved => |fully_resolved| switch (ip.indexToKey(fully_resolved.val)) {
|
||||
.@"extern" => |@"extern"| .{
|
||||
@ -132,7 +132,7 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
.default => true,
|
||||
.hidden, .protected => false,
|
||||
},
|
||||
.type = if (@"extern".is_threadlocal) .tlv else .symbol,
|
||||
.type = if (@"extern".is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
|
||||
.force_pcrel_direct = switch (@"extern".relocation) {
|
||||
.any => false,
|
||||
.pcrel => true,
|
||||
@ -141,7 +141,7 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
.variable => |variable| .{
|
||||
.index = sym_index,
|
||||
.is_extern = false,
|
||||
.type = if (variable.is_threadlocal) .tlv else .symbol,
|
||||
.type = if (variable.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
|
||||
},
|
||||
else => .{ .index = sym_index, .is_extern = false, .type = .symbol },
|
||||
},
|
||||
@ -292,12 +292,8 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
.branch, .tls => unreachable,
|
||||
.tlv => {
|
||||
if (emit.bin_file.cast(.elf)) |elf_file| {
|
||||
if (reloc.target.is_extern) {
|
||||
// TODO handle extern TLS vars, i.e., emit GD model
|
||||
return emit.fail("TODO implement extern {s} reloc for {s}", .{
|
||||
@tagName(reloc.target.type), @tagName(emit.bin_file.tag),
|
||||
});
|
||||
} else if (emit.pic) switch (lowered_inst.encoding.mnemonic) {
|
||||
// TODO handle extern TLS vars, i.e., emit GD model
|
||||
if (emit.pic) switch (lowered_inst.encoding.mnemonic) {
|
||||
.lea, .mov => {
|
||||
// Here, we currently assume local dynamic TLS vars, and so
|
||||
// we emit LD model.
|
||||
@ -507,7 +503,6 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
} };
|
||||
},
|
||||
.pseudo_dbg_arg_m, .pseudo_dbg_var_m => {
|
||||
const ip = &emit.pt.zcu.intern_pool;
|
||||
const mem = emit.lower.mir.resolveMemoryExtra(mir_inst.data.x.payload).decode();
|
||||
break :loc .{ .plus = .{
|
||||
base: {
|
||||
@ -519,7 +514,6 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
emit.bin_file,
|
||||
emit.pt,
|
||||
emit.lower.src_loc,
|
||||
.fromInterned(ip.getNav(nav).typeOf(ip)),
|
||||
nav,
|
||||
emit.lower.target.*,
|
||||
) catch |err| switch (err) {
|
||||
@ -803,9 +797,6 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
|
||||
@tagName(reloc.target.type), @tagName(emit.bin_file.tag),
|
||||
}),
|
||||
.tls => if (emit.bin_file.cast(.elf)) |elf_file| {
|
||||
if (reloc.target.is_extern) return emit.fail("TODO implement extern {s} reloc for {s}", .{
|
||||
@tagName(reloc.target.type), @tagName(emit.bin_file.tag),
|
||||
});
|
||||
const zo = elf_file.zigObjectPtr().?;
|
||||
const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
|
||||
const r_type: std.elf.R_X86_64 = if (emit.pic) .TLSLD else unreachable;
|
||||
@ -818,9 +809,6 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
|
||||
@tagName(reloc.target.type), @tagName(emit.bin_file.tag),
|
||||
}),
|
||||
.tlv => if (emit.bin_file.cast(.elf)) |elf_file| {
|
||||
if (reloc.target.is_extern) return emit.fail("TODO implement extern {s} reloc for {s}", .{
|
||||
@tagName(reloc.target.type), @tagName(emit.bin_file.tag),
|
||||
});
|
||||
const zo = elf_file.zigObjectPtr().?;
|
||||
const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
|
||||
const r_type: std.elf.R_X86_64 = if (emit.pic) .DTPOFF32 else .TPOFF32;
|
||||
|
||||
@ -955,47 +955,18 @@ pub fn genNavRef(
|
||||
lf: *link.File,
|
||||
pt: Zcu.PerThread,
|
||||
src_loc: Zcu.LazySrcLoc,
|
||||
ty: Type,
|
||||
nav_index: InternPool.Nav.Index,
|
||||
target: std.Target,
|
||||
) CodeGenError!GenResult {
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
log.debug("genNavRef: ty = {}", .{ty.fmt(pt)});
|
||||
|
||||
if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) {
|
||||
const imm: u64 = switch (@divExact(target.ptrBitWidth(), 8)) {
|
||||
1 => 0xaa,
|
||||
2 => 0xaaaa,
|
||||
4 => 0xaaaaaaaa,
|
||||
8 => 0xaaaaaaaaaaaaaaaa,
|
||||
else => unreachable,
|
||||
};
|
||||
return .{ .mcv = .{ .immediate = imm } };
|
||||
}
|
||||
|
||||
const comp = lf.comp;
|
||||
const gpa = comp.gpa;
|
||||
|
||||
// TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
|
||||
if (ty.castPtrToFn(zcu)) |fn_ty| {
|
||||
if (zcu.typeToFunc(fn_ty).?.is_generic) {
|
||||
return .{ .mcv = .{ .immediate = fn_ty.abiAlignment(zcu).toByteUnits().? } };
|
||||
}
|
||||
} else if (ty.zigTypeTag(zcu) == .pointer) {
|
||||
const elem_ty = ty.elemType2(zcu);
|
||||
if (!elem_ty.hasRuntimeBits(zcu)) {
|
||||
return .{ .mcv = .{ .immediate = elem_ty.abiAlignment(zcu).toByteUnits().? } };
|
||||
}
|
||||
}
|
||||
|
||||
const nav = ip.getNav(nav_index);
|
||||
log.debug("genNavRef({})", .{nav.fqn.fmt(ip)});
|
||||
|
||||
const lib_name, const linkage, const is_threadlocal = if (nav.getExtern(ip)) |e|
|
||||
.{ e.lib_name, e.linkage, e.is_threadlocal and !zcu.navFileScope(nav_index).mod.?.single_threaded }
|
||||
.{ e.lib_name, e.linkage, e.is_threadlocal and zcu.comp.config.any_non_single_threaded }
|
||||
else
|
||||
.{ .none, .internal, false };
|
||||
|
||||
const name = nav.name;
|
||||
if (lf.cast(.elf)) |elf_file| {
|
||||
const zo = elf_file.zigObjectPtr().?;
|
||||
switch (linkage) {
|
||||
@ -1005,7 +976,7 @@ pub fn genNavRef(
|
||||
return .{ .mcv = .{ .lea_symbol = sym_index } };
|
||||
},
|
||||
.strong, .weak => {
|
||||
const sym_index = try elf_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
|
||||
const sym_index = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
|
||||
switch (linkage) {
|
||||
.internal => unreachable,
|
||||
.strong => {},
|
||||
@ -1026,7 +997,7 @@ pub fn genNavRef(
|
||||
return .{ .mcv = .{ .lea_symbol = sym_index } };
|
||||
},
|
||||
.strong, .weak => {
|
||||
const sym_index = try macho_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
|
||||
const sym_index = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
|
||||
switch (linkage) {
|
||||
.internal => unreachable,
|
||||
.strong => {},
|
||||
@ -1047,8 +1018,8 @@ pub fn genNavRef(
|
||||
return .{ .mcv = .{ .load_got = sym_index } };
|
||||
},
|
||||
.strong, .weak => {
|
||||
const global_index = try coff_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
|
||||
try coff_file.need_got_table.put(gpa, global_index, {}); // needs GOT
|
||||
const global_index = try coff_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
|
||||
try coff_file.need_got_table.put(zcu.gpa, global_index, {}); // needs GOT
|
||||
return .{ .mcv = .{ .load_got = link.File.Coff.global_symbol_bit | global_index } };
|
||||
},
|
||||
.link_once => unreachable,
|
||||
@ -1058,7 +1029,7 @@ pub fn genNavRef(
|
||||
const atom = p9.getAtom(atom_index);
|
||||
return .{ .mcv = .{ .memory = atom.getOffsetTableAddress(p9) } };
|
||||
} else {
|
||||
const msg = try ErrorMsg.create(gpa, src_loc, "TODO genNavRef for target {}", .{target});
|
||||
const msg = try ErrorMsg.create(zcu.gpa, src_loc, "TODO genNavRef for target {}", .{target});
|
||||
return .{ .fail = msg };
|
||||
}
|
||||
}
|
||||
@ -1071,12 +1042,11 @@ pub fn genTypedValue(
|
||||
val: Value,
|
||||
target: std.Target,
|
||||
) CodeGenError!GenResult {
|
||||
const ip = &pt.zcu.intern_pool;
|
||||
return switch (try lowerValue(pt, val, &target)) {
|
||||
.none => .{ .mcv = .none },
|
||||
.undef => .{ .mcv = .undef },
|
||||
.immediate => |imm| .{ .mcv = .{ .immediate = imm } },
|
||||
.lea_nav => |nav| genNavRef(lf, pt, src_loc, .fromInterned(ip.getNav(nav).typeOf(ip)), nav, target),
|
||||
.lea_nav => |nav| genNavRef(lf, pt, src_loc, nav, target),
|
||||
.lea_uav => |uav| switch (try lf.lowerUav(
|
||||
pt,
|
||||
uav.val,
|
||||
|
||||
@ -1142,7 +1142,6 @@ fn getNavShdrIndex(
|
||||
const gpa = elf_file.base.comp.gpa;
|
||||
const ptr_size = elf_file.ptrWidthBytes();
|
||||
const ip = &zcu.intern_pool;
|
||||
const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;
|
||||
const nav_val = zcu.navValue(nav_index);
|
||||
if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) {
|
||||
if (self.text_index) |symbol_index|
|
||||
@ -1162,7 +1161,7 @@ fn getNavShdrIndex(
|
||||
else => .{ true, false, nav_val.toIntern() },
|
||||
};
|
||||
const has_relocs = self.symbol(sym_index).atom(elf_file).?.relocs(elf_file).len > 0;
|
||||
if (any_non_single_threaded and is_threadlocal) {
|
||||
if (is_threadlocal and elf_file.base.comp.config.any_non_single_threaded) {
|
||||
const is_bss = !has_relocs and for (code) |byte| {
|
||||
if (byte != 0) break false;
|
||||
} else true;
|
||||
@ -1542,7 +1541,7 @@ pub fn updateNav(
|
||||
nav.name.toSlice(ip),
|
||||
@"extern".lib_name.toSlice(ip),
|
||||
);
|
||||
if (@"extern".is_threadlocal) self.symbol(sym_index).flags.is_tls = true;
|
||||
if (@"extern".is_threadlocal and elf_file.base.comp.config.any_non_single_threaded) self.symbol(sym_index).flags.is_tls = true;
|
||||
if (self.dwarf) |*dwarf| dwarf: {
|
||||
var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf;
|
||||
defer debug_wip_nav.deinit();
|
||||
|
||||
@ -881,7 +881,7 @@ pub fn updateNav(
|
||||
const name = @"extern".name.toSlice(ip);
|
||||
const lib_name = @"extern".lib_name.toSlice(ip);
|
||||
const sym_index = try self.getGlobalSymbol(macho_file, name, lib_name);
|
||||
if (@"extern".is_threadlocal) self.symbols.items[sym_index].flags.tlv = true;
|
||||
if (@"extern".is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) self.symbols.items[sym_index].flags.tlv = true;
|
||||
if (self.dwarf) |*dwarf| dwarf: {
|
||||
var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf;
|
||||
defer debug_wip_nav.deinit();
|
||||
@ -1154,7 +1154,6 @@ fn getNavOutputSection(
|
||||
) error{OutOfMemory}!u8 {
|
||||
_ = self;
|
||||
const ip = &zcu.intern_pool;
|
||||
const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;
|
||||
const nav_val = zcu.navValue(nav_index);
|
||||
if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) return macho_file.zig_text_sect_index.?;
|
||||
const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
|
||||
@ -1162,7 +1161,7 @@ fn getNavOutputSection(
|
||||
.@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none },
|
||||
else => .{ true, false, nav_val.toIntern() },
|
||||
};
|
||||
if (any_non_single_threaded and is_threadlocal) {
|
||||
if (is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) {
|
||||
for (code) |byte| {
|
||||
if (byte != 0) break;
|
||||
} else return macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user