From 3b947932abbb9f14710c64e3afa6fa88947d1ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 8 Aug 2026 02:52:48 +0200 Subject: [PATCH] std: avoid pointless delay slots and lr writes in inline assembly And fill in some delay slots where we can't avoid them. --- lib/std/Thread.zig | 64 +++++++++++++++++------------------ lib/std/debug/cpu_context.zig | 5 +++ lib/std/os/linux/or1k.zig | 3 ++ lib/std/os/linux/tls.zig | 1 + lib/std/pie.zig | 2 ++ lib/std/start.zig | 18 +++++----- 6 files changed, 53 insertions(+), 40 deletions(-) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 0cc439d07da7d8a6c0de39a65bf83800ea9b6992..bd3f9e1f019fea9de6f06b8da4df47cdf11eaa0a 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -1166,29 +1166,29 @@ const LinuxThreadImpl = struct { posix.sigprocmask(std.posix.SIG.BLOCK, &std.os.linux.sigfillset(), null); switch (target.cpu.arch) { .x86 => asm volatile ( - \\ movl $91, %%eax # SYS_munmap - \\ int $128 - \\ movl $1, %%eax # SYS_exit - \\ movl $0, %%ebx - \\ int $128 + \\ movl $91, %%eax # SYS_munmap + \\ int $128 + \\ movl $1, %%eax # SYS_exit + \\ movl $0, %%ebx + \\ int $128 : : [ptr] "{ebx}" (@intFromPtr(self.mapped.ptr)), [len] "{ecx}" (self.mapped.len), ), .x86_64 => asm volatile (switch (target.abi) { .gnux32, .muslx32, .x32 => - \\ movl $0x4000000b, %%eax # SYS_munmap - \\ syscall - \\ movl $0x4000003c, %%eax # SYS_exit - \\ xor %%rdi, %%rdi - \\ syscall + \\ movl $0x4000000b, %%eax # SYS_munmap + \\ syscall + \\ movl $0x4000003c, %%eax # SYS_exit + \\ xor %%rdi, %%rdi + \\ syscall , else => - \\ movl $11, %%eax # SYS_munmap - \\ syscall - \\ movl $60, %%eax # SYS_exit - \\ xor %%rdi, %%rdi - \\ syscall + \\ movl $11, %%eax # SYS_munmap + \\ syscall + \\ movl $60, %%eax # SYS_exit + \\ xor %%rdi, %%rdi + \\ syscall , } : @@ -1196,21 +1196,21 @@ const LinuxThreadImpl = struct { [len] "{rsi}" (self.mapped.len), ), .arm, .armeb, .thumb, .thumbeb => asm volatile ( - \\ mov r7, #91 // SYS_munmap - \\ svc 0 - \\ mov r7, #1 // SYS_exit - \\ mov r0, #0 - \\ svc 0 + \\ mov r7, #91 // SYS_munmap + \\ svc 0 + \\ mov r7, #1 // SYS_exit + \\ mov r0, #0 + \\ svc 0 : : [ptr] "{r0}" (@intFromPtr(self.mapped.ptr)), [len] "{r1}" (self.mapped.len), ), .aarch64, .aarch64_be => asm volatile ( - \\ mov x8, #215 // SYS_munmap - \\ svc 0 - \\ mov x8, #93 // SYS_exit - \\ mov x0, #0 - \\ svc 0 + \\ mov x8, #215 // SYS_munmap + \\ svc 0 + \\ mov x8, #93 // SYS_exit + \\ mov x0, #0 + \\ svc 0 : : [ptr] "{x0}" (@intFromPtr(self.mapped.ptr)), [len] "{x1}" (self.mapped.len), @@ -1236,21 +1236,21 @@ const LinuxThreadImpl = struct { [len] "{r1}" (self.mapped.len), ), .hexagon => asm volatile ( - \\ r6 = #215 // SYS_munmap - \\ trap0(#1) - \\ r6 = #93 // SYS_exit - \\ r0 = #0 - \\ trap0(#1) + \\ r6 = #215 // SYS_munmap + \\ trap0(#1) + \\ r6 = #93 // SYS_exit + \\ r0 = #0 + \\ trap0(#1) : : [ptr] "{r0}" (@intFromPtr(self.mapped.ptr)), [len] "{r1}" (self.mapped.len), ), .hppa => asm volatile ( - \\ ldi 91, %%r20 /* SYS_munmap */ \\ ble 0x100(%%sr2, %%r0) - \\ ldi 1, %%r20 /* SYS_exit */ + \\ ldi 91, %%r20 /* SYS_munmap */ \\ ldi 0, %%r26 \\ ble 0x100(%%sr2, %%r0) + \\ ldi 1, %%r20 /* SYS_exit */ : : [ptr] "{r26}" (@intFromPtr(self.mapped.ptr)), [len] "{r25}" (self.mapped.len), diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index ab90b9b2c27e374ef56148334eb83fcc13d6ba75..6579ade9f4ca749170294c5a03cf91a9a4b7e3a8 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -1039,6 +1039,7 @@ const Mips = extern struct { \\ sd $fp, 240($t0) \\ sd $ra, 248($t0) \\ bal 1f + \\ nop \\1: \\ sd $ra, 256($t0) \\ .set pop @@ -1080,6 +1081,7 @@ const Mips = extern struct { \\ sw $fp, 120($t4) \\ sw $ra, 124($t4) \\ bal 1f + \\ nop \\1: \\ sw $ra, 128($t4) \\ .set pop @@ -1164,6 +1166,7 @@ const Or1k = extern struct { \\ l.sw 120(r15), r30 \\ l.sw 124(r15), r31 \\ l.jal 1f + \\ l.nop \\1: \\ l.sw 128(r15), r9 : @@ -1558,6 +1561,7 @@ const Sparc = extern struct { \\ stx %i6, [%l0 + 240] \\ stx %i7, [%l0 + 248] \\ call 1f + \\ nop \\1: \\ stx %o7, [%l0 + 256] else @@ -1578,6 +1582,7 @@ const Sparc = extern struct { \\ std %i4, [%l0 + 112] \\ std %i6, [%l0 + 120] \\ call 1f + \\ nop \\1: \\ st %o7, [%l0 + 128] : diff --git a/lib/std/os/linux/or1k.zig b/lib/std/os/linux/or1k.zig index 2d27b49a8f4f44c4a8f601df3d108c8eedfe0f17..75dbef7623a4012cca599fd2d49cd3e9d49a6dcc 100644 --- a/lib/std/os/linux/or1k.zig +++ b/lib/std/os/linux/or1k.zig @@ -138,7 +138,9 @@ pub fn clone() callconv(.naked) u32 { \\ l.sys 1 \\ l.sfeqi r11, 0 \\ l.bf 1f + \\ l.nop \\ l.jr r9 + \\ l.nop \\1: ); if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile ( @@ -151,6 +153,7 @@ pub fn clone() callconv(.naked) u32 { \\ l.lwz r11, 0(r1) \\ l.lwz r3, 4(r1) \\ l.jalr r11 + \\ l.nop \\ \\ l.ori r3, r11, 0 \\ l.ori r11, r0, 93 # SYS_exit diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 81ccd5cb56eb90ff1d2d9582f45c6b22630a5173..798f5666311dbad2edbfd81bdd0e81c02c184019 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -295,6 +295,7 @@ pub fn setThreadPointer(addr: usize) void { .hppa => { asm volatile ( \\ ble 0xe0(%%sr2, %%r0) + \\ nop : : [addr] "={r26}" (addr), : .{ .r29 = true }); diff --git a/lib/std/pie.zig b/lib/std/pie.zig index bcec6acd590f391c56202ff897b364ee0d456554..60829b610d775816e00492428c48a6a0c31850ae 100644 --- a/lib/std/pie.zig +++ b/lib/std/pie.zig @@ -190,6 +190,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ .weak _DYNAMIC \\ .hidden _DYNAMIC \\ l.jal 1f + \\ l.nop \\ .word _DYNAMIC - . \\1: \\ l.lwz %[ret], 0(r9) @@ -245,6 +246,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { \\ mov.l 1f, %[ret] \\ add r0, %[ret] \\ bra 2f + \\ nop \\1: \\ .balign 4 \\ .long DYNAMIC - . diff --git a/lib/std/start.zig b/lib/std/start.zig index 92e0df4ed4b938f64a01a2c9cd51494ae8271447..0e88eed1a478b09afc6490acffa9fca4c01b1fe2 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -295,7 +295,7 @@ fn _start() callconv(.naked) noreturn { \\ r29 = and(r29, #-8) \\ memw(r29 + #-8) = r29 \\ r29 = add(r29, #-8) - \\ call %[posixCallMainAndExit] + \\ jump %[posixCallMainAndExit] , .kvx => \\ make $fp = 0 @@ -327,7 +327,8 @@ fn _start() callconv(.naked) noreturn { \\ l.ori r9, r0, 0 \\ l.ori r3, r1, 0 \\ l.andi r1, r1, -4 - \\ l.jal %[posixCallMainAndExit] + \\ l.j %[posixCallMainAndExit] + \\ l.nop , .riscv32, .riscv32be, .riscv64, .riscv64be => \\ li fp, 0 @@ -356,7 +357,7 @@ fn _start() callconv(.naked) noreturn { \\ or %%r1, %%r0, %%r0 \\ or %%r2, %%r31, %%r0 \\ clr %%r31, %%r31, 4<0> - \\ br.n %[posixCallMainAndExit] + \\ br %[posixCallMainAndExit] , .microblaze, .microblazeel => // r1 = SP, r15 = LR, r19 = FP, r20 = GP @@ -366,7 +367,7 @@ fn _start() callconv(.naked) noreturn { \\ addi r20, r20, _GLOBAL_OFFSET_TABLE_ + 8 \\ ori r5, r1, 0 \\ andi r1, r1, -4 - \\ brlid r15, %[posixCallMainAndExit] + \\ bri %[posixCallMainAndExit] , .mips, .mipsel => \\ move $fp, $zero @@ -385,7 +386,7 @@ fn _start() callconv(.naked) noreturn { \\ move $a0, $sp \\ and $sp, -8 \\ subu $sp, $sp, 16 - \\ jalr $t9 + \\ jr $t9 , .mips64, .mips64el => switch (builtin.abi) { .gnuabin32, .muslabin32, .abin32 => @@ -403,7 +404,7 @@ fn _start() callconv(.naked) noreturn { \\ move $a0, $sp \\ and $sp, -16 \\ subu $sp, $sp, 16 - \\ jalr $t9 + \\ jr $t9 , else => \\ move $fp, $zero @@ -424,7 +425,7 @@ fn _start() callconv(.naked) noreturn { \\ move $a0, $sp \\ and $sp, -16 \\ dsubu $sp, $sp, 16 - \\ jalr $t9 + \\ jr $t9 , }, .powerpc, .powerpcle => @@ -476,7 +477,8 @@ fn _start() callconv(.naked) noreturn { \\ and r0, r15 \\ mov.l 2f, r1 \\1: - \\ bsrf r1 + \\ braf r1 + \\ nop \\2: \\ .balign 4 \\ .long %[posixCallMainAndExit]@PCREL - (1b + 4 - .) -- 2.54.0