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