diff --git a/lib/bcheck.c b/lib/bcheck.c
index e05209c6..1e374f16 100644
--- a/lib/bcheck.c
+++ b/lib/bcheck.c
@@ -41,7 +41,7 @@
 #define BOUND_STATISTIC         (1)
 
 #if BOUND_DEBUG
- #define dprintf(a...)         if (print_calls) { bounds_loc; fprintf(a); }
+ #define dprintf(a...)         if (print_calls) { bounds_loc(a); }
 #else
  #define dprintf(a...)
 #endif
@@ -446,7 +446,6 @@ static unsigned long long bound_splay_delete;
 #endif
 
 int tcc_backtrace(const char *fmt, ...);
-void tcc_location(const char *fmt);
 
 /* print a bound error message */
 #define bound_warning(...) \
@@ -463,10 +462,10 @@ void tcc_location(const char *fmt);
             exit(255);              \
     } while (0)
 
-#define bounds_loc \
+#define bounds_loc(fp, ...) \
     do {                            \
         WAIT_SEM (); \
-        tcc_location("^bcheck.c^"); \
+        tcc_backtrace("^bcheck.c^\001" __VA_ARGS__); \
         POST_SEM (); \
     } while (0)
 
diff --git a/lib/bt-dll.c b/lib/bt-dll.c
index 00c67da7..7c62cefa 100644
--- a/lib/bt-dll.c
+++ b/lib/bt-dll.c
@@ -8,7 +8,6 @@
   REDIR(__bt_init) \
   REDIR(__bt_exit) \
   REDIR(tcc_backtrace) \
-  REDIR(tcc_location) \
   \
   REDIR(__bound_ptr_add) \
   REDIR(__bound_ptr_indir1) \
diff --git a/lib/bt-exe.c b/lib/bt-exe.c
index 7cd56e70..3a2d02e4 100644
--- a/lib/bt-exe.c
+++ b/lib/bt-exe.c
@@ -8,7 +8,6 @@
 #include "../tccrun.c"
 
 int (*__rt_error)(void*, void*, const char *, va_list);
-void (*__rt_location)(void*, void*, const char *);
 __attribute__((weak)) void __bound_checking_lock(void);
 __attribute__((weak)) void __bound_checking_unlock(void);
 
@@ -34,7 +33,6 @@ void __bt_init(rt_context *p, int num_callers)
         rc->num_callers = num_callers - 1;
         rc->top_func = main;
         __rt_error = _rt_error;
-        __rt_location = _rt_location;
         set_exception_handler();
     } else {
         p->next = rc->next, rc->next = p;
diff --git a/lib/bt-log.c b/lib/bt-log.c
index c6a11146..bff9a794 100644
--- a/lib/bt-log.c
+++ b/lib/bt-log.c
@@ -6,7 +6,6 @@
 #include <string.h>
 
 int (*__rt_error)(void*, void*, const char *, va_list);
-void (*__rt_location)(void*, void*, const char *);
 
 #ifdef _WIN32
 # define DLL_EXPORT __declspec(dllexport)
@@ -32,26 +31,19 @@ DLL_EXPORT int tcc_backtrace(const char *fmt, ...)
         ret = __rt_error(fp, ip, fmt, ap);
         va_end(ap);
     } else {
-        const char *p;
+        const char *p, *nl = "\n";
         if (fmt[0] == '^' && (p = strchr(fmt + 1, fmt[0])))
             fmt = p + 1;
+        if (fmt[0] == '\001')
+            ++fmt, nl = "";
         va_start(ap, fmt);
         ret = vfprintf(stderr, fmt, ap);
         va_end(ap);
-        fprintf(stderr, "\n"), fflush(stderr);
+        fprintf(stderr, nl), fflush(stderr);
     }
     return ret;
 }
 
-DLL_EXPORT void tcc_location(const char *fmt)
-{
-    if (__rt_location) {
-        void *fp = __builtin_frame_address(1);
-        void *ip = __builtin_return_address(0);
-        __rt_location(fp, ip, fmt);
-    }
-}
-
 #if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
 #pragma GCC diagnostic pop
 #endif
diff --git a/tccgen.c b/tccgen.c
index 88436a83..529abe9c 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -6010,7 +6010,6 @@ special_math_val:
                 indir();
             qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE);
             test_lvalue();
-            gaddrof();
             /* expect pointer on structure */
             if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
                 expect("struct or union");
@@ -6021,6 +6020,7 @@ special_math_val:
                 expect("field name");
 	    s = find_field(&vtop->type, tok, &cumofs);
             /* add field offset to pointer */
+            gaddrof();
             vtop->type = char_pointer_type; /* change type to 'char *' */
             vpushi(cumofs);
             gen_op('+');
diff --git a/tccrun.c b/tccrun.c
index 40545ad0..b102d829 100644
--- a/tccrun.c
+++ b/tccrun.c
@@ -23,9 +23,9 @@
 /* only native compiler supports -run */
 #ifdef TCC_IS_NATIVE
 
