diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2022-03-01 02:04:35 +0100 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2022-06-27 21:13:31 +0200 |
commit | 4c0c507b1fabbdab557d66eb9d90a2d3c8009880 (patch) | |
tree | 0dd48bda43648b60748235504afbd2c6fa771e16 | |
parent | beb5f78ada79ac90f31f2c4923302c74d9ab38bf (diff) |
Filter: Clean up function call instruction
Pass instructions of function call arguments as vararg arguments to
FI_CALL instruction constructor and move necessary magic from parser
code to interpreter / instruction code.
-rw-r--r-- | filter/config.Y | 23 | ||||
-rw-r--r-- | filter/f-inst.c | 24 |
2 files changed, 26 insertions, 21 deletions
diff --git a/filter/config.Y b/filter/config.Y index 8916ea97..0ab32a57 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -700,27 +700,22 @@ var_list: /* EMPTY */ { $$ = NULL; } | var_list ',' term { $$ = $3; $$->next = $1; } function_call: - CF_SYM_KNOWN '(' var_list ')' { + CF_SYM_KNOWN '(' var_list ')' + { if ($1->class != SYM_FUNCTION) cf_error("You can't call something which is not a function. Really."); - struct f_inst *fc = f_new_inst(FI_CALL, $1); - uint args = 0; + /* Revert the var_list */ + struct f_inst *args = NULL; while ($3) { - args++; - struct f_inst *tmp = $3->next; - $3->next = fc; + struct f_inst *tmp = $3; + $3 = $3->next; - fc = $3; - $3 = tmp; + tmp->next = args; + args = tmp; } - if (args != $1->function->args) - cf_error("Function call '%s' got %u arguments, need %u arguments.", - $1->name, args, $1->function->args); - - $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID }); - $$->next = fc; + $$ = f_new_inst(FI_CALL, args, $1); } ; diff --git a/filter/f-inst.c b/filter/f-inst.c index 901d2939..0d935859 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -1079,8 +1079,22 @@ INST(FI_CALL, 0, 1) { NEVER_CONSTANT; + VARARG; SYMBOL; + FID_NEW_BODY() + ASSERT(sym->class == SYM_FUNCTION); + + if (whati->varcount != sym->function->args) + cf_error("Function '%s' expects %u arguments, got %u arguments", + sym->name, sym->function->args, whati->varcount); + + /* Add implicit void slot for the return value */ + struct f_inst *tmp = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID }); + tmp->next = whati->fvar; + whati->fvar = tmp; + what->size += tmp->size; + FID_SAME_BODY() if (!(f1->sym->flags & SYM_FLAG_SAME)) return 0; @@ -1092,15 +1106,11 @@ /* Push the body on stack */ LINEX(sym->function); + curline.vbase = curline.ventry; curline.emask |= FE_RETURN; - /* Before this instruction was called, there was the T_VOID - * automatic return value pushed on value stack and also - * sym->function->args function arguments. Setting the - * vbase to point to first argument. */ - ASSERT(curline.ventry >= sym->function->args); - curline.ventry -= sym->function->args; - curline.vbase = curline.ventry; + /* Arguments on stack */ + fstk->vcnt += sym->function->args; /* Storage for local variables */ memset(&(fstk->vstk[fstk->vcnt]), 0, sizeof(struct f_val) * sym->function->vars); |