[PATCH] fix sparse warnings
[smatch.git] / inline.c
blob72d2f4f7fff02a6e9a950d05e3b1f2754ee21d29
1 /*
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
8 */
10 #include <stdlib.h>
11 #include <stdio.h>
13 #include "lib.h"
14 #include "allocate.h"
15 #include "token.h"
16 #include "parse.h"
17 #include "symbol.h"
18 #include "expression.h"
20 static struct expression * dup_expression(struct expression *expr)
22 struct expression *dup = alloc_expression(expr->pos, expr->type);
23 *dup = *expr;
24 return dup;
27 static struct statement * dup_statement(struct statement *stmt)
29 struct statement *dup = alloc_statement(stmt->pos, stmt->type);
30 *dup = *stmt;
31 return dup;
34 static struct symbol *copy_symbol(struct position pos, struct symbol *sym)
36 if (!sym)
37 return sym;
38 if (sym->ctype.modifiers & (MOD_STATIC | MOD_EXTERN | MOD_TOPLEVEL | MOD_INLINE))
39 return sym;
40 if (!sym->replace) {
41 warning(pos, "unreplaced symbol '%s'", show_ident(sym->ident));
42 return sym;
44 return sym->replace;
47 static struct symbol_list *copy_symbol_list(struct symbol_list *src)
49 struct symbol_list *dst = NULL;
50 struct symbol *sym;
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);
56 return dst;
59 static struct expression * copy_expression(struct expression *expr)
61 if (!expr)
62 return NULL;
64 switch (expr->type) {
66 * EXPR_SYMBOL is the interesting case, we may need to replace the
67 * symbol to the new copy.
69 case EXPR_SYMBOL: {
70 struct symbol *sym = copy_symbol(expr->pos, expr->symbol);
71 if (sym == expr->symbol)
72 break;
73 expr = dup_expression(expr);
74 expr->symbol = sym;
75 break;
78 /* Atomics, never change, just return the expression directly */
79 case EXPR_VALUE:
80 case EXPR_STRING:
81 case EXPR_FVALUE:
82 break;
84 /* Unops: check if the subexpression is unique */
85 case EXPR_PREOP:
86 case EXPR_POSTOP: {
87 struct expression *unop = copy_expression(expr->unop);
88 if (expr->unop == unop)
89 break;
90 expr = dup_expression(expr);
91 expr->unop = unop;
92 break;
95 case EXPR_SLICE: {
96 struct expression *base = copy_expression(expr->base);
97 expr = dup_expression(expr);
98 expr->base = base;
99 break;
102 /* Binops: copy left/right expressions */
103 case EXPR_BINOP:
104 case EXPR_COMMA:
105 case EXPR_COMPARE:
106 case EXPR_LOGICAL: {
107 struct expression *left = copy_expression(expr->left);
108 struct expression *right = copy_expression(expr->right);
109 if (left == expr->left && right == expr->right)
110 break;
111 expr = dup_expression(expr);
112 expr->left = left;
113 expr->right = right;
114 break;
117 case EXPR_ASSIGNMENT: {
118 struct expression *left = copy_expression(expr->left);
119 struct expression *right = copy_expression(expr->right);
120 if (expr->op == '=' && left == expr->left && right == expr->right)
121 break;
122 expr = dup_expression(expr);
123 expr->left = left;
124 expr->right = right;
125 break;
128 /* Dereference */
129 case EXPR_DEREF: {
130 struct expression *deref = copy_expression(expr->deref);
131 expr = dup_expression(expr);
132 expr->deref = deref;
133 break;
136 /* Cast/sizeof/__alignof__ */
137 case EXPR_CAST:
138 if (expr->cast_expression->type == EXPR_INITIALIZER) {
139 struct expression *cast = expr->cast_expression;
140 struct symbol *sym = expr->cast_type;
141 expr = dup_expression(expr);
142 expr->cast_expression = copy_expression(cast);
143 expr->cast_type = alloc_symbol(sym->pos, sym->type);
144 *expr->cast_type = *sym;
145 break;
147 case EXPR_IMPLIED_CAST:
148 case EXPR_SIZEOF:
149 case EXPR_PTRSIZEOF:
150 case EXPR_ALIGNOF: {
151 struct expression *cast = copy_expression(expr->cast_expression);
152 if (cast == expr->cast_expression)
153 break;
154 expr = dup_expression(expr);
155 expr->cast_expression = cast;
156 break;
159 /* Conditional expression */
160 case EXPR_SELECT:
161 case EXPR_CONDITIONAL: {
162 struct expression *cond = copy_expression(expr->conditional);
163 struct expression *true = copy_expression(expr->cond_true);
164 struct expression *false = copy_expression(expr->cond_false);
165 if (cond == expr->conditional && true == expr->cond_true && false == expr->cond_false)
166 break;
167 expr = dup_expression(expr);
168 expr->conditional = cond;
169 expr->cond_true = true;
170 expr->cond_false = false;
171 break;
174 /* Statement expression */
175 case EXPR_STATEMENT: {
176 struct statement *stmt = alloc_statement(expr->pos, STMT_COMPOUND);
177 copy_statement(expr->statement, stmt);
178 expr = dup_expression(expr);
179 expr->statement = stmt;
180 break;
183 /* Call expression */
184 case EXPR_CALL: {
185 struct expression *fn = copy_expression(expr->fn);
186 struct expression_list *list = expr->args;
187 struct expression *arg;
189 expr = dup_expression(expr);
190 expr->fn = fn;
191 expr->args = NULL;
192 FOR_EACH_PTR(list, arg) {
193 add_expression(&expr->args, copy_expression(arg));
194 } END_FOR_EACH_PTR(arg);
195 break;
198 /* Initializer list statement */
199 case EXPR_INITIALIZER: {
200 struct expression_list *list = expr->expr_list;
201 struct expression *entry;
202 expr = dup_expression(expr);
203 expr->expr_list = NULL;
204 FOR_EACH_PTR(list, entry) {
205 add_expression(&expr->expr_list, copy_expression(entry));
206 } END_FOR_EACH_PTR(entry);
207 break;
210 /* Label in inline function - hmm. */
211 case EXPR_LABEL: {
212 struct symbol *label_symbol = copy_symbol(expr->pos, expr->label_symbol);
213 expr = dup_expression(expr);
214 expr->label_symbol = label_symbol;
215 break;
218 case EXPR_INDEX: {
219 struct expression *sub_expr = copy_expression(expr->idx_expression);
220 if (sub_expr == expr->idx_expression)
221 break;
222 expr = dup_expression(expr);
223 expr->idx_expression = sub_expr;
224 break;
227 case EXPR_IDENTIFIER: {
228 struct expression *sub_expr = copy_expression(expr->ident_expression);
229 expr = dup_expression(expr);
230 expr->ident_expression = sub_expr;
231 break;
234 /* Position in initializer.. */
235 case EXPR_POS: {
236 struct expression *val = copy_expression(expr->init_expr);
237 expr = dup_expression(expr);
238 expr->init_expr = val;
239 break;
242 default:
243 warning(expr->pos, "trying to copy expression type %d", expr->type);
245 return expr;
248 static struct expression_list *copy_asm_constraints(struct expression_list *in)
250 struct expression_list *out = NULL;
251 struct expression *expr;
252 int state = 0;
254 FOR_EACH_PTR(in, expr) {
255 switch (state) {
256 case 0: /* identifier */
257 case 1: /* constraint */
258 state++;
259 add_expression(&out, expr);
260 continue;
261 case 2: /* expression */
262 state = 0;
263 add_expression(&out, copy_expression(expr));
264 continue;
266 } END_FOR_EACH_PTR(expr);
267 return out;
270 static void set_replace(struct symbol *old, struct symbol *new)
272 new->replace = old;
273 old->replace = new;
276 static void unset_replace(struct symbol *sym)
278 struct symbol *r = sym->replace;
279 if (!r) {
280 warning(sym->pos, "symbol '%s' not replaced?", show_ident(sym->ident));
281 return;
283 r->replace = NULL;
284 sym->replace = NULL;
287 static void unset_replace_list(struct symbol_list *list)
289 struct symbol *sym;
290 FOR_EACH_PTR(list, sym) {
291 unset_replace(sym);
292 } END_FOR_EACH_PTR(sym);
295 static struct statement *copy_one_statement(struct statement *stmt)
297 if (!stmt)
298 return NULL;
299 switch(stmt->type) {
300 case STMT_NONE:
301 break;
302 case STMT_CONTEXT:
303 case STMT_EXPRESSION: {
304 struct expression *expr = copy_expression(stmt->expression);
305 if (expr == stmt->expression)
306 break;
307 stmt = dup_statement(stmt);
308 stmt->expression = expr;
309 break;
311 case STMT_RANGE: {
312 struct expression *expr = copy_expression(stmt->range_expression);
313 if (expr == stmt->expression)
314 break;
315 stmt = dup_statement(stmt);
316 stmt->range_expression = expr;
317 break;
319 case STMT_COMPOUND: {
320 struct statement *new = alloc_statement(stmt->pos, STMT_COMPOUND);
321 copy_statement(stmt, new);
322 stmt = new;
323 break;
325 case STMT_IF: {
326 struct expression *cond = stmt->if_conditional;
327 struct statement *true = stmt->if_true;
328 struct statement *false = stmt->if_false;
330 cond = copy_expression(cond);
331 true = copy_one_statement(true);
332 false = copy_one_statement(false);
333 if (stmt->if_conditional == cond &&
334 stmt->if_true == true &&
335 stmt->if_false == false)
336 break;
337 stmt = dup_statement(stmt);
338 stmt->if_conditional = cond;
339 stmt->if_true = true;
340 stmt->if_false = false;
341 break;
343 case STMT_RETURN: {
344 struct expression *retval = copy_expression(stmt->ret_value);
345 struct symbol *sym = copy_symbol(stmt->pos, stmt->ret_target);
347 stmt = dup_statement(stmt);
348 stmt->ret_value = retval;
349 stmt->ret_target = sym;
350 break;
352 case STMT_CASE: {
353 stmt = dup_statement(stmt);
354 stmt->case_label = copy_symbol(stmt->pos, stmt->case_label);
355 stmt->case_expression = copy_expression(stmt->case_expression);
356 stmt->case_to = copy_expression(stmt->case_to);
357 stmt->case_statement = copy_one_statement(stmt->case_statement);
358 break;
360 case STMT_SWITCH: {
361 struct symbol *switch_break = copy_symbol(stmt->pos, stmt->switch_break);
362 struct symbol *switch_case = copy_symbol(stmt->pos, stmt->switch_case);
363 struct expression *expr = copy_expression(stmt->switch_expression);
364 struct statement *switch_stmt = copy_one_statement(stmt->switch_statement);
366 stmt = dup_statement(stmt);
367 switch_case->symbol_list = copy_symbol_list(switch_case->symbol_list);
368 stmt->switch_break = switch_break;
369 stmt->switch_case = switch_case;
370 stmt->switch_expression = expr;
371 stmt->switch_statement = switch_stmt;
372 break;
374 case STMT_ITERATOR: {
375 stmt = dup_statement(stmt);
376 stmt->iterator_break = copy_symbol(stmt->pos, stmt->iterator_break);
377 stmt->iterator_continue = copy_symbol(stmt->pos, stmt->iterator_continue);
378 stmt->iterator_syms = copy_symbol_list(stmt->iterator_syms);
380 stmt->iterator_pre_statement = copy_one_statement(stmt->iterator_pre_statement);
381 stmt->iterator_pre_condition = copy_expression(stmt->iterator_pre_condition);
383 stmt->iterator_statement = copy_one_statement(stmt->iterator_statement);
385 stmt->iterator_post_statement = copy_one_statement(stmt->iterator_post_statement);
386 stmt->iterator_post_condition = copy_expression(stmt->iterator_post_condition);
387 break;
389 case STMT_LABEL: {
390 stmt = dup_statement(stmt);
391 stmt->label_identifier = copy_symbol(stmt->pos, stmt->label_identifier);
392 stmt->label_statement = copy_one_statement(stmt->label_statement);
393 break;
395 case STMT_GOTO: {
396 stmt = dup_statement(stmt);
397 stmt->goto_label = copy_symbol(stmt->pos, stmt->goto_label);
398 stmt->goto_expression = copy_expression(stmt->goto_expression);
399 stmt->target_list = copy_symbol_list(stmt->target_list);
400 break;
402 case STMT_ASM: {
403 stmt = dup_statement(stmt);
404 stmt->asm_inputs = copy_asm_constraints(stmt->asm_inputs);
405 stmt->asm_outputs = copy_asm_constraints(stmt->asm_outputs);
406 /* no need to dup "clobbers", since they are all constant strings */
407 break;
409 default:
410 warning(stmt->pos, "trying to copy statement type %d", stmt->type);
411 break;
413 return stmt;
417 * Copy a stateemnt tree from 'src' to 'dst', where both
418 * source and destination are of type STMT_COMPOUND.
420 * We do this for the tree-level inliner.
422 * This doesn't do the symbol replacement right: it's not
423 * re-entrant.
425 void copy_statement(struct statement *src, struct statement *dst)
427 struct statement *stmt;
428 struct symbol *sym;
430 FOR_EACH_PTR(src->syms, sym) {
431 struct symbol *newsym = copy_symbol(src->pos, sym);
432 if (newsym != sym)
433 newsym->initializer = copy_expression(sym->initializer);
434 add_symbol(&dst->syms, newsym);
435 } END_FOR_EACH_PTR(sym);
437 FOR_EACH_PTR(src->stmts, stmt) {
438 add_statement(&dst->stmts, copy_one_statement(stmt));
439 } END_FOR_EACH_PTR(stmt);
441 dst->ret = copy_symbol(src->pos, src->ret);
444 static struct symbol *create_copy_symbol(struct symbol *orig)
446 struct symbol *sym = orig;
447 if (orig) {
448 sym = alloc_symbol(orig->pos, orig->type);
449 *sym = *orig;
450 sym->bb_target = NULL;
451 sym->pseudo = NULL;
452 set_replace(orig, sym);
453 orig = sym;
455 return orig;
458 static struct symbol_list *create_symbol_list(struct symbol_list *src)
460 struct symbol_list *dst = NULL;
461 struct symbol *sym;
463 FOR_EACH_PTR(src, sym) {
464 struct symbol *newsym = create_copy_symbol(sym);
465 add_symbol(&dst, newsym);
466 } END_FOR_EACH_PTR(sym);
467 return dst;
470 int inline_function(struct expression *expr, struct symbol *sym)
472 struct symbol_list * fn_symbol_list;
473 struct symbol *fn = sym->ctype.base_type;
474 struct expression_list *arg_list = expr->args;
475 struct statement *stmt = alloc_statement(expr->pos, STMT_COMPOUND);
476 struct symbol_list *name_list;
477 struct symbol *name;
478 struct expression *arg;
480 if (!fn->inline_stmt) {
481 sparse_error(fn->pos, "marked inline, but without a definition");
482 return 0;
484 if (fn->expanding)
485 return 0;
486 fn->expanding = 1;
488 name_list = fn->arguments;
490 expr->type = EXPR_STATEMENT;
491 expr->statement = stmt;
492 expr->ctype = fn->ctype.base_type;
494 fn_symbol_list = create_symbol_list(sym->inline_symbol_list);
496 PREPARE_PTR_LIST(name_list, name);
497 FOR_EACH_PTR(arg_list, arg) {
498 struct symbol *a = alloc_symbol(arg->pos, SYM_NODE);
500 a->ctype.base_type = arg->ctype;
501 if (name) {
502 *a = *name;
503 set_replace(name, a);
504 add_symbol(&fn_symbol_list, a);
506 a->initializer = arg;
507 add_symbol(&stmt->syms, a);
509 NEXT_PTR_LIST(name);
510 } END_FOR_EACH_PTR(arg);
511 FINISH_PTR_LIST(name);
513 copy_statement(fn->inline_stmt, stmt);
515 unset_replace_list(fn_symbol_list);
517 evaluate_statement(stmt);
519 fn->expanding = 0;
520 return 1;
523 void uninline(struct symbol *sym)
525 struct symbol *fn = sym->ctype.base_type;
526 struct symbol_list *arg_list = fn->arguments;
527 struct symbol *p;
529 sym->symbol_list = create_symbol_list(sym->inline_symbol_list);
530 FOR_EACH_PTR(arg_list, p) {
531 p->replace = p;
532 } END_FOR_EACH_PTR(p);
533 fn->stmt = alloc_statement(fn->pos, STMT_COMPOUND);
534 copy_statement(fn->inline_stmt, fn->stmt);
535 unset_replace_list(sym->symbol_list);
536 unset_replace_list(arg_list);