-#ifdef CONFIG_TCC_BACKTRACE
 typedef struct rt_context
 {
+#ifdef CONFIG_TCC_BACKTRACE
     /* --> tccelf.c:tcc_add_btstub wants those below in that order: */
     union {
 	struct {
@@ -46,15 +46,27 @@ typedef struct rt_context
     int num_callers;
     addr_t ip, fp, sp;
     void *top_func;
-    jmp_buf jmp_buf;
-    char do_jmp;
+#endif
+    jmp_buf jb;
+    int do_jmp;
+# define NR_AT_EXIT 32
+    int nr_exit;
+    void *exitfunc[NR_AT_EXIT];
+    void *exitarg[NR_AT_EXIT];
 } rt_context;
 
 static rt_context g_rtctxt;
+static void rt_exit(int code)
+{
+    rt_context *rc = &g_rtctxt;
+    if (rc->do_jmp)
+        longjmp(rc->jb, code ? code : 256);
+    exit(code);
+}
+
+#ifdef CONFIG_TCC_BACKTRACE
 static void set_exception_handler(void);
 static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap);
-static void _rt_location(void *fp, void *ip, const char *fmt);
-static void rt_exit(int code);
 #endif /* CONFIG_TCC_BACKTRACE */
 
 /* defined when included from lib/bt-exe.c */
@@ -147,79 +159,35 @@ static void run_cdtors(TCCState *s1, const char *start, const char *end,
         ((void(*)(int, char **, char **))*a++)(argc, argv, envp);
 }
 
-#define	NR_AT_EXIT	32
-
-static struct exit_context {
-    int exit_called;
-    int nr_exit;
-    void (*exitfunc[NR_AT_EXIT])(int, void *);
-    void *exitarg[NR_AT_EXIT];
-#ifndef CONFIG_TCC_BACKTRACE
-    jmp_buf run_jmp_buf;
-#endif
-} g_exit_context;
-
-static void init_exit(void)
+static void run_on_exit(int ret)
 {
-    struct exit_context *e = &g_exit_context;
-
-    e->exit_called = 0;
-    e->nr_exit = 0;
+    rt_context *rc = &g_rtctxt;
+    int n = rc->nr_exit;
+    while (n)
+	--n, ((void(*)(int,void*))rc->exitfunc[n])(ret, rc->exitarg[n]);
 }
 
-static void call_exit(int ret)
+static int rt_on_exit(void *function, void *arg)
 {
-    struct exit_context *e = &g_exit_context;
-
-    while (e->nr_exit) {
-	e->nr_exit--;
-	e->exitfunc[e->nr_exit](ret, e->exitarg[e->nr_exit]);
-    }
-}
-
-static int rt_atexit(void (*function)(void))
-{
-    struct exit_context *e = &g_exit_context;
-
-    if (e->nr_exit < NR_AT_EXIT) {
-	e->exitfunc[e->nr_exit] = (void (*)(int, void *))function;
-	e->exitarg[e->nr_exit++] = NULL;
+    rt_context *rc = &g_rtctxt;
+    if (rc->nr_exit < NR_AT_EXIT) {
+	rc->exitfunc[rc->nr_exit] = function;
+	rc->exitarg[rc->nr_exit++] = arg;
         return 0;
     }
     return 1;
 }
 
-static int rt_on_exit(void (*function)(int, void *), void *arg)
+static int rt_atexit(void *function)
 {
-    struct exit_context *e = &g_exit_context;
-
-    if (e->nr_exit < NR_AT_EXIT) {
-	e->exitfunc[e->nr_exit] = function;
-	e->exitarg[e->nr_exit++] = arg;
-        return 0;
-    }
-    return 1;
-}
-
-static void run_exit(int code)
-{
-    struct exit_context *e = &g_exit_context;
-
-    e->exit_called = 1;
-#ifdef CONFIG_TCC_BACKTRACE
-    longjmp((&g_rtctxt)->jmp_buf, code ? code : 256);
-#else
-    longjmp(e->run_jmp_buf, code ? code : 256);
-#endif
+    return rt_on_exit(function, NULL);
 }
 
 /* launch the compiled program with the given arguments */
 LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
 {
     int (*prog_main)(int, char **, char **), ret;
-#ifdef CONFIG_TCC_BACKTRACE
     rt_context *rc = &g_rtctxt;
-#endif
 
 #if defined(__APPLE__) || defined(__FreeBSD__)
     char **envp = NULL;
@@ -233,17 +201,21 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
     s1->runtime_main = s1->nostdlib ? "_start" : "main";
     if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, s1->runtime_main, 0, 1))
         return 0;
-    tcc_add_symbol(s1, "exit", run_exit);
+
+    tcc_add_symbol(s1, "exit", rt_exit);
     tcc_add_symbol(s1, "atexit", rt_atexit);
     tcc_add_symbol(s1, "on_exit", rt_on_exit);
     if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
         return -1;
+
     prog_main = (void*)get_sym_addr(s1, s1->runtime_main, 1, 1);
     if ((addr_t)-1 == (addr_t)prog_main)
         return -1;
 
-#ifdef CONFIG_TCC_BACKTRACE
     memset(rc, 0, sizeof *rc);
+    rc->do_jmp = 1;
+
+#ifdef CONFIG_TCC_BACKTRACE
     if (s1->do_debug) {
         void *p;
 	if (s1->dwarf) {
@@ -272,11 +244,8 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
 #endif
         rc->top_func = tcc_get_symbol(s1, "main");
         rc->num_callers = s1->rt_num_callers;
-        rc->do_jmp = 1;
         if ((p = tcc_get_symbol(s1, "__rt_error")))
             *(void**)p = _rt_error;
-        if ((p = tcc_get_symbol(s1, "__rt_location")))
-            *(void**)p = _rt_location;
 #ifdef CONFIG_TCC_BCHECK
         if (s1->do_bounds_check) {
             rc->bounds_start = (void*)bounds_section->sh_addr;
@@ -291,23 +260,15 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
     errno = 0; /* clean errno value */
     fflush(stdout);
     fflush(stderr);
-    init_exit();
+
     /* These aren't C symbols, so don't need leading underscore handling.  */
     run_cdtors(s1, "__init_array_start", "__init_array_end", argc, argv, envp);
-#ifdef CONFIG_TCC_BACKTRACE
-    if (!(ret = setjmp(rc->jmp_buf)))
-#else
-    if (!(ret = setjmp((&g_exit_context)->run_jmp_buf)))
-#endif
-    {
+    if (!(ret = setjmp(rc->jb)))
         ret = prog_main(argc, argv, envp);
-    }
     run_cdtors(s1, "__fini_array_start", "__fini_array_end", 0, NULL, NULL);
-    call_exit(ret);
-    if ((s1->dflag & 16) && ret)
+    run_on_exit(ret);
+    if (s1->dflag & 16 && ret) /* tcc -dt -run ... */
         fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp);
-    if ((s1->dflag & 16) == 0 && (&g_exit_context)->exit_called)
-	exit(ret);
     return ret;
 }
 
@@ -1044,7 +1005,7 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
     rt_context *rc = &g_rtctxt;
     addr_t pc = 0;
     char skip[100];
-    int i, level, ret, n;
+    int i, level, ret, n, one;
     const char *a, *b, *msg;
 
     if (fp) {
@@ -1063,6 +1024,10 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
         memcpy(skip, a, b - a), skip[b - a] = 0;
         fmt = b + 1;
     }
+    one = 0;
+    /* hack for bcheck.c:dprintf(): one level, no newline */
+    if (fmt[0] == '\001')
+        ++fmt, one = 1;
 
     n = rc->num_callers ? rc->num_callers : 6;
     for (i = level = 0; level < n; i++) {
@@ -1082,6 +1047,8 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
             rt_vprintf(fmt, ap);
         } else if (ret == -1)
             break;
+        if (one)
+            break;
         rt_printf("\n");
         if (ret == -1 || (pc == (addr_t)rc->top_func && pc))
             break;
@@ -1092,41 +1059,6 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
     return 0;
 }
 
-static void _rt_location(void *fp, void *ip, const char *fmt)
-{
-    rt_context *rc = &g_rtctxt;
-    addr_t pc = 0;
-    char skip[100];
-    int i, ret;
-    const char *a, *b;
-
-    rc->fp = (addr_t)fp;
-    rc->ip = (addr_t)ip;
-
-    skip[0] = 0;
-    /* If fmt is like "^file.c^..." then skip calls from 'file.c' */
-    if (fmt[0] == '^' && (b = strchr(a = fmt + 1, fmt[0])))
-        memcpy(skip, a, b - a), skip[b - a] = 0;
-
-    for (i = 0; ; i++) {
-        ret = rt_get_caller_pc(&pc, rc, i);
-        a = "";
-        if (ret != -1) {
-            if (rc->dwarf)
-                pc = rt_printline_dwarf(rc, pc, "at", skip);
-            else
-                pc = rt_printline(rc, pc, "at", skip);
-            if (pc == (addr_t)-1)
-                continue;
-            a = ": ";
-        }
-        rt_printf(a);
-        break;
-    }
-
-    rc->ip = rc->fp = 0;
-}
-
 /* emit a run time error at position 'pc' */
 static int rt_error(const char *fmt, ...)
 {
@@ -1138,14 +1070,6 @@ static int rt_error(const char *fmt, ...)
     return ret;
 }
 
-static void rt_exit(int code)
-{
-    rt_context *rc = &g_rtctxt;
-    if (rc->do_jmp)
-        longjmp(rc->jmp_buf, code ? code : 256);
-    exit(code);
-}
-
 /* ------------------------------------------------------------- */
 
 #ifndef _WIN32
diff --git a/x86_64-gen.c b/x86_64-gen.c
index a41cbc10..e04df10a 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
@@ -2047,6 +2047,7 @@ void gen_opf(int op)
                 assert(vtop->r & VT_LVAL);
                 gv(RC_FLOAT);
                 vswap();
+                fc = vtop->c.i; /* bcheck may have saved previous vtop[-1] */
             }
             
             if ((ft & VT_BTYPE) == VT_DOUBLE) {