diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2025-05-26 22:59:01 +0100 |
|---|---|---|
| committer | Matthew Lugg <mlugg@mlugg.co.uk> | 2025-05-27 19:23:11 +0100 |
| commit | 92c63126e8a58235625cceaf0ea9e3d4eacfe513 (patch) | |
| tree | ab36da0c91e39622bdd8a9c49e2f636ee341878d /src/codegen.zig | |
| parent | 3ed9155f10b725e6d24c01f5ecbebf359f3599a7 (diff) | |
| download | zig-92c63126e8a58235625cceaf0ea9e3d4eacfe513.tar.gz zig-92c63126e8a58235625cceaf0ea9e3d4eacfe513.zip | |
compiler: tlv pointers are not comptime-known
Pointers to thread-local variables do not have their addresses known
until runtime, so it is nonsensical for them to be comptime-known. There
was logic in the compiler which was essentially attempting to treat them
as not being comptime-known despite the pointer being an interned value.
This was a bit of a mess, the check was frequent enough to actually show
up in compiler profiles, and it was very awkward for backends to deal
with, because they had to grapple with the fact that a "constant" they
were lowering might actually require runtime operations.
So, instead, do not consider these pointers to be comptime-known in
*any* way. Never intern such a pointer; instead, when the address of a
threadlocal is taken, emit an AIR instruction which computes the pointer
at runtime. This avoids lots of special handling for TLVs across
basically all codegen backends; of all somewhat-functional backends, the
only one which wasn't improved by this change was the LLVM backend,
because LLVM pretends this complexity around threadlocals doesn't exist.
This change simplifies Sema and codegen, avoids a potential source of
bugs, and potentially improves Sema performance very slightly by
avoiding a non-trivial check on a hot path.
Diffstat (limited to 'src/codegen.zig')
| -rw-r--r-- | src/codegen.zig | 18 |
1 files changed, 4 insertions, 14 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index c3be335acc..6577667c7c 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -818,10 +818,6 @@ pub const GenResult = union(enum) { /// The bit-width of the immediate may be smaller than `u64`. For example, on 32-bit targets /// such as ARM, the immediate will never exceed 32-bits. immediate: u64, - /// Threadlocal variable with address deferred until the linker allocates - /// everything in virtual memory. - /// Payload is a symbol index. - load_tlv: u32, /// Decl with address deferred until the linker allocates everything in virtual memory. /// Payload is a symbol index. load_direct: u32, @@ -883,13 +879,13 @@ fn genNavRef( } const nav = ip.getNav(nav_index); + assert(!nav.isThreadlocal(ip)); - const is_extern, const lib_name, const is_threadlocal = if (nav.getExtern(ip)) |e| - .{ true, e.lib_name, e.is_threadlocal } + const is_extern, const lib_name = if (nav.getExtern(ip)) |e| + .{ true, e.lib_name } else - .{ false, .none, nav.isThreadlocal(ip) }; + .{ false, .none }; - const single_threaded = zcu.navFileScope(nav_index).mod.?.single_threaded; const name = nav.name; if (lf.cast(.elf)) |elf_file| { const zo = elf_file.zigObjectPtr().?; @@ -899,9 +895,6 @@ fn genNavRef( return .{ .mcv = .{ .lea_symbol = sym_index } }; } const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_index); - if (!single_threaded and is_threadlocal) { - return .{ .mcv = .{ .load_tlv = sym_index } }; - } return .{ .mcv = .{ .lea_symbol = sym_index } }; } else if (lf.cast(.macho)) |macho_file| { const zo = macho_file.getZigObject().?; @@ -912,9 +905,6 @@ fn genNavRef( } const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index); const sym = zo.symbols.items[sym_index]; - if (!single_threaded and is_threadlocal) { - return .{ .mcv = .{ .load_tlv = sym.nlist_idx } }; - } return .{ .mcv = .{ .lea_symbol = sym.nlist_idx } }; } else if (lf.cast(.coff)) |coff_file| { if (is_extern) { |
