]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: Implement constant promotion for multiple dispatch methods
authorOndrej Zajicek <santiago@crfreenet.org>
Tue, 25 Jul 2023 15:43:52 +0000 (17:43 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Tue, 12 Sep 2023 14:33:59 +0000 (16:33 +0200)
filter/decl.m4
filter/f-inst.h
filter/f-util.c

index 217488eca3b2d1b2ddc97aabada3ec6c5170b13d..57bf94546bd6ebf32d69538c2061197db8ecc45b 100644 (file)
@@ -379,7 +379,8 @@ m4_undivert(102)m4_dnl
 [[m4_dnl                                The one case in The Big Switch inside interpreter
   case INST_NAME():
   #define whati (&(what->i_]]INST_NAME()[[))
-  m4_ifelse(m4_eval(INST_INVAL() > 0), 1, [[if (fstk->vcnt < INST_INVAL()) runtime("Stack underflow"); fstk->vcnt -= INST_INVAL(); ]])
+  m4_ifelse(m4_eval(INST_INVAL() > 0), 1, [[if (fstk->vcnt < INST_INVAL()) runtime("Stack underflow");
+  fstk->vcnt -= INST_INVAL();]])
   m4_undivert(108)m4_dnl
   #undef whati
   break;
@@ -572,8 +573,8 @@ fi_constant(struct f_inst *what, struct f_val val)
   return what;
 }
 
-static int
-f_const_promotion(struct f_inst *arg, enum f_type want)
+int
+f_const_promotion_(struct f_inst *arg, enum f_type want, int update)
 {
   if (arg->fi_code != FI_CONSTANT)
     return 0;
@@ -581,15 +582,17 @@ f_const_promotion(struct f_inst *arg, enum f_type want)
   struct f_val *c = &arg->i_FI_CONSTANT.val;
 
   if ((c->type == T_IP) && ipa_is_ip4(c->val.ip) && (want == T_QUAD)) {
-    *c = (struct f_val) {
-      .type = T_QUAD,
-      .val.i = ipa_to_u32(c->val.ip),
-    };
+    if (update)
+      *c = (struct f_val) {
+        .type = T_QUAD,
+        .val.i = ipa_to_u32(c->val.ip),
+      };
     return 1;
   }
 
   else if ((c->type == T_SET) && (!c->val.t) && (want == T_PREFIX_SET)) {
-    *c = f_const_empty_prefix_set;
+    if (update)
+      *c = f_const_empty_prefix_set;
     return 1;
   }
 
index f5dfcd2021c983dded74c48d60e4a747ea1f2fa9..e8147e2683634a0697318d0a73d5198bd4b9f7eb 100644 (file)
@@ -36,6 +36,16 @@ const char *f_instruction_name_(enum f_instruction_code fi);
 static inline const char *f_instruction_name(enum f_instruction_code fi)
 { return f_instruction_name_(fi) + 3; }
 
+
+int f_const_promotion_(struct f_inst *arg, enum f_type want, int update);
+
+static inline int f_const_promotion(struct f_inst *arg, enum f_type want)
+{ return f_const_promotion_(arg, want, 1); }
+
+static inline int f_try_const_promotion(struct f_inst *arg, enum f_type want)
+{ return f_const_promotion_(arg, want, 0); }
+
+
 struct f_arg {
   struct symbol *arg;
   struct f_arg *next;
index e980cef5667688e8d5ad1b5f34c8001be539e535..768ee83b4fda271bacaefa67d99fe5cce4db89b2 100644 (file)
@@ -48,7 +48,8 @@ f_match_signature(const struct f_method *dsc, struct f_inst *args)
   int i, arg_num = (int) dsc->arg_num;
 
   for (i = 1; args && (i < arg_num); args = args->next, i++)
-    if (dsc->args_type[i] && (args->type != dsc->args_type[i]))
+    if (dsc->args_type[i] && (args->type != dsc->args_type[i]) &&
+       !f_try_const_promotion(args, dsc->args_type[i]))
       return 0;
 
   return !args && !(i < arg_num);
@@ -61,7 +62,8 @@ f_match_signature_err(const struct f_method *dsc, struct f_inst *args, int *pos,
   int i, arg_num = (int) dsc->arg_num;
 
   for (i = 1; args && (i < arg_num); args = args->next, i++)
-    if (dsc->args_type[i] && (args->type != dsc->args_type[i]))
+    if (dsc->args_type[i] && (args->type != dsc->args_type[i]) &&
+       !f_try_const_promotion(args, dsc->args_type[i]))
       break;
 
   *pos = i;