|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)stat.c 1.12 9/5/83";
4:
5: #include "whoami.h"
6: #include "0.h"
7: #include "tree.h"
8: #include "objfmt.h"
9: #ifdef PC
10: # include "pcops.h"
11: # include "pc.h"
12: #endif PC
13: #include "tmps.h"
14:
15: int cntstat;
16: short cnts = 3;
17: #include "opcode.h"
18:
19: /*
20: * Statement list
21: */
22: statlist(r)
23: int *r;
24: {
25: register *sl;
26:
27: for (sl=r; sl != NIL; sl=sl[2])
28: statement(sl[1]);
29: }
30:
31: /*
32: * Statement
33: */
34: statement(r)
35: int *r;
36: {
37: register *s;
38: register struct nl *snlp;
39: struct tmps soffset;
40:
41: s = r;
42: snlp = nlp;
43: soffset = sizes[cbn].curtmps;
44: top:
45: if (cntstat) {
46: cntstat = 0;
47: putcnt();
48: }
49: if (s == NIL)
50: return;
51: line = s[1];
52: if (s[0] == T_LABEL) {
53: labeled(s[2]);
54: s = s[3];
55: noreach = 0;
56: cntstat = 1;
57: goto top;
58: }
59: if (noreach) {
60: noreach = 0;
61: warning();
62: error("Unreachable statement");
63: }
64: switch (s[0]) {
65: case T_PCALL:
66: putline();
67: # ifdef OBJ
68: proc(s);
69: # endif OBJ
70: # ifdef PC
71: pcproc( s );
72: # endif PC
73: break;
74: case T_ASGN:
75: putline();
76: asgnop(s);
77: break;
78: case T_GOTO:
79: putline();
80: gotoop(s[2]);
81: noreach = 1;
82: cntstat = 1;
83: break;
84: default:
85: level++;
86: switch (s[0]) {
87: default:
88: panic("stat");
89: case T_IF:
90: case T_IFEL:
91: ifop(s);
92: break;
93: case T_WHILE:
94: whilop(s);
95: noreach = 0;
96: break;
97: case T_REPEAT:
98: repop(s);
99: break;
100: case T_FORU:
101: case T_FORD:
102: forop(s);
103: noreach = 0;
104: break;
105: case T_BLOCK:
106: statlist(s[2]);
107: break;
108: case T_CASE:
109: putline();
110: # ifdef OBJ
111: caseop(s);
112: # endif OBJ
113: # ifdef PC
114: pccaseop( s );
115: # endif PC
116: break;
117: case T_WITH:
118: withop(s);
119: break;
120: }
121: --level;
122: if (gotos[cbn])
123: ungoto();
124: break;
125: }
126: /*
127: * Free the temporary name list entries defined in
128: * expressions, e.g. STRs, and WITHPTRs from withs.
129: */
130: nlfree(snlp);
131: /*
132: * free any temporaries allocated for this statement
133: * these come from strings and sets.
134: */
135: tmpfree(&soffset);
136: }
137:
138: ungoto()
139: {
140: register struct nl *p;
141:
142: for (p = gotos[cbn]; p != NIL; p = p->chain)
143: if ((p->nl_flags & NFORWD) != 0) {
144: if (p->value[NL_GOLEV] != NOTYET)
145: if (p->value[NL_GOLEV] > level)
146: p->value[NL_GOLEV] = level;
147: } else
148: if (p->value[NL_GOLEV] != DEAD)
149: if (p->value[NL_GOLEV] > level)
150: p->value[NL_GOLEV] = DEAD;
151: }
152:
153: putcnt()
154: {
155:
156: if (monflg == 0) {
157: return;
158: }
159: inccnt( getcnt() );
160: }
161:
162: int
163: getcnt()
164: {
165:
166: return ++cnts;
167: }
168:
169: inccnt( counter )
170: int counter;
171: {
172:
173: # ifdef OBJ
174: put(2, O_COUNT, counter );
175: # endif OBJ
176: # ifdef PC
177: putRV( PCPCOUNT , 0 , counter * sizeof (long) , NGLOBAL , P2INT );
178: putleaf( P2ICON , 1 , 0 , P2INT , 0 );
179: putop( P2ASG P2PLUS , P2INT );
180: putdot( filename , line );
181: # endif PC
182: }
183:
184: putline()
185: {
186:
187: # ifdef OBJ
188: if (opt('p') != 0)
189: put(2, O_LINO, line);
190:
191: /*
192: * put out line number information for pdx
193: */
194: lineno(line);
195:
196: # endif OBJ
197: # ifdef PC
198: static lastline;
199:
200: if ( line != lastline ) {
201: stabline( line );
202: lastline = line;
203: }
204: if ( opt( 'p' ) ) {
205: if ( opt('t') ) {
206: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
207: , "_LINO" );
208: putop( P2UNARY P2CALL , P2INT );
209: putdot( filename , line );
210: } else {
211: putRV( STMTCOUNT , 0 , 0 , NGLOBAL , P2INT );
212: putleaf( P2ICON , 1 , 0 , P2INT , 0 );
213: putop( P2ASG P2PLUS , P2INT );
214: putdot( filename , line );
215: }
216: }
217: # endif PC
218: }
219:
220: /*
221: * With varlist do stat
222: *
223: * With statement requires an extra word
224: * in automatic storage for each level of withing.
225: * These indirect pointers are initialized here, and
226: * the scoping effect of the with statement occurs
227: * because lookup examines the field names of the records
228: * associated with the WITHPTRs on the withlist.
229: */
230: withop(s)
231: int *s;
232: {
233: register *p;
234: register struct nl *r;
235: struct nl *tempnlp;
236: int *swl;
237:
238: putline();
239: swl = withlist;
240: for (p = s[2]; p != NIL; p = p[2]) {
241: /*
242: * no one uses the allocated temporary namelist entry,
243: * since we have to use it before we know its type;
244: * but we use its runtime location for the with pointer.
245: */
246: tempnlp = tmpalloc(sizeof(int *), nl + TPTR, REGOK);
247: # ifdef OBJ
248: put(2, O_LV | cbn <<8+INDX, tempnlp -> value[ NL_OFFS ] );
249: # endif OBJ
250: # ifdef PC
251: putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
252: tempnlp -> extra_flags , P2PTR|P2STRTY );
253: # endif PC
254: r = lvalue(p[1], MOD , LREQ );
255: if (r == NIL)
256: continue;
257: if (r->class != RECORD) {
258: error("Variable in with statement refers to %s, not to a record", nameof(r));
259: continue;
260: }
261: r = defnl(0, WITHPTR, r, tempnlp -> value[ NL_OFFS ] );
262: # ifdef PC
263: r -> extra_flags |= tempnlp -> extra_flags;
264: # endif PC
265: r->nl_next = withlist;
266: withlist = r;
267: # ifdef OBJ
268: put(1, PTR_AS);
269: # endif OBJ
270: # ifdef PC
271: putop( P2ASSIGN , P2PTR|P2STRTY );
272: putdot( filename , line );
273: # endif PC
274: }
275: statement(s[3]);
276: withlist = swl;
277: }
278:
279: extern flagwas;
280: /*
281: * var := expr
282: */
283: asgnop(r)
284: int *r;
285: {
286: register struct nl *p;
287: register *av;
288:
289: if (r == NIL)
290: return (NIL);
291: /*
292: * Asgnop's only function is
293: * to handle function variable
294: * assignments. All other assignment
295: * stuff is handled by asgnop1.
296: * the if below checks for unqualified lefthandside:
297: * necessary for fvars.
298: */
299: av = r[2];
300: if (av != NIL && av[0] == T_VAR && av[3] == NIL) {
301: p = lookup1(av[2]);
302: if (p != NIL)
303: p->nl_flags = flagwas;
304: if (p != NIL && p->class == FVAR) {
305: /*
306: * Give asgnop1 the func
307: * which is the chain of
308: * the FVAR.
309: */
310: p->nl_flags |= NUSED|NMOD;
311: p = p->chain;
312: if (p == NIL) {
313: rvalue(r[3], NIL , RREQ );
314: return;
315: }
316: # ifdef OBJ
317: put(2, O_LV | bn << 8+INDX, (int)p->value[NL_OFFS]);
318: if (isa(p->type, "i") && width(p->type) == 1)
319: asgnop1(r, nl+T2INT);
320: else
321: asgnop1(r, p->type);
322: # endif OBJ
323: # ifdef PC
324: /*
325: * this should be the lvalue of the fvar,
326: * but since the second pass knows to use
327: * the address of the left operand of an
328: * assignment, what i want here is an rvalue.
329: * see note in funchdr about fvar allocation.
330: */
331: p = p -> ptr[ NL_FVAR ];
332: putRV( p -> symbol , bn , p -> value[ NL_OFFS ] ,
333: p -> extra_flags , p2type( p -> type ) );
334: asgnop1( r , p -> type );
335: # endif PC
336: return;
337: }
338: }
339: asgnop1(r, NIL);
340: }
341:
342: /*
343: * Asgnop1 handles all assignments.
344: * If p is not nil then we are assigning
345: * to a function variable, otherwise
346: * we look the variable up ourselves.
347: */
348: struct nl *
349: asgnop1(r, p)
350: int *r;
351: register struct nl *p;
352: {
353: register struct nl *p1;
354: int w;
355:
356: if (r == NIL)
357: return (NIL);
358: if (p == NIL) {
359: # ifdef OBJ
360: p = lvalue(r[2], MOD|ASGN|NOUSE , LREQ );
361: w = width(p);
362: # endif OBJ
363: # ifdef PC
364: /*
365: * since the second pass knows that it should reference
366: * the lefthandside of asignments, what i need here is
367: * an rvalue.
368: */
369: p = lvalue( r[2] , MOD|ASGN|NOUSE , RREQ );
370: # endif PC
371: if ( p == NIL ) {
372: rvalue( r[3] , NIL , RREQ );
373: return NIL;
374: }
375: }
376: # ifdef OBJ
377: /*
378: * assigning to the return value, which is at least
379: * of width two since it resides on the stack
380: */
381: else {
382: w = width(p);
383: if (w < 2)
384: w = 2;
385: }
386: p1 = rvalue(r[3], p , RREQ );
387: # endif OBJ
388: # ifdef PC
389: /*
390: * if this is a scalar assignment,
391: * then i want to rvalue the righthandside.
392: * if this is a structure assignment,
393: * then i want an lvalue to the righthandside.
394: * that's what the intermediate form sez.
395: */
396: switch ( classify( p ) ) {
397: case TINT:
398: case TCHAR:
399: case TBOOL:
400: case TSCAL:
401: precheck( p , "_RANG4" , "_RSNG4" );
402: case TDOUBLE:
403: case TPTR:
404: p1 = rvalue( r[3] , p , RREQ );
405: break;
406: default:
407: p1 = rvalue( r[3] , p , LREQ );
408: break;
409: }
410: # endif PC
411: if (p1 == NIL)
412: return (NIL);
413: if (incompat(p1, p, r[3])) {
414: cerror("Type of expression clashed with type of variable in assignment");
415: return (NIL);
416: }
417: # ifdef OBJ
418: switch (classify(p)) {
419: case TINT:
420: case TBOOL:
421: case TCHAR:
422: case TSCAL:
423: rangechk(p, p1);
424: gen(O_AS2, O_AS2, w, width(p1));
425: break;
426: case TDOUBLE:
427: case TPTR:
428: gen(O_AS2, O_AS2, w, width(p1));
429: break;
430: default:
431: put(2, O_AS, w);
432: break;
433: }
434: # endif OBJ
435: # ifdef PC
436: switch (classify(p)) {
437: case TINT:
438: case TBOOL:
439: case TCHAR:
440: case TSCAL:
441: postcheck(p, p1);
442: sconv(p2type(p1), p2type(p));
443: putop( P2ASSIGN , p2type( p ) );
444: putdot( filename , line );
445: break;
446: case TPTR:
447: putop( P2ASSIGN , p2type( p ) );
448: putdot( filename , line );
449: break;
450: case TDOUBLE:
451: sconv(p2type(p1), p2type(p));
452: putop( P2ASSIGN , p2type( p ) );
453: putdot( filename , line );
454: break;
455: default:
456: putstrop(P2STASG, ADDTYPE(p2type(p), P2PTR),
457: lwidth(p), align(p));
458: putdot( filename , line );
459: break;
460: }
461: # endif PC
462: return (p); /* Used by for statement */
463: }
464:
465: /*
466: * if expr then stat [ else stat ]
467: */
468: ifop(r)
469: int *r;
470: {
471: register struct nl *p;
472: register l1, l2; /* l1 is start of else, l2 is end of else */
473: int goc;
474: bool nr;
475:
476: goc = gocnt;
477: if (r == NIL)
478: return;
479: putline();
480: p = rvalue(r[2], NIL , RREQ );
481: if (p == NIL) {
482: statement(r[3]);
483: noreach = 0;
484: statement(r[4]);
485: noreach = 0;
486: return;
487: }
488: if (isnta(p, "b")) {
489: error("Type of expression in if statement must be Boolean, not %s", nameof(p));
490: statement(r[3]);
491: noreach = 0;
492: statement(r[4]);
493: noreach = 0;
494: return;
495: }
496: # ifdef OBJ
497: l1 = put(2, O_IF, getlab());
498: # endif OBJ
499: # ifdef PC
500: l1 = getlab();
501: putleaf( P2ICON , l1 , 0 , P2INT , 0 );
502: putop( P2CBRANCH , P2INT );
503: putdot( filename , line );
504: # endif PC
505: putcnt();
506: statement(r[3]);
507: nr = noreach;
508: if (r[4] != NIL) {
509: /*
510: * else stat
511: */
512: --level;
513: ungoto();
514: ++level;
515: # ifdef OBJ
516: l2 = put(2, O_TRA, getlab());
517: # endif OBJ
518: # ifdef PC
519: l2 = getlab();
520: putjbr( l2 );
521: # endif PC
522: patch(l1);
523: noreach = 0;
524: statement(r[4]);
525: noreach = (noreach && nr);
526: l1 = l2;
527: } else
528: noreach = 0;
529: patch(l1);
530: if (goc != gocnt)
531: putcnt();
532: }
533:
534: /*
535: * while expr do stat
536: */
537: whilop(r)
538: int *r;
539: {
540: register struct nl *p;
541: register l1, l2;
542: int goc;
543:
544: goc = gocnt;
545: if (r == NIL)
546: return;
547: putlab(l1 = getlab());
548: putline();
549: p = rvalue(r[2], NIL , RREQ );
550: if (p == NIL) {
551: statement(r[3]);
552: noreach = 0;
553: return;
554: }
555: if (isnta(p, "b")) {
556: error("Type of expression in while statement must be Boolean, not %s", nameof(p));
557: statement(r[3]);
558: noreach = 0;
559: return;
560: }
561: l2 = getlab();
562: # ifdef OBJ
563: put(2, O_IF, l2);
564: # endif OBJ
565: # ifdef PC
566: putleaf( P2ICON , l2 , 0 , P2INT , 0 );
567: putop( P2CBRANCH , P2INT );
568: putdot( filename , line );
569: # endif PC
570: putcnt();
571: statement(r[3]);
572: # ifdef OBJ
573: put(2, O_TRA, l1);
574: # endif OBJ
575: # ifdef PC
576: putjbr( l1 );
577: # endif PC
578: patch(l2);
579: if (goc != gocnt)
580: putcnt();
581: }
582:
583: /*
584: * repeat stat* until expr
585: */
586: repop(r)
587: int *r;
588: {
589: register struct nl *p;
590: register l;
591: int goc;
592:
593: goc = gocnt;
594: if (r == NIL)
595: return;
596: l = putlab(getlab());
597: putcnt();
598: statlist(r[2]);
599: line = r[1];
600: p = rvalue(r[3], NIL , RREQ );
601: if (p == NIL)
602: return;
603: if (isnta(p,"b")) {
604: error("Until expression type must be Boolean, not %s, in repeat statement", nameof(p));
605: return;
606: }
607: # ifdef OBJ
608: put(2, O_IF, l);
609: # endif OBJ
610: # ifdef PC
611: putleaf( P2ICON , l , 0 , P2INT , 0 );
612: putop( P2CBRANCH , P2INT );
613: putdot( filename , line );
614: # endif PC
615: if (goc != gocnt)
616: putcnt();
617: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.