mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 01:31:55 +00:00
Filter: Change linearization of branches in switch instruction
Most branching instructions (FI_CONDITION, FI_AND, FI_OR) linearize its branches in a recursive way, while FI_SWITCH branches are linearized from parser even before the switch instruction is allocated. Change linearization of FI_SWITCH branches to make it similar to other branching instructions. This also fixes an issue with constant switch evaluation, where linearized branch is mistaken for non-linearized during switch construction. Thanks to Jiten Kumar Pathy for the bugreport.
This commit is contained in:
parent
d1cd5e5a63
commit
e20bef69cc
@ -676,16 +676,15 @@ switch_body: /* EMPTY */ { $$ = NULL; }
|
|||||||
| switch_body switch_items ':' cmds_scoped {
|
| switch_body switch_items ':' cmds_scoped {
|
||||||
/* Fill data fields */
|
/* Fill data fields */
|
||||||
struct f_tree *t;
|
struct f_tree *t;
|
||||||
struct f_line *line = f_linearize($4, 0);
|
|
||||||
for (t = $2; t; t = t->left)
|
for (t = $2; t; t = t->left)
|
||||||
t->data = line;
|
t->data = $4;
|
||||||
$$ = f_merge_items($1, $2);
|
$$ = f_merge_items($1, $2);
|
||||||
}
|
}
|
||||||
| switch_body ELSECOL cmds_scoped {
|
| switch_body ELSECOL cmds_scoped {
|
||||||
struct f_tree *t = f_new_tree();
|
struct f_tree *t = f_new_tree();
|
||||||
t->from.type = t->to.type = T_VOID;
|
t->from.type = t->to.type = T_VOID;
|
||||||
t->right = t;
|
t->right = t;
|
||||||
t->data = f_linearize($3, 0);
|
t->data = $3;
|
||||||
$$ = f_merge_items($1, t);
|
$$ = f_merge_items($1, t);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -972,7 +971,7 @@ cmd:
|
|||||||
}
|
}
|
||||||
| function_call ';' { $$ = f_new_inst(FI_DROP_RESULT, $1); }
|
| function_call ';' { $$ = f_new_inst(FI_DROP_RESULT, $1); }
|
||||||
| CASE term '{' switch_body '}' {
|
| CASE term '{' switch_body '}' {
|
||||||
$$ = f_new_inst(FI_SWITCH, $2, build_tree($4));
|
$$ = f_new_inst(FI_SWITCH, $2, $4);
|
||||||
}
|
}
|
||||||
|
|
||||||
| dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($1); }
|
| dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($1); }
|
||||||
|
@ -198,6 +198,7 @@ struct f_trie_walk_state
|
|||||||
struct f_tree *f_new_tree(void);
|
struct f_tree *f_new_tree(void);
|
||||||
struct f_tree *build_tree(struct f_tree *);
|
struct f_tree *build_tree(struct f_tree *);
|
||||||
const struct f_tree *find_tree(const struct f_tree *t, const struct f_val *val);
|
const struct f_tree *find_tree(const struct f_tree *t, const struct f_val *val);
|
||||||
|
const struct f_tree *find_tree_linear(const struct f_tree *t, const struct f_val *val);
|
||||||
int same_tree(const struct f_tree *t0, const struct f_tree *t2);
|
int same_tree(const struct f_tree *t0, const struct f_tree *t2);
|
||||||
int tree_node_count(const struct f_tree *t);
|
int tree_node_count(const struct f_tree *t);
|
||||||
void tree_format(const struct f_tree *t, buffer *buf);
|
void tree_format(const struct f_tree *t, buffer *buf);
|
||||||
|
@ -1285,14 +1285,33 @@
|
|||||||
|
|
||||||
FID_MEMBER(struct f_tree *, tree, [[!same_tree(f1->tree, f2->tree)]], "tree %p", item->tree);
|
FID_MEMBER(struct f_tree *, tree, [[!same_tree(f1->tree, f2->tree)]], "tree %p", item->tree);
|
||||||
|
|
||||||
|
FID_LINEARIZE_BODY()
|
||||||
|
/* Linearize all branches in switch */
|
||||||
|
struct f_inst *last_inst = NULL;
|
||||||
|
struct f_line *last_line = NULL;
|
||||||
|
for (struct f_tree *t = whati->tree; t; t = t->left)
|
||||||
|
{
|
||||||
|
if (t->data != last_inst)
|
||||||
|
{
|
||||||
|
last_inst = t->data;
|
||||||
|
last_line = f_linearize(t->data, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
t->data = last_line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Balance the tree */
|
||||||
|
item->tree = build_tree(whati->tree);
|
||||||
|
|
||||||
FID_ITERATE_BODY()
|
FID_ITERATE_BODY()
|
||||||
tree_walk(whati->tree, f_add_tree_lines, fit);
|
tree_walk(whati->tree, f_add_tree_lines, fit);
|
||||||
|
|
||||||
FID_INTERPRET_BODY()
|
FID_INTERPRET_BODY()
|
||||||
const struct f_tree *t = find_tree(tree, &v1);
|
/* In parse-time use find_tree_linear(), in runtime use find_tree() */
|
||||||
|
const struct f_tree *t = FID_HIC(,find_tree,find_tree_linear)(tree, &v1);
|
||||||
if (!t) {
|
if (!t) {
|
||||||
v1.type = T_VOID;
|
v1.type = T_VOID;
|
||||||
t = find_tree(tree, &v1);
|
t = FID_HIC(,find_tree,find_tree_linear)(tree, &v1);
|
||||||
if (!t) {
|
if (!t) {
|
||||||
debug( "No else statement?\n");
|
debug( "No else statement?\n");
|
||||||
FID_HIC(,break,return NULL);
|
FID_HIC(,break,return NULL);
|
||||||
|
@ -38,6 +38,26 @@ find_tree(const struct f_tree *t, const struct f_val *val)
|
|||||||
return find_tree(t->left, val);
|
return find_tree(t->left, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_tree_linear
|
||||||
|
* @t: tree to search in
|
||||||
|
* @val: value to find
|
||||||
|
*
|
||||||
|
* Search for given value in the degenerated linear tree, which is generated by
|
||||||
|
* parser before build_tree() is applied. The tree is not sorted and all nodes
|
||||||
|
* are linked by left ptr.
|
||||||
|
*/
|
||||||
|
const struct f_tree *
|
||||||
|
find_tree_linear(const struct f_tree *t, const struct f_val *val)
|
||||||
|
{
|
||||||
|
for (; t; t = t->left)
|
||||||
|
if ((val_compare(&(t->from), val) != 1) &&
|
||||||
|
(val_compare(&(t->to), val) != -1))
|
||||||
|
return t;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static struct f_tree *
|
static struct f_tree *
|
||||||
build_tree_rec(struct f_tree **buf, int l, int h)
|
build_tree_rec(struct f_tree **buf, int l, int h)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user