aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2003-06-09 17:24:50 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:00:51 -0700
commit0bd178e427936765ce3289ec8532483889f657b6 (patch)
tree76058e3b18d316e6c08e451b14c02cafc902ce9f
parentfaccc8f14eab18b1925a36b58f0ab03a59eb1772 (diff)
downloadsparse-0bd178e427936765ce3289ec8532483889f657b6.tar.gz
sparse-0bd178e427936765ce3289ec8532483889f657b6.tar.xz
sparse-0bd178e427936765ce3289ec8532483889f657b6.zip
Start doing real expression copying for the inliner. We need to
replace the symbols encounterd durign an expression copy, and this is the first step showing how. This doesn't get the multi-level inlining right, we'll get there some day. Also, it currently complains about subexpressions it can't copy yet, causing way too much verbosity for the kernel.
-rw-r--r--inline.c110
-rw-r--r--show-parse.c2
-rw-r--r--symbol.h1
3 files changed, 110 insertions, 3 deletions
diff --git a/inline.c b/inline.c
index 7b80f5c..0f41e5f 100644
--- a/inline.c
+++ b/inline.c
@@ -13,9 +13,108 @@
#include "token.h"
#include "parse.h"
#include "symbol.h"
+#include "expression.h"
#define copy_one_statement(stmt) (stmt)
-#define copy_expression(expr) (expr)
+
+static struct expression * dup_expression(struct expression *expr)
+{
+ struct expression *dup = alloc_expression(expr->pos, expr->type);
+ *dup = *expr;
+ return dup;
+}
+
+static struct expression * copy_expression(struct expression *expr)
+{
+ if (!expr)
+ return NULL;
+
+ switch (expr->type) {
+ /*
+ * EXPR_SYMBOL is the interesting case, we may need to replace the
+ * symbol to the new copy.
+ */
+ case EXPR_SYMBOL: {
+ struct symbol *sym = expr->symbol->replace;
+ if (!sym)
+ break;
+ expr = dup_expression(expr);
+ expr->symbol = sym;
+ break;
+ }
+
+ /* Atomics, never change, just return the expression directly */
+ case EXPR_VALUE:
+ case EXPR_STRING:
+ break;
+
+ /* Unops: check if the subexpression is unique */
+ case EXPR_PREOP:
+ case EXPR_POSTOP: {
+ struct expression *unop = copy_expression(expr->unop);
+ if (expr->unop == unop)
+ break;
+ expr = dup_expression(expr);
+ expr->unop = unop;
+ break;
+ }
+
+ /* Binops: copy left/right expressions */
+ case EXPR_BINOP:
+ case EXPR_COMMA:
+ case EXPR_COMPARE:
+ case EXPR_LOGICAL:
+ case EXPR_ASSIGNMENT: {
+ struct expression *left = copy_expression(expr->left);
+ struct expression *right = copy_expression(expr->right);
+ if (left == expr->left && right == expr->right)
+ break;
+ expr = dup_expression(expr);
+ expr->left = left;
+ expr->right = right;
+ break;
+ }
+
+ /* Dereference */
+ case EXPR_DEREF: {
+ struct expression *deref = copy_expression(expr->deref);
+ if (deref == expr->deref)
+ break;
+ expr = dup_expression(expr);
+ expr->deref = deref;
+ break;
+ }
+
+ /* Cast/sizeof */
+ case EXPR_CAST:
+ case EXPR_SIZEOF: {
+ struct expression *cast = copy_expression(expr->cast_expression);
+ if (cast == expr->cast_expression)
+ break;
+ expr = dup_expression(expr);
+ expr->cast_expression = cast;
+ break;
+ }
+
+ /* Conditional expression */
+ case EXPR_CONDITIONAL: {
+ struct expression *cond = copy_expression(expr->conditional);
+ struct expression *true = copy_expression(expr->cond_true);
+ struct expression *false = copy_expression(expr->cond_false);
+ if (cond == expr->conditional && true == expr->cond_true && false == expr->cond_false)
+ break;
+ expr = dup_expression(expr);
+ expr->conditional = cond;
+ expr->cond_true = true;
+ expr->cond_false = false;
+ break;
+ }
+
+ default:
+ warn(expr->pos, "trying to copy expression type %d", expr->type);
+ }
+ return expr;
+}
/*
* Copy a stateemnt tree from 'src' to 'dst', where both
@@ -23,7 +122,8 @@
*
* We do this for the tree-level inliner.
*
- * This doesn't do the symbol replacements right, duh.
+ * This doesn't do the symbol replacement right: it's not
+ * re-entrant.
*/
void copy_statement(struct statement *src, struct statement *dst)
{
@@ -32,6 +132,8 @@ 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);
@@ -40,4 +142,8 @@ void copy_statement(struct statement *src, struct statement *dst)
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;
+ } END_FOR_EACH_PTR;
}
diff --git a/show-parse.c b/show-parse.c
index 2c2cdb4..71564f1 100644
--- a/show-parse.c
+++ b/show-parse.c
@@ -756,7 +756,7 @@ static int show_symbol_expr(struct symbol *sym)
printf("\taddi.%d\t\tv%d,vFP,$%lld\n", BITS_IN_POINTER, new, sym->value);
return new;
}
- printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s)\n", BITS_IN_POINTER, new, show_ident(sym->ident));
+ printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", BITS_IN_POINTER, new, show_ident(sym->ident), sym);
return new;
}
diff --git a/symbol.h b/symbol.h
index b1cbc9b..40f0b83 100644
--- a/symbol.h
+++ b/symbol.h
@@ -63,6 +63,7 @@ struct symbol {
struct ident *ident; /* What identifier this symbol is associated with */
struct symbol *next_id; /* Next semantic symbol that shares this identifier */
struct symbol **id_list; /* Backpointer to symbol list head */
+ struct symbol *replace; /* What is this symbol shadowed by in copy-expression */
struct scope *scope;
struct symbol *same_symbol;
int (*evaluate)(struct expression *);