diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2018-03-19 21:49:44 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2018-03-19 21:49:44 -0700 |
commit | efe9d7029d8187bfaff8332ad4452e9bd64f654e (patch) | |
tree | 0feb9c2efd499edb3faf9ea7b8105412b1d36b17 /vm.c | |
parent | 2cd47459acca8c1e26760264b82586b8645f4e2d (diff) | |
download | txr-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.c | 11 |
1 files changed, 5 insertions, 6 deletions
@@ -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 { |