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