diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index d9765caae..5063e22c1 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -1943,8 +1943,28 @@ GC_INNER void GC_push_all_register_sections( /* Important internal collector routines. */ +/* Return the current stack pointer, approximately. */ GC_INNER ptr_t GC_approx_sp(void); +/* Same as GC_approx_sp() but a macro. sp_ptr should be a pointer */ +/* to a local variable of volatile ptr_t type. */ +#if (defined(E2K) && defined(__clang__) \ + || (defined(S390) && __clang_major__ < 8)) \ + && !defined(CPPCHECK) +/* Workaround some bugs in clang: */ +/* "undefined reference to llvm.frameaddress" error (clang-9/e2k); */ +/* a crash in SystemZTargetLowering of libLLVM-3.8 (s390). */ +# define APPROX_SP(sp_ptr) (void)(*(sp_ptr) = (ptr_t)(sp_ptr)) +#elif defined(CPPCHECK) \ + || (__GNUC__ >= 4 /* GC_GNUC_PREREQ(4, 0) */ \ + && !defined(STACK_NOT_SCANNED)) +/* TODO: Use GC_GNUC_PREREQ after fixing a bug in cppcheck. */ +# define APPROX_SP(sp_ptr) \ + (void)(*(sp_ptr) = (ptr_t)__builtin_frame_address(0)) +#else +# define APPROX_SP(sp_ptr) (void)(*(sp_ptr) = (ptr_t)(sp_ptr)) +#endif + GC_INNER GC_bool GC_should_collect(void); /* Get the next block whose address is at least h. Returned block is */ diff --git a/mark_rts.c b/mark_rts.c index 0456b2968..d08b34569 100644 --- a/mark_rts.c +++ b/mark_rts.c @@ -543,21 +543,7 @@ GC_approx_sp(void) /* This also forces stack to grow if necessary. Otherwise the */ /* later accesses might cause the kernel to think we are doing */ /* something wrong. */ -#if ((defined(E2K) && defined(__clang__)) \ - || (defined(S390) && (__clang_major__ < 8))) \ - && !defined(CPPCHECK) - /* Workaround some bugs in clang: */ - /* "undefined reference to llvm.frameaddress" error (clang-9/e2k); */ - /* a crash in SystemZTargetLowering of libLLVM-3.8 (S390). */ - sp = (ptr_t)(&sp); -#elif defined(CPPCHECK) \ - || (__GNUC__ >= 4 /* GC_GNUC_PREREQ(4, 0) */ \ - && !defined(STACK_NOT_SCANNED)) - /* TODO: Use GC_GNUC_PREREQ after fixing a bug in cppcheck. */ - sp = (ptr_t)__builtin_frame_address(0); -#else - sp = (ptr_t)(&sp); -#endif + APPROX_SP(&sp); return (/* no volatile */ ptr_t)sp; } diff --git a/tools/setjmp_t.c b/tools/setjmp_t.c index 73548feec..6f228d9a1 100644 --- a/tools/setjmp_t.c +++ b/tools/setjmp_t.c @@ -68,13 +68,10 @@ GC_ATTR_NOINLINE static word nested_sp(void) { -#if defined(CPPCHECK) || GC_GNUC_PREREQ(4, 0) - return ADDR(__builtin_frame_address(0)); -#else - volatile word sp; - sp = ADDR(&sp); - return sp; -#endif + volatile ptr_t sp; + + APPROX_SP(&sp); + return ADDR(sp); } /* To prevent nested_sp inlining. */ @@ -91,7 +88,7 @@ const char *a_str = "a"; int main(void) { - volatile word sp; + volatile ptr_t sp; unsigned ps = GETPAGESIZE(); #ifndef WASI JMP_BUF b; @@ -104,20 +101,21 @@ main(void) static volatile int y = 0; #endif - sp = ADDR(&sp); + APPROX_SP(&sp); printf("This appears to be a %s running %s\n", MACH_TYPE, OS_TYPE); #if defined(CPPCHECK) (void)nested_sp(); /* to workaround a bug in cppcheck */ #endif - if (nested_sp_fn() < sp) { + if (nested_sp_fn() < ADDR(sp)) { printf("Stack appears to grow down, which is the default.\n"); printf("A good guess for STACKBOTTOM on this machine is 0x%lx.\n", - ((unsigned long)sp + ps) & ~(unsigned long)(ps - 1)); + ((unsigned long)ADDR(sp) + ps) & ~(unsigned long)(ps - 1)); } else { printf("Stack appears to grow up.\n"); printf("Define STACK_GROWS_UP in gc_priv.h\n"); + /* Note: sp is rounded down. */ printf("A good guess for STACKBOTTOM on this machine is 0x%lx.\n", - (unsigned long)sp & ~(unsigned long)(ps - 1)); /* round down */ + (unsigned long)ADDR(sp) & ~(unsigned long)(ps - 1)); } printf("Note that this may vary between machines of ostensibly\n"); printf("the same architecture (e.g. Sun 3/50s and 3/80s).\n");