[PATCH] evaluate_sign() typo
[smatch.git] / inline.c
bloba7f61768ea989f0f7ac9956d0197326dc7b7c8d6
1 /*
2 * Sparse - a semantic source parser.
4 * Copyright (C) 2003 Transmeta Corp.
5 * 2003 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 "token.h"
15 #include "parse.h"
16 #include "symbol.h"
17 #include "expression.h"
19 static struct expression * dup_expression(struct expression *expr)
21 struct expression *dup = alloc_expression(expr->pos, expr->type);
22 *dup = *expr;
23 return dup;
26 static struct statement * dup_statement(struct statement *stmt)
28 struct statement *dup = alloc_statement(stmt->pos, stmt->type);
29 *dup = *stmt;
30 return dup;
33 static struct symbol *copy_symbol(struct position pos, struct symbol *sym)
35 if (!sym)
36 return sym;
37 if (sym->ctype.modifiers & (MOD_STATIC | MOD_EXTERN | MOD_TOPLEVEL | MOD_INLINE))
38 return sym;
39 if (!sym->replace) {
40 warn(pos, "unreplaced symbol '%s'", show_ident(sym->ident));
41 return sym;
43 return sym->replace;
46 static struct symbol_list *copy_symbol_list(struct symbol_list *src)
48 struct symbol_list *dst = NULL;
49 struct symbol *sym;
51 FOR_EACH_PTR(src, sym) {
52 struct symbol *newsym = copy_symbol(sym->pos, sym);
53 add_symbol(&dst, newsym);
54 } END_FOR_EACH_PTR;
55 return dst;
58 static struct expression * copy_expression(struct expression *expr)
60 if (!expr)
61 return NULL;
63 switch (expr->type) {
65 * EXPR_SYMBOL is the interesting case, we may need to replace the
66 * symbol to the new copy.
68 case EXPR_SYMBOL: {
69 struct symbol *sym = copy_symbol(expr->pos, expr->symbol);
70 if (sym == expr->symbol)
71 break;
72 expr = dup_expression(expr);
73 expr->symbol = sym;
74 break;
77 /* Atomics, never change, just return the expression directly */
78 case EXPR_VALUE:
79 case EXPR_STRING:
80 case EXPR_FVALUE:
81 break;
83 /* Unops: check if the subexpression is unique */
84 case EXPR_PREOP:
85 case EXPR_POSTOP: {
86 struct expression *unop = copy_expression(expr->unop);
87 if (expr->unop == unop)
88 break;
89 expr = dup_expression(expr);
90 expr->unop = unop;
91 break;
94 case EXPR_SLICE: {
95 struct expression *base = copy_expression(expr->base);
96 expr = dup_expression(expr);
97 expr->base = base;
98 break;
101 /* Binops: copy left/right expressions */
102 case EXPR_BINOP:
103 case EXPR_COMMA:
104 case EXPR_COMPARE:
105 case EXPR_LOGICAL: {
106 struct expression *left = copy_expression(expr->left);
107 struct expression *right = copy_expression(expr->right);
108 if (left == expr->left && right == expr->right)
109 break;
110 expr = dup_expression(expr);
111 expr->left = left;
112 expr->right = right;
113 break;
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)
120 break;
121 expr = dup_expression(expr);
122 expr->left = left;
123 expr->right = right;
124 break;
127 /* Dereference */
128 case EXPR_DEREF: {
129 struct expression *deref = copy_expression(expr->deref);
130 expr = dup_expression(expr);
131 expr->deref = deref;
132 break;
135 /* Cast/sizeof/__alignof__ */
136 case EXPR_CAST:
137 case EXPR_SIZEOF:
138 case EXPR_ALIGNOF: {
139 struct expression *cast = copy_expression(expr->cast_expression);
140 if (cast == expr->cast_expression)
141 break;
142 expr = dup_expression(expr);
143 expr->cast_expression = cast;
144 break;
147 /* Conditional expression */
148 case EXPR_SELECT:
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)
154 break;
155 expr = dup_expression(expr);
156 expr->conditional = cond;
157 expr->cond_true = true;
158 expr->cond_false = false;
159 break;
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;
168 break;
171 /* Call expression */
172 case EXPR_CALL: {
173 struct expression *fn = copy_expression(expr->fn);
174 struct expression_list *list = expr->args;
175 struct expression *arg;
177 expr = dup_expression(expr);
178 expr->fn = fn;
179 expr->args = NULL;
180 FOR_EACH_PTR(list, arg) {
181 add_expression(&expr->args, copy_expression(arg));
182 } END_FOR_EACH_PTR;
183 break;
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));
194 } END_FOR_EACH_PTR;
195 break;
198 /* Label in inline function - hmm. */
199 case EXPR_LABEL: {
200 struct symbol *label_symbol = copy_symbol(expr->pos, expr->label_symbol);
201 expr = dup_expression(expr);
202 expr->label_symbol = label_symbol;
203 break;
206 /* Identifier in member dereference is unchanged across a fn copy */
207 /* As is an array index expression */
208 case EXPR_INDEX:
209 case EXPR_IDENTIFIER:
210 break;
212 /* Position in initializer.. */
213 case EXPR_POS: {
214 struct expression *val = copy_expression(expr->init_expr);
215 if (val == expr->init_expr)
216 break;
217 expr = dup_expression(expr);
218 expr->init_expr = val;
219 break;
222 default:
223 warn(expr->pos, "trying to copy expression type %d", expr->type);
225 return expr;
228 void set_replace(struct symbol *old, struct symbol *new)
230 new->replace = old;
231 old->replace = new;
234 void unset_replace(struct symbol *sym)
236 struct symbol *r = sym->replace;
237 if (!r) {
238 warn(sym->pos, "symbol '%s' not replaced?", show_ident(sym->ident));
239 return;
241 r->replace = NULL;
242 sym->replace = NULL;
245 static void unset_replace_list(struct symbol_list *list)
247 struct symbol *sym;
248 FOR_EACH_PTR(list, sym) {
249 unset_replace(sym);
250 } END_FOR_EACH_PTR;
253 static struct statement *copy_one_statement(struct statement *stmt)
255 if (!stmt)
256 return NULL;
257 switch(stmt->type) {
258 case STMT_NONE:
259 break;
260 case STMT_EXPRESSION: {
261 struct expression *expr = copy_expression(stmt->expression);
262 if (expr == stmt->expression)
263 break;
264 stmt = dup_statement(stmt);
265 stmt->expression = expr;
266 break;
268 case STMT_COMPOUND: {
269 struct statement *new = alloc_statement(stmt->pos, STMT_COMPOUND);
270 copy_statement(stmt, new);
271 stmt = new;
272 break;
274 case STMT_IF: {
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)
285 break;
286 stmt = dup_statement(stmt);
287 stmt->if_conditional = cond;
288 stmt->if_true = true;
289 stmt->if_false = false;
290 break;
292 case STMT_RETURN: {
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;
299 break;
301 case STMT_CASE: {
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);
307 break;
309 case STMT_SWITCH: {
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;
319 break;
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);
334 break;
336 case STMT_LABEL: {
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);
340 break;
342 case STMT_GOTO: {
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);
347 break;
349 case STMT_ASM: {
350 /* FIXME! */
351 break;
353 default:
354 warn(stmt->pos, "trying to copy statement type %d", stmt->type);
355 break;
357 return stmt;
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
367 * re-entrant.
369 void copy_statement(struct statement *src, struct statement *dst)
371 struct statement *stmt;
372 struct symbol *sym;
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);
378 } END_FOR_EACH_PTR;
380 FOR_EACH_PTR(src->stmts, stmt) {
381 add_statement(&dst->stmts, copy_one_statement(stmt));
382 } END_FOR_EACH_PTR;
384 dst->ret = copy_symbol(src->pos, src->ret);
387 static struct symbol *create_copy_symbol(struct symbol *orig)
389 struct symbol *sym = orig;
390 if (orig) {
391 sym = alloc_symbol(orig->pos, orig->type);
392 *sym = *orig;
393 set_replace(orig, sym);
394 orig = sym;
396 return orig;
399 static struct symbol_list *create_symbol_list(struct symbol_list *src)
401 struct symbol_list *dst = NULL;
402 struct symbol *sym;
404 FOR_EACH_PTR(src, sym) {
405 struct symbol *newsym = create_copy_symbol(sym);
406 add_symbol(&dst, newsym);
407 } END_FOR_EACH_PTR;
408 return dst;
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;
418 struct symbol *name;
419 struct expression *arg;
421 if (!fn->inline_stmt) {
422 warn(fn->pos, "marked inline, but without a definition");
423 return 0;
425 if (fn->expanding)
426 return 0;
427 fn->expanding = 1;
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;
442 if (name) {
443 *a = *name;
444 set_replace(name, a);
445 add_symbol(&fn_symbol_list, a);
447 a->initializer = arg;
448 add_symbol(&stmt->syms, a);
450 NEXT_PTR_LIST(name);
451 } END_FOR_EACH_PTR;
452 FINISH_PTR_LIST(name);
454 copy_statement(fn->inline_stmt, stmt);
456 unset_replace_list(fn_symbol_list);
458 evaluate_statement(stmt);
460 fn->expanding = 0;
461 return 1;
464 void uninline(struct symbol *sym)
466 struct symbol *fn = sym->ctype.base_type;
467 struct symbol_list *arg_list = fn->arguments;
468 struct symbol *p;
470 sym->symbol_list = create_symbol_list(sym->inline_symbol_list);
471 FOR_EACH_PTR(arg_list, p) {
472 p->replace = p;
473 } END_FOR_EACH_PTR;
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);