2 * Sparse - a semantic source parser.
4 * Copyright (C) 2003 Transmeta Corp.
5 * 2003-2004 Linus Torvalds
7 * Licensed under the Open Software License version 1.1
18 #include "expression.h"
20 static struct expression
* dup_expression(struct expression
*expr
)
22 struct expression
*dup
= alloc_expression(expr
->pos
, expr
->type
);
27 static struct statement
* dup_statement(struct statement
*stmt
)
29 struct statement
*dup
= alloc_statement(stmt
->pos
, stmt
->type
);
34 static struct symbol
*copy_symbol(struct position pos
, struct symbol
*sym
)
38 if (sym
->ctype
.modifiers
& (MOD_STATIC
| MOD_EXTERN
| MOD_TOPLEVEL
| MOD_INLINE
))
41 warning(pos
, "unreplaced symbol '%s'", show_ident(sym
->ident
));
47 static struct symbol_list
*copy_symbol_list(struct symbol_list
*src
)
49 struct symbol_list
*dst
= NULL
;
52 FOR_EACH_PTR(src
, sym
) {
53 struct symbol
*newsym
= copy_symbol(sym
->pos
, sym
);
54 add_symbol(&dst
, newsym
);
55 } END_FOR_EACH_PTR(sym
);
59 static struct expression
* copy_expression(struct expression
*expr
)
66 * EXPR_SYMBOL is the interesting case, we may need to replace the
67 * symbol to the new copy.
70 struct symbol
*sym
= copy_symbol(expr
->pos
, expr
->symbol
);
71 if (sym
== expr
->symbol
)
73 expr
= dup_expression(expr
);
78 /* Atomics, never change, just return the expression directly */
85 /* Unops: check if the subexpression is unique */
88 struct expression
*unop
= copy_expression(expr
->unop
);
89 if (expr
->unop
== unop
)
91 expr
= dup_expression(expr
);
97 struct expression
*base
= copy_expression(expr
->base
);
98 expr
= dup_expression(expr
);
103 /* Binops: copy left/right expressions */
108 struct expression
*left
= copy_expression(expr
->left
);
109 struct expression
*right
= copy_expression(expr
->right
);
110 if (left
== expr
->left
&& right
== expr
->right
)
112 expr
= dup_expression(expr
);
118 case EXPR_ASSIGNMENT
: {
119 struct expression
*left
= copy_expression(expr
->left
);
120 struct expression
*right
= copy_expression(expr
->right
);
121 if (expr
->op
== '=' && left
== expr
->left
&& right
== expr
->right
)
123 expr
= dup_expression(expr
);
131 struct expression
*deref
= copy_expression(expr
->deref
);
132 expr
= dup_expression(expr
);
137 /* Cast/sizeof/__alignof__ */
139 if (expr
->cast_expression
->type
== EXPR_INITIALIZER
) {
140 struct expression
*cast
= expr
->cast_expression
;
141 struct symbol
*sym
= expr
->cast_type
;
142 expr
= dup_expression(expr
);
143 expr
->cast_expression
= copy_expression(cast
);
144 expr
->cast_type
= alloc_symbol(sym
->pos
, sym
->type
);
145 *expr
->cast_type
= *sym
;
148 case EXPR_IMPLIED_CAST
:
152 struct expression
*cast
= copy_expression(expr
->cast_expression
);
153 if (cast
== expr
->cast_expression
)
155 expr
= dup_expression(expr
);
156 expr
->cast_expression
= cast
;
160 /* Conditional expression */
162 case EXPR_CONDITIONAL
: {
163 struct expression
*cond
= copy_expression(expr
->conditional
);
164 struct expression
*true = copy_expression(expr
->cond_true
);
165 struct expression
*false = copy_expression(expr
->cond_false
);
166 if (cond
== expr
->conditional
&& true == expr
->cond_true
&& false == expr
->cond_false
)
168 expr
= dup_expression(expr
);
169 expr
->conditional
= cond
;
170 expr
->cond_true
= true;
171 expr
->cond_false
= false;
175 /* Statement expression */
176 case EXPR_STATEMENT
: {
177 struct statement
*stmt
= alloc_statement(expr
->pos
, STMT_COMPOUND
);
178 copy_statement(expr
->statement
, stmt
);
179 expr
= dup_expression(expr
);
180 expr
->statement
= stmt
;
184 /* Call expression */
186 struct expression
*fn
= copy_expression(expr
->fn
);
187 struct expression_list
*list
= expr
->args
;
188 struct expression
*arg
;
190 expr
= dup_expression(expr
);
193 FOR_EACH_PTR(list
, arg
) {
194 add_expression(&expr
->args
, copy_expression(arg
));
195 } END_FOR_EACH_PTR(arg
);
199 /* Initializer list statement */
200 case EXPR_INITIALIZER
: {
201 struct expression_list
*list
= expr
->expr_list
;
202 struct expression
*entry
;
203 expr
= dup_expression(expr
);
204 expr
->expr_list
= NULL
;
205 FOR_EACH_PTR(list
, entry
) {
206 add_expression(&expr
->expr_list
, copy_expression(entry
));
207 } END_FOR_EACH_PTR(entry
);
211 /* Label in inline function - hmm. */
213 struct symbol
*label_symbol
= copy_symbol(expr
->pos
, expr
->label_symbol
);
214 expr
= dup_expression(expr
);
215 expr
->label_symbol
= label_symbol
;
220 struct expression
*sub_expr
= copy_expression(expr
->idx_expression
);
221 if (sub_expr
== expr
->idx_expression
)
223 expr
= dup_expression(expr
);
224 expr
->idx_expression
= sub_expr
;
228 case EXPR_IDENTIFIER
: {
229 struct expression
*sub_expr
= copy_expression(expr
->ident_expression
);
230 expr
= dup_expression(expr
);
231 expr
->ident_expression
= sub_expr
;
235 /* Position in initializer.. */
237 struct expression
*val
= copy_expression(expr
->init_expr
);
238 expr
= dup_expression(expr
);
239 expr
->init_expr
= val
;
244 warning(expr
->pos
, "trying to copy expression type %d", expr
->type
);
249 static struct expression_list
*copy_asm_constraints(struct expression_list
*in
)
251 struct expression_list
*out
= NULL
;
252 struct expression
*expr
;
255 FOR_EACH_PTR(in
, expr
) {
257 case 0: /* identifier */
258 case 1: /* constraint */
260 add_expression(&out
, expr
);
262 case 2: /* expression */
264 add_expression(&out
, copy_expression(expr
));
267 } END_FOR_EACH_PTR(expr
);
271 static void set_replace(struct symbol
*old
, struct symbol
*new)
277 static void unset_replace(struct symbol
*sym
)
279 struct symbol
*r
= sym
->replace
;
281 warning(sym
->pos
, "symbol '%s' not replaced?", show_ident(sym
->ident
));
288 static void unset_replace_list(struct symbol_list
*list
)
291 FOR_EACH_PTR(list
, sym
) {
293 } END_FOR_EACH_PTR(sym
);
296 static struct statement
*copy_one_statement(struct statement
*stmt
)
303 case STMT_DECLARATION
: {
305 struct statement
*newstmt
= dup_statement(stmt
);
306 newstmt
->declaration
= NULL
;
307 FOR_EACH_PTR(stmt
->declaration
, sym
) {
308 struct symbol
*newsym
= copy_symbol(stmt
->pos
, sym
);
310 newsym
->initializer
= copy_expression(sym
->initializer
);
311 add_symbol(&newstmt
->declaration
, newsym
);
312 } END_FOR_EACH_PTR(sym
);
317 case STMT_EXPRESSION
: {
318 struct expression
*expr
= copy_expression(stmt
->expression
);
319 if (expr
== stmt
->expression
)
321 stmt
= dup_statement(stmt
);
322 stmt
->expression
= expr
;
326 struct expression
*expr
= copy_expression(stmt
->range_expression
);
327 if (expr
== stmt
->expression
)
329 stmt
= dup_statement(stmt
);
330 stmt
->range_expression
= expr
;
333 case STMT_COMPOUND
: {
334 struct statement
*new = alloc_statement(stmt
->pos
, STMT_COMPOUND
);
335 copy_statement(stmt
, new);
340 struct expression
*cond
= stmt
->if_conditional
;
341 struct statement
*true = stmt
->if_true
;
342 struct statement
*false = stmt
->if_false
;
344 cond
= copy_expression(cond
);
345 true = copy_one_statement(true);
346 false = copy_one_statement(false);
347 if (stmt
->if_conditional
== cond
&&
348 stmt
->if_true
== true &&
349 stmt
->if_false
== false)
351 stmt
= dup_statement(stmt
);
352 stmt
->if_conditional
= cond
;
353 stmt
->if_true
= true;
354 stmt
->if_false
= false;
358 struct expression
*retval
= copy_expression(stmt
->ret_value
);
359 struct symbol
*sym
= copy_symbol(stmt
->pos
, stmt
->ret_target
);
361 stmt
= dup_statement(stmt
);
362 stmt
->ret_value
= retval
;
363 stmt
->ret_target
= sym
;
367 stmt
= dup_statement(stmt
);
368 stmt
->case_label
= copy_symbol(stmt
->pos
, stmt
->case_label
);
369 stmt
->case_expression
= copy_expression(stmt
->case_expression
);
370 stmt
->case_to
= copy_expression(stmt
->case_to
);
371 stmt
->case_statement
= copy_one_statement(stmt
->case_statement
);
375 struct symbol
*switch_break
= copy_symbol(stmt
->pos
, stmt
->switch_break
);
376 struct symbol
*switch_case
= copy_symbol(stmt
->pos
, stmt
->switch_case
);
377 struct expression
*expr
= copy_expression(stmt
->switch_expression
);
378 struct statement
*switch_stmt
= copy_one_statement(stmt
->switch_statement
);
380 stmt
= dup_statement(stmt
);
381 switch_case
->symbol_list
= copy_symbol_list(switch_case
->symbol_list
);
382 stmt
->switch_break
= switch_break
;
383 stmt
->switch_case
= switch_case
;
384 stmt
->switch_expression
= expr
;
385 stmt
->switch_statement
= switch_stmt
;
388 case STMT_ITERATOR
: {
389 stmt
= dup_statement(stmt
);
390 stmt
->iterator_break
= copy_symbol(stmt
->pos
, stmt
->iterator_break
);
391 stmt
->iterator_continue
= copy_symbol(stmt
->pos
, stmt
->iterator_continue
);
392 stmt
->iterator_syms
= copy_symbol_list(stmt
->iterator_syms
);
394 stmt
->iterator_pre_statement
= copy_one_statement(stmt
->iterator_pre_statement
);
395 stmt
->iterator_pre_condition
= copy_expression(stmt
->iterator_pre_condition
);
397 stmt
->iterator_statement
= copy_one_statement(stmt
->iterator_statement
);
399 stmt
->iterator_post_statement
= copy_one_statement(stmt
->iterator_post_statement
);
400 stmt
->iterator_post_condition
= copy_expression(stmt
->iterator_post_condition
);
404 stmt
= dup_statement(stmt
);
405 stmt
->label_identifier
= copy_symbol(stmt
->pos
, stmt
->label_identifier
);
406 stmt
->label_statement
= copy_one_statement(stmt
->label_statement
);
410 stmt
= dup_statement(stmt
);
411 stmt
->goto_label
= copy_symbol(stmt
->pos
, stmt
->goto_label
);
412 stmt
->goto_expression
= copy_expression(stmt
->goto_expression
);
413 stmt
->target_list
= copy_symbol_list(stmt
->target_list
);
417 stmt
= dup_statement(stmt
);
418 stmt
->asm_inputs
= copy_asm_constraints(stmt
->asm_inputs
);
419 stmt
->asm_outputs
= copy_asm_constraints(stmt
->asm_outputs
);
420 /* no need to dup "clobbers", since they are all constant strings */
424 warning(stmt
->pos
, "trying to copy statement type %d", stmt
->type
);
431 * Copy a statement tree from 'src' to 'dst', where both
432 * source and destination are of type STMT_COMPOUND.
434 * We do this for the tree-level inliner.
436 * This doesn't do the symbol replacement right: it's not
439 void copy_statement(struct statement
*src
, struct statement
*dst
)
441 struct statement
*stmt
;
443 FOR_EACH_PTR(src
->stmts
, stmt
) {
444 add_statement(&dst
->stmts
, copy_one_statement(stmt
));
445 } END_FOR_EACH_PTR(stmt
);
446 dst
->args
= copy_one_statement(src
->args
);
447 dst
->ret
= copy_symbol(src
->pos
, src
->ret
);
448 dst
->inline_fn
= src
->inline_fn
;
451 static struct symbol
*create_copy_symbol(struct symbol
*orig
)
453 struct symbol
*sym
= orig
;
455 sym
= alloc_symbol(orig
->pos
, orig
->type
);
457 sym
->bb_target
= NULL
;
459 set_replace(orig
, sym
);
465 static struct symbol_list
*create_symbol_list(struct symbol_list
*src
)
467 struct symbol_list
*dst
= NULL
;
470 FOR_EACH_PTR(src
, sym
) {
471 struct symbol
*newsym
= create_copy_symbol(sym
);
472 add_symbol(&dst
, newsym
);
473 } END_FOR_EACH_PTR(sym
);
477 int inline_function(struct expression
*expr
, struct symbol
*sym
)
479 struct symbol_list
* fn_symbol_list
;
480 struct symbol
*fn
= sym
->ctype
.base_type
;
481 struct expression_list
*arg_list
= expr
->args
;
482 struct statement
*stmt
= alloc_statement(expr
->pos
, STMT_COMPOUND
);
483 struct symbol_list
*name_list
, *arg_decl
;
485 struct expression
*arg
;
487 if (!fn
->inline_stmt
) {
488 sparse_error(fn
->pos
, "marked inline, but without a definition");
496 name_list
= fn
->arguments
;
498 expr
->type
= EXPR_STATEMENT
;
499 expr
->statement
= stmt
;
500 expr
->ctype
= fn
->ctype
.base_type
;
502 fn_symbol_list
= create_symbol_list(sym
->inline_symbol_list
);
505 PREPARE_PTR_LIST(name_list
, name
);
506 FOR_EACH_PTR(arg_list
, arg
) {
507 struct symbol
*a
= alloc_symbol(arg
->pos
, SYM_NODE
);
509 a
->ctype
.base_type
= arg
->ctype
;
512 set_replace(name
, a
);
513 add_symbol(&fn_symbol_list
, a
);
515 a
->initializer
= arg
;
516 add_symbol(&arg_decl
, a
);
519 } END_FOR_EACH_PTR(arg
);
520 FINISH_PTR_LIST(name
);
522 copy_statement(fn
->inline_stmt
, stmt
);
525 struct statement
*decl
= alloc_statement(expr
->pos
, STMT_DECLARATION
);
526 decl
->declaration
= arg_decl
;
529 stmt
->inline_fn
= sym
;
531 unset_replace_list(fn_symbol_list
);
533 evaluate_statement(stmt
);
539 void uninline(struct symbol
*sym
)
541 struct symbol
*fn
= sym
->ctype
.base_type
;
542 struct symbol_list
*arg_list
= fn
->arguments
;
545 sym
->symbol_list
= create_symbol_list(sym
->inline_symbol_list
);
546 FOR_EACH_PTR(arg_list
, p
) {
548 } END_FOR_EACH_PTR(p
);
549 fn
->stmt
= alloc_statement(fn
->pos
, STMT_COMPOUND
);
550 copy_statement(fn
->inline_stmt
, fn
->stmt
);
551 unset_replace_list(sym
->symbol_list
);
552 unset_replace_list(arg_list
);