|
|
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.