|
|
1.1 root 1: /*ident "@(#)ctrans:src/expand.c 1.5" */
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: expand.c:
11:
12: expand inline functions
13:
14: ******************************************************************/
15:
16: #include "cfront.h"
17: static Ptable Scope;
18: // extern void display_expr(Pexpr);
19:
20: static char* temp(char* vn, Pname fn)
21: //
22: // make the name of the temporary: __Xvn00xxxxxx
23: // xxxxxx is a representation of fn's address -
24: // anything unique will do. we use radix 32 here
25: // add two bytes to make the name sensitive to the scope
26: // to avoid re-using temps when an inline is expanded in
27: // more than one other inline that is then called in the
28: // same expression
29: //
30: {
31: if (vn[0]!='_' || vn[1]!='_' || vn[2]!='X') {
32: unsigned long a = (unsigned long) fn->tp;
33:
34: // al = the number of radix-32 chars in a
35: unsigned long aa = a;
36: int al = 0;
37: while (aa) {
38: al++;
39: aa >>= 5;
40: }
41:
42: // allocate memory for the result
43: int ll = strlen(vn);
44: char* s = new char[ll+al+8];
45: register char* p = s;
46:
47: // append _ _ X vn
48: *p++ = '_';
49: *p++ = '_';
50: *p++ = 'X';
51: strcpy(p,vn);
52: p += ll;
53: *p++ = '0';
54: *p++ = '0';
55:
56: // append representation of `a'
57: while (a) {
58: *p++ = "abcdefghijklmnopqrstuvwxyz012345"[a&037];
59: a >>= 5;
60: }
61:
62: // append scope representation and trailing null
63: *p++ = 'a' + ((int(Scope)>>4)&15);
64: *p++ = 'a' + ((int(Scope)>>8)&15);
65: *p = '\0';
66: //tmp error('d',"temp(%s,%n) -- scope %d -- returning %s",vn,fn,scope,s);
67: return s;
68: }
69: else {
70: //tmp error('d',"temp(%s,%n) -- scope %d -- returning %s",vn,fn,scope,vn);
71: return vn;
72: }
73:
74: }
75:
76: Pnlist inllist; // keep track of ctors defined inline so dtors won't be called if succeeding goto
77:
78: Pname dcl_local(Ptable scope, Pname an, Pname fn)
79: {
80: if (scope == 0 || scope->base == 0) {
81: if (sti_tbl == 0) sti_tbl = new table(8,gtbl,0);
82: scope = sti_tbl;
83: // error('s',"cannot expand inlineF needing temporaryV in nonF context");
84: // return an;
85: }
86:
87: if (an->n_stclass == STATIC) {
88: if (an->tp->base!=FCT) error('s',&fn->where,"cannot expand inlineF with static%n",an);
89: return an;
90: }
91:
92: Pname cn = fn->n_table->t_name;
93: char* s = temp(an->string,fn);
94: Pname nx = new name(s);
95: Ptype atp = an->tp;
96: //error('d',"dcl_local(%d,%n,%n) -> %s",scope,an,fn,s);
97: while (atp->base == TYPE) atp = Pbase(atp)->b_name->tp;
98: if (atp->base == VEC) {
99: if (an->n_scope == ARG) {
100: Pptr t = new ptr(PTR,Pvec(atp)->typ);
101: nx->tp = t;
102: }
103: else {
104: error('s',&fn->where,"cannot expand inlineF needing temporaryV of vectorT");
105: return an;
106: }
107: }
108: else
109: nx->tp = atp;
110: PERM(nx->tp);
111:
112: nx->n_used = an->n_used;
113: nx->n_assigned_to = an->n_assigned_to;
114: nx->n_addr_taken = an->n_addr_taken;
115: nx->n_xref = an->n_xref;
116: //error('d',"nx %n %t,",nx,nx->tp);
117: Pname r = scope->look(nx->string,0);
118: if (r) {
119: //error('d',"ll %n %t",ll,ll->tp);
120: if (r->tp->check(nx->tp,0))
121: error('s',&fn->where,"cannot expand inlineF %n with two local variables with the sameN (%s)",fn,an->string);
122: else
123: r = 0;
124: }
125: if (r==0) {
126: r = scope->insert(nx,0);
127: //error('d',"%d %d %d %d",r->n_stclass,an->n_stclass,r->lex_level,an->lex_level);
128:
129: if (r->tp->base==COBJ) {
130: if (inllist==0)
131: inllist = new nlist(r);
132: else inllist->add(r);
133: }
134:
135: r->n_stclass = an->n_stclass;
136: r->lex_level = an->lex_level;
137: delete nx;
138: r->where.line = 0;
139: }
140: return r;
141: }
142:
143: int ck_cast(Ptype t1, Ptype t2)
144: /*
145: return a value of type t2 from a function returning a t1
146: return 1 if cast is needed
147: */
148: {
149: st:
150: while (t1->base == TYPE) t1 = Pbase(t1)->b_name->tp;
151: while (t2->base == TYPE) t2 = Pbase(t2)->b_name->tp;
152:
153: if (t1 == t2) return 0;
154:
155: if (t1->base != t2->base) return 1;
156:
157: switch (t1->base) {
158: case RPTR:
159: case PTR:
160: { t1 = Pptr(t1)->typ;
161: if (t1->base == VOID) return 1;
162: t2 = Pptr(t2)->typ;
163: goto st;
164: }
165: case CHAR:
166: case SHORT:
167: case INT:
168: case LONG:
169: if (Pbase(t1)->b_unsigned != Pbase(t2)->b_unsigned) return 1;
170: break;
171: case COBJ:
172: {
173: Pname nn = Pbase(t1)->b_name;
174:
175: if (Pclass(nn->tp)->csu==UNION ) return 0;
176:
177: if (t2->base==COBJ && nn->tp==Pbase(t2)->b_name->tp) return 0;
178:
179: return 1;
180: }
181: }
182:
183: return 0;
184: }
185:
186: int makeCM( Ptype t )
187: /* return 1 if the type is not a primitive type
188: * this will cause the generation of (t,0)
189: * note: ``t'' is guaranteed not to be 0
190: */
191: {
192: while ( t->base == TYPE )
193: t = Pbase(t)->b_name->tp;
194:
195: switch (t->base) {
196: case FLOAT:
197: case DOUBLE:
198: case LDOUBLE:
199: case CHAR:
200: case SHORT:
201: case INT:
202: case LONG:
203: case EOBJ:
204: return 0;
205: default:
206: return 1;
207: }
208: }
209:
210: static ret_seen = 0;
211:
212: Pstmt stmt::expand()
213: /*
214: copy the statements with the formal arguments replaced by ANAMES
215:
216: called once only per inline function
217: expand_tbl!=0 if the function should be transformed into an expression
218: and expand_tbl is the table for local variables
219: */
220: {
221: if (this == 0) error('i',"0->S::expand() for%n",expand_fn);
222: Pstmt ostmt = Cstmt;
223: if ( where.line ) Cstmt = this;
224:
225: if (memtbl) { /* check for static variables */
226: register Ptable t = memtbl;
227: register int i;
228: for (register Pname n = t->get_mem(i=1); n; n=t->get_mem(++i)) {
229: if (n->n_stclass == STATIC) {
230: if (n->tp->base == FCT) continue;
231: error('s',"cannot expand inlineF with static%n",n);
232: n->n_stclass = AUTO;
233: }
234: n->where.line = 0;
235: }
236: }
237:
238: if (expand_tbl) { /* make expression */
239: Pexpr ee;
240:
241: if (memtbl) { // temporaries
242: int i;
243: for (Pname n=memtbl->get_mem(i=1); n; n=memtbl->get_mem(++i)) {
244: //error('d',"block %n %k %d %d",n,base,memtbl->real_block == this,n->lex_level);
245: if (n->base!=NAME || n->tp==any_type) continue;
246:
247: if (base==BLOCK
248: && memtbl->real_block == this
249: && n->lex_level < 2
250: && (n->string[0]!='_' // promoted from called
251: // inlines
252: || n->string[1]!='_'
253: || ( n->string[2]!='X'
254: && n->string[2]!='K'))
255: ) {
256: //error('d',"not promoting%n",n);
257: continue;
258: }
259:
260: if (memtbl != scope)
261: {
262: Pname nn = dcl_local(scope,n,expand_fn);
263: nn->base = NAME;
264: n->string = nn->string;
265: }
266: else if (n->tp->base!=FCT && n->tp->base!=OVERLOAD){
267: n->string = temp(n->string, expand_fn);
268: n->where.line = 0;
269: }
270: }
271: }
272:
273: switch (base) {
274: default:
275: error('s',"cannot expand inlineF%n with %kS in inline",expand_fn,base);
276: Cstmt = ostmt;
277: return Pstmt(dummy);
278:
279: case BLOCK:
280: DB(if(Edebug>=2){error('d',"stmt::expand() -- block");display_stmt(this);});
281: if (s_list) {
282: ee = Pexpr(s_list->expand());
283: if (s) {
284: ee = new expr(CM, Pexpr(s->expand()), ee);
285: ee->tp = ee->e2->tp;
286: PERM(ee);
287: }
288: Cstmt = ostmt;
289: return Pstmt(ee);
290: }
291:
292: if (s) {
293: Pstmt st = s->expand();
294: Cstmt = ostmt;
295: return st;
296: }
297:
298: Cstmt = ostmt;
299: return Pstmt(zero);
300:
301: case PAIR:
302: ee = s2 ? Pexpr(s2->expand()) : 0;
303: ee = new expr(CM, s?Pexpr(s->expand()):0, ee);
304: ee->tp = ee->e2->tp;
305: if (s_list) {
306: ee = new expr(CM, ee, Pexpr(s_list->expand()));
307: ee->tp = ee->e2->tp;
308: }
309: PERM(ee);
310: Cstmt = ostmt;
311: return Pstmt(ee);
312:
313: case RETURN:
314: ret_seen = 1;
315: s_list = 0;
316:
317: if (e == 0)
318: ee = zero;
319: else {
320: ee = e->expand();
321: Ptype tt = Pfct(expand_fn->tp)->returns;
322: if (tt == 0) tt = Pfct(expand_fn->tp)->returns;
323: //error('d',"return::expand() -- ee==%k tt==%t",ee?ee->base:0,tt);
324: //display_expr(ee);
325: if (tt!=ee->tp && ck_cast(tt,ee->tp)) ee = new cast(tt,ee);
326: }
327:
328: Cstmt = ostmt;
329: return Pstmt(ee);
330:
331: case SM:
332: if (e== 0 || e==dummy)
333: ee = zero;
334: else {
335: if (e->base == DEREF) e = e->e1;
336: ee = e->expand();
337: }
338: // no break;
339:
340: case ASM:
341: if (s_list) {
342: ee = new expr(CM, ee, (Pexpr)s_list->expand());
343: ee->tp = ee->e2->tp;
344: PERM(ee);
345: }
346: Cstmt = ostmt;
347: return (Pstmt)ee;
348:
349: case IF:
350: {
351: int ors = ret_seen;
352: ret_seen = 0;
353: ee = Pexpr(s->expand());
354: if(ee->base==ASSIGN && ee->e1->tp &&
355: ee->e1->tp->base != PTR)
356: ee = new expr(G_CM,ee,zero);
357: Pexpr qq = new expr(QUEST,ee,zero);
358: int ret1 = ret_seen;
359: ret_seen = 0;
360:
361: qq->cond = e->expand();
362: qq->e2 = else_stmt ? Pexpr(else_stmt->expand()) : zero;
363: int ret2 = ret_seen;
364: if (ret1+ret2 && s_list) {
365: error('s',"cannot expand inlineF%n with S after \"return\"",expand_fn);
366: ret_seen = 0;
367: }
368: ret_seen += ret1;
369: ret_seen += ret2;
370: ret_seen += ors;
371:
372: // handle ``if (x) class_object_valued_expression;''
373:
374: Ptype t1 = qq->e1->tp;
375: if (qq->e1->base == G_CM)
376: t1=qq->e1->e1->tp;
377: Ptype t2 = qq->e2->tp;
378:
379: if (t1 && t1->base==FCT)
380: t1 = Pfct(t1)->s_returns ? Pfct(t1)->s_returns : Pfct(t1)->returns;
381:
382: if (t2 && t2->base==FCT)
383: t2 = Pfct(t2)->s_returns ? Pfct(t2)->s_returns : Pfct(t2)->returns;
384:
385: Pname c1 = t1?t1->is_cl_obj():0;
386: Pname c2 = t2?t2->is_cl_obj():0;
387:
388: int z1 = c1 && c1!=c2;
389: int z2 = c2 && c1!=c2;
390:
391: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
392: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
393: //display_expr(qq);
394: if (c1==0
395: && c2==0
396: && t1
397: && t2
398: && t2->check(t1,ASSIGN)
399: && t1->check(t2,ASSIGN)) {
400: z1 = makeCM( t1 );
401: z2 = makeCM( t2 );
402: if ((z1 && ret1) || (z2 && ret2))
403: error('s',"cannot expand inlineF with return in ifS");
404: }
405:
406: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
407: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
408: //display_expr(qq);
409: if (t1 && z1==0) {
410: // since zero is acceptable to all pointer types
411: // we need only ``fix'' z1 and z2 will take care
412: // of itself
413: z1 = t1->is_ptr_or_ref()
414: && t2
415: && t2->is_ptr_or_ref()
416: && t1->check(t2,0)
417: && !const_problem;
418: }
419:
420: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
421: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
422: //display_expr(qq);
423: if (z1) {
424: Pexpr v = (z2==0 && (t2->is_ptr_or_ref())) ? new cast(t2,zero) : zero;
425: qq->e1 = new expr(CM,qq->e1,v);
426: qq->e1->tp = qq->e1->e1->tp;
427: }
428:
429: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
430: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
431: //display_expr(qq);
432: if (z2) {
433: Pexpr v = (z1==0 && (t1->is_ptr_or_ref())) ? new cast(t1,zero) : zero;
434: qq->e2 = new expr(CM,qq->e2,v);
435: qq->e2->tp = qq->e2->e1->tp;
436: }
437:
438: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
439: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
440: //display_expr(qq);
441: if (s_list) {
442: qq = new expr(CM,qq,Pexpr(s_list->expand()));
443: qq->tp = qq->e2->tp;
444: }
445: else
446: qq->tp = qq->e1->tp;
447: PERM(qq);
448: Cstmt = ostmt;
449: return Pstmt(qq);
450: }
451: }
452: }
453:
454: where.line = 0;
455:
456: switch (base) {
457: default:
458: if (e) e = e->expand();
459: break;
460: case PAIR:
461: if (s2) s2 = s2->expand();
462: break;
463: case BLOCK:
464: break;
465: case FOR:
466: if (for_init) for_init = for_init->expand();
467: if (e2) e2 = e2->expand();
468: case ASM:
469: break;
470: // case LABEL:
471: // case GOTO:
472: case RETURN:
473: // case BREAK:
474: // case CONTINUE:
475: error('s',"cannot expand inlineF%n with %kS",expand_fn,base);
476: }
477:
478: if (s) s = s->expand();
479: if (s_list) s_list = s_list->expand();
480: PERM(this);
481: Cstmt = ostmt;
482: return this;
483: }
484:
485: Pexpr expr::expand()
486: {
487: if (this == 0) error('i',"E::expand(0)");
488:
489: switch (base) {
490: case NAME:
491: if (expand_tbl && Pname(this)->n_scope==FCT) {
492: Pname n = Pname(this);
493: char* s = n->string;
494: if (s[0]=='_' && s[1]=='_' && s[2]=='X') break;
495: Pname cn = expand_fn->n_table->t_name;
496: // n->string = temp(s,expand_fn->string,(cn)?cn->string:0);
497: n->string = temp(s,expand_fn);
498: }
499: case DUMMY:
500: case ICON:
501: case FCON:
502: case CCON:
503: case IVAL:
504: //case FVAL:
505: //case LVAL:
506: case STRING:
507: case ZERO:
508: case TEXT:
509: case ANAME:
510: case MDOT:
511: break;
512: case ICALL:
513: if (expand_tbl && e1==0) {
514: int ors = ret_seen;
515: ret_seen = 0;
516: Pname fn = il->fct_name;
517: Pfct f = Pfct(fn->tp);
518: if (f->f_expr==0
519: // f->returns==void_type
520: // && f->s_returns!=int_type
521: // && fn->n_oper!=CTOR
522: )
523: error('s',&fn->where,"cannot expand value-returning inline%n with call of non-value-returning inline%n",expand_fn,fn);
524: // else
525: // error("inline%n called before defined",fn);
526: ret_seen = ors;
527: }
528: break;
529: case SIZEOF:
530: case CAST:
531: if (tp2) PERM(tp2);
532: goto rrr;
533: case QUEST:
534: cond = cond->expand();
535: default:
536: if (e2) e2 = e2->expand();
537: case REF:
538: case DOT:
539: rrr:
540: if (e1) e1 = e1->expand();
541: break;
542: }
543:
544: switch (base) {
545: case CM:
546: case G_CM:
547: if (tp==0) tp=e2->tp;
548: }
549:
550: PERM(this);
551: return this;
552: }
553:
554: int nin;
555:
556: static int watch_out;
557: bit expr::not_simple()
558: /*
559: is a temporary variable needed to hold the value of this expression
560: as an argument for an inline expansion?
561: return 1; if side effect
562: return 2; if modifies expression
563: */
564: {
565: int s;
566: //error('d',"not_simple%k",base);
567: switch (base) {
568: default:
569: return 2;
570: case NAME:
571: if (nin==0 && Pname(this)->n_table==gtbl) return 2; // unsafe: aliasing
572: case ZERO:
573: case IVAL:
574: //case FVAL:
575: case ICON:
576: case CCON:
577: case FCON:
578: return 0;
579: case STRING:
580: ::watch_out = 1;
581: return 0;
582: case MDOT:
583: return mem->not_simple();
584: case SIZEOF:
585: return (e1==0 || e1==dummy) ? 0 : e1->not_simple();
586: case G_ADDROF:
587: case ADDROF:
588: return e2->not_simple();
589: case CAST:
590: return e1->not_simple();
591: case DOT:
592: ::watch_out = 1;
593: return e1->not_simple();
594: case REF:
595: ::watch_out = 1;
596: return e1->not_simple();
597: case UMINUS:
598: case NOT:
599: case COMPL:
600: return e2->not_simple();
601: case DEREF:
602: s = e1->not_simple();
603: if (1<s) return 2;
604: if (e2==0) return s;
605: return s |= e2->not_simple();
606: case MUL:
607: case DIV:
608: case MOD:
609: case PLUS:
610: case MINUS:
611: case LS:
612: case RS:
613: case AND:
614: case OR:
615: case ER:
616: case LT:
617: case LE:
618: case GT:
619: case GE:
620: case EQ:
621: case NE:
622: case ANDAND:
623: case OROR:
624: case CM:
625: s = e1->not_simple();
626: if (1<s) return 2;
627: return s |= e2->not_simple();
628: case QUEST:
629: s = cond->not_simple();
630: if (1<s) return 2;
631: s |= e1->not_simple();
632: if (1<s) return 2;
633: return s |= e2->not_simple();
634: case ANAME:
635: if (curr_icall) {
636: Pname n = (Pname)this;
637: int argno = int(n->n_val);
638: for (Pin il=curr_icall; il; il=il->i_next)
639: if (n->n_table == il->i_table) goto aok;
640: goto bok;
641: aok:
642: return (il->i_args[argno].local) ? 0 : il->i_args[argno].arg->not_simple();
643: }
644: bok: error('i',"expand aname%n",this);
645: case G_CM:
646: case VALUE:
647: case NEW:
648: case GNEW:
649: case CALL:
650: case G_CALL:
651: case ICALL:
652: case ASSIGN:
653: case INCR:
654: case DECR:
655: case ASPLUS:
656: case ASMINUS:
657: case ASMUL:
658: case ASDIV:
659: case ASMOD:
660: case ASAND:
661: case ASOR:
662: case ASER:
663: case ASLS:
664: case ASRS:
665: return 2;
666: }
667: }
668:
669: extern void uninline(Pname fn);
670: //extern Pname new_fct;
671: //extern Pname del_fct;
672: extern Pstmt del_list;
673: extern Pstmt break_del_list;
674: extern Pstmt continue_del_list;
675: extern Pname curr_fct;
676: extern Pexpr init_list;
677:
678: extern Pname make_default_ctor(Pclass cl);
679: void expand_itor(Pclass cl)
680: {
681: //error('d',"expand_itor(%t)",cl);
682: Pexpr s2 = curr_expr;
683: Pstmt s5 = del_list;
684: Pstmt s6 = break_del_list;
685: Pstmt s7 = continue_del_list;
686: Pname s8 = curr_fct;
687: Pexpr s9 = init_list;
688: (void) cl->make_itor(1);
689: curr_expr = s2;
690: del_list = s5;
691: break_del_list = s6;
692: continue_del_list = s7;
693: curr_fct = s8;
694: init_list = s9;
695: }
696: /*
697: extern Pname make_default_dtor(Pclass cl);
698: void expand_dtor(Pclass cl)
699: {
700: //error('d',"expand_itor(%t)",cl);
701: Pexpr s2 = curr_expr;
702: Pstmt s5 = del_list;
703: Pstmt s6 = break_del_list;
704: Pstmt s7 = continue_del_list;
705: Pname s8 = curr_fct;
706: Pexpr s9 = init_list;
707: (void) make_default_dtor(cl);
708: curr_expr = s2;
709: del_list = s5;
710: break_del_list = s6;
711: continue_del_list = s7;
712: curr_fct = s8;
713: init_list = s9;
714: }
715:
716:
717: void expand_ictor(Pclass cl)
718: {
719: //error('d',"expand_itor(%t)",cl);
720: Pexpr s2 = curr_expr;
721: Pstmt s5 = del_list;
722: Pstmt s6 = break_del_list;
723: Pstmt s7 = continue_del_list;
724: Pname s8 = curr_fct;
725: Pexpr s9 = init_list;
726: (void) make_default_ctor(cl);
727: curr_expr = s2;
728: del_list = s5;
729: break_del_list = s6;
730: continue_del_list = s7;
731: curr_fct = s8;
732: init_list = s9;
733: }
734: */
735: Pexpr fct::expand(Pname fn, Ptable scope, Pexpr ll)
736: /*
737: expand call to (previously defined) inline function in "scope"
738: with the argument list "ll"
739: (1) declare variables in "scope"
740: (2) initialize argument variables
741: (3) link to body
742: */
743: {
744: Scope = scope;
745: //error('d',"expand%s() body %d f_expr %d inline %d",fn->string,body,f_expr,f_inline);
746: if (f_inline == ITOR) {
747: Pexpr s1 = last_expanded;
748: expand_itor(memof);
749: last_expanded = s1;
750: last_stmt = stmtno;
751: this = Pfct(fn->tp);
752: if (f_inline==0 && f_imeasure) {
753: uninline(fn);
754: return 0;
755: }
756: }
757:
758: //error('d',"expand %n body %d f_expr %d defined %d",fn,body,f_expr,defined);
759: //error('d',"inline %d memtbl %d scope %d",f_inline,Pfct(fn->tp)->body->memtbl,scope);
760: //display_stmt(body);
761: if ((body==0 && f_expr==0) // before defined
762: || ((defined&SIMPLIFIED)==0) // before simplified
763: || (Pfct(fn->tp)->body->memtbl==scope) // while defining
764: || (f_inline>1) // recursive call
765: ) { // so don't expand
766: if (warning_opt) error('w',"cannot inline%n in thisE",fn);
767: if (fn->n_addr_taken++==0) fn->dcl_print(0);
768: return 0;
769: }
770:
771: if (fn->n_oper==CTOR) {
772: Pclass cl = Pclass(fn->n_table->t_name->tp);
773: if (cl->c_body == 3) cl->print_all_vtbls(cl);
774: }
775:
776: Pin il = new iline;
777: Pexpr ic = new texpr(ICALL,0,0);
778: int ns = 0;
779: for (Pname an = f_args; an; an=an->n_list) ns++;
780: il->fct_name = fn;
781: il->i_args = new ia[il->i_slots = ns];
782: ic->il = il;
783: ic->tp = s_returns ? s_returns : returns;
784: // Pname at = (f_this) ? f_this : (f_result) ? f_result : argtype;
785: Pname at = f_args;
786:
787: f_inline++;
788:
789: if (at) il->i_table = at->n_table;
790: int i = 0;
791: int not_simple = 0; /* is a temporary argument needed? */
792:
793: for (Pname n=at; n; n=n->n_list, i++) {
794: /* check formal/actual argument pairs
795: and generate temporaries as necessary
796: */
797:
798: if (ll == 0) error('i',"F::expand(%n):AX",fn);
799: Pexpr ee;
800:
801: if (ll->base == ELIST) {
802: ee = ll->e1;
803: ll = ll->e2;
804: }
805: else {
806: ee = ll;
807: ll = 0;
808: }
809:
810: /* could be avoided when expanding into a block */
811: il->i_args[i].local = 0;
812: int s ;
813:
814: // try to protect agains aliasing through pointers and references
815: for (Pname m=at; m; m=m->n_list) {
816: Pptr p;
817: if (n!=m) {
818: // if ((p=m->tp->is_ptr()) || (p=m->tp->is_ref()))
819: if (p=m->tp->is_ptr_or_ref())
820: if (p->check(n->tp,0)==0 || p->typ->check(n->tp,0)==0) goto zxc;
821:
822: }
823: }
824:
825: ::watch_out = 0;
826: int notsimple; notsimple = ee->not_simple();
827: if ( notsimple==0 && ::watch_out && n->n_used > 1 ) goto zxc;
828: if (n->n_assigned_to==FUDGE111
829: && ee!=zero
830: && notsimple==0) {
831: if (ee && ee->e1 && (ee->e1->base == NAME) &&
832: (! strcmp (ee->e1->string,"this"))) goto zxc;
833: }
834: else if (n->n_addr_taken || n->n_assigned_to)
835: goto zxc;
836: else if (s=notsimple) {
837: if (/*n->n_used==0 // n_used not set for ``this''
838: || */1<s
839: || 1<n->n_used ) { // not safe
840: zxc:
841: if (last_expanded && last_expanded==curr_expr && last_stmt==stmtno) {
842: if (warning_opt)
843: error('w',"%n not inlined, called twice in an expression",fn);
844: f_inline--;
845: delete il->i_args;
846: delete il;
847: if (fn->n_addr_taken++==0) fn->dcl_print(0);
848: return 0;
849: }
850: //error('d',"zxc %n %t ee %d %t",n,n->tp,ee->base,ee->tp);
851: if (ee && ee->tp && (ee->tp->base==EOBJ) && ansi_opt)
852: ; // do nothing
853: else {
854: Pname nn = dcl_local(scope,n,fn);
855: nn->base = NAME;
856: il->i_args[i].local = nn;
857: ++not_simple;
858: // if (nn->tp->is_ref()
859: // && ee->tp
860: // && ee->tp->is_ptr_or_ref()==0) ee = ee->address();
861: }
862: }
863: }
864:
865: il->i_args[i].arg = ee;
866: il->i_args[i].tp = n->tp;
867: }
868:
869: Ptable tbl = body->memtbl;
870: if (f_expr) { // generate comma expression
871:
872: char loc_var = 0;
873:
874: /* look for local variables needing declaration: */
875: for (n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i) ) {
876: //error('d',"n %n %d",n,n->base);
877: //error('d',"loc %n %d %d %d",n,n->n_used,n->n_assigned_to,n->n_addr_taken);
878: if (n->base==NAME // don't re-declare the args
879: && (n->tp->base!=FCT && n->tp->base!=OVERLOAD)
880: && (n->n_used || n->n_assigned_to || n->n_addr_taken)) {
881: if (last_expanded && last_expanded==curr_expr && last_stmt == stmtno) {
882: if (warning_opt) error('w',"cannot inline%n in thisE",fn);
883: f_inline--;
884: delete il->i_args;
885: delete il;
886: if (fn->n_addr_taken++==0) fn->dcl_print(0);
887: return 0;
888: }
889: Pname nn = dcl_local(scope,n,fn);
890: nn->base = NAME;
891: n->string = nn->string;
892:
893: loc_var++;
894: }
895: }
896:
897: if (i /*not_simple*/ || loc_var) {
898: if(!curr_expr) curr_expr = dummy;
899: last_expanded = curr_expr;
900: last_stmt = stmtno;
901: }
902:
903: Pexpr ex;
904: if (not_simple) {
905: Pexpr etail = ex = new expr(CM,0,0);
906: for (i=0; i<il->i_slots; i++) {
907: Pname n = il->i_args[i].local;
908: if (n == 0) continue;
909: Pexpr e = il->i_args[i].arg;
910: // if used assign
911: // otherwise (e.g. unused argument)
912: // simply evaluate for sideeffects
913: if (n->n_used
914: || n->n_assigned_to
915: || n->n_addr_taken) {
916: Pexpr mptr_assign(Pexpr n, Pexpr in);
917: Pptr p1 = n->tp->is_ptr();
918: Pptr p2 = e->tp ? e->tp->is_ptr() : 0;
919: if (p1 && p1->memof && p1!=p2) {
920: switch (e->base) {
921: case CM:
922: case G_CM:
923: e->e2 = mptr_assign(n,e->e2);
924: break;
925: case ICALL:
926: break;
927: default:
928: e = mptr_assign(n,e);
929: }
930: etail->e1 = e;
931: }
932: else
933: etail->e1 = new expr(ASSIGN,n,e);
934: }
935: else
936: etail->e1 = e;
937: if (--not_simple)
938: etail = etail->e2 = new expr(CM,0,0);
939: else
940: break;
941: }
942: etail->e2 = f_expr;
943: }
944: else
945: ex = f_expr;
946: ic->e1 = ex;
947: }
948: else { // generate block:
949: for (n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i) ) {
950: // mangle local names
951: if (n->base==NAME
952: && (n->n_used || n->n_assigned_to || n->n_addr_taken)) {
953: // Pname cn = fn->n_table->t_name;
954: // n->string = temp(n->string,fn->string,(cn)?cn->string:0);
955: n->string = temp(n->string,fn);
956: }
957: }
958: Pstmt ss;
959: if (not_simple) {
960: if(!curr_expr) curr_expr = dummy;
961: last_expanded = curr_expr;
962: last_stmt = stmtno;
963: Pstmt st = new estmt(SM,curloc,0,0);
964: st->where.line = 0;
965: Pstmt stail = st;
966: for (i=0; i<il->i_slots; i++) {
967: Pname n = il->i_args[i].local;
968: if (n == 0) continue;
969: Pexpr e = il->i_args[i].arg;
970: Pptr p1 = n->tp->is_ptr();
971: Pptr p2 = e->tp->is_ptr();
972: Pexpr mptr_assign(Pexpr n, Pexpr in);
973: if (p1 && p1->memof && p1!=p2) {
974: switch (e->base) {
975: case CM:
976: case G_CM:
977: e->e2 = mptr_assign(n,e->e2);
978: break;
979: default:
980: e = mptr_assign(n,e);
981: }
982: stail->e = e;
983: }
984: else
985: stail->e = new expr(ASSIGN,n,e);
986: if (--not_simple) {
987: stail = stail->s_list = new estmt(SM,curloc,0,0);
988: stail->where.line = 0;
989: }
990: else
991: break;
992: }
993: stail->s_list = body;
994: ss = new block(curloc,0,st);
995: ss->where.line = 0;
996: }
997: else
998: ss = body;
999: ic->e2 = Pexpr(ss);
1000: }
1001:
1002: f_inline--;
1003: //error('d',"expand%n -- returning%k", fn, ic?ic->base:0);
1004: //display_expr(ic);
1005: return ic;
1006: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.