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