aboutsummaryrefslogtreecommitdiffstats
path: root/filter
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2023-07-25 17:43:52 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2023-09-12 16:33:59 +0200
commitf0d1396073dc7c3a6ab5f88baa07f2494cbd5328 (patch)
tree6cb43268324d06a8c7ef1c0ae351171d2cada331 /filter
parente88695913148ae63e1f8c8ac64f7b039dd3fc286 (diff)
downloadbird-f0d1396073dc7c3a6ab5f88baa07f2494cbd5328.tar.gz
Filter: Implement constant promotion for multiple dispatch methods
Diffstat (limited to 'filter')
-rw-r--r--filter/decl.m419
-rw-r--r--filter/f-inst.h10
-rw-r--r--filter/f-util.c6
3 files changed, 25 insertions, 10 deletions
diff --git a/filter/decl.m4 b/filter/decl.m4
index 217488ec..57bf9454 100644
--- a/filter/decl.m4
+++ b/filter/decl.m4
@@ -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;
}
diff --git a/filter/f-inst.h b/filter/f-inst.h
index f5dfcd20..e8147e26 100644
--- a/filter/f-inst.h
+++ b/filter/f-inst.h
@@ -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;
diff --git a/filter/f-util.c b/filter/f-util.c
index e980cef5..768ee83b 100644
--- a/filter/f-util.c
+++ b/filter/f-util.c
@@ -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;