Commit 6b2c8fc688

Alex Rønne Petersen <alex@alexrp.com>
2024-11-03 13:36:11
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.
1 parent 814a41b
Changed files (3)
lib
stage1
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"),
     };
 }
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)::);
+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 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 (_MSC_VER && _M_IX86) || defined(__i386__) || defined(__X86__)
+#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)::);
+    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
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)::);
+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 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 (_MSC_VER && _M_IX86) || defined(__i386__) || defined(__X86__)
+#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)::);
+    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