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