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