Fix pointer addition
[smatch.git] / inline.c
blob21788528e36b4225a14e46ea960f62d54854c7a3
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 break;
82 /* Unops: check if the subexpression is unique */
83 case EXPR_PREOP:
84 case EXPR_POSTOP: {
85 struct expression *unop = copy_expression(expr->unop);
86 if (expr->unop == unop)
87 break;
88 expr = dup_expression(expr);
89 expr->unop = unop;
90 break;
93 /* Binops: copy left/right expressions */
94 case EXPR_BINOP:
95 case EXPR_COMMA:
96 case EXPR_COMPARE:
97 case EXPR_LOGICAL:
98 case EXPR_ASSIGNMENT: {
99 struct expression *left = copy_expression(expr->left);
100 struct expression *right = copy_expression(expr->right);
101 if (left == expr->left && right == expr->right)
102 break;
103 expr = dup_expression(expr);
104 expr->left = left;
105 expr->right = right;
106 break;
109 /* Dereference */
110 case EXPR_DEREF: {
111 struct expression *deref = copy_expression(expr->deref);
112 if (deref == expr->deref)
113 break;
114 expr = dup_expression(expr);
115 expr->deref = deref;
116 break;
119 /* Cast/sizeof */
120 case EXPR_CAST:
121 case EXPR_SIZEOF: {
122 struct expression *cast = copy_expression(expr->cast_expression);
123 if (cast == expr->cast_expression)
124 break;
125 expr = dup_expression(expr);
126 expr->cast_expression = cast;
127 break;
130 /* Conditional expression */
131 case EXPR_CONDITIONAL: {
132 struct expression *cond = copy_expression(expr->conditional);
133 struct expression *true = copy_expression(expr->cond_true);
134 struct expression *false = copy_expression(expr->cond_false);
135 if (cond == expr->conditional && true == expr->cond_true && false == expr->cond_false)
136 break;
137 expr = dup_expression(expr);
138 expr->conditional = cond;
139 expr->cond_true = true;
140 expr->cond_false = false;
141 break;
144 /* Statement expression */
145 case EXPR_STATEMENT: {
146 struct statement *stmt = alloc_statement(expr->pos, STMT_COMPOUND);
147 copy_statement(expr->statement, stmt);
148 expr = dup_expression(expr);
149 expr->statement = stmt;
150 break;
153 /* Call expression */
154 case EXPR_CALL: {
155 struct expression *fn = copy_expression(expr->fn);
156 struct expression_list *list = expr->args;
157 struct expression *arg;
159 expr = dup_expression(expr);
160 expr->fn = fn;
161 expr->args = NULL;
162 FOR_EACH_PTR(list, arg) {
163 add_expression(&expr->args, copy_expression(arg));
164 } END_FOR_EACH_PTR;
165 break;
168 /* Initializer list statement */
169 case EXPR_INITIALIZER: {
170 struct expression_list *list = expr->expr_list;
171 struct expression *entry;
172 expr = dup_expression(expr);
173 expr->expr_list = NULL;
174 FOR_EACH_PTR(list, entry) {
175 add_expression(&expr->expr_list, copy_expression(entry));
176 } END_FOR_EACH_PTR;
177 break;
180 default:
181 if (verbose)
182 warn(expr->pos, "trying to copy expression type %d", expr->type);
184 return expr;
187 void set_replace(struct symbol *old, struct symbol *new)
189 new->replace = old;
190 old->replace = new;
193 void unset_replace(struct symbol *sym)
195 struct symbol *r = sym->replace;
196 if (!r) {
197 warn(sym->pos, "symbol '%s' not replaced?", show_ident(sym->ident));
198 return;
200 r->replace = NULL;
201 sym->replace = NULL;
204 static void unset_replace_list(struct symbol_list *list)
206 struct symbol *sym;
207 FOR_EACH_PTR(list, sym) {
208 unset_replace(sym);
209 } END_FOR_EACH_PTR;
212 static struct statement *copy_one_statement(struct statement *stmt)
214 if (!stmt)
215 return NULL;
216 switch(stmt->type) {
217 case STMT_NONE:
218 break;
219 case STMT_EXPRESSION: {
220 struct expression *expr = copy_expression(stmt->expression);
221 if (expr == stmt->expression)
222 break;
223 stmt = dup_statement(stmt);
224 stmt->expression = expr;
225 break;
227 case STMT_COMPOUND: {
228 struct statement *new = alloc_statement(stmt->pos, STMT_COMPOUND);
229 copy_statement(stmt, new);
230 stmt = new;
231 break;
233 case STMT_IF: {
234 struct expression *cond = stmt->if_conditional;
235 struct statement *true = stmt->if_true;
236 struct statement *false = stmt->if_false;
238 cond = copy_expression(cond);
239 true = copy_one_statement(true);
240 false = copy_one_statement(false);
241 if (stmt->if_conditional == cond &&
242 stmt->if_true == true &&
243 stmt->if_false == false)
244 break;
245 stmt = dup_statement(stmt);
246 stmt->if_conditional = cond;
247 stmt->if_true = true;
248 stmt->if_false = false;
249 break;
251 case STMT_RETURN: {
252 struct expression *retval = copy_expression(stmt->ret_value);
253 struct symbol *sym = copy_symbol(stmt->pos, stmt->ret_target);
255 stmt = dup_statement(stmt);
256 stmt->ret_value = retval;
257 stmt->ret_target = sym;
258 break;
260 case STMT_CASE: {
261 stmt = dup_statement(stmt);
262 stmt->case_label = copy_symbol(stmt->pos, stmt->case_label);
263 stmt->case_expression = copy_expression(stmt->case_expression);
264 stmt->case_to = copy_expression(stmt->case_to);
265 stmt->case_statement = copy_one_statement(stmt->case_statement);
266 break;
268 case STMT_SWITCH: {
269 struct symbol *switch_break = copy_symbol(stmt->pos, stmt->switch_break);
270 struct symbol *switch_case = copy_symbol(stmt->pos, stmt->switch_case);
271 struct expression *expr = copy_expression(stmt->switch_expression);
272 struct statement *switch_stmt = copy_one_statement(stmt->switch_statement);
273 stmt = dup_statement(stmt);
274 stmt->switch_break = switch_break;
275 stmt->switch_case = switch_case;
276 stmt->switch_expression = expr;
277 stmt->switch_statement = switch_stmt;
278 break;
280 case STMT_ITERATOR: {
281 stmt = dup_statement(stmt);
282 stmt->iterator_break = copy_symbol(stmt->pos, stmt->iterator_break);
283 stmt->iterator_continue = copy_symbol(stmt->pos, stmt->iterator_continue);
284 stmt->iterator_syms = copy_symbol_list(stmt->iterator_syms);
286 stmt->iterator_pre_statement = copy_one_statement(stmt->iterator_pre_statement);
287 stmt->iterator_pre_condition = copy_expression(stmt->iterator_pre_condition);
289 stmt->iterator_statement = copy_one_statement(stmt->iterator_statement);
291 stmt->iterator_post_statement = copy_one_statement(stmt->iterator_post_statement);
292 stmt->iterator_post_condition = copy_expression(stmt->iterator_post_condition);
293 break;
295 case STMT_LABEL: {
296 stmt = dup_statement(stmt);
297 stmt->label_identifier = copy_symbol(stmt->pos, stmt->label_identifier);
298 stmt->label_statement = copy_one_statement(stmt->label_statement);
299 break;
301 case STMT_GOTO: {
302 /* FIXME! */
303 break;
305 case STMT_ASM: {
306 /* FIXME! */
307 break;
309 default:
310 if (verbose)
311 warn(stmt->pos, "trying to copy statement type %d", stmt->type);
312 break;
314 return stmt;
318 * Copy a stateemnt tree from 'src' to 'dst', where both
319 * source and destination are of type STMT_COMPOUND.
321 * We do this for the tree-level inliner.
323 * This doesn't do the symbol replacement right: it's not
324 * re-entrant.
326 void copy_statement(struct statement *src, struct statement *dst)
328 struct statement *stmt;
329 struct symbol *sym;
331 FOR_EACH_PTR(src->syms, sym) {
332 struct symbol *newsym = copy_symbol(src->pos, sym);
333 newsym->initializer = copy_expression(sym->initializer);
334 add_symbol(&dst->syms, newsym);
335 } END_FOR_EACH_PTR;
337 FOR_EACH_PTR(src->stmts, stmt) {
338 add_statement(&dst->stmts, copy_one_statement(stmt));
339 } END_FOR_EACH_PTR;
341 dst->ret = copy_symbol(src->pos, src->ret);
344 static struct symbol *create_copy_symbol(struct symbol *orig)
346 struct symbol *sym = orig;
347 if (orig) {
348 sym = alloc_symbol(orig->pos, orig->type);
349 sym->ctype = orig->ctype;
350 sym->initializer = NULL;
351 set_replace(orig, sym);
353 return orig;
356 static struct symbol_list *create_symbol_list(struct symbol_list *src)
358 struct symbol_list *dst = NULL;
359 struct symbol *sym;
361 FOR_EACH_PTR(src, sym) {
362 struct symbol *newsym = create_copy_symbol(sym);
363 add_symbol(&dst, newsym);
364 } END_FOR_EACH_PTR;
365 return dst;
368 int inline_function(struct expression *expr, struct symbol *sym)
370 struct symbol_list * fn_symbol_list;
371 struct symbol *fn = sym->ctype.base_type;
372 struct expression_list *arg_list = expr->args;
373 struct statement *stmt = alloc_statement(expr->pos, STMT_COMPOUND);
374 struct symbol_list *name_list;
375 struct symbol *name;
376 struct expression *arg;
378 if (!fn->stmt) {
379 warn(fn->pos, "marked inline, but without a definition");
380 return 0;
382 name_list = fn->arguments;
384 stmt = alloc_statement(expr->pos, STMT_COMPOUND);
386 expr->type = EXPR_STATEMENT;
387 expr->statement = stmt;
388 expr->ctype = fn->ctype.base_type;
390 fn_symbol_list = create_symbol_list(sym->symbol_list);
392 PREPARE_PTR_LIST(name_list, name);
393 FOR_EACH_PTR(arg_list, arg) {
394 struct symbol *a = alloc_symbol(arg->pos, SYM_NODE);
396 a->ctype.base_type = arg->ctype;
397 if (name) {
398 a->ident = name->ident;
399 a->ctype = name->ctype;
400 set_replace(name, a);
401 add_symbol(&fn_symbol_list, a);
403 a->initializer = arg;
404 add_symbol(&stmt->syms, a);
406 NEXT_PTR_LIST(name);
407 } END_FOR_EACH_PTR;
408 FINISH_PTR_LIST(name);
410 copy_statement(fn->stmt, stmt);
412 unset_replace_list(fn_symbol_list);
414 evaluate_statement(stmt);
416 return 1;