Commit b5cc658ab4

Alex Rønne Petersen <alex@alexrp.com>
2025-07-06 22:19:08
llvm: Use emulated TLS when appropriate for the target
Closes #24236.
1 parent c96c913
src/codegen/llvm/bindings.zig
@@ -79,6 +79,7 @@ pub const TargetMachine = opaque {
         data_sections: bool,
         float_abi: FloatABI,
         abi_name: ?[*:0]const u8,
+        emulated_tls: bool,
     ) *TargetMachine;
 
     pub const dispose = LLVMDisposeTargetMachine;
src/codegen/llvm.zig
@@ -1047,6 +1047,7 @@ pub const Object = struct {
             comp.data_sections,
             float_abi,
             if (target_util.llvmMachineAbi(&comp.root_mod.resolved_target.result)) |s| s.ptr else null,
+            target_util.useEmulatedTls(&comp.root_mod.resolved_target.result),
         );
         errdefer target_machine.dispose();
 
src/main.zig
@@ -6324,7 +6324,7 @@ fn cmdDumpLlvmInts(
         if (llvm.Target.getFromTriple(triple, &target, &error_message) != .False) @panic("bad");
         break :t target;
     };
-    const tm = llvm.TargetMachine.create(target, triple, null, null, .None, .Default, .Default, false, false, .Default, null);
+    const tm = llvm.TargetMachine.create(target, triple, null, null, .None, .Default, .Default, false, false, .Default, null, false);
     const dl = tm.createTargetDataLayout();
     const context = llvm.Context.create();
 
src/target.zig
@@ -85,6 +85,19 @@ pub fn defaultSingleThreaded(target: *const std.Target) bool {
     return false;
 }
 
+pub fn useEmulatedTls(target: *const std.Target) bool {
+    if (target.abi.isAndroid()) {
+        if (target.os.version_range.linux.android < 29) return true;
+        return false;
+    }
+    if (target.abi.isOpenHarmony()) return true;
+    return switch (target.os.tag) {
+        .openbsd => true,
+        .windows => target.abi == .cygnus,
+        else => false,
+    };
+}
+
 pub fn hasValgrindSupport(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {
     // We can't currently output the necessary Valgrind client request assembly when using the C
     // backend and compiling with an MSVC-like compiler.
src/zig_llvm.cpp
@@ -83,7 +83,7 @@ static const bool assertions_on = false;
 LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple,
     const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
     LLVMCodeModel CodeModel, bool function_sections, bool data_sections, ZigLLVMFloatABI float_abi,
-    const char *abi_name)
+    const char *abi_name, bool emulated_tls)
 {
     std::optional<Reloc::Model> RM;
     switch (Reloc){
@@ -149,6 +149,10 @@ LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Tri
         opt.MCOptions.ABIName = abi_name;
     }
 
+    if (emulated_tls) {
+        opt.EmulatedTLS = true;
+    }
+
     TargetMachine *TM = reinterpret_cast<Target*>(T)->createTargetMachine(Triple, CPU, Features, opt, RM, CM,
             OL, JIT);
     return reinterpret_cast<LLVMTargetMachineRef>(TM);
src/zig_llvm.h
@@ -105,7 +105,7 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi
 ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple,
     const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
     LLVMCodeModel CodeModel, bool function_sections, bool data_sections, ZigLLVMFloatABI float_abi,
-    const char *abi_name);
+    const char *abi_name, bool emulated_tls);
 
 ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit);