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