Print this page
new smatch
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/inline.c
+++ new/usr/src/tools/smatch/src/inline.c
1 1 /*
2 2 * Sparse - a semantic source parser.
3 3 *
4 4 * Copyright (C) 2003 Transmeta Corp.
5 5 * 2003-2004 Linus Torvalds
6 6 *
7 7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 8 * of this software and associated documentation files (the "Software"), to deal
9 9 * in the Software without restriction, including without limitation the rights
10 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 11 * copies of the Software, and to permit persons to whom the Software is
12 12 * furnished to do so, subject to the following conditions:
13 13 *
14 14 * The above copyright notice and this permission notice shall be included in
15 15 * all copies or substantial portions of the Software.
16 16 *
17 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 23 * THE SOFTWARE.
24 24 */
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
25 25
26 26 #include <stdlib.h>
27 27 #include <stdio.h>
28 28
29 29 #include "lib.h"
30 30 #include "allocate.h"
31 31 #include "token.h"
32 32 #include "parse.h"
33 33 #include "symbol.h"
34 34 #include "expression.h"
35 +#include "evaluate.h"
35 36
37 +static void copy_statement(struct statement *src, struct statement *dst);
38 +
36 39 static struct expression * dup_expression(struct expression *expr)
37 40 {
38 41 struct expression *dup = alloc_expression(expr->pos, expr->type);
39 42 *dup = *expr;
40 43 return dup;
41 44 }
42 45
43 46 static struct statement * dup_statement(struct statement *stmt)
44 47 {
45 48 struct statement *dup = alloc_statement(stmt->pos, stmt->type);
46 49 *dup = *stmt;
47 50 return dup;
48 51 }
49 52
50 53 static struct symbol *copy_symbol(struct position pos, struct symbol *sym)
51 54 {
52 55 if (!sym)
53 56 return sym;
54 57 if (sym->ctype.modifiers & (MOD_STATIC | MOD_EXTERN | MOD_TOPLEVEL | MOD_INLINE))
55 58 return sym;
56 59 if (!sym->replace) {
57 60 warning(pos, "unreplaced symbol '%s'", show_ident(sym->ident));
58 61 return sym;
59 62 }
60 63 return sym->replace;
61 64 }
62 65
63 66 static struct symbol_list *copy_symbol_list(struct symbol_list *src)
64 67 {
65 68 struct symbol_list *dst = NULL;
66 69 struct symbol *sym;
67 70
68 71 FOR_EACH_PTR(src, sym) {
69 72 struct symbol *newsym = copy_symbol(sym->pos, sym);
70 73 add_symbol(&dst, newsym);
71 74 } END_FOR_EACH_PTR(sym);
72 75 return dst;
73 76 }
74 77
75 78 static struct expression * copy_expression(struct expression *expr)
76 79 {
77 80 if (!expr)
78 81 return NULL;
79 82
80 83 switch (expr->type) {
81 84 /*
82 85 * EXPR_SYMBOL is the interesting case, we may need to replace the
83 86 * symbol to the new copy.
84 87 */
85 88 case EXPR_SYMBOL: {
86 89 struct symbol *sym = copy_symbol(expr->pos, expr->symbol);
87 90 if (sym == expr->symbol)
88 91 break;
89 92 expr = dup_expression(expr);
90 93 expr->symbol = sym;
91 94 break;
92 95 }
93 96
94 97 /* Atomics, never change, just return the expression directly */
95 98 case EXPR_VALUE:
96 99 case EXPR_STRING:
97 100 case EXPR_FVALUE:
98 101 case EXPR_TYPE:
99 102 break;
100 103
101 104 /* Unops: check if the subexpression is unique */
102 105 case EXPR_PREOP:
103 106 case EXPR_POSTOP: {
104 107 struct expression *unop = copy_expression(expr->unop);
105 108 if (expr->unop == unop)
106 109 break;
107 110 expr = dup_expression(expr);
108 111 expr->unop = unop;
109 112 break;
110 113 }
111 114
112 115 case EXPR_SLICE: {
113 116 struct expression *base = copy_expression(expr->base);
114 117 expr = dup_expression(expr);
115 118 expr->base = base;
116 119 break;
117 120 }
118 121
119 122 /* Binops: copy left/right expressions */
120 123 case EXPR_BINOP:
121 124 case EXPR_COMMA:
122 125 case EXPR_COMPARE:
123 126 case EXPR_LOGICAL: {
124 127 struct expression *left = copy_expression(expr->left);
125 128 struct expression *right = copy_expression(expr->right);
126 129 if (left == expr->left && right == expr->right)
127 130 break;
128 131 expr = dup_expression(expr);
129 132 expr->left = left;
130 133 expr->right = right;
131 134 break;
132 135 }
133 136
134 137 case EXPR_ASSIGNMENT: {
135 138 struct expression *left = copy_expression(expr->left);
136 139 struct expression *right = copy_expression(expr->right);
137 140 if (expr->op == '=' && left == expr->left && right == expr->right)
138 141 break;
139 142 expr = dup_expression(expr);
140 143 expr->left = left;
141 144 expr->right = right;
142 145 break;
143 146 }
144 147
145 148 /* Dereference */
146 149 case EXPR_DEREF: {
147 150 struct expression *deref = copy_expression(expr->deref);
148 151 expr = dup_expression(expr);
149 152 expr->deref = deref;
150 153 break;
151 154 }
152 155
153 156 /* Cast/sizeof/__alignof__ */
154 157 case EXPR_CAST:
155 158 if (expr->cast_expression->type == EXPR_INITIALIZER) {
156 159 struct expression *cast = expr->cast_expression;
157 160 struct symbol *sym = expr->cast_type;
158 161 expr = dup_expression(expr);
159 162 expr->cast_expression = copy_expression(cast);
160 163 expr->cast_type = alloc_symbol(sym->pos, sym->type);
161 164 *expr->cast_type = *sym;
162 165 break;
163 166 }
164 167 case EXPR_FORCE_CAST:
165 168 case EXPR_IMPLIED_CAST:
166 169 case EXPR_SIZEOF:
167 170 case EXPR_PTRSIZEOF:
168 171 case EXPR_ALIGNOF: {
169 172 struct expression *cast = copy_expression(expr->cast_expression);
170 173 if (cast == expr->cast_expression)
↓ open down ↓ |
125 lines elided |
↑ open up ↑ |
171 174 break;
172 175 expr = dup_expression(expr);
173 176 expr->cast_expression = cast;
174 177 break;
175 178 }
176 179
177 180 /* Conditional expression */
178 181 case EXPR_SELECT:
179 182 case EXPR_CONDITIONAL: {
180 183 struct expression *cond = copy_expression(expr->conditional);
181 - struct expression *true = copy_expression(expr->cond_true);
182 - struct expression *false = copy_expression(expr->cond_false);
183 - if (cond == expr->conditional && true == expr->cond_true && false == expr->cond_false)
184 + struct expression *valt = copy_expression(expr->cond_true);
185 + struct expression *valf = copy_expression(expr->cond_false);
186 + if (cond == expr->conditional && valt == expr->cond_true && valf == expr->cond_false)
184 187 break;
185 188 expr = dup_expression(expr);
186 189 expr->conditional = cond;
187 - expr->cond_true = true;
188 - expr->cond_false = false;
190 + expr->cond_true = valt;
191 + expr->cond_false = valf;
189 192 break;
190 193 }
191 194
192 195 /* Statement expression */
193 196 case EXPR_STATEMENT: {
194 197 struct statement *stmt = alloc_statement(expr->pos, STMT_COMPOUND);
195 198 copy_statement(expr->statement, stmt);
196 199 expr = dup_expression(expr);
197 200 expr->statement = stmt;
198 201 break;
199 202 }
200 203
201 204 /* Call expression */
202 205 case EXPR_CALL: {
203 206 struct expression *fn = copy_expression(expr->fn);
204 207 struct expression_list *list = expr->args;
205 208 struct expression *arg;
206 209
207 210 expr = dup_expression(expr);
208 211 expr->fn = fn;
209 212 expr->args = NULL;
210 213 FOR_EACH_PTR(list, arg) {
211 214 add_expression(&expr->args, copy_expression(arg));
212 215 } END_FOR_EACH_PTR(arg);
213 216 break;
214 217 }
215 218
216 219 /* Initializer list statement */
217 220 case EXPR_INITIALIZER: {
218 221 struct expression_list *list = expr->expr_list;
219 222 struct expression *entry;
220 223 expr = dup_expression(expr);
221 224 expr->expr_list = NULL;
222 225 FOR_EACH_PTR(list, entry) {
223 226 add_expression(&expr->expr_list, copy_expression(entry));
224 227 } END_FOR_EACH_PTR(entry);
225 228 break;
226 229 }
227 230
228 231 /* Label in inline function - hmm. */
229 232 case EXPR_LABEL: {
230 233 struct symbol *label_symbol = copy_symbol(expr->pos, expr->label_symbol);
231 234 expr = dup_expression(expr);
232 235 expr->label_symbol = label_symbol;
233 236 break;
234 237 }
235 238
236 239 case EXPR_INDEX: {
237 240 struct expression *sub_expr = copy_expression(expr->idx_expression);
238 241 expr = dup_expression(expr);
239 242 expr->idx_expression = sub_expr;
240 243 break;
241 244 }
242 245
243 246 case EXPR_IDENTIFIER: {
244 247 struct expression *sub_expr = copy_expression(expr->ident_expression);
245 248 expr = dup_expression(expr);
246 249 expr->ident_expression = sub_expr;
247 250 break;
248 251 }
249 252
250 253 /* Position in initializer.. */
251 254 case EXPR_POS: {
252 255 struct expression *val = copy_expression(expr->init_expr);
253 256 expr = dup_expression(expr);
254 257 expr->init_expr = val;
255 258 break;
256 259 }
257 260 case EXPR_OFFSETOF: {
258 261 struct expression *val = copy_expression(expr->down);
259 262 if (expr->op == '.') {
260 263 if (expr->down != val) {
261 264 expr = dup_expression(expr);
262 265 expr->down = val;
263 266 }
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
264 267 } else {
265 268 struct expression *idx = copy_expression(expr->index);
266 269 if (expr->down != val || expr->index != idx) {
267 270 expr = dup_expression(expr);
268 271 expr->down = val;
269 272 expr->index = idx;
270 273 }
271 274 }
272 275 break;
273 276 }
277 + case EXPR_ASM_OPERAND: {
278 + expr = dup_expression(expr);
279 + expr->constraint = copy_expression(expr->constraint);
280 + expr->expr = copy_expression(expr->expr);
281 + break;
282 + }
274 283 default:
275 284 warning(expr->pos, "trying to copy expression type %d", expr->type);
276 285 }
277 286 return expr;
278 287 }
279 288
280 289 static struct expression_list *copy_asm_constraints(struct expression_list *in)
281 290 {
282 291 struct expression_list *out = NULL;
283 292 struct expression *expr;
284 - int state = 0;
285 293
286 294 FOR_EACH_PTR(in, expr) {
287 - switch (state) {
288 - case 0: /* identifier */
289 - case 1: /* constraint */
290 - state++;
291 - add_expression(&out, expr);
292 - continue;
293 - case 2: /* expression */
294 - state = 0;
295 - add_expression(&out, copy_expression(expr));
296 - continue;
297 - }
295 + add_expression(&out, copy_expression(expr));
298 296 } END_FOR_EACH_PTR(expr);
299 297 return out;
300 298 }
301 299
302 300 static void set_replace(struct symbol *old, struct symbol *new)
303 301 {
304 302 new->replace = old;
305 303 old->replace = new;
306 304 }
307 305
308 306 static void unset_replace(struct symbol *sym)
309 307 {
310 308 struct symbol *r = sym->replace;
311 309 if (!r) {
312 310 warning(sym->pos, "symbol '%s' not replaced?", show_ident(sym->ident));
313 311 return;
314 312 }
315 313 r->replace = NULL;
316 314 sym->replace = NULL;
317 315 }
318 316
319 317 static void unset_replace_list(struct symbol_list *list)
320 318 {
321 319 struct symbol *sym;
322 320 FOR_EACH_PTR(list, sym) {
323 321 unset_replace(sym);
324 322 } END_FOR_EACH_PTR(sym);
325 323 }
326 324
327 325 static struct statement *copy_one_statement(struct statement *stmt)
328 326 {
329 327 if (!stmt)
330 328 return NULL;
331 329 switch(stmt->type) {
332 330 case STMT_NONE:
333 331 break;
334 332 case STMT_DECLARATION: {
335 333 struct symbol *sym;
336 334 struct statement *newstmt = dup_statement(stmt);
337 335 newstmt->declaration = NULL;
338 336 FOR_EACH_PTR(stmt->declaration, sym) {
339 337 struct symbol *newsym = copy_symbol(stmt->pos, sym);
340 338 if (newsym != sym)
341 339 newsym->initializer = copy_expression(sym->initializer);
342 340 add_symbol(&newstmt->declaration, newsym);
343 341 } END_FOR_EACH_PTR(sym);
344 342 stmt = newstmt;
345 343 break;
346 344 }
347 345 case STMT_CONTEXT:
348 346 case STMT_EXPRESSION: {
349 347 struct expression *expr = copy_expression(stmt->expression);
350 348 if (expr == stmt->expression)
351 349 break;
352 350 stmt = dup_statement(stmt);
353 351 stmt->expression = expr;
354 352 break;
355 353 }
356 354 case STMT_RANGE: {
357 355 struct expression *expr = copy_expression(stmt->range_expression);
358 356 if (expr == stmt->expression)
359 357 break;
360 358 stmt = dup_statement(stmt);
361 359 stmt->range_expression = expr;
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
362 360 break;
363 361 }
364 362 case STMT_COMPOUND: {
365 363 struct statement *new = alloc_statement(stmt->pos, STMT_COMPOUND);
366 364 copy_statement(stmt, new);
367 365 stmt = new;
368 366 break;
369 367 }
370 368 case STMT_IF: {
371 369 struct expression *cond = stmt->if_conditional;
372 - struct statement *true = stmt->if_true;
373 - struct statement *false = stmt->if_false;
370 + struct statement *valt = stmt->if_true;
371 + struct statement *valf = stmt->if_false;
374 372
375 373 cond = copy_expression(cond);
376 - true = copy_one_statement(true);
377 - false = copy_one_statement(false);
374 + valt = copy_one_statement(valt);
375 + valf = copy_one_statement(valf);
378 376 if (stmt->if_conditional == cond &&
379 - stmt->if_true == true &&
380 - stmt->if_false == false)
377 + stmt->if_true == valt &&
378 + stmt->if_false == valf)
381 379 break;
382 380 stmt = dup_statement(stmt);
383 381 stmt->if_conditional = cond;
384 - stmt->if_true = true;
385 - stmt->if_false = false;
382 + stmt->if_true = valt;
383 + stmt->if_false = valf;
386 384 break;
387 385 }
388 386 case STMT_RETURN: {
389 387 struct expression *retval = copy_expression(stmt->ret_value);
390 388 struct symbol *sym = copy_symbol(stmt->pos, stmt->ret_target);
391 389
392 390 stmt = dup_statement(stmt);
393 391 stmt->ret_value = retval;
394 392 stmt->ret_target = sym;
395 393 break;
396 394 }
397 395 case STMT_CASE: {
398 396 stmt = dup_statement(stmt);
399 397 stmt->case_label = copy_symbol(stmt->pos, stmt->case_label);
400 398 stmt->case_label->stmt = stmt;
401 399 stmt->case_expression = copy_expression(stmt->case_expression);
402 400 stmt->case_to = copy_expression(stmt->case_to);
403 401 stmt->case_statement = copy_one_statement(stmt->case_statement);
404 402 break;
405 403 }
406 404 case STMT_SWITCH: {
407 405 struct symbol *switch_break = copy_symbol(stmt->pos, stmt->switch_break);
408 406 struct symbol *switch_case = copy_symbol(stmt->pos, stmt->switch_case);
409 407 struct expression *expr = copy_expression(stmt->switch_expression);
410 408 struct statement *switch_stmt = copy_one_statement(stmt->switch_statement);
411 409
412 410 stmt = dup_statement(stmt);
413 411 switch_case->symbol_list = copy_symbol_list(switch_case->symbol_list);
414 412 stmt->switch_break = switch_break;
415 413 stmt->switch_case = switch_case;
416 414 stmt->switch_expression = expr;
417 415 stmt->switch_statement = switch_stmt;
418 416 break;
419 417 }
420 418 case STMT_ITERATOR: {
421 419 stmt = dup_statement(stmt);
422 420 stmt->iterator_break = copy_symbol(stmt->pos, stmt->iterator_break);
423 421 stmt->iterator_continue = copy_symbol(stmt->pos, stmt->iterator_continue);
424 422 stmt->iterator_syms = copy_symbol_list(stmt->iterator_syms);
425 423
426 424 stmt->iterator_pre_statement = copy_one_statement(stmt->iterator_pre_statement);
427 425 stmt->iterator_pre_condition = copy_expression(stmt->iterator_pre_condition);
428 426
429 427 stmt->iterator_statement = copy_one_statement(stmt->iterator_statement);
430 428
431 429 stmt->iterator_post_statement = copy_one_statement(stmt->iterator_post_statement);
432 430 stmt->iterator_post_condition = copy_expression(stmt->iterator_post_condition);
433 431 break;
434 432 }
435 433 case STMT_LABEL: {
436 434 stmt = dup_statement(stmt);
437 435 stmt->label_identifier = copy_symbol(stmt->pos, stmt->label_identifier);
438 436 stmt->label_statement = copy_one_statement(stmt->label_statement);
439 437 break;
440 438 }
441 439 case STMT_GOTO: {
442 440 stmt = dup_statement(stmt);
443 441 stmt->goto_label = copy_symbol(stmt->pos, stmt->goto_label);
444 442 stmt->goto_expression = copy_expression(stmt->goto_expression);
445 443 stmt->target_list = copy_symbol_list(stmt->target_list);
446 444 break;
447 445 }
448 446 case STMT_ASM: {
449 447 stmt = dup_statement(stmt);
450 448 stmt->asm_inputs = copy_asm_constraints(stmt->asm_inputs);
451 449 stmt->asm_outputs = copy_asm_constraints(stmt->asm_outputs);
452 450 /* no need to dup "clobbers", since they are all constant strings */
453 451 break;
454 452 }
455 453 default:
456 454 warning(stmt->pos, "trying to copy statement type %d", stmt->type);
457 455 break;
458 456 }
459 457 return stmt;
460 458 }
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
461 459
462 460 /*
463 461 * Copy a statement tree from 'src' to 'dst', where both
464 462 * source and destination are of type STMT_COMPOUND.
465 463 *
466 464 * We do this for the tree-level inliner.
467 465 *
468 466 * This doesn't do the symbol replacement right: it's not
469 467 * re-entrant.
470 468 */
471 -void copy_statement(struct statement *src, struct statement *dst)
469 +static void copy_statement(struct statement *src, struct statement *dst)
472 470 {
473 471 struct statement *stmt;
474 472
475 473 FOR_EACH_PTR(src->stmts, stmt) {
476 474 add_statement(&dst->stmts, copy_one_statement(stmt));
477 475 } END_FOR_EACH_PTR(stmt);
478 476 dst->args = copy_one_statement(src->args);
479 477 dst->ret = copy_symbol(src->pos, src->ret);
480 478 dst->inline_fn = src->inline_fn;
481 479 }
482 480
483 481 static struct symbol *create_copy_symbol(struct symbol *orig)
484 482 {
485 483 struct symbol *sym = orig;
486 484 if (orig) {
487 485 sym = alloc_symbol(orig->pos, orig->type);
488 486 *sym = *orig;
489 487 sym->bb_target = NULL;
490 488 sym->pseudo = NULL;
491 489 set_replace(orig, sym);
492 490 orig = sym;
493 491 }
494 492 return orig;
495 493 }
496 494
497 495 static struct symbol_list *create_symbol_list(struct symbol_list *src)
498 496 {
499 497 struct symbol_list *dst = NULL;
500 498 struct symbol *sym;
501 499
502 500 FOR_EACH_PTR(src, sym) {
503 501 struct symbol *newsym = create_copy_symbol(sym);
504 502 add_symbol(&dst, newsym);
505 503 } END_FOR_EACH_PTR(sym);
506 504 return dst;
507 505 }
508 506
509 507 int inline_function(struct expression *expr, struct symbol *sym)
510 508 {
511 509 struct symbol_list * fn_symbol_list;
512 510 struct symbol *fn = sym->ctype.base_type;
513 511 struct expression_list *arg_list = expr->args;
514 512 struct statement *stmt = alloc_statement(expr->pos, STMT_COMPOUND);
515 513 struct symbol_list *name_list, *arg_decl;
516 514 struct symbol *name;
517 515 struct expression *arg;
518 516
519 517 if (!fn->inline_stmt) {
520 518 sparse_error(fn->pos, "marked inline, but without a definition");
521 519 return 0;
522 520 }
523 521 if (fn->expanding)
524 522 return 0;
525 523
526 524 fn->expanding = 1;
527 525
528 526 name_list = fn->arguments;
529 527
530 528 expr->type = EXPR_STATEMENT;
531 529 expr->statement = stmt;
532 530 expr->ctype = fn->ctype.base_type;
533 531
534 532 fn_symbol_list = create_symbol_list(sym->inline_symbol_list);
535 533
536 534 arg_decl = NULL;
537 535 PREPARE_PTR_LIST(name_list, name);
538 536 FOR_EACH_PTR(arg_list, arg) {
539 537 struct symbol *a = alloc_symbol(arg->pos, SYM_NODE);
540 538
541 539 a->ctype.base_type = arg->ctype;
542 540 if (name) {
543 541 *a = *name;
544 542 set_replace(name, a);
545 543 add_symbol(&fn_symbol_list, a);
546 544 }
547 545 a->initializer = arg;
548 546 add_symbol(&arg_decl, a);
549 547
550 548 NEXT_PTR_LIST(name);
551 549 } END_FOR_EACH_PTR(arg);
552 550 FINISH_PTR_LIST(name);
553 551
554 552 copy_statement(fn->inline_stmt, stmt);
555 553
556 554 if (arg_decl) {
557 555 struct statement *decl = alloc_statement(expr->pos, STMT_DECLARATION);
558 556 decl->declaration = arg_decl;
559 557 stmt->args = decl;
560 558 }
561 559 stmt->inline_fn = sym;
562 560
563 561 unset_replace_list(fn_symbol_list);
564 562
565 563 evaluate_statement(stmt);
566 564
567 565 fn->expanding = 0;
568 566 return 1;
569 567 }
570 568
571 569 void uninline(struct symbol *sym)
572 570 {
573 571 struct symbol *fn = sym->ctype.base_type;
574 572 struct symbol_list *arg_list = fn->arguments;
575 573 struct symbol *p;
576 574
577 575 sym->symbol_list = create_symbol_list(sym->inline_symbol_list);
578 576 FOR_EACH_PTR(arg_list, p) {
579 577 p->replace = p;
580 578 } END_FOR_EACH_PTR(p);
581 579 fn->stmt = alloc_statement(fn->pos, STMT_COMPOUND);
582 580 copy_statement(fn->inline_stmt, fn->stmt);
583 581 unset_replace_list(sym->symbol_list);
584 582 unset_replace_list(arg_list);
585 583 }
↓ open down ↓ |
104 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX