summaryrefslogtreecommitdiffstats
path: root/vm.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-03-19 21:49:44 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-03-19 21:49:44 -0700
commitefe9d7029d8187bfaff8332ad4452e9bd64f654e (patch)
tree0feb9c2efd499edb3faf9ea7b8105412b1d36b17 /vm.c
parent2cd47459acca8c1e26760264b82586b8645f4e2d (diff)
downloadtxr-efe9d7029d8187bfaff8332ad4452e9bd64f654e.tar.gz
txr-efe9d7029d8187bfaff8332ad4452e9bd64f654e.tar.bz2
txr-efe9d7029d8187bfaff8332ad4452e9bd64f654e.zip
vm: variadic arg closures bug 2/3.
* vm.c (vm_execute_closure): Remove bogus nargs local variable, and replace its uses by fixparam which is the correct one to use for getting the list of trailing arguments using args_get_rest and for the loop which extracts the fixed arguments. The "if (variadic)" statement near the end specifically depends on the variadic destination register not having been extracted yet from the instruction space, so the argument count used in the previousl loop cannot include that register. This bug was causing that statement to extract a zero, thus register t0, which then blew up in the vm execution as an attempt to modify t0.
Diffstat (limited to 'vm.c')
-rw-r--r--vm.c11
1 files changed, 5 insertions, 6 deletions
diff --git a/vm.c b/vm.c
index cb0731de..a837a268 100644
--- a/vm.c
+++ b/vm.c
@@ -892,13 +892,12 @@ val vm_execute_closure(val fun, struct args *args)
val desc = fun->f.f.vm_desc;
int fixparam = fun->f.fixparam;
int variadic = fun->f.variadic;
- int nargs = fixparam + variadic;
struct vm_desc *vd = vm_desc_struct(desc);
struct vm_closure *vc = coerce(struct vm_closure *, closure->co.handle);
struct vm vm;
val *frame = coerce(val *, alloca(sizeof *frame * vd->frsz));
struct vm_env *dspl = coerce(struct vm_env *, frame + vd->nreg);
- val vargs = if3(variadic, args_get_rest(args, nargs), nil);
+ val vargs = if3(variadic, args_get_rest(args, fixparam), nil);
cnum ix = 0;
vm_word_t argw = 0;
@@ -922,8 +921,8 @@ val vm_execute_closure(val fun, struct args *args)
vm.dspl[vm.lev].vec = num_fast(vc->frsz);
}
- while (nargs >= 2) {
- nargs -= 2;
+ while (fixparam >= 2) {
+ fixparam -= 2;
argw = vm.code[vm.ip++];
unsigned xreg = vm_arg_operand_lo(argw);
unsigned yreg = vm_arg_operand_hi(argw);
@@ -931,7 +930,7 @@ val vm_execute_closure(val fun, struct args *args)
vm_set(dspl, yreg, args_get(args, &ix));
}
- if (nargs) {
+ if (fixparam) {
argw = vm.code[vm.ip++];
unsigned xreg = vm_arg_operand_lo(argw);
vm_set(dspl, xreg, args_get(args, &ix));
@@ -939,7 +938,7 @@ val vm_execute_closure(val fun, struct args *args)
if (variadic) {
unsigned vreg;
- if (!nargs) {
+ if (!fixparam) {
argw = vm.code[vm.ip++];
vreg = vm_arg_operand_lo(argw);
} else {