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