summaryrefslogtreecommitdiffstats
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
commit851a46fd4b6ed9b65bfd33eef9f2fd759ac25c82 (patch)
tree0feb9c2efd499edb3faf9ea7b8105412b1d36b17
parent9fb3148a6e23c15eea8e979229ff53081df7ef76 (diff)
downloadtxr-851a46fd4b6ed9b65bfd33eef9f2fd759ac25c82.tar.gz
txr-851a46fd4b6ed9b65bfd33eef9f2fd759ac25c82.tar.bz2
txr-851a46fd4b6ed9b65bfd33eef9f2fd759ac25c82.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.
-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 {