2 * Sparse - a semantic source parser.
4 * Copyright (C) 2003 Transmeta Corp.
7 * Licensed under the Open Software License version 1.1
17 #include "expression.h"
19 static struct expression
* dup_expression(struct expression
*expr
)
21 struct expression
*dup
= alloc_expression(expr
->pos
, expr
->type
);
26 static struct statement
* dup_statement(struct statement
*stmt
)
28 struct statement
*dup
= alloc_statement(stmt
->pos
, stmt
->type
);
33 static struct symbol
*copy_symbol(struct position pos
, struct symbol
*sym
)
37 if (sym
->ctype
.modifiers
& (MOD_STATIC
| MOD_EXTERN
| MOD_TOPLEVEL
| MOD_INLINE
))
40 warn(pos
, "unreplaced symbol '%s'", show_ident(sym
->ident
));
46 static struct symbol_list
*copy_symbol_list(struct symbol_list
*src
)
48 struct symbol_list
*dst
= NULL
;
51 FOR_EACH_PTR(src
, sym
) {
52 struct symbol
*newsym
= copy_symbol(sym
->pos
, sym
);
53 add_symbol(&dst
, newsym
);
58 static struct expression
* copy_expression(struct expression
*expr
)
65 * EXPR_SYMBOL is the interesting case, we may need to replace the
66 * symbol to the new copy.
69 struct symbol
*sym
= copy_symbol(expr
->pos
, expr
->symbol
);
70 if (sym
== expr
->symbol
)
72 expr
= dup_expression(expr
);
77 /* Atomics, never change, just return the expression directly */
83 /* Unops: check if the subexpression is unique */
86 struct expression
*unop
= copy_expression(expr
->unop
);
87 if (expr
->unop
== unop
)
89 expr
= dup_expression(expr
);
95 struct expression
*base
= copy_expression(expr
->base
);
96 expr
= dup_expression(expr
);
101 /* Binops: copy left/right expressions */
106 struct expression
*left
= copy_expression(expr
->left
);
107 struct expression
*right
= copy_expression(expr
->right
);
108 if (left
== expr
->left
&& right
== expr
->right
)
110 expr
= dup_expression(expr
);
116 case EXPR_ASSIGNMENT
: {
117 struct expression
*left
= copy_expression(expr
->left
);
118 struct expression
*right
= copy_expression(expr
->right
);
119 if (expr
->op
== '=' && left
== expr
->left
&& right
== expr
->right
)
121 expr
= dup_expression(expr
);
129 struct expression
*deref
= copy_expression(expr
->deref
);
130 expr
= dup_expression(expr
);
135 /* Cast/sizeof/__alignof__ */
139 struct expression
*cast
= copy_expression(expr
->cast_expression
);
140 if (cast
== expr
->cast_expression
)
142 expr
= dup_expression(expr
);
143 expr
->cast_expression
= cast
;
147 /* Conditional expression */
149 case EXPR_CONDITIONAL
: {
150 struct expression
*cond
= copy_expression(expr
->conditional
);
151 struct expression
*true = copy_expression(expr
->cond_true
);
152 struct expression
*false = copy_expression(expr
->cond_false
);
153 if (cond
== expr
->conditional
&& true == expr
->cond_true
&& false == expr
->cond_false
)
155 expr
= dup_expression(expr
);
156 expr
->conditional
= cond
;
157 expr
->cond_true
= true;
158 expr
->cond_false
= false;
162 /* Statement expression */
163 case EXPR_STATEMENT
: {
164 struct statement
*stmt
= alloc_statement(expr
->pos
, STMT_COMPOUND
);
165 copy_statement(expr
->statement
, stmt
);
166 expr
= dup_expression(expr
);
167 expr
->statement
= stmt
;
171 /* Call expression */
173 struct expression
*fn
= copy_expression(expr
->fn
);
174 struct expression_list
*list
= expr
->args
;
175 struct expression
*arg
;
177 expr
= dup_expression(expr
);
180 FOR_EACH_PTR(list
, arg
) {
181 add_expression(&expr
->args
, copy_expression(arg
));
186 /* Initializer list statement */
187 case EXPR_INITIALIZER
: {
188 struct expression_list
*list
= expr
->expr_list
;
189 struct expression
*entry
;
190 expr
= dup_expression(expr
);
191 expr
->expr_list
= NULL
;
192 FOR_EACH_PTR(list
, entry
) {
193 add_expression(&expr
->expr_list
, copy_expression(entry
));
198 /* Label in inline function - hmm. */
200 struct symbol
*label_symbol
= copy_symbol(expr
->pos
, expr
->label_symbol
);
201 expr
= dup_expression(expr
);
202 expr
->label_symbol
= label_symbol
;
206 /* Identifier in member dereference is unchanged across a fn copy */
207 /* As is an array index expression */
209 case EXPR_IDENTIFIER
:
212 /* Position in initializer.. */
214 struct expression
*val
= copy_expression(expr
->init_expr
);
215 if (val
== expr
->init_expr
)
217 expr
= dup_expression(expr
);
218 expr
->init_expr
= val
;
223 warn(expr
->pos
, "trying to copy expression type %d", expr
->type
);
228 void set_replace(struct symbol
*old
, struct symbol
*new)
234 void unset_replace(struct symbol
*sym
)
236 struct symbol
*r
= sym
->replace
;
238 warn(sym
->pos
, "symbol '%s' not replaced?", show_ident(sym
->ident
));
245 static void unset_replace_list(struct symbol_list
*list
)
248 FOR_EACH_PTR(list
, sym
) {
253 static struct statement
*copy_one_statement(struct statement
*stmt
)
260 case STMT_EXPRESSION
: {
261 struct expression
*expr
= copy_expression(stmt
->expression
);
262 if (expr
== stmt
->expression
)
264 stmt
= dup_statement(stmt
);
265 stmt
->expression
= expr
;
268 case STMT_COMPOUND
: {
269 struct statement
*new = alloc_statement(stmt
->pos
, STMT_COMPOUND
);
270 copy_statement(stmt
, new);
275 struct expression
*cond
= stmt
->if_conditional
;
276 struct statement
*true = stmt
->if_true
;
277 struct statement
*false = stmt
->if_false
;
279 cond
= copy_expression(cond
);
280 true = copy_one_statement(true);
281 false = copy_one_statement(false);
282 if (stmt
->if_conditional
== cond
&&
283 stmt
->if_true
== true &&
284 stmt
->if_false
== false)
286 stmt
= dup_statement(stmt
);
287 stmt
->if_conditional
= cond
;
288 stmt
->if_true
= true;
289 stmt
->if_false
= false;
293 struct expression
*retval
= copy_expression(stmt
->ret_value
);
294 struct symbol
*sym
= copy_symbol(stmt
->pos
, stmt
->ret_target
);
296 stmt
= dup_statement(stmt
);
297 stmt
->ret_value
= retval
;
298 stmt
->ret_target
= sym
;
302 stmt
= dup_statement(stmt
);
303 stmt
->case_label
= copy_symbol(stmt
->pos
, stmt
->case_label
);
304 stmt
->case_expression
= copy_expression(stmt
->case_expression
);
305 stmt
->case_to
= copy_expression(stmt
->case_to
);
306 stmt
->case_statement
= copy_one_statement(stmt
->case_statement
);
310 struct symbol
*switch_break
= copy_symbol(stmt
->pos
, stmt
->switch_break
);
311 struct symbol
*switch_case
= copy_symbol(stmt
->pos
, stmt
->switch_case
);
312 struct expression
*expr
= copy_expression(stmt
->switch_expression
);
313 struct statement
*switch_stmt
= copy_one_statement(stmt
->switch_statement
);
314 stmt
= dup_statement(stmt
);
315 stmt
->switch_break
= switch_break
;
316 stmt
->switch_case
= switch_case
;
317 stmt
->switch_expression
= expr
;
318 stmt
->switch_statement
= switch_stmt
;
321 case STMT_ITERATOR
: {
322 stmt
= dup_statement(stmt
);
323 stmt
->iterator_break
= copy_symbol(stmt
->pos
, stmt
->iterator_break
);
324 stmt
->iterator_continue
= copy_symbol(stmt
->pos
, stmt
->iterator_continue
);
325 stmt
->iterator_syms
= copy_symbol_list(stmt
->iterator_syms
);
327 stmt
->iterator_pre_statement
= copy_one_statement(stmt
->iterator_pre_statement
);
328 stmt
->iterator_pre_condition
= copy_expression(stmt
->iterator_pre_condition
);
330 stmt
->iterator_statement
= copy_one_statement(stmt
->iterator_statement
);
332 stmt
->iterator_post_statement
= copy_one_statement(stmt
->iterator_post_statement
);
333 stmt
->iterator_post_condition
= copy_expression(stmt
->iterator_post_condition
);
337 stmt
= dup_statement(stmt
);
338 stmt
->label_identifier
= copy_symbol(stmt
->pos
, stmt
->label_identifier
);
339 stmt
->label_statement
= copy_one_statement(stmt
->label_statement
);
343 stmt
= dup_statement(stmt
);
344 stmt
->goto_label
= copy_symbol(stmt
->pos
, stmt
->goto_label
);
345 stmt
->goto_expression
= copy_expression(stmt
->goto_expression
);
346 stmt
->target_list
= copy_symbol_list(stmt
->target_list
);
354 warn(stmt
->pos
, "trying to copy statement type %d", stmt
->type
);
361 * Copy a stateemnt tree from 'src' to 'dst', where both
362 * source and destination are of type STMT_COMPOUND.
364 * We do this for the tree-level inliner.
366 * This doesn't do the symbol replacement right: it's not
369 void copy_statement(struct statement
*src
, struct statement
*dst
)
371 struct statement
*stmt
;
374 FOR_EACH_PTR(src
->syms
, sym
) {
375 struct symbol
*newsym
= copy_symbol(src
->pos
, sym
);
376 newsym
->initializer
= copy_expression(sym
->initializer
);
377 add_symbol(&dst
->syms
, newsym
);
380 FOR_EACH_PTR(src
->stmts
, stmt
) {
381 add_statement(&dst
->stmts
, copy_one_statement(stmt
));
384 dst
->ret
= copy_symbol(src
->pos
, src
->ret
);
387 static struct symbol
*create_copy_symbol(struct symbol
*orig
)
389 struct symbol
*sym
= orig
;
391 sym
= alloc_symbol(orig
->pos
, orig
->type
);
393 set_replace(orig
, sym
);
399 static struct symbol_list
*create_symbol_list(struct symbol_list
*src
)
401 struct symbol_list
*dst
= NULL
;
404 FOR_EACH_PTR(src
, sym
) {
405 struct symbol
*newsym
= create_copy_symbol(sym
);
406 add_symbol(&dst
, newsym
);
411 int inline_function(struct expression
*expr
, struct symbol
*sym
)
413 struct symbol_list
* fn_symbol_list
;
414 struct symbol
*fn
= sym
->ctype
.base_type
;
415 struct expression_list
*arg_list
= expr
->args
;
416 struct statement
*stmt
= alloc_statement(expr
->pos
, STMT_COMPOUND
);
417 struct symbol_list
*name_list
;
419 struct expression
*arg
;
421 if (!fn
->inline_stmt
) {
422 warn(fn
->pos
, "marked inline, but without a definition");
429 name_list
= fn
->arguments
;
431 expr
->type
= EXPR_STATEMENT
;
432 expr
->statement
= stmt
;
433 expr
->ctype
= fn
->ctype
.base_type
;
435 fn_symbol_list
= create_symbol_list(sym
->inline_symbol_list
);
437 PREPARE_PTR_LIST(name_list
, name
);
438 FOR_EACH_PTR(arg_list
, arg
) {
439 struct symbol
*a
= alloc_symbol(arg
->pos
, SYM_NODE
);
441 a
->ctype
.base_type
= arg
->ctype
;
444 set_replace(name
, a
);
445 add_symbol(&fn_symbol_list
, a
);
447 a
->initializer
= arg
;
448 add_symbol(&stmt
->syms
, a
);
452 FINISH_PTR_LIST(name
);
454 copy_statement(fn
->inline_stmt
, stmt
);
456 unset_replace_list(fn_symbol_list
);
458 evaluate_statement(stmt
);
464 void uninline(struct symbol
*sym
)
466 struct symbol
*fn
= sym
->ctype
.base_type
;
467 struct symbol_list
*arg_list
= fn
->arguments
;
470 sym
->symbol_list
= create_symbol_list(sym
->inline_symbol_list
);
471 FOR_EACH_PTR(arg_list
, p
) {
474 fn
->stmt
= alloc_statement(fn
->pos
, STMT_COMPOUND
);
475 copy_statement(fn
->inline_stmt
, fn
->stmt
);
476 unset_replace_list(sym
->symbol_list
);
477 unset_replace_list(arg_list
);