|
|
1.1 ! root 1: /*ident "@(#)ctrans:src/simpl.c 1.5.4.25" */ ! 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: simpl.c: ! 11: ! 12: simplify the typechecked function ! 13: remove: classes: ! 14: class fct-calls ! 15: operators ! 16: value constructors and destructors ! 17: new and delete operators (replace with function calls) ! 18: initializers (turn them into statements) ! 19: constant expressions (evaluate them) ! 20: inline functions (expand the calls) ! 21: enums (make const ints) ! 22: unreachable code (delete it) ! 23: make implicit coersions explicit ! 24: ! 25: in general you cannot simplify something twice ! 26: ! 27: *******************************************************************/ ! 28: ! 29: #include "cfront.h" ! 30: ! 31: Pname new_fct; ! 32: Pname del_fct; ! 33: Pname vec_new_fct; ! 34: Pname vec_del_fct; ! 35: ! 36: Pstmt del_list; ! 37: Pstmt break_del_list; ! 38: Pstmt continue_del_list; ! 39: ! 40: //bit not_inl; // is the current function an inline? ! 41: Pname curr_fct; // current function ! 42: Pexpr init_list; ! 43: Pexpr one; ! 44: ! 45: Ptype Pfct_type; ! 46: Ptype Pvptr_type; ! 47: Pbase mptr_type; ! 48: Ptype size_t_type; ! 49: ! 50: Pexpr cdvec(Pname f, Pexpr vec, Pclass cl, Pname cd, int,Pexpr); ! 51: Pstmt trim_tail(Pstmt tt); ! 52: Pname find_vptr(Pclass); ! 53: char *get_classname(char*); ! 54: char *drop_classname(char*); ! 55: loc no_where; // 0,0 ! 56: ! 57: int imeasure; // a counter trying to measure the complexity of a function ! 58: // body to try to avoid expanding ``monster'' inlines. ! 59: ! 60: extern Pexpr initialize_vptrs (Pclass cl, Pexpr this_expr); ! 61: ! 62: /* Constructs an expression which initializes the given class's vptrs. ! 63: The this_expr forms the first part of the path expression for each ! 64: vptr assignment. The vptr assignments are combined into a comma ! 65: expression. */ ! 66: ! 67: ! 68: static Pclass topclass; ! 69: ! 70: void simpl_init() ! 71: { ! 72: char* ns = oper_name(NEW); ! 73: char* ds = oper_name(DELETE); ! 74: ! 75: size_t_type = Pvoid_type->tsizeof()>uint_type->tsizeof()?ulong_type:uint_type; ! 76: ! 77: Pname nw = new name(ns); ! 78: nw->n_oper = NEW; ! 79: Pname a = new name; ! 80: a->tp = size_t_type; ! 81: nw->tp = new fct(Pvoid_type,a,1); ! 82: new_fct = nw->dcl(gtbl,EXTERN); // void* operator new(long); ! 83: delete nw; ! 84: // new_fct->use(); ! 85: ! 86: Pname dl = new name(ds); ! 87: dl->n_oper = DELETE; ! 88: a = new name; ! 89: a->tp = Pvoid_type; ! 90: dl->tp = new fct(void_type,a,1); ! 91: del_fct = dl->dcl(gtbl,EXTERN); ! 92: delete dl; ! 93: // del_fct->use(); ! 94: ! 95: ! 96: Pname vn = new name("__vec_new"); ! 97: Pname vd = new name("__vec_delete"); ! 98: ! 99: a = new name; ! 100: a->tp = Pvoid_type; ! 101: Pname al = a; ! 102: a = new name; ! 103: a->tp = int_type; ! 104: a->n_list = al; ! 105: al = a; ! 106: a = new name; ! 107: a->tp = int_type; ! 108: a->n_list = al; ! 109: al = a; ! 110: a = new name; ! 111: a->tp = Pvoid_type; ! 112: a->n_list = al; ! 113: al = a; /* (Pvoid, int, int, Pvoid) */ ! 114: ! 115: vec_new_fct = gtbl->insert(vn,0); ! 116: delete vn; ! 117: vec_new_fct->tp = new fct(Pvoid_type,al,1); ! 118: vec_new_fct->n_scope = EXTERN; ! 119: PERM(vec_new_fct); ! 120: PERM(vec_new_fct->tp); ! 121: vec_new_fct->use(); ! 122: ! 123: vec_new_fct->dcl_print(0); ! 124: ! 125: a = new name; ! 126: a->tp = int_type; ! 127: al = a; ! 128: a = new name; ! 129: a->tp = int_type; ! 130: a->n_list = al; ! 131: al = a; ! 132: a = new name; ! 133: a->tp = Pvoid_type; ! 134: a->n_list = al; ! 135: al = a; ! 136: a = new name; ! 137: a->tp = int_type; ! 138: a->n_list = al; ! 139: al = a; ! 140: a = new name; ! 141: a->tp = int_type; ! 142: a->n_list = al; ! 143: al = a; ! 144: a = new name; ! 145: a->tp = Pvoid_type; ! 146: a->n_list = al; ! 147: al = a; /* (Pvoid, int, int, Pvoid, int, int) */ ! 148: ! 149: vec_del_fct = gtbl->insert(vd,0); ! 150: delete vd; ! 151: vec_del_fct->tp = new fct(void_type,al,1); ! 152: vec_del_fct->n_scope = EXTERN; ! 153: PERM(vec_del_fct); ! 154: PERM(vec_del_fct->tp); ! 155: vec_del_fct->use(); ! 156: ! 157: vec_del_fct->dcl_print(0); ! 158: ! 159: one = new ival(1); ! 160: one->tp = int_type; ! 161: PERM(one); ! 162: ! 163: Pfct_type = new fct(int_type,0,1); // int (*)() ! 164: Pfct_type = Pfct_type->addrof(); ! 165: PERM(Pfct_type); ! 166: ! 167: putstring("typedef int (*__vptp)();\n"); ! 168: putstring("struct __mptr {short d; short i; __vptp f; };\n"); ! 169: ! 170: Pname b = new name("__mptr"); ! 171: b->tp = new classdef(STRUCT); ! 172: b->tp->defined = 1; ! 173: Pclass(b->tp)->obj_size = 8; ! 174: mptr_type = new basetype(COBJ,b); ! 175: PERM(mptr_type); ! 176: ! 177: Pvptr_type = mptr_type->addrof(); ! 178: PERM(Pvptr_type); ! 179: } ! 180: ! 181: Ptable scope; /* current scope for simpl() */ ! 182: Pname expand_fn; /* name of function being expanded or 0 */ ! 183: Ptable expand_tbl; /* scope for inline function variables */ ! 184: ! 185: Pname classdef::has_oper(TOK op) ! 186: { ! 187: Pexpr n = find_name(oper_name(op),0); ! 188: if (n == 0) return 0; ! 189: ! 190: while (n->base==REF || n->base==MDOT) { ! 191: Pexpr e = Pexpr(n); ! 192: n = Pname(n->mem); ! 193: delete e; ! 194: } ! 195: if (n->tp->base==FCT && Pname(n)->n_dcl_printed==0) Pname(n)->dcl_print(0); ! 196: return Pname(n); ! 197: } ! 198: ! 199: int is_expr(Pstmt s) ! 200: /* ! 201: is this statement simple enough to be converted into an expression for ! 202: inline expansion? ! 203: */ ! 204: { ! 205: int i = 0; ! 206: if (s->base == BLOCK) { ! 207: if (s->s == 0) return 1; ! 208: s = s->s; ! 209: } ! 210: for (Pstmt ss = s; ss; ss = ss->s_list) { ! 211: //error('d',"ss %k",ss->base); ! 212: switch (ss->base) { ! 213: case BLOCK: ! 214: if (Pblock(ss)->memtbl || is_expr(ss->s)==0) return 0; ! 215: case SM: ! 216: if (ss->e && ss->e->base==ICALL) { ! 217: Pname fn = ss->e->il->fct_name; ! 218: Pfct f = Pfct(fn->tp); ! 219: if (f->f_expr == 0) return 0; ! 220: } ! 221: break; ! 222: case IF: ! 223: if (is_expr(ss->s)==0) return 0; ! 224: if (ss->else_stmt && is_expr(ss->else_stmt)==0) return 0; ! 225: break; ! 226: default: ! 227: return 0; ! 228: } ! 229: i++; ! 230: } ! 231: return i; ! 232: } ! 233: ! 234: int no_of_returns; ! 235: ! 236: void name::simpl() ! 237: { ! 238: //error('d',"name::simpl%n %d %k",this,tp->base,tp->base); ! 239: if (base == PUBLIC) return; ! 240: ! 241: if (tp == 0) error('i',"%n->N::simple(tp==0)",this); ! 242: ! 243: switch (tp->base) { ! 244: case 0: ! 245: error('i',"%n->N::simpl(tp->B==0)",this); ! 246: ! 247: case OVERLOAD: ! 248: { for (Plist gl = Pgen(tp)->fct_list; gl; gl=gl->l) gl->f->simpl(); ! 249: break; ! 250: } ! 251: ! 252: case FCT: ! 253: { Pfct f = Pfct(tp); ! 254: Pname n; ! 255: Pname th = f->f_this; ! 256: ! 257: if (th) { ! 258: // Make "this" a register if it is used more than twice: ! 259: if (th->n_addr_taken) error("&this"); ! 260: th->n_stclass = (2 < th->n_used) ? REGISTER : AUTO; ! 261: if (warning_opt ! 262: && th->n_assigned_to ! 263: && th->n_assigned_to!=FUDGE111) ! 264: error('w',&where,"assignment to this"); ! 265: } ! 266: ! 267: ! 268: if (ansi_opt && f->body==0) { ! 269: // make sure arguments can be printed for decls ! 270: ! 271: for (Pname n = f->f_args; n; n = n->n_list) { ! 272: n->n_scope = ARG; ! 273: if (n->string) { ! 274: char* ps = new char[strlen(n->string)+1]; ! 275: strcpy(ps,n->string); ! 276: n->string = ps; ! 277: } ! 278: /* ! 279: if (n_oper==DTOR && n->n_list==0) { ! 280: // add __free argument ! 281: Pname fa=new name; ! 282: fa->tp = int_type; ! 283: n->n_scope = ARG; ! 284: // ps = new char[6]; ! 285: // strcpy(ps, "__free"); ! 286: // fa->string = ps; ! 287: n->n_list = fa; ! 288: break; ! 289: } ! 290: */ ! 291: } ! 292: } ! 293: ! 294: if (tp->defined & (SIMPLIFIED | ~DEFINED) ) return; ! 295: ! 296: for (n=f->f_args; n; n=n->n_list) n->simpl(); ! 297: ! 298: if (f->body) { ! 299: Ptable oscope = scope; ! 300: Pname ocurr = curr_fct; ! 301: int oim = imeasure; ! 302: scope = f->body->memtbl; ! 303: //error('d',"body"); ! 304: if (scope == 0) error('i',"%n memtbl missing",this); ! 305: curr_fct = this; ! 306: f->simpl(); ! 307: if (f->f_inline==0 || debug_opt) ! 308: f->f_imeasure = 0; // not a converted inline ! 309: else { ! 310: // first check if the function is too large to ! 311: // be worth inlining ! 312: if (12<f->f_imeasure) { // cut-over point: ! 313: // about 12 assignments ! 314: // f->f_imeasure indicates ! 315: f->f_inline = 0;// a converted inline ! 316: //error('d',"don't inline%n %d %d %d",this,this,f,f->f_imeasure); ! 317: tp->defined |= SIMPLIFIED; ! 318: return; ! 319: } ! 320: int i = 0; ! 321: for (n=f->f_args; n; n=n->n_list) { ! 322: n->base = ANAME; ! 323: n->n_val = i++; ! 324: // ?? if (n->n_table != scope) error('i',"aname scope: %d %n %d %d\n",n,n,n->n_table,scope); ! 325: } ! 326: expand_tbl = (f->returns->base!=VOID || n_oper==CTOR) ? scope : 0; ! 327: expand_fn = this; ! 328: ! 329: if (expand_tbl) { ! 330: genlab: ! 331: // value returning: generate expr ! 332: // the body still holds the memtbl ! 333: Pexpr ee = Pexpr(f->body->expand()); ! 334: Ptype t = 0; ! 335: if (f->s_returns) { ! 336: if (ee->tp!=f->s_returns) t = f->s_returns; ! 337: } ! 338: else if (ee->tp!=f->returns) ! 339: t = f->returns; ! 340: // VCVC assumes VOID is output as CHAR: ! 341: /* But this is not needed on a sun, and just makes the debugger print trash */ ! 342: #ifndef sun ! 343: if (t && t==void_type && ansi_opt == 0) ! 344: ee = new expr(CM,ee,new cast(char_type,zero)); ! 345: #endif ! 346: f->f_expr = (ee->base==CM) ? ee : new expr(CM,zero,ee); ! 347: // print.c assumes expansion into comma expression ! 348: } ! 349: else { ! 350: if (is_expr(f->body)) { ! 351: // can generate expr: do ! 352: expand_tbl = scope; ! 353: goto genlab; ! 354: } ! 355: // not value return: can generate block ! 356: f->f_expr = 0; ! 357: f->body = Pblock(f->body->expand()); ! 358: } ! 359: expand_fn = 0; ! 360: expand_tbl = 0; ! 361: } ! 362: scope = oscope; ! 363: curr_fct = ocurr; ! 364: imeasure = oim; ! 365: } ! 366: break; ! 367: } ! 368: ! 369: case CLASS: ! 370: Pclass(tp)->simpl(); ! 371: } ! 372: ! 373: if (n_initializer) n_initializer->simpl(); ! 374: tp->defined |= SIMPLIFIED; ! 375: } ! 376: ! 377: Pexpr call_ctor(Ptable tbl, Pexpr p, Pexpr ctor, Pexpr args, int d, Pexpr vb_args) ! 378: { ! 379: Pexpr ee = new ref(d,p,ctor); ! 380: if (p==0 || tbl==0) ee->tp = ctor->tp; ! 381: //error('d',"call_ctor(tbl %d, p %d, %n, args %d)",tbl,p,ctor,args); ! 382: if (args && args->base!=ELIST) args = new expr(ELIST,args,0); ! 383: ee = new expr(G_CALL,ee,args); ! 384: Pname n = Pname(ctor); ! 385: while (n->base == MDOT) n = Pname(n->mem); ! 386: if (n->tp->base == FCT) ee->fct_name = n; ! 387: if (tbl) ! 388: ee = ee->typ(tbl); ! 389: else if (n->tp->base == FCT) ! 390: ee->tp = Pfct(n->tp)->s_returns; ! 391: if (ee->tp == any_type) return ee; ! 392: args = ee->e2; ! 393: ! 394: if (vb_args == 0) { // attach zero vbase arguments ! 395: Pfct f = Pfct(ee->fct_name->tp); // not n->fct_name ! 396: for (Pname nn = f->f_args->n_list; nn && nn!=f->argtype; nn=nn->n_list) ! 397: args = new expr(ELIST,zero,args); ! 398: } ! 399: else { // attach vbase arguments ! 400: if (args) { ! 401: for (Pexpr d = vb_args; d->e2; d=d->e2); ! 402: d->e2 = args; ! 403: } ! 404: args = vb_args; ! 405: } ! 406: ! 407: ee->e2 = args; ! 408: return ee; ! 409: } ! 410: ! 411: Pexpr call_dtor(Pexpr p, Pexpr dtor, Pexpr arg, int d, Pexpr vb_args) ! 412: { ! 413: // error('d',"call dtor %k %n %t vb_args %d",d,dtor,dtor->tp,vb_args); ! 414: Pexpr r = new ref(d,p,dtor); ! 415: ! 416: if (arg && vb_args) { ! 417: arg = new ival(3); ! 418: arg->tp = int_type; ! 419: } ! 420: else if (vb_args) { ! 421: arg = new ival(2); ! 422: arg->tp = int_type; ! 423: } ! 424: else if (arg==0) ! 425: arg = zero; ! 426: ! 427: Pexpr aa = new expr(ELIST,arg,0); // argument controlling deallocation ! 428: // 2: destroy vbases ! 429: // 1: dealllocate, 0: don't ! 430: ! 431: Pfct f = Pfct(dtor->tp); // attach virtual base arguments ! 432: // for (Pname nn = f->f_args->n_list; nn && nn->n_list; nn=nn->n_list) { ! 433: // Pexpr xx = vb_args ? new cast(nn->tp,one) : zero; ! 434: // aa = new expr(ELIST,xx,aa); ! 435: // } ! 436: ! 437: ! 438: Pexpr ee = new call(r,aa); ! 439: while (dtor->base == MDOT) dtor = dtor->mem; ! 440: if (d == REF) // could be virtual ! 441: ee->fct_name = Pname(dtor); ! 442: else { // virtual suppressed, store fct name ! 443: r->n_initializer = dtor; ! 444: ee->fct_name = 0; ! 445: } ! 446: ee->base = G_CALL; ! 447: ee->tp = void_type; ! 448: ! 449: if (f->memof->c_body == 1) f->memof->dcl_print(0); ! 450: if (Pname(dtor)->n_dcl_printed==0) Pname(dtor)->dcl_print(0); ! 451: ! 452: return ee; ! 453: } ! 454: ! 455: //extern int new_used; // pre-define new and delete only if the user didn't ! 456: ! 457: Pstmt fct::dtor_simpl(Pclass cl, Pexpr th) ! 458: { ! 459: Pstmt dtail = 0; ! 460: //error('d',"simpl_dtor(%t) a %d",cl,f_args); ! 461: // if (new_used == 0) new_init(); ! 462: ! 463: Pname fa = new name("__free"); // fake argument for dtor ! 464: fa->tp = int_type; ! 465: Pname free_arg = fa->dcl(body->memtbl,ARG); ! 466: free_arg->where = no_where; ! 467: delete fa; ! 468: Pname a = f_args; ! 469: if (a==0 || a->n_list==0) error('i',"__freeA missing in destructor for %t",cl); ! 470: Pname p = 0; ! 471: for(;;p=a,a=a->n_list) { // replace nameless fake argument ! 472: //error('d',"a %d %t",a,a->tp); ! 473: if (a->n_list == 0) { ! 474: // a->n_list = free_arg; ! 475: DEL(p->n_list); ! 476: p->n_list = free_arg; ! 477: break; ! 478: } ! 479: } ! 480: ! 481: // generate calls to destructors for all members of class cl: ! 482: Ptable tbl = cl->memtbl; ! 483: int i = 1; ! 484: for (Pname m=tbl->get_mem(i); m; m=tbl->get_mem(++i) ) { ! 485: ! 486: if (m->n_stclass == STATIC) continue; ! 487: ! 488: Ptype t = m->tp; ! 489: Pexpr ee = 0; ! 490: Pname cn; ! 491: Pname dtor; ! 492: ! 493: if (cn = t->is_cl_obj()) { ! 494: Pclass cl = (Pclass)cn->tp; ! 495: if (dtor = cl->has_dtor()) { // dtor(this,0,ones); ! 496: ee = new ref(REF,th,m); ! 497: ee->tp = m->tp; ! 498: ee = call_dtor(ee,dtor,0,DOT,one); ! 499: check_visibility(dtor,0,Pclass(dtor->n_table->t_name->tp),tbl,curr_fct); ! 500: } ! 501: } ! 502: else if (cl_obj_vec) { ! 503: Pclass cl = Pclass(cl_obj_vec->tp); ! 504: if (dtor = cl->has_dtor()) { ! 505: Pfct f = Pfct(dtor->tp); ! 506: int i = 0; ! 507: for (Pname nn = f->f_args->n_list; nn && nn->n_list; nn=nn->n_list) i++; ! 508: //error('d',"dtor %n i %d",dtor,i); ! 509: ee = new ref(REF,th,m); ! 510: ee->tp = m->tp; ! 511: ee = cdvec(vec_del_fct,ee,cl,dtor,0,new ival(i)); ! 512: check_visibility(dtor,0,Pclass(dtor->n_table->t_name->tp),tbl,curr_fct); ! 513: } ! 514: } ! 515: ! 516: if (ee) { ! 517: Pstmt es = new estmt(SM,curloc,ee,0); ! 518: // reverse order of destructors for members ! 519: es->s_list = del_list; ! 520: del_list = es; ! 521: if (dtail == 0) dtail = es; ! 522: } ! 523: } ! 524: ! 525: ! 526: Pexpr ee = 0; ! 527: // look for bases with destructors: ! 528: // generate: dtor(base,0); ! 529: ! 530: Pbcl b = 0; // get dtors in order with virtual bases last ! 531: Pbcl t = 0; ! 532: for (Pbcl l = cl->baselist; l; l=l->next) { ! 533: if (l->base != VIRTUAL) { ! 534: Pbcl x = new basecl(l->bclass,0); ! 535: if (t == 0) ! 536: b = x; ! 537: else ! 538: t->next = x; ! 539: t = x; ! 540: x->base = l->base; ! 541: x->obj_offset = l->obj_offset; ! 542: } ! 543: } ! 544: for (l = cl->baselist; l; l=l->next) { ! 545: if (l->base == VIRTUAL) { ! 546: b = new basecl(l->bclass,b); ! 547: b->base = l->base; ! 548: b->obj_offset = l->obj_offset; ! 549: } ! 550: } ! 551: Pexpr ve = 0; ! 552: ! 553: for (; b; b=l) { ! 554: Pclass bcl = b->bclass; ! 555: l = b->next; ! 556: Pname dtor = bcl->has_dtor(); ! 557: ! 558: if (dtor) { ! 559: Pexpr val = rptr(bcl->this_type,th,b->obj_offset); ! 560: val = val->contents(); ! 561: Pexpr e = call_dtor(val,dtor); ! 562: if (b->base == VIRTUAL) { ! 563: // if (x) this->x.dtor(); where x is a vbase ! 564: for (Pname dd = f_this->n_list; dd!=argtype; dd=dd->n_list) ! 565: if (strcmp(dd->string,bcl->string)==0) break; ! 566: ! 567: #ifndef sun ! 568: if (ansi_opt) { // q?void:int would be an error ! 569: #endif ! 570: e = new expr(G_CM,e,zero); ! 571: e->tp = zero_type; ! 572: #ifndef sun ! 573: } ! 574: #endif ! 575: e = new expr(QUEST,e,zero); ! 576: Pexpr two = new ival(2); ! 577: two->tp = int_type; ! 578: e->cond = new expr (AND,free_arg,two);//dd; ! 579: } ! 580: ee = ee ? new expr(CM,e,ee) : e; ! 581: } ! 582: delete b; ! 583: } ! 584: ! 585: Pstmt es = ee ? new estmt(SM,curloc,ee,0) : 0; ! 586: ! 587: ee = new expr(ELIST,th,0); // free storage ! 588: Pname n = new name(oper_name(DELETE)); ! 589: Pexpr del = find_name(n,cl,scope,CALL,curr_fct); ! 590: if (del->tp->base==OVERLOAD || Pfct(del->tp)->nargs==2) { ! 591: Pexpr ss = new texpr(SIZEOF,cl,0); ! 592: ss->tp = uint_type; ! 593: ee->e2 = new expr(ELIST,ss,0); ! 594: } ! 595: ee = new call(del,ee); ! 596: ee->tp = ee->call_fct(scope); ! 597: ! 598: Pstmt ess = new estmt(SM,curloc,ee,0); ! 599: ess = new ifstmt(curloc,new expr(AND,free_arg,one),ess,0); ! 600: if (es) ! 601: es->s_list = ess; ! 602: else ! 603: es = ess; ! 604: ! 605: free_arg->use(); ! 606: Pname(th)->use(); ! 607: ! 608: if (dtail) ! 609: dtail->s_list = es; ! 610: else ! 611: del_list = es; ! 612: ! 613: del_list = new ifstmt(curloc,th,del_list,0); ! 614: if (del_list) del_list->simpl(); ! 615: return dtail; ! 616: } ! 617: ! 618: ! 619: Pclass find_vbase_ptr(Pclass cl, Pclass vbase) ! 620: { ! 621: for (Pbcl bb = cl->baselist; bb; bb = bb->next) { ! 622: if (bb->bclass==vbase && bb->ptr_offset) return cl; ! 623: Pclass f = find_vbase_ptr(bb->bclass,vbase); ! 624: if (f) return f; ! 625: } ! 626: return 0; ! 627: } ! 628: ! 629: Pclass second_base(Pclass cl, Pclass base) ! 630: { ! 631: //error('d',"second_base(%t,%t)",cl,base); ! 632: for (Pbcl b = cl->baselist; b && b->base==NAME; b = b->next) { ! 633: if (b->bclass==base) { ! 634: if (b==cl->baselist) return 0; ! 635: return base; ! 636: } ! 637: Pclass bb = second_base(b->bclass,base); ! 638: if (bb == Pclass(-1)) continue; // not found ! 639: if (bb) { ! 640: if (b!=cl->baselist) error('s',"C hierarchy too complicated"); ! 641: return bb; // second base of b->bclass ! 642: } ! 643: if (b==cl->baselist) return 0; ! 644: return b->bclass; // b->bclass is second base ! 645: } ! 646: return Pclass(-1); ! 647: } ! 648: ! 649: //Pclass topclass; ! 650: ! 651: Pexpr classdef::get_vptr_exp(char *s) ! 652: { ! 653: //error('d',"%t::get_vptr_exp(%s)",this,s?s:"0"); ! 654: if (c_body == 1) dcl_print(0); ! 655: if (c_body == 3) print_all_vtbls(this); ! 656: if (s == 0) return find_vptr(this); ! 657: Pbcl b = get_base(get_classname(s)); ! 658: Pexpr vp = b->bclass->get_vptr_exp(drop_classname(s)); ! 659: if (b==baselist && b->base!=VIRTUAL) return vp; ! 660: vp = new mdot(b->bclass->string,vp); ! 661: if (c_body == 1) b->bclass->dcl_print(0); ! 662: if (c_body == 3) b->bclass->print_all_vtbls(b->bclass); ! 663: if (b->base == VIRTUAL) { ! 664: vp->i1 = 1; ! 665: if (b->ptr_offset == 0) { // pointer to base in intermediate base ! 666: Pclass bb = find_vbase_ptr(this,b->bclass); ! 667: Pclass sb = second_base(topclass,bb); ! 668: //error('d',"mdot %t %t : %d %t ",topclass,bb,sb,sb==Pclass(-1)?0:sb); ! 669: if (sb && sb!=Pclass(-1)) vp = new mdot(sb->string,vp); ! 670: } ! 671: } ! 672: return vp; ! 673: } ! 674: ! 675: int fct::ctor_simpl(Pclass cl, Pexpr th) ! 676: { ! 677: Ptable tbl = cl->memtbl; ! 678: ! 679: int ass_count = 0; ! 680: init_list = 0; ! 681: //error('d',"ctor_simpl %t: %t",cl,this); ! 682: /* ! 683: initialization order: ! 684: (1) virtual base pointers and virtual bases ! 685: (they may be used in non-virtual bases) ! 686: (2) non-virtual bases ! 687: (3) virtual function pointers ! 688: (4) members ! 689: */ ! 690: ! 691: // initialize virtual base pointers and virtual base objects ! 692: for (Pbcl l = cl->baselist; l; l=l->next) { ! 693: Pexpr i = l->init; ! 694: if (l->base != VIRTUAL) continue; ! 695: l->init = 0; ! 696: //error('d',"simpl virtual base %t i %d ",l->bclass,i); ! 697: ! 698: // assign virtual OP to virtual base AP ! 699: Pclass bc = l->bclass; ! 700: Pexpr dp = 0; ! 701: ! 702: // dd = pointer argument for this base; ! 703: // non-zero if already initialized ! 704: for (Pname dd = f_this->n_list; dd!=argtype; dd=dd->n_list) ! 705: if (strcmp(dd->string,bc->string)==0) break; ! 706: ! 707: // initialize virtual base object ! 708: //error('d',"bc %t dd %n offset %d init %d",bc,dd,l->obj_offset,l->init); ! 709: // => bc_arg = (bc*)((char*)this+offset) ! 710: int off = l->obj_offset; ! 711: Pexpr val = rptr(bc->this_type,th,off); ! 712: dp = new expr(ASSIGN,dd,val); ! 713: dd->assign(); ! 714: ! 715: // => bc::bc() ! 716: if (i) { ! 717: switch (i->base) { ! 718: case ASSIGN: ! 719: case CM: ! 720: break; ! 721: case CALL: ! 722: case G_CALL: ! 723: { Pcall cc = Pcall(i); ! 724: Pname bn = cc->fct_name; ! 725: ass_count = Pfct(bn->tp)->f_this->n_assigned_to; ! 726: cc->simpl(); ! 727: break; ! 728: } ! 729: default: ! 730: error('i',"badBCIr %k",i->base); ! 731: } ! 732: dp = new expr(CM,dp,i); ! 733: } ! 734: ! 735: // => (bc_arg==0)?dp:bc_arg ! 736: for (Pname a = f_args->n_list; a; a = a->n_list) ! 737: if (strcmp(bc->string,a->string)==0) { ! 738: dp = new expr(QUEST,dp,a); ! 739: dp->cond = new expr(EQ,a,zero); ! 740: break; ! 741: } ! 742: ! 743: // Pname dpp = find_vbase_ptr(bc,cl); ! 744: for (Pbcl ll=cl->baselist; ll; ll=ll->next) { ! 745: if (ll->bclass==bc && ll->ptr_offset) { ! 746: // make sure that the delegate_arg is needed ! 747: // here and not just in a base ! 748: ! 749: // this->Pd = (bc_arg==0)?dp:bc_arg ! 750: Pexpr dpp = new mdot(bc->string,th); ! 751: dpp->i1 = 3; ! 752: dp = new expr(ASSIGN,dpp,dp); ! 753: //error('d',"dpp %n",dpp); ! 754: break; ! 755: } ! 756: } ! 757: ! 758: // reverse init order ! 759: if (dp) init_list = init_list ? new expr(CM,dp,init_list) : dp; ! 760: } ! 761: ! 762: // generate: this=base::base(args) (non-virtual bases) ! 763: { ! 764: for (Pbcl l = cl->baselist; l; l=l->next) { ! 765: Pexpr i = l->init; ! 766: if (i==0 || l->base==VIRTUAL) continue; ! 767: //error('d',"simpl base %t i %d ",l->bclass,i); ! 768: l->init = 0; ! 769: ! 770: switch (i->base) { ! 771: case ASSIGN: ! 772: case CM: ! 773: break; ! 774: case CALL: ! 775: case G_CALL: ! 776: { Pcall cc = Pcall(i); ! 777: Pname bn = cc->fct_name; ! 778: ass_count = Pfct(bn->tp)->f_this->n_assigned_to; ! 779: cc->simpl(); ! 780: // assign to ``this'' only from only base ! 781: if (l==cl->baselist && cl->baselist->next==0) i = new expr(ASSIGN,th,cc); ! 782: break; ! 783: } ! 784: default: ! 785: error('i',"badBCIr %k",i->base); ! 786: } ! 787: ! 788: init_list = init_list ? new expr(G_CM,init_list,i) : i; ! 789: } ! 790: } ! 791: ! 792: // initialize the vptrs that are updated by this class ! 793: ! 794: if (th) { ! 795: Pexpr ee = initialize_vptrs (cl, th); ! 796: if (ee) ! 797: init_list = init_list ? new expr(CM,init_list,ee) : ee; ! 798: } ! 799: ! 800: else { ! 801: error('i', "%t->fct::ctor_simpl(): th found to be null", cl); ! 802: } ! 803: ! 804: ! 805: // initialize members in declaration order: ! 806: int i; ! 807: for (Pname m=tbl->get_mem(i=1); m; m=tbl->get_mem(++i) ) { ! 808: Ptype t = m->tp; ! 809: Pname cn; ! 810: Pname ctor; ! 811: if (t == 0) continue; ! 812: ! 813: switch (t->base) { ! 814: case FCT: ! 815: case OVERLOAD: ! 816: case CLASS: ! 817: case ENUM: ! 818: continue; ! 819: } ! 820: ! 821: switch (m->n_stclass) { ! 822: case STATIC: ! 823: case ENUM: ! 824: continue; ! 825: } ! 826: ! 827: if (m->base == PUBLIC) continue; ! 828: ! 829: Pexpr ee = m->n_initializer; ! 830: if (ee) m->n_initializer = 0; // from fct must not persist until next fct ! 831: //error('d',"simpl m %n ee %d",m,ee); ! 832: if (ee) { ! 833: // init of non-class mem ! 834: // set in fct::mem_init() ! 835: } ! 836: else if (cn=t->is_cl_obj()) { // try for default ! 837: Pclass cl = Pclass(cn->tp); ! 838: if (ctor = cl->has_ictor()) { ! 839: Pexpr r = new ref(REF,th,m); ! 840: ee = call_ctor(tbl,r,ctor,0,DOT); ! 841: check_visibility(ctor,0,Pclass(ctor->n_table->t_name->tp),tbl,curr_fct); ! 842: } ! 843: else if (cl->has_ctor()) { ! 844: error("M%n needsIr (no defaultK forC %s)",m,cl->string); ! 845: } ! 846: } ! 847: else if (cl_obj_vec) { ! 848: Pclass cl = Pclass(cl_obj_vec->tp); ! 849: if (ctor = cl->has_ictor()) { // _new_vec(vec,noe,sz,ctor); ! 850: Pexpr mm = new ref(REF,th,m); ! 851: mm->tp = m->tp; ! 852: ee = cdvec(vec_new_fct,mm,cl,ctor,-1,0); ! 853: check_visibility(ctor,0,Pclass(ctor->n_table->t_name->tp),tbl,curr_fct); ! 854: } ! 855: else if (cl->has_ctor()) { ! 856: error("M%n[] needsIr (no defaultK forC %s)",m,cl->string); ! 857: } ! 858: } ! 859: else if (t->is_ref()) { ! 860: error("RM%n needsIr",m); ! 861: } ! 862: else if (t->tconst() && vec_const==0) { ! 863: error("constM%n needsIr",m); ! 864: } ! 865: ! 866: if (ee) { ! 867: ee->simpl(); ! 868: init_list = init_list ? new expr(CM,init_list,ee) : ee; ! 869: } ! 870: } // for m ! 871: //error('d',"ctor->"); ! 872: return ass_count; ! 873: } ! 874: ! 875: void fct::simpl() ! 876: /* ! 877: call only for the function definition (body != 0) ! 878: ! 879: simplify argument initializers, and base class initializer, if any ! 880: then simplify the body, if any ! 881: ! 882: for constructor:call allocator if this==0 and this not assigned to ! 883: (auto and static objects call constructor with this!=0, ! 884: the new operator generates calls with this==0) ! 885: call base & member constructors ! 886: for destructor: call deallocator (no effect if this==0) ! 887: case base & member destructors ! 888: ! 889: for arguments and function return values look for class objects ! 890: that must be passed by constructor X(X&). ! 891: ! 892: Allocate temporaries for class object expressions, and see if ! 893: class object return values can be passed as pointers. ! 894: ! 895: call constructor and destructor for local class variables. ! 896: */ ! 897: { ! 898: Pexpr th = f_this; ! 899: Ptable tbl = body->memtbl; ! 900: Pstmt ss = 0; ! 901: Pstmt tail; ! 902: Pclass cl = th ? Pclass(Pbase(Pptr(th->tp)->typ)->b_name->tp) : 0; ! 903: Pstmt dtail = 0; ! 904: ! 905: Pname ocurr_fct = curr_fct; ! 906: int oret = no_of_returns; ! 907: int oim = imeasure; ! 908: ! 909: //error('d',"fct::simpl %n %t",curr_fct,this); ! 910: // not_inl = f_inline==0; ! 911: del_list = 0; ! 912: continue_del_list = 0; ! 913: break_del_list = 0; ! 914: scope = tbl; ! 915: if (scope == 0) error('i',"F::simpl()"); ! 916: int ass_count = 0; ! 917: imeasure = 0; ! 918: no_of_returns = 0; ! 919: ! 920: cc->stack(); ! 921: cc->nof = curr_fct; ! 922: cc->ftbl = tbl; ! 923: ! 924: // modification for local classes defined within inline functions ! 925: extern Plist local_class; ! 926: // error( 'd', "simpl local_class: %d", local_class ); ! 927: for ( Plist l = local_class; l; l = l->l ) { ! 928: Pname n = l->f; ! 929: Pclass cl = Pclass(Pbase(n->tp)->b_name->tp); ! 930: if ( cl->in_fct == 0 ) cl->in_fct = cc->nof; ! 931: if ( cl->lcl == 0 ) cl->lcl = make_name( 'L' ); ! 932: if ( cl->c_body == 1 ) cl->dcl_print(0); ! 933: } ! 934: ! 935: Pfct(cc->nof->tp)->local_class = local_class; ! 936: local_class = 0; ! 937: // error( 'd', "simpl nof: %n %d local_class: %d", cc->nof, cc->nof, Pfct(cc->nof->tp)->local_class ); ! 938: ! 939: switch (curr_fct->n_scope) { ! 940: case 0: ! 941: case PUBLIC: ! 942: cc->not = curr_fct->n_table->t_name; ! 943: cc->cot = Pclass(cc->not->tp); ! 944: cc->tot = cc->cot->this_type; ! 945: } ! 946: ! 947: switch (curr_fct->n_oper) { ! 948: case DTOR: ! 949: dtail = dtor_simpl(cl,th); ! 950: break; ! 951: case CTOR: ! 952: ass_count = ctor_simpl(cl,th); ! 953: } ! 954: ! 955: tail = body->simpl(); ! 956: ! 957: if (returns->base!=VOID || f_result) { // return must have been seen ! 958: if (no_of_returns) { // could be OK ! 959: Pstmt tt = (tail->base==RETURN || tail->base==LABEL) ? tail : trim_tail(tail); ! 960: ! 961: switch (tt->base) { ! 962: case RETURN: ! 963: case GOTO: ! 964: del_list = 0; // no need for del_list ! 965: break; ! 966: case SM: ! 967: if (tt->e) ! 968: switch (tt->e->base) { ! 969: case ICALL: ! 970: case G_CALL: ! 971: goto chicken; ! 972: } ! 973: default: ! 974: if (warning_opt || strcmp(curr_fct->string,"main")) ! 975: error('w',"maybe no value returned from%n",curr_fct); ! 976: case IF: ! 977: case SWITCH: ! 978: case DO: ! 979: case WHILE: ! 980: case FOR: ! 981: case LABEL: ! 982: chicken: // don't dare write a warning ! 983: break; ! 984: } ! 985: } ! 986: else { // must be an error ! 987: // but we don't dare complain about main() ! 988: // if (strcmp(curr_fct->string,"main")) ! 989: // error(Pfct(curr_fct->tp)->returns->is_cl_obj()?0:'w',"no value returned from%n",curr_fct); ! 990: // else if (warning_opt) ! 991: // error('w',"no value returned from%n",curr_fct); ! 992: if (Pfct(curr_fct->tp)->f_inline ! 993: && Pfct(curr_fct->tp)->returns!=void_type ! 994: && Pfct(curr_fct->tp)->returns->is_cl_obj()) ! 995: // can cause code generation errors if allowed ! 996: error("no value returned from%n",curr_fct); ! 997: else if (warning_opt || strcmp(curr_fct->string,"main")) ! 998: error('w',"no value returned from%n",curr_fct); ! 999: } ! 1000: if (del_list) goto zaq; ! 1001: } ! 1002: else if (del_list) { // return may not have been seen ! 1003: zaq: ! 1004: if (tail) ! 1005: tail->s_list = del_list; ! 1006: else ! 1007: body->s = del_list; ! 1008: tail = dtail; ! 1009: } ! 1010: ! 1011: if (curr_fct->n_oper == DTOR) { // body => if (this == 0) body ! 1012: ! 1013: // reset the vptrs that were set by this class ! 1014: for (Pvirt blist = cl->virt_list; blist; blist = blist->next) { ! 1015: //error('d',"vptr init %s in %s",blist->string,cl->string); ! 1016: topclass = cl; ! 1017: Pexpr vp = cl->get_vptr_exp(blist->string); ! 1018: ! 1019: extern char *make_local_name(Pclass, int=0); ! 1020: char *str = 0; ! 1021: if ( cl->lex_level ) str = make_local_name( cl ); ! 1022: Pexpr vtbl = new text_expr(blist->string,str?str:cl->string); ! 1023: ! 1024: Pexpr ee = new ref(REF,th,vp); ! 1025: ee->tp = vp->tp; ! 1026: ee = new expr(ASSIGN,ee,vtbl); ! 1027: Pstmt es = new estmt(SM,curloc,ee,0); ! 1028: es->s_list = body->s; ! 1029: body->s = es; ! 1030: } ! 1031: ! 1032: body->s = new ifstmt(body->where,th,body->s,0); ! 1033: } ! 1034: ! 1035: if (curr_fct->n_oper == CTOR) { ! 1036: ! 1037: if (Pname(th)->n_assigned_to == 0) { ! 1038: /* generate: ! 1039: if (this || (this=_new( sizeof(class cl) ))) { ! 1040: init_list ; ! 1041: body; ! 1042: } ! 1043: */ ! 1044: Pname(th)->n_assigned_to = ass_count ? ass_count : FUDGE111; ! 1045: Pexpr sz = new texpr(SIZEOF,cl,0); ! 1046: (void) cl->tsizeof(); ! 1047: sz->tp = uint_type; ! 1048: Pexpr ee = new expr(ELIST,sz,0); ! 1049: Pname n = new name(oper_name(NEW)); ! 1050: Pexpr p = find_name(n,cl,scope,CALL,curr_fct); ! 1051: //error('d',"in ctor %n call %n",curr_fct,p); ! 1052: ee = new call(p,ee); ! 1053: ee->tp = ee->call_fct(cl->memtbl); ! 1054: ee->simpl(); ! 1055: ee = new expr(ASSIGN,th,ee); ! 1056: ee = new expr(OROR,th,ee); ! 1057: /*ifs->simpl(); ! 1058: do not simplify ! 1059: or "this = " will cause an extra call of base::base ! 1060: */ ! 1061: if (init_list) { ! 1062: Pstmt es = new estmt(SM,body->where,init_list,0); ! 1063: es->s_list = body->s; ! 1064: body->s = es; ! 1065: // if (tail == 0) tail = es; ! 1066: } ! 1067: else if (body->s == 0) ! 1068: body->s = new estmt(SM,body->where,0,0); ! 1069: ifstmt* ifs = new ifstmt(body->where,ee,body->s,0); ! 1070: body->s = ifs; ! 1071: // if (tail == 0) ! 1072: tail = ifs; ! 1073: } ! 1074: // generate: body; return this; ! 1075: Pstmt st = new estmt(RETURN,curloc,th,0); ! 1076: if (tail) ! 1077: tail->s_list = st; ! 1078: else ! 1079: body->s = st; ! 1080: tail = st; ! 1081: } ! 1082: f_imeasure = imeasure; ! 1083: curr_fct = ocurr_fct; ! 1084: no_of_returns = oret; ! 1085: imeasure = oim; ! 1086: cc->unstack(); ! 1087: } ! 1088: ! 1089: ! 1090: void classdef::simpl() ! 1091: { ! 1092: int i; ! 1093: //error('d',"classdef::simpl %s %d",string,defined&SIMPLIFIED); ! 1094: ! 1095: if (defined&SIMPLIFIED) return; ! 1096: ! 1097: Pclass oc = in_class; ! 1098: in_class = this; ! 1099: ! 1100: for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) { ! 1101: Pexpr i = m->n_initializer; ! 1102: m->n_initializer = 0; ! 1103: m->simpl(); ! 1104: m->n_initializer = i; ! 1105: } ! 1106: ! 1107: in_class = oc; ! 1108: ! 1109: for (Plist fl=friend_list; fl; fl=fl->l) { // simplify friends ! 1110: Pname p = fl->f; ! 1111: switch (p->tp->base) { ! 1112: case FCT: ! 1113: case OVERLOAD: ! 1114: p->simpl(); ! 1115: } ! 1116: } ! 1117: ! 1118: defined |= SIMPLIFIED; ! 1119: } ! 1120: ! 1121: ! 1122: ! 1123: ! 1124: Pexpr initialize_vptrs (Pclass cl, Pexpr this_expr) ! 1125: ! 1126: /* Constructs an expression which initializes the given class's vptrs. ! 1127: The this_expr forms the first part of the path expression for each ! 1128: vptr assignment. The vptr assignments are combined into a comma ! 1129: expression. */ ! 1130: ! 1131: { ! 1132: ! 1133: Pexpr init_list = 0; ! 1134: ! 1135: ! 1136: /* initialize the vptrs that are updated by this class */ ! 1137: ! 1138: for (Pvirt blist = cl->virt_list; blist; blist = blist->next) { ! 1139: ! 1140: topclass = cl; ! 1141: Pexpr vptr_exp = cl->get_vptr_exp(blist->string); ! 1142: ! 1143: extern char *make_local_name(Pclass, int=0); ! 1144: char *str = 0; ! 1145: if ( cl->lex_level ) str = make_local_name(cl); ! 1146: Pexpr vtbl = new text_expr(blist->string,str?str:cl->string); ! 1147: ! 1148: Pexpr ee; ! 1149: if (this_expr) ! 1150: ee = new ref(REF, this_expr, vptr_exp); ! 1151: else ! 1152: ee = vptr_exp; ! 1153: ! 1154: ee->tp = vptr_exp->tp; ! 1155: ee = new expr(ASSIGN, ee, vtbl); ! 1156: init_list = init_list ? new expr(CM, init_list, ee) : ee; ! 1157: } ! 1158: ! 1159: return init_list; ! 1160: ! 1161: } /* initialize_vptrs */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.