summaryrefslogtreecommitdiff
path: root/libguile/vm.c
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2013-11-01 19:28:36 +0100
committerAndy Wingo <wingo@pobox.com>2013-11-01 19:28:36 +0100
commit03f16599e37d91fdc7564e4baed9a489b2901dec (patch)
tree000d3527061dbfb37f40cd1a92467bb06a913491 /libguile/vm.c
parent14b9aa95e61e2d593bd96ab0a7675ed72d55503c (diff)
downloadguile-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.c38
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