From 6b2c8fc6886cdf251146aa3674e87f6ca3111e24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sun, 3 Nov 2024 13:36:11 +0100 Subject: [PATCH] zig.h: Improve portability of zig_*_windows_teb() helpers. * Make it work for thumb and aarch64. * Clean up std.os.windows.teb() a bit. I also updated stage1/zig.h since the changes are backwards-compatible and are necessary due to the std.os.windows changes that call the newly-added functions. --- lib/std/os/windows.zig | 58 ++++++++++++++++++++++-------------------- lib/zig.h | 54 ++++++++++++++++++++++++++++----------- stage1/zig.h | 54 ++++++++++++++++++++++++++++----------- 3 files changed, 108 insertions(+), 58 deletions(-) diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 010bbcd005..9a18c31363 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -2101,39 +2101,41 @@ pub fn UnlockFile( /// This is a workaround for the C backend until zig has the ability to put /// C code in inline assembly. +extern fn zig_thumb_windows_teb() callconv(.c) *anyopaque; +extern fn zig_aarch64_windows_teb() callconv(.c) *anyopaque; extern fn zig_x86_windows_teb() callconv(.c) *anyopaque; extern fn zig_x86_64_windows_teb() callconv(.c) *anyopaque; pub fn teb() *TEB { return switch (native_arch) { - .x86 => blk: { - if (builtin.zig_backend == .stage2_c) { - break :blk @ptrCast(@alignCast(zig_x86_windows_teb())); - } else { - break :blk asm ( - \\ movl %%fs:0x18, %[ptr] - : [ptr] "=r" (-> *TEB), - ); - } - }, - .x86_64 => blk: { - if (builtin.zig_backend == .stage2_c) { - break :blk @ptrCast(@alignCast(zig_x86_64_windows_teb())); - } else { - break :blk asm ( - \\ movq %%gs:0x30, %[ptr] - : [ptr] "=r" (-> *TEB), - ); - } - }, - .thumb => asm ( - \\ mrc p15, 0, %[ptr], c13, c0, 2 - : [ptr] "=r" (-> *TEB), - ), - .aarch64 => asm ( - \\ mov %[ptr], x18 - : [ptr] "=r" (-> *TEB), - ), + .thumb => if (builtin.zig_backend == .stage2_c) + @ptrCast(@alignCast(zig_thumb_windows_teb())) + else + asm ( + \\ mrc p15, 0, %[ptr], c13, c0, 2 + : [ptr] "=r" (-> *TEB), + ), + .aarch64 => if (builtin.zig_backend == .stage2_c) + @ptrCast(@alignCast(zig_aarch64_windows_teb())) + else + asm ( + \\ mov %[ptr], x18 + : [ptr] "=r" (-> *TEB), + ), + .x86 => if (builtin.zig_backend == .stage2_c) + @ptrCast(@alignCast(zig_x86_windows_teb())) + else + asm ( + \\ movl %%fs:0x18, %[ptr] + : [ptr] "=r" (-> *TEB), + ), + .x86_64 => if (builtin.zig_backend == .stage2_c) + @ptrCast(@alignCast(zig_x86_64_windows_teb())) + else + asm ( + \\ movq %%gs:0x30, %[ptr] + : [ptr] "=r" (-> *TEB), + ), else => @compileError("unsupported arch"), }; } diff --git a/lib/zig.h b/lib/zig.h index 2f2575fdcf..248bb8641c 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -3926,28 +3926,52 @@ static inline void zig_msvc_atomic_store_i128(zig_i128 volatile* obj, zig_i128 a /* ======================== Special Case Intrinsics ========================= */ -#if (_MSC_VER && _M_X64) || defined(__x86_64__) +#if defined(_M_ARM) || defined(__thumb__) -static inline void* zig_x86_64_windows_teb(void) { -#if _MSC_VER - return (void*)__readgsqword(0x30); -#else - void* teb; - __asm volatile(" movq %%gs:0x30, %[ptr]": [ptr]"=r"(teb)::); - return teb; +static inline void* zig_thumb_windows_teb(void) { + void* teb = 0; +#if defined(_MSC_VER) + teb = (void*)_MoveFromCoprocessor(15, 0, 13, 0, 2); +#elif defined(__GNUC__) + __asm__ ("mrc p15, 0, %[ptr], c13, c0, 2" : [ptr] "=r" (teb)); #endif + return teb; } -#elif (_MSC_VER && _M_IX86) || defined(__i386__) || defined(__X86__) +#elif defined(_M_ARM64) || defined(__arch64__) + +static inline void* zig_aarch64_windows_teb(void) { + void* teb = 0; +#if defined(_MSC_VER) + teb = (void*)__readx18qword(0x0); +#elif defined(__GNUC__) + __asm__ ("mov %[ptr], x18" : [ptr] "=r" (teb)); +#endif + return teb; +} + +#elif defined(_M_IX86) || defined(__i386__) static inline void* zig_x86_windows_teb(void) { -#if _MSC_VER - return (void*)__readfsdword(0x18); -#else - void* teb; - __asm volatile(" movl %%fs:0x18, %[ptr]": [ptr]"=r"(teb)::); - return teb; + void* teb = 0; +#if defined(_MSC_VER) + teb = (void*)__readfsdword(0x18); +#elif defined(__GNUC__) + __asm__ ("movl %%fs:0x18, %[ptr]" : [ptr] "=r" (teb)); #endif + return teb; +} + +#elif defined(_M_X64) || defined(__x86_64__) + +static inline void* zig_x86_64_windows_teb(void) { + void* teb = 0; +#if defined(_MSC_VER) + teb = (void*)__readgsqword(0x30); +#elif defined(__GNUC__) + __asm__ ("movq %%gs:0x30, %[ptr]" : [ptr] "=r" (teb)); +#endif + return teb; } #endif diff --git a/stage1/zig.h b/stage1/zig.h index 2f2575fdcf..248bb8641c 100644 --- a/stage1/zig.h +++ b/stage1/zig.h @@ -3926,28 +3926,52 @@ static inline void zig_msvc_atomic_store_i128(zig_i128 volatile* obj, zig_i128 a /* ======================== Special Case Intrinsics ========================= */ -#if (_MSC_VER && _M_X64) || defined(__x86_64__) +#if defined(_M_ARM) || defined(__thumb__) -static inline void* zig_x86_64_windows_teb(void) { -#if _MSC_VER - return (void*)__readgsqword(0x30); -#else - void* teb; - __asm volatile(" movq %%gs:0x30, %[ptr]": [ptr]"=r"(teb)::); - return teb; +static inline void* zig_thumb_windows_teb(void) { + void* teb = 0; +#if defined(_MSC_VER) + teb = (void*)_MoveFromCoprocessor(15, 0, 13, 0, 2); +#elif defined(__GNUC__) + __asm__ ("mrc p15, 0, %[ptr], c13, c0, 2" : [ptr] "=r" (teb)); #endif + return teb; } -#elif (_MSC_VER && _M_IX86) || defined(__i386__) || defined(__X86__) +#elif defined(_M_ARM64) || defined(__arch64__) + +static inline void* zig_aarch64_windows_teb(void) { + void* teb = 0; +#if defined(_MSC_VER) + teb = (void*)__readx18qword(0x0); +#elif defined(__GNUC__) + __asm__ ("mov %[ptr], x18" : [ptr] "=r" (teb)); +#endif + return teb; +} + +#elif defined(_M_IX86) || defined(__i386__) static inline void* zig_x86_windows_teb(void) { -#if _MSC_VER - return (void*)__readfsdword(0x18); -#else - void* teb; - __asm volatile(" movl %%fs:0x18, %[ptr]": [ptr]"=r"(teb)::); - return teb; + void* teb = 0; +#if defined(_MSC_VER) + teb = (void*)__readfsdword(0x18); +#elif defined(__GNUC__) + __asm__ ("movl %%fs:0x18, %[ptr]" : [ptr] "=r" (teb)); #endif + return teb; +} + +#elif defined(_M_X64) || defined(__x86_64__) + +static inline void* zig_x86_64_windows_teb(void) { + void* teb = 0; +#if defined(_MSC_VER) + teb = (void*)__readgsqword(0x30); +#elif defined(__GNUC__) + __asm__ ("movq %%gs:0x30, %[ptr]" : [ptr] "=r" (teb)); +#endif + return teb; } #endif