| ... | @@ -726,12 +726,14 @@ comptime { | ... | @@ -726,12 +726,14 @@ comptime { |
| 726 | // function for the GD and LD models. This function is unlikely to actually be used, since | 726 | // function for the GD and LD models. This function is unlikely to actually be used, since |
| 727 | // the linker should be able to relax every TLS access to the LE model and therefore | 727 | // the linker should be able to relax every TLS access to the LE model and therefore |
| 728 | // eliminate all calls to this function, but that isn't guaranteed. | 728 | // eliminate all calls to this function, but that isn't guaranteed. |
| 729 | _ = struct { | 729 | const Fns = struct { |
| 730 | const TlsIndex = switch (native_arch) { | 730 | const TlsIndex = switch (native_arch) { |
| 731 | .x86_64 => extern struct { module: u64, offset: u64 }, // Even for x32... | 731 | .x86_64 => extern struct { module: u64, offset: u64 }, // Even for x32... |
| 732 | else => extern struct { module: usize, offset: usize }, // ...but not MIPS N32! | 732 | else => extern struct { module: usize, offset: usize }, // ...but not MIPS N32! |
| 733 | }; | 733 | }; |
| 734 | export fn __tls_get_addr(ti: *const TlsIndex) *anyopaque { | 734 | fn __tls_get_addr(ti: *const TlsIndex) callconv(.c) *anyopaque { |
| | 735 | comptime assert(native_arch != .s390x); |
| | 736 | |
| 735 | assert(ti.module == 1); // The executable's module ID is always 1 | 737 | assert(ti.module == 1); // The executable's module ID is always 1 |
| 736 | const tp = getThreadPointer(); | 738 | const tp = getThreadPointer(); |
| 737 | const block: [*]u8 = switch (current_variant) { | 739 | const block: [*]u8 = switch (current_variant) { |
| ... | @@ -743,6 +745,25 @@ comptime { | ... | @@ -743,6 +745,25 @@ comptime { |
| 743 | }; | 745 | }; |
| 744 | return block[@intCast(ti.offset)..]; | 746 | return block[@intCast(ti.offset)..]; |
| 745 | } | 747 | } |
| | 748 | fn __tls_get_offset() callconv(.naked) noreturn { |
| | 749 | comptime assert(native_arch == .s390x); |
| | 750 | |
| | 751 | // We receive the module's GOT pointer in r12 and the GOT offset in r2. |
| | 752 | asm volatile ( |
| | 753 | \\ la %%r1, 0(%%r12, %%r2) |
| | 754 | \\ lg %%r2, 8(%%r1) |
| | 755 | \\ lgrl %%r0, %[block_size] |
| | 756 | \\ sgr %%r2, %%r0 |
| | 757 | \\ br %%r14 |
| | 758 | : |
| | 759 | : [block_size] "s" (&area_desc.block.size), |
| | 760 | ); |
| | 761 | } |
| 746 | }; | 762 | }; |
| | 763 | |
| | 764 | if (native_arch == .s390x) |
| | 765 | @export(&Fns.__tls_get_offset, .{ .name = "__tls_get_offset" }) |
| | 766 | else |
| | 767 | @export(&Fns.__tls_get_addr, .{ .name = "__tls_get_addr" }); |
| 747 | } | 768 | } |
| 748 | } | 769 | } |