aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLinus Torvalds <torvalds@penguin.transmeta.com>2003-04-09 14:23:20 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:00:24 -0700
commitce96e2585847e1f1482d55d49b14574b3af47cf3 (patch)
tree1b9bd1ef2330f63c304de91be11270b4008d0fd9
parentc5dd7c8e714f9264e95dd9e376e4bba4c600c9f2 (diff)
downloadsparse-dev-ce96e2585847e1f1482d55d49b14574b3af47cf3.tar.gz
Show iterators and goto's properly as pseudo-assembler.
-rw-r--r--parse.c5
-rw-r--r--show-parse.c76
-rw-r--r--symbol.c4
-rw-r--r--symbol.h4
4 files changed, 47 insertions, 42 deletions
diff --git a/parse.c b/parse.c
index 281a67f7..2bcba887 100644
--- a/parse.c
+++ b/parse.c
@@ -631,9 +631,10 @@ struct token *statement(struct token *token, struct statement **tree)
return expression_statement(token->next, &stmt->expression);
}
if (token->ident == &break_ident || token->ident == &continue_ident) {
+ struct symbol *target = lookup_symbol(token->ident, NS_ITERATOR);
stmt->type = STMT_GOTO;
- stmt->goto_label = lookup_symbol(token->ident, NS_ITERATOR);
- if (!stmt->goto_label)
+ stmt->goto_label = target;
+ if (!target)
warn(stmt->pos, "break/continue not in iterator scope");
return expect(token->next, ';', "at end of statement");
}
diff --git a/show-parse.c b/show-parse.c
index 1437f374..343cc38a 100644
--- a/show-parse.c
+++ b/show-parse.c
@@ -328,6 +328,12 @@ static int show_return_stmt(struct statement *stmt)
static int show_symbol_init(struct symbol *sym);
+static int new_label(void)
+{
+ static int label = 0;
+ return ++label;
+}
+
/*
* Print out a statement
*/
@@ -393,43 +399,38 @@ int show_statement(struct statement *stmt)
struct statement *statement = stmt->iterator_statement;
struct statement *post_statement = stmt->iterator_post_statement;
struct expression *post_condition = stmt->iterator_post_condition;
-
- /*
- * THIS IS ONLY APPROXIMATE!
- *
- * Real iterators are more generic than
- * any of for/while/do-while, and can't
- * be printed out as C without goto's
- */
- if (post_statement || !post_condition) {
- printf("\tfor ( ");
- show_statement(pre_statement);
- printf(" ; ");
- show_expression(pre_condition);
- printf(" ; ");
- show_statement(post_statement);
- printf(" )\n");
- show_statement(statement);
- } else if (pre_condition) {
- if (pre_statement) {
- show_statement(pre_statement);
- printf(";\n");
+ int val, loop_top = 0, loop_bottom = 0;
+
+ show_statement(pre_statement);
+ if (pre_condition) {
+ if (pre_condition->type == EXPR_VALUE) {
+ if (!pre_condition->value)
+ break;
+ pre_condition = NULL;
+ } else {
+ loop_bottom = new_label();
+ val = show_expression(pre_condition);
+ printf("\tje v%d, .L%d\n", val, loop_bottom);
}
- printf("\twhile (");
- show_expression(pre_condition);
- printf(")\n");
- show_statement(statement);
+ }
+ if (post_condition->type != EXPR_VALUE || post_condition->value)
+ loop_top = new_label();
+ printf(".L%d:\n", loop_top);
+ show_statement(statement);
+ if (stmt->cont_symbol->used)
+ printf(".L%p:\n", stmt->cont_symbol);
+ show_statement(post_statement);
+ if (post_condition->type == EXPR_VALUE) {
+ if (post_condition->value)
+ printf("\tjmp .L%d\n", loop_top);
} else {
- if (pre_statement) {
- show_statement(pre_statement);
- printf(";\n");
- }
- printf("\tdo\n");
- show_statement(statement);
- printf("\twhile (");
- show_expression(post_condition);
- printf(")");
+ val = show_expression(post_condition);
+ printf("\tjne v%d, .L%d\n", val, loop_top);
}
+ if (stmt->break_symbol->used)
+ printf(".L%p:\n", stmt->break_symbol);
+ if (pre_condition)
+ printf(".L%d:\n", loop_bottom);
break;
}
case STMT_NONE:
@@ -444,11 +445,10 @@ int show_statement(struct statement *stmt)
case STMT_GOTO:
if (stmt->goto_expression) {
- printf("\tgoto *");
- show_expression(stmt->goto_expression);
+ int val = show_expression(stmt->goto_expression);
+ printf("\tgoto *v%d\n", val);
} else {
- printf("\tgoto ");
- show_symbol(stmt->goto_label);
+ printf("\tgoto .L%p\n", stmt->goto_label);
}
break;
case STMT_ASM:
diff --git a/symbol.c b/symbol.c
index 23550859..2dc99f3a 100644
--- a/symbol.c
+++ b/symbol.c
@@ -41,8 +41,10 @@ struct symbol *lookup_symbol(struct ident *ident, enum namespace ns)
struct symbol *sym;
for (sym = ident->symbols; sym; sym = sym->next_id) {
- if (sym->namespace == ns)
+ if (sym->namespace == ns) {
+ sym->used = 1;
return sym;
+ }
}
return sym;
}
diff --git a/symbol.h b/symbol.h
index 42612a3a..86e65e49 100644
--- a/symbol.h
+++ b/symbol.h
@@ -74,7 +74,9 @@ struct symbol {
unsigned int bit_offset:8,
fieldwidth:8,
arg_count:10,
- variadic:1;
+ variadic:1,
+ used:1,
+ initialized:1;
int array_size;
struct ctype ctype;
struct symbol_list *arguments;