From ca6f609c266da41c86e294dda18ca7c6b7db44b3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 11 Feb 2004 18:18:39 -0700 Subject: [PATCH] Linearize iterators, at least a first try at it. As with labels, this required us to do indirection through a symbol for branch targets. Now everything is handled that way, and things look a lot saner. --- linearize.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- parse.h | 2 +- show-parse.c | 6 ++--- 3 files changed, 79 insertions(+), 7 deletions(-) diff --git a/linearize.c b/linearize.c index a96423c5..481bf5c5 100644 --- a/linearize.c +++ b/linearize.c @@ -82,8 +82,9 @@ static struct basic_block * linearize_statement(struct symbol_list **syms, switch (stmt->type) { case STMT_NONE: - return bb; + break; + case STMT_ASM: case STMT_EXPRESSION: add_statement(&bb->stmts, stmt); break; @@ -93,6 +94,7 @@ static struct basic_block * linearize_statement(struct symbol_list **syms, bb = new_basic_block(bbs); break; + case STMT_CASE: case STMT_LABEL: { struct basic_block *new_bb = new_basic_block(bbs); struct symbol *sym = stmt->label_identifier; @@ -135,7 +137,7 @@ static struct basic_block * linearize_statement(struct symbol_list **syms, last_bb = new_basic_block(bbs); goto_bb->bb_conditional = stmt->if_conditional; - goto_bb->bb_target = last_bb; + goto_bb->bb_target = target; bb = linearize_statement(syms, bbs, bb, stmt->if_true); bb->next = target; @@ -147,7 +149,7 @@ static struct basic_block * linearize_statement(struct symbol_list **syms, else_target->bb_target = else_bb; else_bb = linearize_statement(syms, bbs, else_bb, stmt->if_false); - goto_bb->bb_target = else_bb; + goto_bb->bb_target = else_target; else_bb->next = target; } @@ -155,6 +157,76 @@ static struct basic_block * linearize_statement(struct symbol_list **syms, break; } + case STMT_SWITCH: + add_statement(&bb->stmts, stmt); + bb = new_basic_block(bbs); + break; + + case STMT_ITERATOR: { + struct statement *pre_statement = stmt->iterator_pre_statement; + struct expression *pre_condition = stmt->iterator_pre_condition; + struct statement *statement = stmt->iterator_statement; + struct statement *post_statement = stmt->iterator_post_statement; + struct expression *post_condition = stmt->iterator_post_condition; + struct symbol *loop_top = NULL, *loop_bottom = NULL; + + concat_symbol_list(stmt->iterator_syms, syms); + bb = linearize_statement(syms, bbs, bb, pre_statement); + if (pre_condition) { + if (pre_condition->type == EXPR_VALUE) { + if (!pre_condition->value) { + loop_bottom = alloc_symbol(stmt->pos, SYM_LABEL); + bb->next = loop_bottom; + bb = new_basic_block(bbs); + } + } else { + struct statement *pre_cond = alloc_statement(stmt->pos, STMT_GOTO_BB); + loop_bottom = alloc_symbol(stmt->pos, SYM_LABEL); + pre_cond->bb_conditional = pre_condition; + pre_cond->bb_target = loop_bottom; + add_statement(&bb->stmts, pre_cond); + } + } + + if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) { + struct basic_block *loop = new_basic_block(bbs); + loop_top = alloc_symbol(stmt->pos, SYM_LABEL); + loop_top->bb_target = loop; + bb->next = loop_top; + bb = loop; + } + + bb = linearize_statement(syms, bbs, bb, statement); + + if (stmt->iterator_continue->used) { + struct basic_block *cont = new_basic_block(bbs); + stmt->iterator_continue->bb_target = cont; + bb->next = stmt->iterator_continue; + bb = cont; + } + + bb = linearize_statement(syms, bbs, bb, post_statement); + + if (!post_condition) { + bb->next = loop_top; + } else { + if (post_condition->type != EXPR_VALUE || post_condition->value) { + struct statement *post_cond = alloc_statement(stmt->pos, STMT_GOTO_BB); + post_cond->bb_conditional = post_condition; + post_cond->bb_target = loop_top; + add_statement(&bb->stmts, post_cond); + } + } + + if (stmt->iterator_break->used) { + struct basic_block *brk = new_basic_block(bbs); + stmt->iterator_break->bb_target = brk; + bb->next = stmt->iterator_break; + bb = brk; + } + break; + } + default: break; } diff --git a/parse.h b/parse.h index b0ff6df8..8387d8ac 100644 --- a/parse.h +++ b/parse.h @@ -84,7 +84,7 @@ struct statement { }; struct /* goto_bb */ { struct expression *bb_conditional; - struct basic_block *bb_target; + struct symbol *bb_target; }; }; }; diff --git a/show-parse.c b/show-parse.c index e4161513..a57a0971 100644 --- a/show-parse.c +++ b/show-parse.c @@ -380,14 +380,14 @@ static void show_switch_statement(struct statement *stmt) } else printf(" what?"); } - printf(": .L%p\n", sym); + printf(": .L%p\n", sym->bb_target); } END_FOR_EACH_PTR; printf("# end case table\n"); show_statement(stmt->switch_statement); if (stmt->switch_break->used) - printf(".L%p:\n", stmt->switch_break); + printf(".L%p:\n", stmt->switch_break->bb_target); } static void show_symbol_decl(struct symbol_list *syms) @@ -535,7 +535,7 @@ int show_statement(struct statement *stmt) case STMT_GOTO_BB: { int val = show_expression(stmt->bb_conditional); - printf("\tje v%d,.L%p\n", val, stmt->bb_target); + printf("\tje v%d,.L%p\n", val, stmt->bb_target->bb_target); break; } -- 2.11.4.GIT