|
|
1.1 ! root 1: /*ident "@(#)ctrans:src/expand.c 1.3.4.20" */ ! 2: /***************************************************************** ! 3: ! 4: C++ source for cfront, the C++ compiler front-end ! 5: written in the computer science research center of Bell Labs ! 6: ! 7: Copyright (c) 1984 AT&T, Inc. All rigths Reserved ! 8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 9: ! 10: expand.c: ! 11: ! 12: expand inline functions ! 13: ! 14: ******************************************************************/ ! 15: ! 16: #include "cfront.h" ! 17: Ptable Scope; ! 18: // extern void display_expr(Pexpr); ! 19: ! 20: static int inline_name_count = 1; ! 21: char* temp(char* vn, Pname fn) ! 22: // ! 23: // type.inline_temp_index is used to construct the name ! 24: // in place of the address of fn. That way, cfront ! 25: // output dosen't change as nodes move around. ! 26: // AT&T uses the address. --benson@odi ! 27: // - anything unique will do ! 28: // add two bytes to make the name sensitive to the scope ! 29: // to avoid re-using temps when an inline is expanded in ! 30: // more than one other inline that is then called in the ! 31: // same expression ! 32: // ! 33: { ! 34: char temp[50]; /* Big enough for any purpose */ ! 35: ! 36: if (vn[0]!='_' || vn[1]!='_' || vn[2]!='X') { ! 37: if(fn->tp->inline_temp_index == 0) ! 38: fn->tp->inline_temp_index = inline_name_count ++; ! 39: // this used to be the low 3 bytes of fn->tp. ! 40: // this may be slower, but it works. ! 41: // tune later. ! 42: long a = fn->tp->inline_temp_index; ! 43: sprintf(temp, "%lx", a); ! 44: int al = strlen(temp); ! 45: // allocate memory for the result ! 46: int ll = strlen(vn); ! 47: char* s = new char[ll+al+8]; ! 48: register char* p = s; ! 49: ! 50: // append _ _ X vn ! 51: *p++ = '_'; ! 52: *p++ = '_'; ! 53: *p++ = 'X'; ! 54: strcpy(p,vn); ! 55: p += ll; ! 56: strcat(p,temp); ! 57: p += al; ! 58: // append scope representation and trailing null ! 59: *p++ = 'a' + ((int(Scope)>>4)&15); ! 60: *p++ = 'a' + ((int(Scope)>>8)&15); ! 61: *p = '\0'; ! 62: return s; ! 63: } ! 64: else ! 65: return vn; ! 66: ! 67: } ! 68: ! 69: Pname dcl_local(Ptable scope, Pname an, Pname fn) ! 70: { ! 71: if (scope == 0) { ! 72: if (sti_tbl == 0) sti_tbl = new table(8,gtbl,0); ! 73: scope = sti_tbl; ! 74: // error('s',"cannot expand inlineF needing temporaryV in nonF context"); ! 75: // return an; ! 76: } ! 77: ! 78: if (an->n_stclass == STATIC) { ! 79: if (an->tp->base!=FCT) error('s',"cannot expand inlineF with static%n",an); ! 80: return an; ! 81: } ! 82: ! 83: Pname cn = fn->n_table->t_name; ! 84: char* s = temp(an->string,fn); ! 85: Pname nx = new name(s); ! 86: Ptype atp = an->tp; ! 87: //error('d',"dcl_local(%d,%n,%n) -> %s",scope,an,fn,s); ! 88: while (atp->base == TYPE) atp = Pbase(atp)->b_name->tp; ! 89: if (atp->base == VEC) { ! 90: if (an->n_scope == ARG) { ! 91: Pptr t = new ptr(PTR,Pvec(atp)->typ); ! 92: nx->tp = t; ! 93: } ! 94: else { ! 95: error('s',"cannot expand inlineF needing temporaryV of vectorT"); ! 96: return an; ! 97: } ! 98: } ! 99: else ! 100: nx->tp = atp; ! 101: PERM(nx->tp); ! 102: ! 103: nx->n_used = an->n_used; ! 104: nx->n_assigned_to = an->n_assigned_to; ! 105: nx->n_addr_taken = an->n_addr_taken; ! 106: nx->n_xref = an->n_xref; ! 107: //error('d',"nx %n %t,",nx,nx->tp); ! 108: Pname r = scope->look(nx->string,0); ! 109: if (r) { ! 110: //error('d',"ll %n %t",ll,ll->tp); ! 111: if (r->tp->check(nx->tp,0)) ! 112: error('s',"cannot expand inlineF %n with two local variables with the sameN (%s)",fn,an->string); ! 113: else ! 114: r = 0; ! 115: } ! 116: if (r==0) { ! 117: r = scope->insert(nx,0); ! 118: //error('d',"%d %d %d %d",r->n_stclass,an->n_stclass,r->lex_level,an->lex_level); ! 119: r->n_stclass = an->n_stclass; ! 120: r->lex_level = an->lex_level; ! 121: delete nx; ! 122: r->where.line = 0; ! 123: } ! 124: return r; ! 125: } ! 126: ! 127: int ck_cast(Ptype t1, Ptype t2) ! 128: /* ! 129: return a value of type t2 from a function returning a t1 ! 130: return 1 if cast is needed ! 131: */ ! 132: { ! 133: st: ! 134: while (t1->base == TYPE) t1 = Pbase(t1)->b_name->tp; ! 135: while (t2->base == TYPE) t2 = Pbase(t2)->b_name->tp; ! 136: ! 137: if (t1 == t2) return 0; ! 138: ! 139: if (t1->base != t2->base) return 1; ! 140: ! 141: switch (t1->base) { ! 142: case RPTR: ! 143: case PTR: ! 144: { t1 = Pptr(t1)->typ; ! 145: if (t1->base == VOID) return 1; ! 146: t2 = Pptr(t2)->typ; ! 147: goto st; ! 148: } ! 149: case CHAR: ! 150: case SHORT: ! 151: case INT: ! 152: case LONG: ! 153: if (Pbase(t1)->b_unsigned != Pbase(t2)->b_unsigned) return 1; ! 154: break; ! 155: case COBJ: ! 156: { ! 157: Pname nn = Pbase(t1)->b_name; ! 158: ! 159: if (Pclass(nn->tp)->csu==UNION ) return 0; ! 160: ! 161: if (t2->base==COBJ && nn->tp==Pbase(t2)->b_name->tp) return 0; ! 162: ! 163: return 1; ! 164: } ! 165: } ! 166: ! 167: return 0; ! 168: } ! 169: ! 170: int makeCM( Ptype t ) ! 171: /* return 1 if the type is not a primitive type ! 172: * this will cause the generation of (t,0) ! 173: * note: ``t'' is guaranteed not to be 0 ! 174: */ ! 175: { ! 176: while ( t->base == TYPE ) ! 177: t = Pbase(t)->b_name->tp; ! 178: ! 179: switch (t->base) { ! 180: case FLOAT: ! 181: case DOUBLE: ! 182: case LDOUBLE: ! 183: case CHAR: ! 184: case SHORT: ! 185: case INT: ! 186: case LONG: ! 187: case EOBJ: ! 188: return 0; ! 189: default: ! 190: return 1; ! 191: } ! 192: } ! 193: ! 194: static ret_seen = 0; ! 195: ! 196: Pstmt stmt::expand() ! 197: /* ! 198: copy the statements with the formal arguments replaced by ANAMES ! 199: ! 200: called once only per inline function ! 201: expand_tbl!=0 if the function should be transformed into an expression ! 202: and expand_tbl is the table for local variables ! 203: */ ! 204: { ! 205: if (this == 0) error('i',"0->S::expand() for%n",expand_fn); ! 206: ! 207: if (memtbl) { /* check for static variables */ ! 208: register Ptable t = memtbl; ! 209: register int i; ! 210: for (register Pname n = t->get_mem(i=1); n; n=t->get_mem(++i)) { ! 211: if (n->n_stclass == STATIC) { ! 212: if (n->tp->base == FCT) continue; ! 213: error('s',"cannot expand inlineF with static%n",n); ! 214: n->n_stclass = AUTO; ! 215: } ! 216: n->where.line = 0; ! 217: } ! 218: } ! 219: ! 220: if (expand_tbl) { /* make expression */ ! 221: Pexpr ee; ! 222: ! 223: if (memtbl) { // temporaries ! 224: int i; ! 225: for (Pname n=memtbl->get_mem(i=1); n; n=memtbl->get_mem(++i)) { ! 226: //error('d',"block %n %k %d %d",n,base,memtbl->real_block == this,n->lex_level); ! 227: if (n->base!=NAME || n->tp==any_type) continue; ! 228: ! 229: if (base==BLOCK ! 230: && memtbl->real_block == this ! 231: && n->lex_level < 2 ! 232: && (n->string[0]!='_' // promoted from called ! 233: // inlines ! 234: || n->string[1]!='_' ! 235: || n->string[2]!='X') ! 236: ) ! 237: continue; ! 238: ! 239: if (memtbl != scope) ! 240: { ! 241: Pname nn = dcl_local(scope,n,expand_fn); ! 242: nn->base = NAME; ! 243: n->string = nn->string; ! 244: } ! 245: else if (n->tp->base!=FCT && n->tp->base!=OVERLOAD){ ! 246: n->string = temp(n->string, expand_fn); ! 247: n->where.line = 0; ! 248: } ! 249: } ! 250: } ! 251: ! 252: switch (base) { ! 253: default: ! 254: error('s',"cannot expand inlineF%n with %kS in inline",expand_fn,base); ! 255: return Pstmt(dummy); ! 256: ! 257: case BLOCK: ! 258: if (s_list) { ! 259: ee = Pexpr(s_list->expand()); ! 260: if (s) { ! 261: ee = new expr(CM, Pexpr(s->expand()), ee); ! 262: ee->tp = ee->e2->tp; ! 263: PERM(ee); ! 264: } ! 265: return Pstmt(ee); ! 266: } ! 267: ! 268: if (s) return s->expand(); ! 269: ! 270: return Pstmt(zero); ! 271: ! 272: case PAIR: ! 273: ee = s2 ? Pexpr(s2->expand()) : 0; ! 274: ee = new expr(CM, s?Pexpr(s->expand()):0, ee); ! 275: ee->tp = ee->e2->tp; ! 276: if (s_list) { ! 277: ee = new expr(CM, ee, Pexpr(s_list->expand())); ! 278: ee->tp = ee->e2->tp; ! 279: } ! 280: PERM(ee); ! 281: return Pstmt(ee); ! 282: ! 283: case RETURN: ! 284: ret_seen = 1; ! 285: s_list = 0; ! 286: // return Pstmt(e ? e->expand() : zero); ! 287: ! 288: if (e == 0) ! 289: ee = zero; ! 290: else { ! 291: ee = e->expand(); ! 292: Ptype tt = Pfct(expand_fn->tp)->returns; ! 293: if (tt == 0) tt = Pfct(expand_fn->tp)->returns; ! 294: if (tt!=ee->tp && ck_cast(tt,ee->tp)) ee = new cast(tt,ee); ! 295: } ! 296: ! 297: return Pstmt(ee); ! 298: ! 299: case SM: ! 300: if (e== 0 || e==dummy) ! 301: ee = zero; ! 302: else { ! 303: if (e->base == DEREF) e = e->e1; ! 304: ee = e->expand(); ! 305: } ! 306: // no break; ! 307: ! 308: case ASM: ! 309: if (s_list) { ! 310: ee = new expr(CM, ee, (Pexpr)s_list->expand()); ! 311: ee->tp = ee->e2->tp; ! 312: PERM(ee); ! 313: } ! 314: return (Pstmt)ee; ! 315: ! 316: case IF: ! 317: { ! 318: int ors = ret_seen; ! 319: ret_seen = 0; ! 320: Pexpr qq = new expr(QUEST,Pexpr(s->expand()),0); ! 321: int ret1 = ret_seen; ! 322: ret_seen = 0; ! 323: ! 324: qq->cond = e->expand(); ! 325: qq->e2 = else_stmt ? Pexpr(else_stmt->expand()) : zero; ! 326: int ret2 = ret_seen; ! 327: if (ret1+ret2 && s_list) { ! 328: error('s',"cannot expand inlineF%n with S after \"return\"",expand_fn); ! 329: ret_seen = 0; ! 330: } ! 331: ret_seen += ors; ! 332: ! 333: // handle ``if (x) class_object_valued_expression;'' ! 334: ! 335: Ptype t1 = qq->e1->tp; ! 336: Ptype t2 = qq->e2->tp; ! 337: ! 338: if (t1 && t1->base==FCT) ! 339: t1 = Pfct(t1)->s_returns ? Pfct(t1)->s_returns : Pfct(t1)->returns; ! 340: ! 341: if (t2 && t2->base==FCT) ! 342: t2 = Pfct(t2)->s_returns ? Pfct(t2)->s_returns : Pfct(t2)->returns; ! 343: ! 344: Pname c1 = t1?t1->is_cl_obj():0; ! 345: Pname c2 = t2?t2->is_cl_obj():0; ! 346: ! 347: int z1 = c1 && c1!=c2; ! 348: int z2 = c2 && c1!=c2; ! 349: ! 350: //error('d',"t1 %t t2 %t",t1,t2); ! 351: if (c1==0 ! 352: && c2==0 ! 353: && t1 ! 354: && t2 ! 355: && t2->check(t1,ASSIGN) ! 356: && t1->check(t2,ASSIGN)) { ! 357: z1 = makeCM( t1 ); ! 358: z2 = makeCM( t2 ); ! 359: if ((z1 && ret1) || (z2 && ret2)) ! 360: error('s',"cannot expand inlineF with return in ifS"); ! 361: } ! 362: ! 363: if (t1 && z1==0) { ! 364: // since zero is acceptable to all pointer types ! 365: // we need only ``fix'' z1 and z2 will take care ! 366: // of itself ! 367: z1 = t1->is_ptr_or_ref() ! 368: && t2 ! 369: && t2->is_ptr_or_ref() ! 370: && t1->check(t2,0); ! 371: } ! 372: ! 373: if (z1) { ! 374: Pexpr v = (z2==0 && (t2->is_ptr_or_ref())) ? new cast(t2,zero) : zero; ! 375: qq->e1 = new expr(CM,qq->e1,v); ! 376: qq->e1->tp = qq->e1->e1->tp; ! 377: } ! 378: ! 379: if (z2) { ! 380: Pexpr v = (z1==0 && (t1->is_ptr_or_ref())) ? new cast(t1,zero) : zero; ! 381: qq->e2 = new expr(CM,qq->e2,v); ! 382: qq->e2->tp = qq->e2->e1->tp; ! 383: } ! 384: ! 385: if (s_list) { ! 386: qq = new expr(CM,qq,Pexpr(s_list->expand())); ! 387: qq->tp = qq->e2->tp; ! 388: } ! 389: else ! 390: qq->tp = qq->e1->tp; ! 391: PERM(qq); ! 392: return Pstmt(qq); ! 393: } ! 394: } ! 395: } ! 396: ! 397: where.line = 0; ! 398: ! 399: switch (base) { ! 400: default: ! 401: if (e) e = e->expand(); ! 402: break; ! 403: case PAIR: ! 404: if (s2) s2 = s2->expand(); ! 405: break; ! 406: case BLOCK: ! 407: break; ! 408: case FOR: ! 409: if (for_init) for_init = for_init->expand(); ! 410: if (e2) e2 = e2->expand(); ! 411: case ASM: ! 412: break; ! 413: // case LABEL: ! 414: // case GOTO: ! 415: case RETURN: ! 416: // case BREAK: ! 417: // case CONTINUE: ! 418: error('s',"cannot expand inlineF%n with %kS",expand_fn,base); ! 419: } ! 420: ! 421: if (s) s = s->expand(); ! 422: if (s_list) s_list = s_list->expand(); ! 423: PERM(this); ! 424: return this; ! 425: } ! 426: ! 427: Pexpr expr::expand() ! 428: { ! 429: if (this == 0) error('i',"E::expand(0)"); ! 430: ! 431: switch (base) { ! 432: case NAME: ! 433: if (expand_tbl && Pname(this)->n_scope==FCT) { ! 434: Pname n = Pname(this); ! 435: char* s = n->string; ! 436: if (s[0]=='_' && s[1]=='_' && s[2]=='X') break; ! 437: Pname cn = expand_fn->n_table->t_name; ! 438: // n->string = temp(s,expand_fn->string,(cn)?cn->string:0); ! 439: n->string = temp(s,expand_fn); ! 440: } ! 441: case DUMMY: ! 442: case ICON: ! 443: case FCON: ! 444: case CCON: ! 445: case IVAL: ! 446: case FVAL: ! 447: case LVAL: ! 448: case STRING: ! 449: case ZERO: ! 450: case TEXT: ! 451: case ANAME: ! 452: case MDOT: ! 453: break; ! 454: case ICALL: ! 455: if (expand_tbl && e1==0) { ! 456: int ors = ret_seen; ! 457: ret_seen = 0; ! 458: Pname fn = il->fct_name; ! 459: Pfct f = Pfct(fn->tp); ! 460: if (f->f_expr==0 ! 461: // f->returns==void_type ! 462: // && f->s_returns!=int_type ! 463: // && fn->n_oper!=CTOR ! 464: ) ! 465: error('s',"cannot expand value-returning inline%n with call of non-value-returning inline%n",expand_fn,fn); ! 466: // else ! 467: // error("inline%n called before defined",fn); ! 468: ret_seen = ors; ! 469: } ! 470: break; ! 471: case SIZEOF: ! 472: case CAST: ! 473: if (tp2) PERM(tp2); ! 474: goto rrr; ! 475: case QUEST: ! 476: cond = cond->expand(); ! 477: default: ! 478: if (e2) e2 = e2->expand(); ! 479: case REF: ! 480: case DOT: ! 481: rrr: ! 482: if (e1) e1 = e1->expand(); ! 483: break; ! 484: } ! 485: ! 486: switch (base) { ! 487: case CM: ! 488: case G_CM: ! 489: if (tp==0) tp=e2->tp; ! 490: } ! 491: ! 492: PERM(this); ! 493: return this; ! 494: } ! 495: ! 496: int nin; ! 497: ! 498: bit expr::not_simple() ! 499: /* ! 500: is a temporary variable needed to hold the value of this expression ! 501: as an argument for an inline expansion? ! 502: return 1; if side effect ! 503: return 2; if modifies expression ! 504: */ ! 505: { ! 506: int s; ! 507: //error('d',"not_simple%k",base); ! 508: switch (base) { ! 509: default: ! 510: return 2; ! 511: case NAME: ! 512: if (nin==0 && Pname(this)->n_table==gtbl) return 2; // unsafe: aliasing ! 513: case ZERO: ! 514: case IVAL: ! 515: case FVAL: ! 516: case ICON: ! 517: case CCON: ! 518: case FCON: ! 519: case STRING: ! 520: return 0; ! 521: case MDOT: ! 522: return mem->not_simple(); ! 523: case SIZEOF: ! 524: return (e1==0 || e1==dummy) ? 0 : e1->not_simple(); ! 525: case G_ADDROF: ! 526: case ADDROF: ! 527: return e2->not_simple(); ! 528: case CAST: ! 529: case DOT: ! 530: case REF: ! 531: return e1->not_simple(); ! 532: case UMINUS: ! 533: case NOT: ! 534: case COMPL: ! 535: return e2->not_simple(); ! 536: case DEREF: ! 537: s = e1->not_simple(); ! 538: if (1<s) return 2; ! 539: if (e2==0) return s; ! 540: return s |= e2->not_simple(); ! 541: case MUL: ! 542: case DIV: ! 543: case MOD: ! 544: case PLUS: ! 545: case MINUS: ! 546: case LS: ! 547: case RS: ! 548: case AND: ! 549: case OR: ! 550: case ER: ! 551: case LT: ! 552: case LE: ! 553: case GT: ! 554: case GE: ! 555: case EQ: ! 556: case NE: ! 557: case ANDAND: ! 558: case OROR: ! 559: case CM: ! 560: s = e1->not_simple(); ! 561: if (1<s) return 2; ! 562: return s |= e2->not_simple(); ! 563: case QUEST: ! 564: s = cond->not_simple(); ! 565: if (1<s) return 2; ! 566: s |= e1->not_simple(); ! 567: if (1<s) return 2; ! 568: return s |= e2->not_simple(); ! 569: case ANAME: ! 570: if (curr_icall) { ! 571: Pname n = (Pname)this; ! 572: int argno = int(n->n_val); ! 573: for (Pin il=curr_icall; il; il=il->i_next) ! 574: if (n->n_table == il->i_table) goto aok; ! 575: goto bok; ! 576: aok: ! 577: return (il->i_args[argno].local) ? 0 : il->i_args[argno].arg->not_simple(); ! 578: } ! 579: bok: error('i',"expand aname%n",this); ! 580: case G_CM: ! 581: case VALUE: ! 582: case NEW: ! 583: case GNEW: ! 584: case CALL: ! 585: case G_CALL: ! 586: case ICALL: ! 587: case ASSIGN: ! 588: case INCR: ! 589: case DECR: ! 590: case ASPLUS: ! 591: case ASMINUS: ! 592: case ASMUL: ! 593: case ASDIV: ! 594: case ASMOD: ! 595: case ASAND: ! 596: case ASOR: ! 597: case ASER: ! 598: case ASLS: ! 599: case ASRS: ! 600: return 2; ! 601: } ! 602: } ! 603: ! 604: extern void uninline(Pname fn); ! 605: //extern Pname new_fct; ! 606: //extern Pname del_fct; ! 607: extern Pstmt del_list; ! 608: extern Pstmt break_del_list; ! 609: extern Pstmt continue_del_list; ! 610: extern Pname curr_fct; ! 611: extern Pexpr init_list; ! 612: ! 613: extern Pname make_default_ctor(Pclass cl); ! 614: void expand_itor(Pclass cl) ! 615: { ! 616: //error('d',"expand_itor(%t)",cl); ! 617: Pexpr s2 = curr_expr; ! 618: Pstmt s5 = del_list; ! 619: Pstmt s6 = break_del_list; ! 620: Pstmt s7 = continue_del_list; ! 621: Pname s8 = curr_fct; ! 622: Pexpr s9 = init_list; ! 623: (void) cl->make_itor(1); ! 624: curr_expr = s2; ! 625: del_list = s5; ! 626: break_del_list = s6; ! 627: continue_del_list = s7; ! 628: curr_fct = s8; ! 629: init_list = s9; ! 630: } ! 631: /* ! 632: extern Pname make_default_dtor(Pclass cl); ! 633: void expand_dtor(Pclass cl) ! 634: { ! 635: //error('d',"expand_itor(%t)",cl); ! 636: Pexpr s2 = curr_expr; ! 637: Pstmt s5 = del_list; ! 638: Pstmt s6 = break_del_list; ! 639: Pstmt s7 = continue_del_list; ! 640: Pname s8 = curr_fct; ! 641: Pexpr s9 = init_list; ! 642: (void) make_default_dtor(cl); ! 643: curr_expr = s2; ! 644: del_list = s5; ! 645: break_del_list = s6; ! 646: continue_del_list = s7; ! 647: curr_fct = s8; ! 648: init_list = s9; ! 649: } ! 650: ! 651: ! 652: void expand_ictor(Pclass cl) ! 653: { ! 654: //error('d',"expand_itor(%t)",cl); ! 655: Pexpr s2 = curr_expr; ! 656: Pstmt s5 = del_list; ! 657: Pstmt s6 = break_del_list; ! 658: Pstmt s7 = continue_del_list; ! 659: Pname s8 = curr_fct; ! 660: Pexpr s9 = init_list; ! 661: (void) make_default_ctor(cl); ! 662: curr_expr = s2; ! 663: del_list = s5; ! 664: break_del_list = s6; ! 665: continue_del_list = s7; ! 666: curr_fct = s8; ! 667: init_list = s9; ! 668: } ! 669: */ ! 670: Pexpr fct::expand(Pname fn, Ptable scope, Pexpr ll) ! 671: /* ! 672: expand call to (previously defined) inline function in "scope" ! 673: with the argument list "ll" ! 674: (1) declare variables in "scope" ! 675: (2) initialize argument variables ! 676: (3) link to body ! 677: */ ! 678: { ! 679: Scope = scope; ! 680: //error('d',"expand%s() body %d f_expr %d inline %d",fn->string,body,f_expr,f_inline); ! 681: if (f_inline == ITOR) { ! 682: Pexpr s1 = last_expanded; ! 683: expand_itor(memof); ! 684: last_expanded = s1; ! 685: this = Pfct(fn->tp); ! 686: if (f_inline==0 && f_imeasure) { ! 687: uninline(fn); ! 688: return 0; ! 689: } ! 690: } ! 691: /* ! 692: if (f_inline == ICTOR) { ! 693: Pexpr s1 = last_expanded; ! 694: expand_ictor(memof); ! 695: last_expanded = s1; ! 696: this = Pfct(fn->tp); ! 697: if (f_inline==0 && f_imeasure) { ! 698: uninline(fn); ! 699: return 0; ! 700: } ! 701: } ! 702: if (f_inline == IDTOR) { ! 703: Pexpr s1 = last_expanded; ! 704: expand_dtor(memof); ! 705: last_expanded = s1; ! 706: this = Pfct(fn->tp); ! 707: if (f_inline==0 && f_imeasure) { ! 708: uninline(fn); ! 709: return 0; ! 710: } ! 711: } ! 712: */ ! 713: //error('d',"expand %n body %d f_expr %d defined %d",fn,body,f_expr,defined); ! 714: //error('d',"inline %d scope %d %d",f_inline,Pfct(fn->tp)->body->memtbl,scope); ! 715: if ((body==0 && f_expr==0) // before defined ! 716: || ((defined&SIMPLIFIED)==0) // before simplified ! 717: || (Pfct(fn->tp)->body->memtbl==scope) // while defining ! 718: || (f_inline>1) // recursive call ! 719: // || (last_expanded && last_expanded==curr_expr) // twice in an expression ! 720: ) { // so don't expand ! 721: if (warning_opt) error('w',"cannot inline%n in thisE",fn); ! 722: if (fn->n_addr_taken++==0) fn->dcl_print(0); ! 723: return 0; ! 724: } ! 725: ! 726: if (fn->n_oper==CTOR) { ! 727: Pclass cl = Pclass(fn->n_table->t_name->tp); ! 728: if (cl->c_body == 3) cl->print_all_vtbls(cl); ! 729: } ! 730: ! 731: Pin il = new iline; ! 732: Pexpr ic = new texpr(ICALL,0,0); ! 733: int ns = 0; ! 734: for (Pname an = f_args; an; an=an->n_list) ns++; ! 735: il->fct_name = fn; ! 736: il->i_args = new ia[il->i_slots = ns]; ! 737: ic->il = il; ! 738: ic->tp = s_returns ? s_returns : returns; ! 739: // Pname at = (f_this) ? f_this : (f_result) ? f_result : argtype; ! 740: Pname at = f_args; ! 741: ! 742: f_inline++; ! 743: ! 744: if (at) il->i_table = at->n_table; ! 745: int i = 0; ! 746: int not_simple = 0; /* is a temporary argument needed? */ ! 747: ! 748: for (Pname n=at; n; n=n->n_list, i++) { ! 749: /* check formal/actual argument pairs ! 750: and generate temporaries as necessary ! 751: */ ! 752: if (ll == 0) error('i',"F::expand(%n):AX",fn); ! 753: Pexpr ee; ! 754: ! 755: if (ll->base == ELIST) { ! 756: ee = ll->e1; ! 757: ll = ll->e2; ! 758: } ! 759: else { ! 760: ee = ll; ! 761: ll = 0; ! 762: } ! 763: ! 764: /* could be avoided when expanding into a block */ ! 765: il->i_args[i].local = 0; ! 766: int s ; ! 767: ! 768: // try to protect agains aliasing through pointers and references ! 769: for (Pname m=at; m; m=m->n_list) { ! 770: Pptr p; ! 771: if (n!=m) { ! 772: // if ((p=m->tp->is_ptr()) || (p=m->tp->is_ref())) ! 773: if (p=m->tp->is_ptr_or_ref()) ! 774: if (p->check(n->tp,0)==0 || p->typ->check(n->tp,0)==0) goto zxc; ! 775: ! 776: } ! 777: } ! 778: ! 779: if (n->n_assigned_to==FUDGE111 ! 780: && ee!=zero ! 781: && ee->not_simple()==0) ! 782: ; ! 783: else if (n->n_addr_taken || n->n_assigned_to) ! 784: goto zxc; ! 785: else if (s=ee->not_simple()) { ! 786: if (/*n->n_used==0 // n_used not set for ``this'' ! 787: || */1<s ! 788: || 1<n->n_used ) { // not safe ! 789: zxc: ! 790: if (last_expanded && last_expanded==curr_expr) { ! 791: f_inline--; ! 792: delete il->i_args; ! 793: delete il; ! 794: if (fn->n_addr_taken++==0) fn->dcl_print(0); ! 795: return 0; ! 796: } ! 797: //error('d',"zxc %n %t ee %d %t",n,n->tp,ee->base,ee->tp); ! 798: Pname nn = dcl_local(scope,n,fn); ! 799: nn->base = NAME; ! 800: il->i_args[i].local = nn; ! 801: ++not_simple; ! 802: // if (nn->tp->is_ref() ! 803: // && ee->tp ! 804: // && ee->tp->is_ptr_or_ref()==0) ee = ee->address(); ! 805: } ! 806: } ! 807: ! 808: il->i_args[i].arg = ee; ! 809: il->i_args[i].tp = n->tp; ! 810: } ! 811: ! 812: Ptable tbl = body->memtbl; ! 813: if (f_expr) { // generate comma expression ! 814: ! 815: char loc_var = 0; ! 816: ! 817: /* look for local variables needing declaration: */ ! 818: for (n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i) ) { ! 819: //error('d',"n %n %d",n,n->base); ! 820: //error('d',"loc %n %d %d %d",n,n->n_used,n->n_assigned_to,n->n_addr_taken); ! 821: if (n->base==NAME // don't re-declare the args ! 822: && (n->tp->base!=FCT && n->tp->base!=OVERLOAD) ! 823: && (n->n_used || n->n_assigned_to || n->n_addr_taken)) { ! 824: if (last_expanded && last_expanded==curr_expr) { ! 825: f_inline--; ! 826: delete il->i_args; ! 827: delete il; ! 828: if (fn->n_addr_taken++==0) fn->dcl_print(0); ! 829: return 0; ! 830: } ! 831: Pname nn = dcl_local(scope,n,fn); ! 832: nn->base = NAME; ! 833: n->string = nn->string; ! 834: ! 835: loc_var++; ! 836: } ! 837: } ! 838: ! 839: if (i /*not_simple*/ || loc_var) last_expanded = curr_expr; ! 840: ! 841: Pexpr ex; ! 842: if (not_simple) { ! 843: Pexpr etail = ex = new expr(CM,0,0); ! 844: for (i=0; i<il->i_slots; i++) { ! 845: Pname n = il->i_args[i].local; ! 846: if (n == 0) continue; ! 847: Pexpr e = il->i_args[i].arg; ! 848: // if used assign ! 849: // otherwise (e.g. unused argument) ! 850: // simply evaluate for sideeffects ! 851: if (n->n_used ! 852: || n->n_assigned_to ! 853: || n->n_addr_taken) { ! 854: Pexpr mptr_assign(Pexpr n, Pexpr in); ! 855: Pptr p1 = n->tp->is_ptr(); ! 856: Pptr p2 = e->tp ? e->tp->is_ptr() : 0; ! 857: if (p1 && p1->memof && p1!=p2) { ! 858: switch (e->base) { ! 859: case CM: ! 860: case G_CM: ! 861: e->e2 = mptr_assign(n,e->e2); ! 862: break; ! 863: default: ! 864: e = mptr_assign(n,e); ! 865: } ! 866: etail->e1 = e; ! 867: } ! 868: else ! 869: etail->e1 = new expr(ASSIGN,n,e); ! 870: } ! 871: else ! 872: etail->e1 = e; ! 873: if (--not_simple) ! 874: etail = etail->e2 = new expr(CM,0,0); ! 875: else ! 876: break; ! 877: } ! 878: etail->e2 = f_expr; ! 879: } ! 880: else ! 881: ex = f_expr; ! 882: ic->e1 = ex; ! 883: } ! 884: else { // generate block: ! 885: for (n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i) ) { ! 886: // mangle local names ! 887: if (n->base==NAME ! 888: && (n->n_used || n->n_assigned_to || n->n_addr_taken)) { ! 889: // Pname cn = fn->n_table->t_name; ! 890: // n->string = temp(n->string,fn->string,(cn)?cn->string:0); ! 891: n->string = temp(n->string,fn); ! 892: } ! 893: } ! 894: Pstmt ss; ! 895: if (not_simple) { ! 896: last_expanded = curr_expr; ! 897: Pstmt st = new estmt(SM,curloc,0,0); ! 898: st->where.line = 0; ! 899: Pstmt stail = st; ! 900: for (i=0; i<il->i_slots; i++) { ! 901: Pname n = il->i_args[i].local; ! 902: if (n == 0) continue; ! 903: Pexpr e = il->i_args[i].arg; ! 904: Pptr p1 = n->tp->is_ptr(); ! 905: Pptr p2 = e->tp->is_ptr(); ! 906: Pexpr mptr_assign(Pexpr n, Pexpr in); ! 907: if (p1 && p1->memof && p1!=p2) { ! 908: switch (e->base) { ! 909: case CM: ! 910: case G_CM: ! 911: e->e2 = mptr_assign(n,e->e2); ! 912: break; ! 913: default: ! 914: e = mptr_assign(n,e); ! 915: } ! 916: stail->e = e; ! 917: } ! 918: else ! 919: stail->e = new expr(ASSIGN,n,e); ! 920: if (--not_simple) { ! 921: stail = stail->s_list = new estmt(SM,curloc,0,0); ! 922: stail->where.line = 0; ! 923: } ! 924: else ! 925: break; ! 926: } ! 927: stail->s_list = body; ! 928: ss = new block(curloc,0,st); ! 929: ss->where.line = 0; ! 930: } ! 931: else ! 932: ss = body; ! 933: ic->e2 = Pexpr(ss); ! 934: } ! 935: ! 936: f_inline--; ! 937: return ic; ! 938: } ! 939: ! 940: /* ODI Notes ! 941: ! 942: change address sensitive name to be address-insensitive ! 943: that way cfront output can be diffed to regress the compiler. ! 944: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.