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