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