From 3199700ab667063556470bdd45bfce0905465974 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 31 Dec 2005 13:13:52 -0800 Subject: [PATCH] Make local declarations be statements of their own This removes the list of symbols for block statements, and instead makes a declaration be a statement of its own. This is necessary to correctly handle the case of mixed statements and declarations correctly, since the order of declarations and statements is meaningful. Signed-off-by: Linus Torvalds --- compile-i386.c | 4 +++- dissect.c | 4 +++- evaluate.c | 14 +++++++++----- expand.c | 33 +++++++++++++++++---------------- expression.h | 2 +- inline.c | 32 ++++++++++++++++++++++---------- linearize.c | 22 +++++++++++++++------- parse.c | 17 +++++++++++------ parse.h | 5 ++++- show-parse.c | 4 +++- 10 files changed, 88 insertions(+), 49 deletions(-) diff --git a/compile-i386.c b/compile-i386.c index 9ea09ede..d61652e6 100644 --- a/compile-i386.c +++ b/compile-i386.c @@ -1987,11 +1987,13 @@ static struct storage *x86_statement(struct statement *stmt) return NULL; case STMT_RETURN: return emit_return_stmt(stmt); + case STMT_DECLARATION: + x86_symbol_decl(stmt->declaration); + break; case STMT_COMPOUND: { struct statement *s; struct storage *last = NULL; - x86_symbol_decl(stmt->syms); FOR_EACH_PTR(stmt->stmts, s) { last = x86_statement(s); } END_FOR_EACH_PTR(s); diff --git a/dissect.c b/dissect.c index 7a13ffa7..018cebb1 100644 --- a/dissect.c +++ b/dissect.c @@ -442,6 +442,9 @@ static struct symbol *do_statement(usage_t mode, struct statement *stmt) case STMT_RANGE: case STMT_CONTEXT: + break; case STMT_DECLARATION: + do_sym_list(stmt->declaration); + break; case STMT_EXPRESSION: ret = do_expression(mode, stmt->expression); @@ -456,7 +459,6 @@ static struct symbol *do_statement(usage_t mode, struct statement *stmt) break; case STMT_COMPOUND: { int count; - do_sym_list(stmt->syms); count = statement_list_size(stmt->stmts); DO_LIST(stmt->stmts, st, ret = do_statement(--count ? U_VOID : mode, st)); diff --git a/evaluate.c b/evaluate.c index 224b064e..c75ab37c 100644 --- a/evaluate.c +++ b/evaluate.c @@ -2642,6 +2642,14 @@ struct symbol *evaluate_statement(struct statement *stmt) return NULL; switch (stmt->type) { + case STMT_DECLARATION: { + struct symbol *s; + FOR_EACH_PTR(stmt->declaration, s) { + evaluate_symbol(s); + } END_FOR_EACH_PTR(s); + return NULL; + } + case STMT_RETURN: return evaluate_return_expression(stmt); @@ -2653,12 +2661,8 @@ struct symbol *evaluate_statement(struct statement *stmt) case STMT_COMPOUND: { struct statement *s; struct symbol *type = NULL; - struct symbol *sym; - /* Evaluate each symbol in the compound statement */ - FOR_EACH_PTR(stmt->syms, sym) { - evaluate_symbol(sym); - } END_FOR_EACH_PTR(sym); + /* Evaluate the return symbol in the compound statement */ evaluate_symbol(stmt->ret); /* diff --git a/expand.c b/expand.c index 159b9ae1..474344da 100644 --- a/expand.c +++ b/expand.c @@ -963,22 +963,24 @@ static void expand_const_expression(struct expression *expr, const char *where) } } -void expand_symbol(struct symbol *sym) +int expand_symbol(struct symbol *sym) { + int retval; struct symbol *base_type; if (!sym) - return; + return 0; base_type = sym->ctype.base_type; if (!base_type) - return; + return 0; - expand_expression(sym->initializer); + retval = expand_expression(sym->initializer); /* expand the body of the symbol */ if (base_type->type == SYM_FN) { if (base_type->stmt) expand_statement(base_type->stmt); } + return retval; } static void expand_return_expression(struct statement *stmt) @@ -1029,20 +1031,11 @@ static int expand_if_statement(struct statement *stmt) */ static int expand_compound(struct statement *stmt) { - struct symbol *sym; struct statement *s, *last; - int cost, symbols, statements; + int cost, statements; - symbols = 0; - FOR_EACH_PTR(stmt->syms, sym) { - symbols++; - expand_symbol(sym); - } END_FOR_EACH_PTR(sym); - - if (stmt->ret) { - symbols++; + if (stmt->ret) expand_symbol(stmt->ret); - } cost = 0; last = NULL; @@ -1053,7 +1046,7 @@ static int expand_compound(struct statement *stmt) cost += expand_statement(s); } END_FOR_EACH_PTR(s); - if (!symbols && statements == 1) + if (statements == 1 && !stmt->ret) *stmt = *last; return cost; @@ -1065,6 +1058,14 @@ static int expand_statement(struct statement *stmt) return 0; switch (stmt->type) { + case STMT_DECLARATION: { + struct symbol *sym; + FOR_EACH_PTR(stmt->declaration, sym) { + expand_symbol(sym); + } END_FOR_EACH_PTR(sym); + return SIDE_EFFECTS; + } + case STMT_RETURN: expand_return_expression(stmt); return SIDE_EFFECTS; diff --git a/expression.h b/expression.h index bd81d371..ea6ab342 100644 --- a/expression.h +++ b/expression.h @@ -143,7 +143,7 @@ extern void evaluate_symbol_list(struct symbol_list *list); extern struct symbol *evaluate_statement(struct statement *stmt); extern struct symbol *evaluate_expression(struct expression *); -extern void expand_symbol(struct symbol *); +extern int expand_symbol(struct symbol *); static inline struct expression *alloc_expression(struct position pos, int type) { diff --git a/inline.c b/inline.c index 72d2f4f7..1f0172ea 100644 --- a/inline.c +++ b/inline.c @@ -299,6 +299,19 @@ static struct statement *copy_one_statement(struct statement *stmt) switch(stmt->type) { case STMT_NONE: break; + case STMT_DECLARATION: { + struct symbol *sym; + struct statement *newstmt = dup_statement(stmt); + newstmt->declaration = NULL; + FOR_EACH_PTR(stmt->declaration, sym) { + struct symbol *newsym = copy_symbol(stmt->pos, sym); + if (newsym != sym) + newsym->initializer = copy_expression(sym->initializer); + add_symbol(&newstmt->declaration, newsym); + } END_FOR_EACH_PTR(sym); + stmt = newstmt; + break; + } case STMT_CONTEXT: case STMT_EXPRESSION: { struct expression *expr = copy_expression(stmt->expression); @@ -425,14 +438,6 @@ static struct statement *copy_one_statement(struct statement *stmt) void copy_statement(struct statement *src, struct statement *dst) { struct statement *stmt; - struct symbol *sym; - - FOR_EACH_PTR(src->syms, sym) { - struct symbol *newsym = copy_symbol(src->pos, sym); - if (newsym != sym) - newsym->initializer = copy_expression(sym->initializer); - add_symbol(&dst->syms, newsym); - } END_FOR_EACH_PTR(sym); FOR_EACH_PTR(src->stmts, stmt) { add_statement(&dst->stmts, copy_one_statement(stmt)); @@ -473,7 +478,7 @@ int inline_function(struct expression *expr, struct symbol *sym) struct symbol *fn = sym->ctype.base_type; struct expression_list *arg_list = expr->args; struct statement *stmt = alloc_statement(expr->pos, STMT_COMPOUND); - struct symbol_list *name_list; + struct symbol_list *name_list, *arg_decl; struct symbol *name; struct expression *arg; @@ -493,6 +498,7 @@ int inline_function(struct expression *expr, struct symbol *sym) fn_symbol_list = create_symbol_list(sym->inline_symbol_list); + arg_decl = NULL; PREPARE_PTR_LIST(name_list, name); FOR_EACH_PTR(arg_list, arg) { struct symbol *a = alloc_symbol(arg->pos, SYM_NODE); @@ -504,12 +510,18 @@ int inline_function(struct expression *expr, struct symbol *sym) add_symbol(&fn_symbol_list, a); } a->initializer = arg; - add_symbol(&stmt->syms, a); + add_symbol(&arg_decl, a); NEXT_PTR_LIST(name); } END_FOR_EACH_PTR(arg); FINISH_PTR_LIST(name); + if (arg_decl) { + struct statement *decl = alloc_statement(expr->pos, STMT_DECLARATION); + decl->declaration = arg_decl; + add_statement(&stmt->stmts, decl); + } + copy_statement(fn->inline_stmt, stmt); unset_replace_list(fn_symbol_list); diff --git a/linearize.c b/linearize.c index 29d76cf1..f47bad93 100644 --- a/linearize.c +++ b/linearize.c @@ -1603,15 +1603,8 @@ static pseudo_t linearize_compound_statement(struct entrypoint *ep, struct state { pseudo_t pseudo; struct statement *s; - struct symbol *sym; struct symbol *ret = stmt->ret; - concat_symbol_list(stmt->syms, &ep->syms); - - FOR_EACH_PTR(stmt->syms, sym) { - linearize_one_symbol(ep, sym); - } END_FOR_EACH_PTR(sym); - pseudo = VOID; FOR_EACH_PTR(stmt->stmts, s) { pseudo = linearize_statement(ep, s); @@ -1787,6 +1780,18 @@ static void sort_switch_cases(struct instruction *insn) sort_list((struct ptr_list **)&insn->multijmp_list, multijmp_cmp); } +static pseudo_t linearize_declaration(struct entrypoint *ep, struct statement *stmt) +{ + struct symbol *sym; + + concat_symbol_list(stmt->declaration, &ep->syms); + + FOR_EACH_PTR(stmt->declaration, sym) { + linearize_one_symbol(ep, sym); + } END_FOR_EACH_PTR(sym); + return VOID; +} + pseudo_t linearize_statement(struct entrypoint *ep, struct statement *stmt) { struct basic_block *bb; @@ -1803,6 +1808,9 @@ pseudo_t linearize_statement(struct entrypoint *ep, struct statement *stmt) case STMT_NONE: break; + case STMT_DECLARATION: + return linearize_declaration(ep, stmt); + case STMT_CONTEXT: return linearize_context(ep, stmt); diff --git a/parse.c b/parse.c index cd3c2136..d871afdc 100644 --- a/parse.c +++ b/parse.c @@ -1409,8 +1409,9 @@ default_statement: return expression_statement(token, &stmt->expression); } -static struct token * statement_list(struct token *token, struct statement_list **list, struct symbol_list **syms) +static struct token * statement_list(struct token *token, struct statement_list **list) { + int seen_statement = 0; for (;;) { struct statement * stmt; if (eof_token(token)) @@ -1418,12 +1419,16 @@ static struct token * statement_list(struct token *token, struct statement_list if (match_op(token, '}')) break; if (lookup_type(token)) { - if (warn_on_mixed && *list) + if (seen_statement) { warning(token->pos, "mixing declarations and code"); - token = external_declaration(token, syms); - continue; + seen_statement = 0; + } + stmt = alloc_statement(token->pos, STMT_DECLARATION); + token = external_declaration(token, &stmt->declaration); + } else { + seen_statement = warn_on_mixed; + token = statement(token, &stmt); } - token = statement(token, &stmt); add_statement(list, stmt); } return token; @@ -1471,7 +1476,7 @@ static struct token *parameter_type_list(struct token *token, struct symbol *fn, struct token *compound_statement(struct token *token, struct statement *stmt) { - token = statement_list(token, &stmt->stmts, &stmt->syms); + token = statement_list(token, &stmt->stmts); return token; } diff --git a/parse.h b/parse.h index bc4781f9..2f3a3fe9 100644 --- a/parse.h +++ b/parse.h @@ -13,6 +13,7 @@ enum statement_type { STMT_NONE, + STMT_DECLARATION, STMT_EXPRESSION, STMT_COMPOUND, STMT_IF, @@ -31,6 +32,9 @@ struct statement { enum statement_type type; struct position pos; union { + struct /* declaration */ { + struct symbol_list *declaration; + }; struct /* label_arg */ { struct symbol *label; struct statement *label_statement; @@ -46,7 +50,6 @@ struct statement { struct statement *if_false; }; struct /* compound_struct */ { - struct symbol_list *syms; struct statement_list *stmts; struct symbol *ret; }; diff --git a/show-parse.c b/show-parse.c index 72c408b8..70a5b086 100644 --- a/show-parse.c +++ b/show-parse.c @@ -437,13 +437,15 @@ int show_statement(struct statement *stmt) if (!stmt) return 0; switch (stmt->type) { + case STMT_DECLARATION: + show_symbol_decl(stmt->declaration); + return 0; case STMT_RETURN: return show_return_stmt(stmt); case STMT_COMPOUND: { struct statement *s; int last = 0; - show_symbol_decl(stmt->syms); FOR_EACH_PTR(stmt->stmts, s) { last = show_statement(s); } END_FOR_EACH_PTR(s); -- 2.11.4.GIT