Skip to content

Commit aadd392

Browse files
jacobly0mlugg
authored andcommitted
codegen: make threadlocal logic consistent
1 parent 884893c commit aadd392

File tree

5 files changed

+23
-66
lines changed

5 files changed

+23
-66
lines changed

src/arch/x86_64/CodeGen.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163354,7 +163354,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
163354163354
},
163355163355
.runtime_nav_ptr => {
163356163356
const ty_nav = air_datas[@intFromEnum(inst)].ty_nav;
163357-
const is_threadlocal = ip.getNav(ty_nav.nav).isThreadlocal(ip);
163357+
const nav = ip.getNav(ty_nav.nav);
163358+
const is_threadlocal = zcu.comp.config.any_non_single_threaded and nav.isThreadlocal(ip);
163358163359
if (is_threadlocal) if (cg.mod.pic) {
163359163360
try cg.spillRegisters(&.{ .rdi, .rax });
163360163361
} else {

src/arch/x86_64/Emit.zig

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ pub const Error = Lower.Error || error{
2121
} || link.File.UpdateDebugInfoError;
2222

2323
pub fn emitMir(emit: *Emit) Error!void {
24-
const gpa = emit.bin_file.comp.gpa;
24+
const comp = emit.bin_file.comp;
25+
const gpa = comp.gpa;
2526
try emit.code_offset_mapping.resize(gpa, emit.lower.mir.instructions.len);
2627
emit.relocs.clearRetainingCapacity();
2728
emit.table_relocs.clearRetainingCapacity();
@@ -99,12 +100,10 @@ pub fn emitMir(emit: *Emit) Error!void {
99100
.inst => |inst| .{ .index = inst, .is_extern = false, .type = .inst },
100101
.table => .{ .index = undefined, .is_extern = false, .type = .table },
101102
.nav => |nav| {
102-
const ip = &emit.pt.zcu.intern_pool;
103103
const sym_index = switch (try codegen.genNavRef(
104104
emit.bin_file,
105105
emit.pt,
106106
emit.lower.src_loc,
107-
.fromInterned(ip.getNav(nav).typeOf(ip)),
108107
nav,
109108
emit.lower.target.*,
110109
)) {
@@ -118,12 +117,13 @@ pub fn emitMir(emit: *Emit) Error!void {
118117
return error.EmitFail;
119118
},
120119
};
120+
const ip = &emit.pt.zcu.intern_pool;
121121
break :target switch (ip.getNav(nav).status) {
122122
.unresolved => unreachable,
123123
.type_resolved => |type_resolved| .{
124124
.index = sym_index,
125125
.is_extern = false,
126-
.type = if (type_resolved.is_threadlocal) .tlv else .symbol,
126+
.type = if (type_resolved.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
127127
},
128128
.fully_resolved => |fully_resolved| switch (ip.indexToKey(fully_resolved.val)) {
129129
.@"extern" => |@"extern"| .{
@@ -132,7 +132,7 @@ pub fn emitMir(emit: *Emit) Error!void {
132132
.default => true,
133133
.hidden, .protected => false,
134134
},
135-
.type = if (@"extern".is_threadlocal) .tlv else .symbol,
135+
.type = if (@"extern".is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
136136
.force_pcrel_direct = switch (@"extern".relocation) {
137137
.any => false,
138138
.pcrel => true,
@@ -141,7 +141,7 @@ pub fn emitMir(emit: *Emit) Error!void {
141141
.variable => |variable| .{
142142
.index = sym_index,
143143
.is_extern = false,
144-
.type = if (variable.is_threadlocal) .tlv else .symbol,
144+
.type = if (variable.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
145145
},
146146
else => .{ .index = sym_index, .is_extern = false, .type = .symbol },
147147
},
@@ -292,12 +292,8 @@ pub fn emitMir(emit: *Emit) Error!void {
292292
.branch, .tls => unreachable,
293293
.tlv => {
294294
if (emit.bin_file.cast(.elf)) |elf_file| {
295-
if (reloc.target.is_extern) {
296-
// TODO handle extern TLS vars, i.e., emit GD model
297-
return emit.fail("TODO implement extern {s} reloc for {s}", .{
298-
@tagName(reloc.target.type), @tagName(emit.bin_file.tag),
299-
});
300-
} else if (emit.pic) switch (lowered_inst.encoding.mnemonic) {
295+
// TODO handle extern TLS vars, i.e., emit GD model
296+
if (emit.pic) switch (lowered_inst.encoding.mnemonic) {
301297
.lea, .mov => {
302298
// Here, we currently assume local dynamic TLS vars, and so
303299
// we emit LD model.
@@ -507,7 +503,6 @@ pub fn emitMir(emit: *Emit) Error!void {
507503
} };
508504
},
509505
.pseudo_dbg_arg_m, .pseudo_dbg_var_m => {
510-
const ip = &emit.pt.zcu.intern_pool;
511506
const mem = emit.lower.mir.resolveMemoryExtra(mir_inst.data.x.payload).decode();
512507
break :loc .{ .plus = .{
513508
base: {
@@ -519,7 +514,6 @@ pub fn emitMir(emit: *Emit) Error!void {
519514
emit.bin_file,
520515
emit.pt,
521516
emit.lower.src_loc,
522-
.fromInterned(ip.getNav(nav).typeOf(ip)),
523517
nav,
524518
emit.lower.target.*,
525519
) catch |err| switch (err) {
@@ -803,9 +797,6 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
803797
@tagName(reloc.target.type), @tagName(emit.bin_file.tag),
804798
}),
805799
.tls => if (emit.bin_file.cast(.elf)) |elf_file| {
806-
if (reloc.target.is_extern) return emit.fail("TODO implement extern {s} reloc for {s}", .{
807-
@tagName(reloc.target.type), @tagName(emit.bin_file.tag),
808-
});
809800
const zo = elf_file.zigObjectPtr().?;
810801
const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
811802
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
818809
@tagName(reloc.target.type), @tagName(emit.bin_file.tag),
819810
}),
820811
.tlv => if (emit.bin_file.cast(.elf)) |elf_file| {
821-
if (reloc.target.is_extern) return emit.fail("TODO implement extern {s} reloc for {s}", .{
822-
@tagName(reloc.target.type), @tagName(emit.bin_file.tag),
823-
});
824812
const zo = elf_file.zigObjectPtr().?;
825813
const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
826814
const r_type: std.elf.R_X86_64 = if (emit.pic) .DTPOFF32 else .TPOFF32;

src/codegen.zig

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -955,47 +955,18 @@ pub fn genNavRef(
955955
lf: *link.File,
956956
pt: Zcu.PerThread,
957957
src_loc: Zcu.LazySrcLoc,
958-
ty: Type,
959958
nav_index: InternPool.Nav.Index,
960959
target: std.Target,
961960
) CodeGenError!GenResult {
962961
const zcu = pt.zcu;
963962
const ip = &zcu.intern_pool;
964-
log.debug("genNavRef: ty = {}", .{ty.fmt(pt)});
965-
966-
if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) {
967-
const imm: u64 = switch (@divExact(target.ptrBitWidth(), 8)) {
968-
1 => 0xaa,
969-
2 => 0xaaaa,
970-
4 => 0xaaaaaaaa,
971-
8 => 0xaaaaaaaaaaaaaaaa,
972-
else => unreachable,
973-
};
974-
return .{ .mcv = .{ .immediate = imm } };
975-
}
976-
977-
const comp = lf.comp;
978-
const gpa = comp.gpa;
979-
980-
// TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
981-
if (ty.castPtrToFn(zcu)) |fn_ty| {
982-
if (zcu.typeToFunc(fn_ty).?.is_generic) {
983-
return .{ .mcv = .{ .immediate = fn_ty.abiAlignment(zcu).toByteUnits().? } };
984-
}
985-
} else if (ty.zigTypeTag(zcu) == .pointer) {
986-
const elem_ty = ty.elemType2(zcu);
987-
if (!elem_ty.hasRuntimeBits(zcu)) {
988-
return .{ .mcv = .{ .immediate = elem_ty.abiAlignment(zcu).toByteUnits().? } };
989-
}
990-
}
991-
992963
const nav = ip.getNav(nav_index);
964+
log.debug("genNavRef({})", .{nav.fqn.fmt(ip)});
965+
993966
const lib_name, const linkage, const is_threadlocal = if (nav.getExtern(ip)) |e|
994-
.{ e.lib_name, e.linkage, e.is_threadlocal and !zcu.navFileScope(nav_index).mod.?.single_threaded }
967+
.{ e.lib_name, e.linkage, e.is_threadlocal and zcu.comp.config.any_non_single_threaded }
995968
else
996969
.{ .none, .internal, false };
997-
998-
const name = nav.name;
999970
if (lf.cast(.elf)) |elf_file| {
1000971
const zo = elf_file.zigObjectPtr().?;
1001972
switch (linkage) {
@@ -1005,7 +976,7 @@ pub fn genNavRef(
1005976
return .{ .mcv = .{ .lea_symbol = sym_index } };
1006977
},
1007978
.strong, .weak => {
1008-
const sym_index = try elf_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
979+
const sym_index = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
1009980
switch (linkage) {
1010981
.internal => unreachable,
1011982
.strong => {},
@@ -1026,7 +997,7 @@ pub fn genNavRef(
1026997
return .{ .mcv = .{ .lea_symbol = sym_index } };
1027998
},
1028999
.strong, .weak => {
1029-
const sym_index = try macho_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
1000+
const sym_index = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
10301001
switch (linkage) {
10311002
.internal => unreachable,
10321003
.strong => {},
@@ -1047,8 +1018,8 @@ pub fn genNavRef(
10471018
return .{ .mcv = .{ .load_got = sym_index } };
10481019
},
10491020
.strong, .weak => {
1050-
const global_index = try coff_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip));
1051-
try coff_file.need_got_table.put(gpa, global_index, {}); // needs GOT
1021+
const global_index = try coff_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
1022+
try coff_file.need_got_table.put(zcu.gpa, global_index, {}); // needs GOT
10521023
return .{ .mcv = .{ .load_got = link.File.Coff.global_symbol_bit | global_index } };
10531024
},
10541025
.link_once => unreachable,
@@ -1058,7 +1029,7 @@ pub fn genNavRef(
10581029
const atom = p9.getAtom(atom_index);
10591030
return .{ .mcv = .{ .memory = atom.getOffsetTableAddress(p9) } };
10601031
} else {
1061-
const msg = try ErrorMsg.create(gpa, src_loc, "TODO genNavRef for target {}", .{target});
1032+
const msg = try ErrorMsg.create(zcu.gpa, src_loc, "TODO genNavRef for target {}", .{target});
10621033
return .{ .fail = msg };
10631034
}
10641035
}
@@ -1071,12 +1042,11 @@ pub fn genTypedValue(
10711042
val: Value,
10721043
target: std.Target,
10731044
) CodeGenError!GenResult {
1074-
const ip = &pt.zcu.intern_pool;
10751045
return switch (try lowerValue(pt, val, &target)) {
10761046
.none => .{ .mcv = .none },
10771047
.undef => .{ .mcv = .undef },
10781048
.immediate => |imm| .{ .mcv = .{ .immediate = imm } },
1079-
.lea_nav => |nav| genNavRef(lf, pt, src_loc, .fromInterned(ip.getNav(nav).typeOf(ip)), nav, target),
1049+
.lea_nav => |nav| genNavRef(lf, pt, src_loc, nav, target),
10801050
.lea_uav => |uav| switch (try lf.lowerUav(
10811051
pt,
10821052
uav.val,

src/link/Elf/ZigObject.zig

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,6 @@ fn getNavShdrIndex(
11421142
const gpa = elf_file.base.comp.gpa;
11431143
const ptr_size = elf_file.ptrWidthBytes();
11441144
const ip = &zcu.intern_pool;
1145-
const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;
11461145
const nav_val = zcu.navValue(nav_index);
11471146
if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) {
11481147
if (self.text_index) |symbol_index|
@@ -1162,7 +1161,7 @@ fn getNavShdrIndex(
11621161
else => .{ true, false, nav_val.toIntern() },
11631162
};
11641163
const has_relocs = self.symbol(sym_index).atom(elf_file).?.relocs(elf_file).len > 0;
1165-
if (any_non_single_threaded and is_threadlocal) {
1164+
if (is_threadlocal and elf_file.base.comp.config.any_non_single_threaded) {
11661165
const is_bss = !has_relocs and for (code) |byte| {
11671166
if (byte != 0) break false;
11681167
} else true;
@@ -1542,7 +1541,7 @@ pub fn updateNav(
15421541
nav.name.toSlice(ip),
15431542
@"extern".lib_name.toSlice(ip),
15441543
);
1545-
if (@"extern".is_threadlocal) self.symbol(sym_index).flags.is_tls = true;
1544+
if (@"extern".is_threadlocal and elf_file.base.comp.config.any_non_single_threaded) self.symbol(sym_index).flags.is_tls = true;
15461545
if (self.dwarf) |*dwarf| dwarf: {
15471546
var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf;
15481547
defer debug_wip_nav.deinit();

src/link/MachO/ZigObject.zig

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ pub fn updateNav(
881881
const name = @"extern".name.toSlice(ip);
882882
const lib_name = @"extern".lib_name.toSlice(ip);
883883
const sym_index = try self.getGlobalSymbol(macho_file, name, lib_name);
884-
if (@"extern".is_threadlocal) self.symbols.items[sym_index].flags.tlv = true;
884+
if (@"extern".is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) self.symbols.items[sym_index].flags.tlv = true;
885885
if (self.dwarf) |*dwarf| dwarf: {
886886
var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf;
887887
defer debug_wip_nav.deinit();
@@ -1154,15 +1154,14 @@ fn getNavOutputSection(
11541154
) error{OutOfMemory}!u8 {
11551155
_ = self;
11561156
const ip = &zcu.intern_pool;
1157-
const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;
11581157
const nav_val = zcu.navValue(nav_index);
11591158
if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) return macho_file.zig_text_sect_index.?;
11601159
const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
11611160
.variable => |variable| .{ false, variable.is_threadlocal, variable.init },
11621161
.@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none },
11631162
else => .{ true, false, nav_val.toIntern() },
11641163
};
1165-
if (any_non_single_threaded and is_threadlocal) {
1164+
if (is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) {
11661165
for (code) |byte| {
11671166
if (byte != 0) break;
11681167
} else return macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection(

0 commit comments

Comments
 (0)