aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2003-06-14 20:15:46 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:00:52 -0700
commitb020fece6e9b85066d4a6c306e6d2208c61e22f1 (patch)
treef74d08b396bc59e6737d3c707fbce5b34239b0e8
parent6615981184a97439c2ebd9eeae6704c402f35ca8 (diff)
downloadsparse-b020fece6e9b85066d4a6c306e6d2208c61e22f1.tar.gz
sparse-b020fece6e9b85066d4a6c306e6d2208c61e22f1.tar.xz
sparse-b020fece6e9b85066d4a6c306e6d2208c61e22f1.zip
Clean up function inlining some, and fix the type of the
argument symbols that got corrupted by the incorrect partial symbol copy when creating the new argument symbols.
-rw-r--r--evaluate.c66
-rw-r--r--inline.c75
-rw-r--r--parse.h1
3 files changed, 80 insertions, 62 deletions
diff --git a/evaluate.c b/evaluate.c
index 680f1ae..fc16e94 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1389,62 +1389,6 @@ static struct symbol *evaluate_cast(struct expression *expr)
return ctype;
}
-static int inline_function(struct expression *expr, struct symbol *sym)
-{
- struct symbol *curr;
- 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 = sym->ctype.base_type->arguments;
- struct symbol *name;
- struct expression *arg;
-
- if (!fn->stmt) {
- warn(fn->pos, "marked inline, but without a definition");
- return 0;
- }
-
- stmt = alloc_statement(expr->pos, STMT_COMPOUND);
- expr->type = EXPR_STATEMENT;
- expr->statement = stmt;
- expr->ctype = fn->ctype.base_type;
-
- /*
- * FIXME! On expansion, we'll need to replace the original return
- * symbol with this local one!
- */
- stmt->ret = alloc_symbol(sym->pos, SYM_NODE);
-
- /*
- * FIXME! On expansion, we'll also need to replace the original
- * argument symbols with these!
- */
- PREPARE_PTR_LIST(name_list, name);
- FOR_EACH_PTR(arg_list, arg) {
- struct symbol *a = alloc_symbol(arg->pos, SYM_NODE);
-
- if (name) {
- a->ident = name->ident;
- a->ctype.modifiers = name->ctype.modifiers;
- name->replace = a;
- }
- a->ctype.base_type = arg->ctype;
- a->initializer = arg;
- add_symbol(&stmt->syms, a);
-
- NEXT_PTR_LIST(name);
- } END_FOR_EACH_PTR;
- FINISH_PTR_LIST(name);
-
- copy_statement(fn->stmt, stmt);
-
- curr = current_fn;
- current_fn = fn;
- evaluate_statement(stmt);
- current_fn = curr;
- return 1;
-}
-
/*
* Evaluate a call expression with a symbol. This
* should expand inline functions, and evaluate
@@ -1466,8 +1410,14 @@ static int evaluate_symbol_call(struct expression *expr)
* For now we just mark them accessed so that they show
* up on the list of used symbols.
*/
- if (ctype->ctype.modifiers & MOD_INLINE)
- return inline_function(expr, ctype);
+ if (ctype->ctype.modifiers & MOD_INLINE) {
+ int ret;
+ struct symbol *curr = current_fn;
+ current_fn = ctype->ctype.base_type;
+ ret = inline_function(expr, ctype);
+ current_fn = curr;
+ return ret;
+ }
return 0;
}
diff --git a/inline.c b/inline.c
index 318ad02..1a09130 100644
--- a/inline.c
+++ b/inline.c
@@ -240,6 +240,20 @@ static struct statement *copy_one_statement(struct statement *stmt)
return stmt;
}
+void set_replace(struct symbol *old, struct symbol *new)
+{
+ new->replace = old;
+ old->replace = new;
+}
+
+void unset_replace(struct symbol *sym)
+{
+ struct symbol *r = sym->replace;
+ if (r) {
+ r->replace = NULL;
+ sym->replace = NULL;
+ }
+}
/*
* Copy a stateemnt tree from 'src' to 'dst', where both
@@ -257,18 +271,71 @@ void copy_statement(struct statement *src, struct statement *dst)
FOR_EACH_PTR(src->syms, sym) {
struct symbol *newsym = alloc_symbol(sym->pos, sym->type);
- newsym->replace = sym;
- sym->replace = newsym;
newsym->ctype = sym->ctype;
newsym->initializer = copy_expression(sym->initializer);
add_symbol(&dst->syms, newsym);
+
+ set_replace(sym, newsym);
} END_FOR_EACH_PTR;
FOR_EACH_PTR(src->stmts, stmt) {
add_statement(&dst->stmts, copy_one_statement(stmt));
} END_FOR_EACH_PTR;
- FOR_EACH_PTR(src->syms, sym) {
- sym->replace = NULL;
+ FOR_EACH_PTR(dst->syms, sym) {
+ unset_replace(sym);
+ } END_FOR_EACH_PTR;
+}
+
+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 = sym->ctype.base_type->arguments;
+ struct symbol *name;
+ struct expression *arg;
+
+ if (!fn->stmt) {
+ warn(fn->pos, "marked inline, but without a definition");
+ return 0;
+ }
+
+ stmt = alloc_statement(expr->pos, STMT_COMPOUND);
+
+ expr->type = EXPR_STATEMENT;
+ expr->statement = stmt;
+ expr->ctype = fn->ctype.base_type;
+
+ /*
+ * FIXME! On expansion, we'll need to replace the original return
+ * symbol with this local one!
+ */
+ stmt->ret = alloc_symbol(sym->pos, SYM_NODE);
+
+ /*
+ * FIXME! On expansion, we'll also need to replace the original
+ * argument symbols with these!
+ */
+ PREPARE_PTR_LIST(name_list, name);
+ FOR_EACH_PTR(arg_list, arg) {
+ struct symbol *a = alloc_symbol(arg->pos, SYM_NODE);
+
+ a->ctype.base_type = arg->ctype;
+ if (name) {
+ a->ident = name->ident;
+ a->ctype = name->ctype;
+ set_replace(name, a);
+ }
+ a->initializer = arg;
+ add_symbol(&stmt->syms, a);
+
+ NEXT_PTR_LIST(name);
} END_FOR_EACH_PTR;
+ FINISH_PTR_LIST(name);
+
+ copy_statement(fn->stmt, stmt);
+ evaluate_statement(stmt);
+
+ return 1;
}
diff --git a/parse.h b/parse.h
index 9443972..be4106f 100644
--- a/parse.h
+++ b/parse.h
@@ -95,5 +95,6 @@ extern struct symbol *ctype_fp(unsigned int spec);
extern int match_string_ident(struct ident *, const char *);
extern void copy_statement(struct statement *src, struct statement *dst);
+extern int inline_function(struct expression *expr, struct symbol *sym);
#endif /* PARSE_H */