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