diff options
| author | Linus Torvalds <torvalds@home.osdl.org> | 2004-02-12 13:41:42 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-07 21:01:23 -0700 |
| commit | dcc3d37fdc742914668f4e37f17024a95466ed80 (patch) | |
| tree | 9b2a9c2cb59f439ac82b426cb7042bb41b39586d | |
| parent | 80458cde49e9fe8ea090279f94713f6410d35032 (diff) | |
| download | sparse-dev-dcc3d37fdc742914668f4e37f17024a95466ed80.tar.gz | |
Add proper linearization of switch statements.
| -rw-r--r-- | compile-i386.c | 8 | ||||
| -rw-r--r-- | evaluate.c | 2 | ||||
| -rw-r--r-- | expand.c | 2 | ||||
| -rw-r--r-- | linearize.c | 41 | ||||
| -rw-r--r-- | parse.h | 7 | ||||
| -rw-r--r-- | show-parse.c | 17 |
6 files changed, 74 insertions, 3 deletions
diff --git a/compile-i386.c b/compile-i386.c index f15362ec..dab66c05 100644 --- a/compile-i386.c +++ b/compile-i386.c @@ -1828,6 +1828,14 @@ static struct storage *x86_statement(struct statement *stmt) case STMT_CONDFALSE: printf("\tje xxx*\n"); break; + + case STMT_MULTIVALUE: + printf("\tswitch value!!\n"); + break; + + case STMT_MULTIJMP: + printf("\tswitch case xxx\n"); + break; } return NULL; } @@ -1602,6 +1602,8 @@ struct symbol *evaluate_statement(struct statement *stmt) /* These should not exist at evaluation time */ case STMT_CONDTRUE: case STMT_CONDFALSE: + case STMT_MULTIVALUE: + case STMT_MULTIJMP: break; } return NULL; @@ -588,6 +588,8 @@ static void expand_statement(struct statement *stmt) /* Should not show up at this stage */ case STMT_CONDTRUE: case STMT_CONDFALSE: + case STMT_MULTIVALUE: + case STMT_MULTIJMP: break; } } diff --git a/linearize.c b/linearize.c index 39c229df..c2637c53 100644 --- a/linearize.c +++ b/linearize.c @@ -94,7 +94,17 @@ static struct basic_block * linearize_statement(struct symbol_list **syms, bb = new_basic_block(bbs); break; - case STMT_CASE: + case STMT_CASE: { + struct basic_block *new_bb = new_basic_block(bbs); + struct symbol *sym = stmt->case_label; + + bb->next = sym; + sym->bb_target = new_bb; + + bb = linearize_statement(syms, bbs, new_bb, stmt->case_statement); + break; + } + case STMT_LABEL: { struct basic_block *new_bb = new_basic_block(bbs); struct symbol *sym = stmt->label_identifier; @@ -157,10 +167,35 @@ static struct basic_block * linearize_statement(struct symbol_list **syms, break; } - case STMT_SWITCH: - add_statement(&bb->stmts, stmt); + case STMT_SWITCH: { + struct symbol *sym; + struct statement *switch_value; + + /* Create the "head node" */ + switch_value = alloc_statement(stmt->pos, STMT_MULTIVALUE); + switch_value->expression = stmt->switch_expression; + add_statement(&bb->stmts, switch_value); + + /* Create all the sub-jumps */ + FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) { + struct statement *case_stmt = sym->stmt; + struct statement *sw_bb = alloc_statement(case_stmt->pos, STMT_MULTIJMP); + sw_bb->multi_from = case_stmt->case_expression; + sw_bb->multi_to = case_stmt->case_to; + sw_bb->multi_target = sym; + add_statement(&bb->stmts, sw_bb); + } END_FOR_EACH_PTR; + + /* And linearize the actual statement */ + bb = linearize_statement(syms, bbs, new_basic_block(bbs), stmt->switch_statement); + + /* ..then tie it all together at the end.. */ + bb->next = stmt->switch_break; bb = new_basic_block(bbs); + stmt->switch_break->bb_target = bb; + break; + } case STMT_ITERATOR: { struct statement *pre_statement = stmt->iterator_pre_statement; @@ -27,6 +27,8 @@ enum statement_type { /* These only show up after linearization */ STMT_CONDTRUE, STMT_CONDFALSE, + STMT_MULTIVALUE, + STMT_MULTIJMP, }; struct statement { @@ -87,6 +89,11 @@ struct statement { struct expression *bb_conditional; struct symbol *bb_target; }; + struct /* multijmp */ { + struct expression *multi_from; + struct expression *multi_to; + struct symbol *multi_target; + }; }; }; diff --git a/show-parse.c b/show-parse.c index 4e5989b7..f58b046a 100644 --- a/show-parse.c +++ b/show-parse.c @@ -542,6 +542,23 @@ int show_statement(struct statement *stmt) break; } + case STMT_MULTIVALUE: { + int val = show_expression(stmt->expression); + printf("\tSWITCH\t\tv%d\n", val); + break; + } + + case STMT_MULTIJMP: { + long long from = 0, to = 0; + if (stmt->multi_from && stmt->multi_from->type == EXPR_VALUE) + from = stmt->multi_from->value; + to = from; + if (stmt->multi_to && stmt->multi_to->type == EXPR_VALUE) + to = stmt->multi_to->value; + printf("\tIF %lld..%lld goto .L%p\n", from, to, stmt->multi_target->bb_target); + break; + } + } return 0; } |
