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