aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2003-05-31 17:21:09 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:00:47 -0700
commit047821f7db2a4c4dd348bbc30d1cbcd46d404e5a (patch)
treea00e0288eecf1218d6270900fcc954f387242ff6
parent32dc632cf37e8a7a9443e6b38085420ec74ac9ac (diff)
downloadsparse-047821f7db2a4c4dd348bbc30d1cbcd46d404e5a.tar.gz
sparse-047821f7db2a4c4dd348bbc30d1cbcd46d404e5a.tar.xz
sparse-047821f7db2a4c4dd348bbc30d1cbcd46d404e5a.zip
Make function returns a bit more realistic
-rw-r--r--parse.c50
-rw-r--r--parse.h5
-rw-r--r--show-parse.c7
3 files changed, 52 insertions, 10 deletions
diff --git a/parse.c b/parse.c
index c570a8a..51c2029 100644
--- a/parse.c
+++ b/parse.c
@@ -624,6 +624,25 @@ static void end_iterator(struct statement *stmt)
end_symbol_scope();
}
+static struct statement *start_function(struct symbol *sym)
+{
+ struct symbol *ret;
+ struct statement *stmt = alloc_statement(sym->pos, STMT_COMPOUND);
+
+ start_function_scope();
+ ret = alloc_symbol(sym->pos, SYM_NODE);
+ ret->ident = &return_ident;
+ ret->ctype = sym->ctype;
+ bind_symbol(ret, &return_ident, NS_ITERATOR);
+ stmt->ret = ret;
+ return stmt;
+}
+
+static void end_function(struct symbol *sym)
+{
+ end_function_scope();
+}
+
/*
* A "switch()" statement, like an iterator, has a
* the "break" symbol associated with it. It works
@@ -677,6 +696,17 @@ static void add_case_statement(struct statement *stmt)
stmt->case_label = sym;
}
+static struct token *parse_return_statement(struct token *token, struct statement *stmt)
+{
+ struct symbol *target = lookup_symbol(&return_ident, NS_ITERATOR);
+
+ if (!target)
+ error(token->pos, "internal error: return without a function target");
+ stmt->type = STMT_RETURN;
+ stmt->ret_target = target;
+ return expression_statement(token->next, &stmt->ret_value);
+}
+
static struct token *parse_for_statement(struct token *token, struct statement *stmt)
{
struct symbol_list *syms;
@@ -765,10 +795,10 @@ static struct token *statement(struct token *token, struct statement **tree)
return token;
return statement(token->next, &stmt->if_false);
}
- if (token->ident == &return_ident) {
- stmt->type = STMT_RETURN;
- return expression_statement(token->next, &stmt->expression);
- }
+
+ if (token->ident == &return_ident)
+ return parse_return_statement(token, stmt);
+
if (token->ident == &break_ident || token->ident == &continue_ident) {
struct symbol *target = lookup_symbol(token->ident, NS_ITERATOR);
stmt->type = STMT_GOTO;
@@ -1029,17 +1059,21 @@ static struct token *external_declaration(struct token *token, struct symbol_lis
base_type = decl->ctype.base_type;
if (!is_typedef && base_type && base_type->type == SYM_FN) {
if (match_op(token, '{')) {
+ struct statement *stmt;
if (decl->ctype.modifiers & MOD_EXTERN) {
if (!(decl->ctype.modifiers & MOD_INLINE))
warn(decl->pos, "function with external linkage has definition");
}
if (!(decl->ctype.modifiers & MOD_STATIC))
decl->ctype.modifiers |= MOD_EXTERN;
- base_type->stmt = alloc_statement(token->pos, STMT_COMPOUND);
- start_function_scope();
+
+ stmt = start_function(decl);
+
+ base_type->stmt = stmt;
symbol_iterate(base_type->arguments, declare_argument, decl);
- token = compound_statement(token->next, base_type->stmt);
- end_function_scope();
+ token = compound_statement(token->next, stmt);
+
+ end_function(decl);
if (!(decl->ctype.modifiers & MOD_INLINE))
add_symbol(list, decl);
check_declaration(decl);
diff --git a/parse.h b/parse.h
index d6e223a..8dee193 100644
--- a/parse.h
+++ b/parse.h
@@ -33,6 +33,10 @@ struct statement {
struct statement *label_statement;
};
struct expression *expression;
+ struct return_statement {
+ struct expression *ret_value;
+ struct symbol *ret_target;
+ };
struct if_statement {
struct expression *if_conditional;
struct statement *if_true;
@@ -41,6 +45,7 @@ struct statement {
struct compound_struct {
struct symbol_list *syms;
struct statement_list *stmts;
+ struct symbol *ret;
};
struct labeled_struct {
struct symbol *label_identifier;
diff --git a/show-parse.c b/show-parse.c
index 509403a..a689205 100644
--- a/show-parse.c
+++ b/show-parse.c
@@ -305,6 +305,8 @@ void show_symbol(struct symbol *sym)
case SYM_FN:
printf("\n");
show_statement(type->stmt);
+ printf(".L%p:\n", type->stmt->ret);
+ printf("\tret\n");
break;
default:
@@ -319,14 +321,15 @@ void show_symbol(struct symbol *sym)
static int show_return_stmt(struct statement *stmt)
{
- struct expression *expr = stmt->expression;
+ struct expression *expr = stmt->ret_value;
+ struct symbol *target = stmt->ret_target;
if (expr && expr->ctype) {
int val = show_expression(expr);
printf("\tmov.%d\t\tretval,v%d\n",
expr->ctype->bit_size, val);
}
- printf("\tret\n");
+ printf("\tgoto .L%p\n", target);
return 0;
}