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