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