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