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