mirror of
https://github.com/micropython/micropython.git
synced 2026-06-10 08:35:15 +02:00
py/nlrx86: Fix nlr_push to build with Clang 19.
This version is believed to work from Clang 3.0 to 22.1.0 (all versions on godbolt at the time of writing). Clang rejects the `(void)x;` notation for a used variable in a naked asm function, so do this only conditionally. Introduces use of `__builtin_unreachable()` with gcc. This saves 1 byte by causing gcc not to emit an `ud2` opcode at the end. However, the unreachable sanitizer (enabled by default(!) on Ubuntu 24.04 with gcc version 13.3.0) corrupts the ebx register, so it must be disabled. Clang does not accept `__builtin_unreachable` or `return 0;` here, UNREACHABLE must expand to nothing. Closes: #17415 Signed-off-by: Jeff Epler <jepler@unpythonic.net>
This commit is contained in:
committed by
Damien George
parent
d6a1d37156
commit
a254bbca79
+24
-14
@@ -40,23 +40,35 @@ __attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr);
|
||||
#endif
|
||||
|
||||
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 8
|
||||
// Since gcc 8.0 the naked attribute is supported
|
||||
#define USE_NAKED (1)
|
||||
#define UNDO_PRELUDE (0)
|
||||
// Since gcc 8.0 the naked and no-sanitize attributes are supported
|
||||
#define NLR_PUSH_ATTRIBUTE __attribute__((naked, no_sanitize("unreachable")))
|
||||
#define UNDO_PRELUDE (0)
|
||||
#define ARG_USED(x) (void)x;
|
||||
#define NLR_UNREACHABLE __builtin_unreachable();
|
||||
#elif defined(__ZEPHYR__) || defined(__ANDROID__)
|
||||
// Zephyr and Android use a different calling convention by default
|
||||
#define USE_NAKED (0)
|
||||
#define UNDO_PRELUDE (0)
|
||||
#define NLR_PUSH_ATTRIBUTE /* NOTHING */
|
||||
#define UNDO_PRELUDE (0)
|
||||
#define ARG_USED(x) (void)x;
|
||||
#define NLR_UNREACHABLE return 0;
|
||||
#elif defined(__clang__)
|
||||
// clang on Ubuntu 24.04 enables -fsanitize=unreachable by default, but this
|
||||
// destroys the content of the ebx register.
|
||||
#define NLR_PUSH_ATTRIBUTE __attribute__((naked, no_sanitize("unreachable")))
|
||||
#define UNDO_PRELUDE (0)
|
||||
#define ARG_USED(x) /* NOTHING */
|
||||
#define NLR_UNREACHABLE /* NOTHING */
|
||||
#else
|
||||
#define USE_NAKED (0)
|
||||
#define UNDO_PRELUDE (1)
|
||||
// gcc before 8 unavoidably emits a 'push %ebp' prologue instruction
|
||||
#define NLR_PUSH_ATTRIBUTE /* NOTHING */
|
||||
#define UNDO_PRELUDE (1)
|
||||
#define ARG_USED(x) (void)x;
|
||||
#define NLR_UNREACHABLE return 0;
|
||||
#endif
|
||||
|
||||
#if USE_NAKED
|
||||
__attribute__((naked))
|
||||
#endif
|
||||
NLR_PUSH_ATTRIBUTE
|
||||
unsigned int nlr_push(nlr_buf_t *nlr) {
|
||||
(void)nlr;
|
||||
ARG_USED(nlr)
|
||||
|
||||
__asm volatile (
|
||||
#if UNDO_PRELUDE
|
||||
@@ -73,9 +85,7 @@ unsigned int nlr_push(nlr_buf_t *nlr) {
|
||||
"jmp nlr_push_tail \n" // do the rest in C
|
||||
);
|
||||
|
||||
#if !USE_NAKED
|
||||
return 0; // needed to silence compiler warning
|
||||
#endif
|
||||
NLR_UNREACHABLE
|
||||
}
|
||||
|
||||
MP_NORETURN void nlr_jump(void *val) {
|
||||
|
||||
Reference in New Issue
Block a user