aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorUlf Magnusson <ulfalizer@gmail.com>2017-10-08 13:50:55 -0400
committerMasahiro Yamada <yamada.masahiro@socionext.com>2018-01-21 10:49:28 -0500
commit0735f7e5def2ab4158aac8d35f3661e8819dc232 (patch)
treefcfa05a71fd849636b385af003b79d66b997296d /scripts
parent05cccce580456d9b1a4548d9aba758856cac6455 (diff)
kconfig: Document important expression functions
Many of these functions are quite the head scratchers if you don't know what they're trying to do. Document them. Also make it clear which functions rewrite expressions in-place and which return new expressions. This prevents memory errors. No functional changes. Only comments added. Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/kconfig/expr.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index ed29bad1f03a..fd8a416ceab7 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -138,8 +138,18 @@ static int trans_count;
138#define e1 (*ep1) 138#define e1 (*ep1)
139#define e2 (*ep2) 139#define e2 (*ep2)
140 140
141/*
142 * expr_eliminate_eq() helper.
143 *
144 * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
145 * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
146 * against all other leaves. Two equal leaves are both replaced with either 'y'
147 * or 'n' as appropriate for 'type', to be eliminated later.
148 */
141static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) 149static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
142{ 150{
151 /* Recurse down to leaves */
152
143 if (e1->type == type) { 153 if (e1->type == type) {
144 __expr_eliminate_eq(type, &e1->left.expr, &e2); 154 __expr_eliminate_eq(type, &e1->left.expr, &e2);
145 __expr_eliminate_eq(type, &e1->right.expr, &e2); 155 __expr_eliminate_eq(type, &e1->right.expr, &e2);
@@ -150,12 +160,18 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
150 __expr_eliminate_eq(type, &e1, &e2->right.expr); 160 __expr_eliminate_eq(type, &e1, &e2->right.expr);
151 return; 161 return;
152 } 162 }
163
164 /* e1 and e2 are leaves. Compare them. */
165
153 if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && 166 if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
154 e1->left.sym == e2->left.sym && 167 e1->left.sym == e2->left.sym &&
155 (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) 168 (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
156 return; 169 return;
157 if (!expr_eq(e1, e2)) 170 if (!expr_eq(e1, e2))
158 return; 171 return;
172
173 /* e1 and e2 are equal leaves. Prepare them for elimination. */
174
159 trans_count++; 175 trans_count++;
160 expr_free(e1); expr_free(e2); 176 expr_free(e1); expr_free(e2);
161 switch (type) { 177 switch (type) {
@@ -172,6 +188,35 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
172 } 188 }
173} 189}
174 190
191/*
192 * Rewrites the expressions 'ep1' and 'ep2' to remove operands common to both.
193 * Example reductions:
194 *
195 * ep1: A && B -> ep1: y
196 * ep2: A && B && C -> ep2: C
197 *
198 * ep1: A || B -> ep1: n
199 * ep2: A || B || C -> ep2: C
200 *
201 * ep1: A && (B && FOO) -> ep1: FOO
202 * ep2: (BAR && B) && A -> ep2: BAR
203 *
204 * ep1: A && (B || C) -> ep1: y
205 * ep2: (C || B) && A -> ep2: y
206 *
207 * Comparisons are done between all operands at the same "level" of && or ||.
208 * For example, in the expression 'e1 && (e2 || e3) && (e4 || e5)', the
209 * following operands will be compared:
210 *
211 * - 'e1', 'e2 || e3', and 'e4 || e5', against each other
212 * - e2 against e3
213 * - e4 against e5
214 *
215 * Parentheses are irrelevant within a single level. 'e1 && (e2 && e3)' and
216 * '(e1 && e2) && e3' are both a single level.
217 *
218 * See __expr_eliminate_eq() as well.
219 */
175void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) 220void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
176{ 221{
177 if (!e1 || !e2) 222 if (!e1 || !e2)
@@ -197,6 +242,12 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
197#undef e1 242#undef e1
198#undef e2 243#undef e2
199 244
245/*
246 * Returns true if 'e1' and 'e2' are equal, after minor simplification. Two
247 * &&/|| expressions are considered equal if every operand in one expression
248 * equals some operand in the other (operands do not need to appear in the same
249 * order), recursively.
250 */
200static int expr_eq(struct expr *e1, struct expr *e2) 251static int expr_eq(struct expr *e1, struct expr *e2)
201{ 252{
202 int res, old_count; 253 int res, old_count;
@@ -243,6 +294,17 @@ static int expr_eq(struct expr *e1, struct expr *e2)
243 return 0; 294 return 0;
244} 295}
245 296
297/*
298 * Recursively performs the following simplifications in-place (as well as the
299 * corresponding simplifications with swapped operands):
300 *
301 * expr && n -> n
302 * expr && y -> expr
303 * expr || n -> expr
304 * expr || y -> y
305 *
306 * Returns the optimized expression.
307 */
246static struct expr *expr_eliminate_yn(struct expr *e) 308static struct expr *expr_eliminate_yn(struct expr *e)
247{ 309{
248 struct expr *tmp; 310 struct expr *tmp;
@@ -516,12 +578,21 @@ static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
516 return NULL; 578 return NULL;
517} 579}
518 580
581/*
582 * expr_eliminate_dups() helper.
583 *
584 * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
585 * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
586 * against all other leaves to look for simplifications.
587 */
519static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) 588static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
520{ 589{
521#define e1 (*ep1) 590#define e1 (*ep1)
522#define e2 (*ep2) 591#define e2 (*ep2)
523 struct expr *tmp; 592 struct expr *tmp;
524 593
594 /* Recurse down to leaves */
595
525 if (e1->type == type) { 596 if (e1->type == type) {
526 expr_eliminate_dups1(type, &e1->left.expr, &e2); 597 expr_eliminate_dups1(type, &e1->left.expr, &e2);
527 expr_eliminate_dups1(type, &e1->right.expr, &e2); 598 expr_eliminate_dups1(type, &e1->right.expr, &e2);
@@ -532,6 +603,9 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct
532 expr_eliminate_dups1(type, &e1, &e2->right.expr); 603 expr_eliminate_dups1(type, &e1, &e2->right.expr);
533 return; 604 return;
534 } 605 }
606
607 /* e1 and e2 are leaves. Compare and process them. */
608
535 if (e1 == e2) 609 if (e1 == e2)
536 return; 610 return;
537 611
@@ -568,6 +642,17 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct
568#undef e2 642#undef e2
569} 643}
570 644
645/*
646 * Rewrites 'e' in-place to remove ("join") duplicate and other redundant
647 * operands.
648 *
649 * Example simplifications:
650 *
651 * A || B || A -> A || B
652 * A && B && A=y -> A=y && B
653 *
654 * Returns the deduplicated expression.
655 */
571struct expr *expr_eliminate_dups(struct expr *e) 656struct expr *expr_eliminate_dups(struct expr *e)
572{ 657{
573 int oldcount; 658 int oldcount;
@@ -584,6 +669,7 @@ struct expr *expr_eliminate_dups(struct expr *e)
584 ; 669 ;
585 } 670 }
586 if (!trans_count) 671 if (!trans_count)
672 /* No simplifications done in this pass. We're done */
587 break; 673 break;
588 e = expr_eliminate_yn(e); 674 e = expr_eliminate_yn(e);
589 } 675 }
@@ -591,6 +677,12 @@ struct expr *expr_eliminate_dups(struct expr *e)
591 return e; 677 return e;
592} 678}
593 679
680/*
681 * Performs various simplifications involving logical operators and
682 * comparisons.
683 *
684 * Allocates and returns a new expression.
685 */
594struct expr *expr_transform(struct expr *e) 686struct expr *expr_transform(struct expr *e)
595{ 687{
596 struct expr *tmp; 688 struct expr *tmp;
@@ -805,6 +897,20 @@ bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
805 return false; 897 return false;
806} 898}
807 899
900/*
901 * Inserts explicit comparisons of type 'type' to symbol 'sym' into the
902 * expression 'e'.
903 *
904 * Examples transformations for type == E_UNEQUAL, sym == &symbol_no:
905 *
906 * A -> A!=n
907 * !A -> A=n
908 * A && B -> !(A=n || B=n)
909 * A || B -> !(A=n && B=n)
910 * A && (B || C) -> !(A=n || (B=n && C=n))
911 *
912 * Allocates and returns a new expression.
913 */
808struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) 914struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
809{ 915{
810 struct expr *e1, *e2; 916 struct expr *e1, *e2;