]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: Clean up function call instruction
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 1 Mar 2022 01:04:35 +0000 (02:04 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Mon, 27 Jun 2022 19:13:31 +0000 (21:13 +0200)
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.

filter/config.Y
filter/f-inst.c

index 8916ea9770964183724af1843b89f4adec228679..0ab32a579fffcb1c668317bc88e0cd3a70a684f9 100644 (file)
@@ -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);
    }
  ;
 
index 901d29391377f7bfe1fc1f83192ac93fe8173653..0d935859c429a358b05467a8f8383649025be89c 100644 (file)
 
   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;
 
     /* 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);