diff options
author | Andy Wingo <wingo@pobox.com> | 2013-11-01 19:28:36 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2013-11-01 19:28:36 +0100 |
commit | 03f16599e37d91fdc7564e4baed9a489b2901dec (patch) | |
tree | 000d3527061dbfb37f40cd1a92467bb06a913491 /libguile/vm.c | |
parent | 14b9aa95e61e2d593bd96ab0a7675ed72d55503c (diff) | |
download | guile-03f16599e37d91fdc7564e4baed9a489b2901dec.tar.gz |
Fix call/cc with the RTL VM
* libguile/vm.c (vm_return_to_continuation): The RTL VM saves the
registers for the caller of call/cc, but the caller will expect values
in the normal MV return location: above the frame. Make it so, number
four!
Diffstat (limited to 'libguile/vm.c')
-rw-r--r-- | libguile/vm.c | 38 |
1 files changed, 19 insertions, 19 deletions
diff --git a/libguile/vm.c b/libguile/vm.c index c9ce3a31a..bf1a269af 100644 --- a/libguile/vm.c +++ b/libguile/vm.c @@ -150,7 +150,7 @@ vm_return_to_continuation (SCM vm, SCM cont, size_t n, SCM *argv) scm_misc_error (NULL, "Too few values returned to continuation", SCM_EOL); - if (vp->stack_size < cp->stack_size + n + 1) + if (vp->stack_size < cp->stack_size + n + 4) scm_misc_error ("vm-engine", "not enough space to reinstate continuation", scm_list_2 (vm, cont)); @@ -167,24 +167,24 @@ vm_return_to_continuation (SCM vm, SCM cont, size_t n, SCM *argv) vp->fp = cp->fp; memcpy (vp->stack_base, cp->stack_base, cp->stack_size * sizeof (SCM)); - if (n == 1 || !cp->mvra) - { - vp->ip = cp->ra; - vp->sp++; - *vp->sp = argv_copy[0]; - } - else - { - size_t i; - for (i = 0; i < n; i++) - { - vp->sp++; - *vp->sp = argv_copy[i]; - } - vp->sp++; - *vp->sp = scm_from_size_t (n); - vp->ip = cp->mvra; - } + { + size_t i; + + /* Push on an empty frame, as the continuation expects. */ + for (i = 0; i < 4; i++) + { + vp->sp++; + *vp->sp = SCM_BOOL_F; + } + + /* Push the return values. */ + for (i = 0; i < n; i++) + { + vp->sp++; + *vp->sp = argv_copy[i]; + } + vp->ip = cp->mvra; + } } SCM |