Skip to content

Commit 9e43ef9

Browse files
committed
toolchain/gcc: Add "memory" clobber to asm traps before CODE_UNREACHABLE
GCC 14.3 will happily delete any code that appears before __builtin_unreachable that isn't separated with an obvious branch. That includes __asm__ statements, even those which generate traps. The failure case that I debugged was on x86 in z_check_stack_sentinel. There is a store to restore the sentinel to the correct value just before the ARCH_EXCEPT, and that macro emits 'int $32' followed by CODE_UNREACHABLE. Because the compiler didn't understand that ARCH_EXCEPT was changing execution flow, it decided that the sentinel restoring store 'couldn't' be reached and elided it. I added the "memory" clobber to the asm statement in ARCH_EXCEPT before CODE_UNREACHABLE to enforce that all pending store operations be performed before the asm statement occurs. This ensures that they are not deleted by the compiler. I think this might be a GCC bug. The GCC documentation explicitly documents that asm statements which change the flow of control should be followed by __builtin_unreachable. Signed-off-by: Keith Packard <[email protected]>
1 parent d12147f commit 9e43ef9

File tree

5 files changed

+7
-5
lines changed

5 files changed

+7
-5
lines changed

arch/arm/core/cortex_m/thread.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ FUNC_NORETURN void z_arm_switch_to_main_no_multithreading(k_thread_entry_t main_
649649
,
650650
[_psplim] "r"(psplim)
651651
#endif
652-
: "r0", "r1", "r2", "ip", "lr");
652+
: "r0", "r1", "r2", "ip", "lr", "memory");
653653

654654
CODE_UNREACHABLE; /* LCOV_EXCL_LINE */
655655
}

arch/x86/core/ia32/fatal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ static FUNC_NORETURN __used void df_handler_top(void)
219219
/* NT bit is set in EFLAGS so we will task switch back to _main_tss
220220
* and run df_handler_bottom
221221
*/
222-
__asm__ volatile ("iret");
222+
__asm__ volatile ("iret" ::: "memory");
223223
CODE_UNREACHABLE;
224224
}
225225

arch/xtensa/core/fatal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ void xtensa_simulator_exit(int return_code)
118118
"simcall\n\t"
119119
:
120120
: [code] "r" (return_code), [call] "i" (SYS_exit)
121-
: "a3", "a2");
121+
: "a3", "a2", "memory");
122122

123123
CODE_UNREACHABLE;
124124
}

include/zephyr/arch/x86/ia32/arch.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,8 @@ extern struct task_state_segment _main_tss;
362362
"int %[vector]\n\t" \
363363
: \
364364
: [vector] "i" (Z_X86_OOPS_VECTOR), \
365-
[reason] "i" (reason_p)); \
365+
[reason] "i" (reason_p) \
366+
: "memory"); \
366367
CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ \
367368
} while (false)
368369

include/zephyr/arch/x86/intel64/arch.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ static ALWAYS_INLINE unsigned int arch_irq_lock(void)
6666
"movq %[reason], %%rax\n\t" \
6767
"int $32\n\t" \
6868
: \
69-
: [reason] "i" (reason_p)); \
69+
: [reason] "i" (reason_p) \
70+
: "memory"); \
7071
CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ \
7172
} while (false)
7273

0 commit comments

Comments
 (0)