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 
  37 static void copy_statement(struct statement *src, struct statement *dst);
  38 
  39 static 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 
  46 static 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 
  53 static 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 
  66 static 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 
  78 static 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_ASM_OPERAND: {
 278                 expr = dup_expression(expr);
 279                 expr->constraint = copy_expression(expr->constraint);
 280                 expr->expr = copy_expression(expr->expr);
 281                 break;
 282         }
 283         default:
 284                 warning(expr->pos, "trying to copy expression type %d", expr->type);
 285         }
 286         return expr;
 287 }
 288 
 289 static struct expression_list *copy_asm_constraints(struct expression_list *in)
 290 {
 291         struct expression_list *out = NULL;
 292         struct expression *expr;
 293 
 294         FOR_EACH_PTR(in, expr) {
 295                 add_expression(&out, copy_expression(expr));
 296         } END_FOR_EACH_PTR(expr);
 297         return out;
 298 }
 299 
 300 static void set_replace(struct symbol *old, struct symbol *new)
 301 {
 302         new->replace = old;
 303         old->replace = new;
 304 }
 305 
 306 static void unset_replace(struct symbol *sym)
 307 {
 308         struct symbol *r = sym->replace;
 309         if (!r) {
 310                 warning(sym->pos, "symbol '%s' not replaced?", show_ident(sym->ident));
 311                 return;
 312         }
 313         r->replace = NULL;
 314         sym->replace = NULL;
 315 }
 316 
 317 static void unset_replace_list(struct symbol_list *list)
 318 {
 319         struct symbol *sym;
 320         FOR_EACH_PTR(list, sym) {
 321                 unset_replace(sym);
 322         } END_FOR_EACH_PTR(sym);
 323 }
 324 
 325 static struct statement *copy_one_statement(struct statement *stmt)
 326 {
 327         if (!stmt)
 328                 return NULL;
 329         switch(stmt->type) {
 330         case STMT_NONE:
 331                 break;
 332         case STMT_DECLARATION: {
 333                 struct symbol *sym;
 334                 struct statement *newstmt = dup_statement(stmt);
 335                 newstmt->declaration = NULL;
 336                 FOR_EACH_PTR(stmt->declaration, sym) {
 337                         struct symbol *newsym = copy_symbol(stmt->pos, sym);
 338                         if (newsym != sym)
 339                                 newsym->initializer = copy_expression(sym->initializer);
 340                         add_symbol(&newstmt->declaration, newsym);
 341                 } END_FOR_EACH_PTR(sym);
 342                 stmt = newstmt;
 343                 break;
 344         }
 345         case STMT_CONTEXT:
 346         case STMT_EXPRESSION: {
 347                 struct expression *expr = copy_expression(stmt->expression);
 348                 if (expr == stmt->expression)
 349                         break;
 350                 stmt = dup_statement(stmt);
 351                 stmt->expression = expr;
 352                 break;
 353         }
 354         case STMT_RANGE: {
 355                 struct expression *expr = copy_expression(stmt->range_expression);
 356                 if (expr == stmt->expression)
 357                         break;
 358                 stmt = dup_statement(stmt);
 359                 stmt->range_expression = expr;
 360                 break;
 361         }
 362         case STMT_COMPOUND: {
 363                 struct statement *new = alloc_statement(stmt->pos, STMT_COMPOUND);
 364                 copy_statement(stmt, new);
 365                 stmt = new;
 366                 break;
 367         }
 368         case STMT_IF: {
 369                 struct expression *cond = stmt->if_conditional;
 370                 struct statement *valt = stmt->if_true;
 371                 struct statement *valf = stmt->if_false;
 372 
 373                 cond = copy_expression(cond);
 374                 valt = copy_one_statement(valt);
 375                 valf = copy_one_statement(valf);
 376                 if (stmt->if_conditional == cond &&
 377                     stmt->if_true == valt &&
 378                     stmt->if_false == valf)
 379                         break;
 380                 stmt = dup_statement(stmt);
 381                 stmt->if_conditional = cond;
 382                 stmt->if_true = valt;
 383                 stmt->if_false = valf;
 384                 break;
 385         }
 386         case STMT_RETURN: {
 387                 struct expression *retval = copy_expression(stmt->ret_value);
 388                 struct symbol *sym = copy_symbol(stmt->pos, stmt->ret_target);
 389 
 390                 stmt = dup_statement(stmt);
 391                 stmt->ret_value = retval;
 392                 stmt->ret_target = sym;
 393                 break;
 394         }
 395         case STMT_CASE: {
 396                 stmt = dup_statement(stmt);
 397                 stmt->case_label = copy_symbol(stmt->pos, stmt->case_label);
 398                 stmt->case_label->stmt = stmt;
 399                 stmt->case_expression = copy_expression(stmt->case_expression);
 400                 stmt->case_to = copy_expression(stmt->case_to);
 401                 stmt->case_statement = copy_one_statement(stmt->case_statement);
 402                 break;
 403         }
 404         case STMT_SWITCH: {
 405                 struct symbol *switch_break = copy_symbol(stmt->pos, stmt->switch_break);
 406                 struct symbol *switch_case = copy_symbol(stmt->pos, stmt->switch_case);
 407                 struct expression *expr = copy_expression(stmt->switch_expression);
 408                 struct statement *switch_stmt = copy_one_statement(stmt->switch_statement);
 409 
 410                 stmt = dup_statement(stmt);
 411                 switch_case->symbol_list = copy_symbol_list(switch_case->symbol_list);
 412                 stmt->switch_break = switch_break;
 413                 stmt->switch_case = switch_case;
 414                 stmt->switch_expression = expr;
 415                 stmt->switch_statement = switch_stmt;
 416                 break;          
 417         }
 418         case STMT_ITERATOR: {
 419                 stmt = dup_statement(stmt);
 420                 stmt->iterator_break = copy_symbol(stmt->pos, stmt->iterator_break);
 421                 stmt->iterator_continue = copy_symbol(stmt->pos, stmt->iterator_continue);
 422                 stmt->iterator_syms = copy_symbol_list(stmt->iterator_syms);
 423 
 424                 stmt->iterator_pre_statement = copy_one_statement(stmt->iterator_pre_statement);
 425                 stmt->iterator_pre_condition = copy_expression(stmt->iterator_pre_condition);
 426 
 427                 stmt->iterator_statement = copy_one_statement(stmt->iterator_statement);
 428 
 429                 stmt->iterator_post_statement = copy_one_statement(stmt->iterator_post_statement);
 430                 stmt->iterator_post_condition = copy_expression(stmt->iterator_post_condition);
 431                 break;
 432         }
 433         case STMT_LABEL: {
 434                 stmt = dup_statement(stmt);
 435                 stmt->label_identifier = copy_symbol(stmt->pos, stmt->label_identifier);
 436                 stmt->label_statement = copy_one_statement(stmt->label_statement);
 437                 break;
 438         }
 439         case STMT_GOTO: {
 440                 stmt = dup_statement(stmt);
 441                 stmt->goto_label = copy_symbol(stmt->pos, stmt->goto_label);
 442                 stmt->goto_expression = copy_expression(stmt->goto_expression);
 443                 stmt->target_list = copy_symbol_list(stmt->target_list);
 444                 break;
 445         }
 446         case STMT_ASM: {
 447                 stmt = dup_statement(stmt);
 448                 stmt->asm_inputs = copy_asm_constraints(stmt->asm_inputs);
 449                 stmt->asm_outputs = copy_asm_constraints(stmt->asm_outputs);
 450                 /* no need to dup "clobbers", since they are all constant strings */
 451                 break;
 452         }
 453         default:
 454                 warning(stmt->pos, "trying to copy statement type %d", stmt->type);
 455                 break;
 456         }
 457         return stmt;
 458 }
 459 
 460 /*
 461  * Copy a statement tree from 'src' to 'dst', where both
 462  * source and destination are of type STMT_COMPOUND.
 463  *
 464  * We do this for the tree-level inliner.
 465  *
 466  * This doesn't do the symbol replacement right: it's not
 467  * re-entrant.
 468  */
 469 static void copy_statement(struct statement *src, struct statement *dst)
 470 {
 471         struct statement *stmt;
 472 
 473         FOR_EACH_PTR(src->stmts, stmt) {
 474                 add_statement(&dst->stmts, copy_one_statement(stmt));
 475         } END_FOR_EACH_PTR(stmt);
 476         dst->args = copy_one_statement(src->args);
 477         dst->ret = copy_symbol(src->pos, src->ret);
 478         dst->inline_fn = src->inline_fn;
 479 }
 480 
 481 static struct symbol *create_copy_symbol(struct symbol *orig)
 482 {
 483         struct symbol *sym = orig;
 484         if (orig) {
 485                 sym = alloc_symbol(orig->pos, orig->type);
 486                 *sym = *orig;
 487                 sym->bb_target = NULL;
 488                 sym->pseudo = NULL;
 489                 set_replace(orig, sym);
 490                 orig = sym;
 491         }
 492         return orig;
 493 }
 494 
 495 static struct symbol_list *create_symbol_list(struct symbol_list *src)
 496 {
 497         struct symbol_list *dst = NULL;
 498         struct symbol *sym;
 499 
 500         FOR_EACH_PTR(src, sym) {
 501                 struct symbol *newsym = create_copy_symbol(sym);
 502                 add_symbol(&dst, newsym);
 503         } END_FOR_EACH_PTR(sym);
 504         return dst;
 505 }
 506 
 507 int inline_function(struct expression *expr, struct symbol *sym)
 508 {
 509         struct symbol_list * fn_symbol_list;
 510         struct symbol *fn = sym->ctype.base_type;
 511         struct expression_list *arg_list = expr->args;
 512         struct statement *stmt = alloc_statement(expr->pos, STMT_COMPOUND);
 513         struct symbol_list *name_list, *arg_decl;
 514         struct symbol *name;
 515         struct expression *arg;
 516 
 517         if (!fn->inline_stmt) {
 518                 sparse_error(fn->pos, "marked inline, but without a definition");
 519                 return 0;
 520         }
 521         if (fn->expanding)
 522                 return 0;
 523 
 524         fn->expanding = 1;
 525 
 526         name_list = fn->arguments;
 527 
 528         expr->type = EXPR_STATEMENT;
 529         expr->statement = stmt;
 530         expr->ctype = fn->ctype.base_type;
 531 
 532         fn_symbol_list = create_symbol_list(sym->inline_symbol_list);
 533 
 534         arg_decl = NULL;
 535         PREPARE_PTR_LIST(name_list, name);
 536         FOR_EACH_PTR(arg_list, arg) {
 537                 struct symbol *a = alloc_symbol(arg->pos, SYM_NODE);
 538 
 539                 a->ctype.base_type = arg->ctype;
 540                 if (name) {
 541                         *a = *name;
 542                         set_replace(name, a);
 543                         add_symbol(&fn_symbol_list, a);
 544                 }
 545                 a->initializer = arg;
 546                 add_symbol(&arg_decl, a);
 547 
 548                 NEXT_PTR_LIST(name);
 549         } END_FOR_EACH_PTR(arg);
 550         FINISH_PTR_LIST(name);
 551 
 552         copy_statement(fn->inline_stmt, stmt);
 553 
 554         if (arg_decl) {
 555                 struct statement *decl = alloc_statement(expr->pos, STMT_DECLARATION);
 556                 decl->declaration = arg_decl;
 557                 stmt->args = decl;
 558         }
 559         stmt->inline_fn = sym;
 560 
 561         unset_replace_list(fn_symbol_list);
 562 
 563         evaluate_statement(stmt);
 564 
 565         fn->expanding = 0;
 566         return 1;
 567 }
 568 
 569 void uninline(struct symbol *sym)
 570 {
 571         struct symbol *fn = sym->ctype.base_type;
 572         struct symbol_list *arg_list = fn->arguments;
 573         struct symbol *p;
 574 
 575         sym->symbol_list = create_symbol_list(sym->inline_symbol_list);
 576         FOR_EACH_PTR(arg_list, p) {
 577                 p->replace = p;
 578         } END_FOR_EACH_PTR(p);
 579         fn->stmt = alloc_statement(fn->pos, STMT_COMPOUND);
 580         copy_statement(fn->inline_stmt, fn->stmt);
 581         unset_replace_list(sym->symbol_list);
 582         unset_replace_list(arg_list);
 583 }