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