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