|
|
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[] = "@(#)rval.c 5.2 (Berkeley) 4/7/87";
9: #endif not lint
10:
11: #include "whoami.h"
12: #include "0.h"
13: #include "tree.h"
14: #include "opcode.h"
15: #include "objfmt.h"
16: #ifdef PC
17: # include "pc.h"
18: # include <pcc.h>
19: #endif PC
20: #include "tmps.h"
21: #include "tree_ty.h"
22:
23: extern char *opnames[];
24:
25: /* line number of the last record comparison warning */
26: short reccompline = 0;
27: /* line number of the last non-standard set comparison */
28: short nssetline = 0;
29:
30: #ifdef PC
31: char *relts[] = {
32: "_RELEQ" , "_RELNE" ,
33: "_RELTLT" , "_RELTGT" ,
34: "_RELTLE" , "_RELTGE"
35: };
36: char *relss[] = {
37: "_RELEQ" , "_RELNE" ,
38: "_RELSLT" , "_RELSGT" ,
39: "_RELSLE" , "_RELSGE"
40: };
41: long relops[] = {
42: PCC_EQ , PCC_NE ,
43: PCC_LT , PCC_GT ,
44: PCC_LE , PCC_GE
45: };
46: long mathop[] = { PCC_MUL , PCC_PLUS , PCC_MINUS };
47: char *setop[] = { "_MULT" , "_ADDT" , "_SUBT" };
48: #endif PC
49: /*
50: * Rvalue - an expression.
51: *
52: * Contype is the type that the caller would prefer, nand is important
53: * if constant strings are involved, because of string padding.
54: * required is a flag whether an lvalue or an rvalue is required.
55: * only VARs and structured things can have gt their lvalue this way.
56: */
57: /*ARGSUSED*/
58: struct nl *
59: rvalue(r, contype , required )
60: struct tnode *r;
61: struct nl *contype;
62: int required;
63: {
64: register struct nl *p, *p1;
65: register struct nl *q;
66: int c, c1, w;
67: #ifdef OBJ
68: int g;
69: #endif
70: struct tnode *rt;
71: char *cp, *cp1, *opname;
72: long l;
73: union
74: {
75: long plong[2];
76: double pdouble;
77: }f;
78: extern int flagwas;
79: struct csetstr csetd;
80: # ifdef PC
81: struct nl *rettype;
82: long ctype;
83: struct nl *tempnlp;
84: # endif PC
85:
86: if (r == TR_NIL)
87: return (NLNIL);
88: if (nowexp(r))
89: return (NLNIL);
90: /*
91: * Pick up the name of the operation
92: * for future error messages.
93: */
94: if (r->tag <= T_IN)
95: opname = opnames[r->tag];
96:
97: /*
98: * The root of the tree tells us what sort of expression we have.
99: */
100: switch (r->tag) {
101:
102: /*
103: * The constant nil
104: */
105: case T_NIL:
106: # ifdef OBJ
107: (void) put(2, O_CON2, 0);
108: # endif OBJ
109: # ifdef PC
110: putleaf( PCC_ICON , 0 , 0 , PCCTM_PTR|PCCT_UNDEF , (char *) 0 );
111: # endif PC
112: return (nl+TNIL);
113:
114: /*
115: * Function call with arguments.
116: */
117: case T_FCALL:
118: # ifdef OBJ
119: return (funccod(r));
120: # endif OBJ
121: # ifdef PC
122: return (pcfunccod( r ));
123: # endif PC
124:
125: case T_VAR:
126: p = lookup(r->var_node.cptr);
127: if (p == NLNIL || p->class == BADUSE)
128: return (NLNIL);
129: switch (p->class) {
130: case VAR:
131: /*
132: * If a variable is
133: * qualified then get
134: * the rvalue by a
135: * lvalue and an ind.
136: */
137: if (r->var_node.qual != TR_NIL)
138: goto ind;
139: q = p->type;
140: if (q == NIL)
141: return (NLNIL);
142: # ifdef OBJ
143: w = width(q);
144: switch (w) {
145: case 8:
146: (void) put(2, O_RV8 | bn << 8+INDX,
147: (int)p->value[0]);
148: break;
149: case 4:
150: (void) put(2, O_RV4 | bn << 8+INDX,
151: (int)p->value[0]);
152: break;
153: case 2:
154: (void) put(2, O_RV2 | bn << 8+INDX,
155: (int)p->value[0]);
156: break;
157: case 1:
158: (void) put(2, O_RV1 | bn << 8+INDX,
159: (int)p->value[0]);
160: break;
161: default:
162: (void) put(3, O_RV | bn << 8+INDX,
163: (int)p->value[0], w);
164: }
165: # endif OBJ
166: # ifdef PC
167: if ( required == RREQ ) {
168: putRV( p -> symbol , bn , p -> value[0] ,
169: p -> extra_flags , p2type( q ) );
170: } else {
171: putLV( p -> symbol , bn , p -> value[0] ,
172: p -> extra_flags , p2type( q ) );
173: }
174: # endif PC
175: return (q);
176:
177: case WITHPTR:
178: case REF:
179: /*
180: * A lvalue for these
181: * is actually what one
182: * might consider a rvalue.
183: */
184: ind:
185: q = lvalue(r, NOFLAGS , LREQ );
186: if (q == NIL)
187: return (NLNIL);
188: # ifdef OBJ
189: w = width(q);
190: switch (w) {
191: case 8:
192: (void) put(1, O_IND8);
193: break;
194: case 4:
195: (void) put(1, O_IND4);
196: break;
197: case 2:
198: (void) put(1, O_IND2);
199: break;
200: case 1:
201: (void) put(1, O_IND1);
202: break;
203: default:
204: (void) put(2, O_IND, w);
205: }
206: # endif OBJ
207: # ifdef PC
208: if ( required == RREQ ) {
209: putop( PCCOM_UNARY PCC_MUL , p2type( q ) );
210: }
211: # endif PC
212: return (q);
213:
214: case CONST:
215: if (r->var_node.qual != TR_NIL) {
216: error("%s is a constant and cannot be qualified", r->var_node.cptr);
217: return (NLNIL);
218: }
219: q = p->type;
220: if (q == NLNIL)
221: return (NLNIL);
222: if (q == nl+TSTR) {
223: /*
224: * Find the size of the string
225: * constant if needed.
226: */
227: cp = (char *) p->ptr[0];
228: cstrng:
229: cp1 = cp;
230: for (c = 0; *cp++; c++)
231: continue;
232: w = c;
233: if (contype != NIL && !opt('s')) {
234: if (width(contype) < c && classify(contype) == TSTR) {
235: error("Constant string too long");
236: return (NLNIL);
237: }
238: w = width(contype);
239: }
240: # ifdef OBJ
241: (void) put(2, O_CONG, w);
242: putstr(cp1, w - c);
243: # endif OBJ
244: # ifdef PC
245: putCONG( cp1 , w , required );
246: # endif PC
247: /*
248: * Define the string temporarily
249: * so later people can know its
250: * width.
251: * cleaned out by stat.
252: */
253: q = defnl((char *) 0, STR, NLNIL, w);
254: q->type = q;
255: return (q);
256: }
257: if (q == nl+T1CHAR) {
258: # ifdef OBJ
259: (void) put(2, O_CONC, (int)p->value[0]);
260: # endif OBJ
261: # ifdef PC
262: putleaf( PCC_ICON , p -> value[0] , 0
263: , PCCT_CHAR , (char *) 0 );
264: # endif PC
265: return (q);
266: }
267: /*
268: * Every other kind of constant here
269: */
270: switch (width(q)) {
271: case 8:
272: #ifndef DEBUG
273: # ifdef OBJ
274: (void) put(2, O_CON8, p->real);
275: # endif OBJ
276: # ifdef PC
277: putCON8( p -> real );
278: # endif PC
279: #else
280: if (hp21mx) {
281: f.pdouble = p->real;
282: conv((int *) (&f.pdouble));
283: l = f.plong[1];
284: (void) put(2, O_CON4, l);
285: } else
286: # ifdef OBJ
287: (void) put(2, O_CON8, p->real);
288: # endif OBJ
289: # ifdef PC
290: putCON8( p -> real );
291: # endif PC
292: #endif
293: break;
294: case 4:
295: # ifdef OBJ
296: (void) put(2, O_CON4, p->range[0]);
297: # endif OBJ
298: # ifdef PC
299: putleaf( PCC_ICON , (int) p->range[0] , 0
300: , PCCT_INT , (char *) 0 );
301: # endif PC
302: break;
303: case 2:
304: # ifdef OBJ
305: (void) put(2, O_CON2, (short)p->range[0]);
306: # endif OBJ
307: # ifdef PC
308: putleaf( PCC_ICON , (short) p -> range[0]
309: , 0 , PCCT_SHORT , (char *) 0 );
310: # endif PC
311: break;
312: case 1:
313: # ifdef OBJ
314: (void) put(2, O_CON1, p->value[0]);
315: # endif OBJ
316: # ifdef PC
317: putleaf( PCC_ICON , p -> value[0] , 0
318: , PCCT_CHAR , (char *) 0 );
319: # endif PC
320: break;
321: default:
322: panic("rval");
323: }
324: return (q);
325:
326: case FUNC:
327: case FFUNC:
328: /*
329: * Function call with no arguments.
330: */
331: if (r->var_node.qual != TR_NIL) {
332: error("Can't qualify a function result value");
333: return (NLNIL);
334: }
335: # ifdef OBJ
336: return (funccod(r));
337: # endif OBJ
338: # ifdef PC
339: return (pcfunccod( r ));
340: # endif PC
341:
342: case TYPE:
343: error("Type names (e.g. %s) allowed only in declarations", p->symbol);
344: return (NLNIL);
345:
346: case PROC:
347: case FPROC:
348: error("Procedure %s found where expression required", p->symbol);
349: return (NLNIL);
350: default:
351: panic("rvid");
352: }
353: /*
354: * Constant sets
355: */
356: case T_CSET:
357: # ifdef OBJ
358: if ( precset( r , contype , &csetd ) ) {
359: if ( csetd.csettype == NIL ) {
360: return (NLNIL);
361: }
362: postcset( r , &csetd );
363: } else {
364: (void) put( 2, O_PUSH, -lwidth(csetd.csettype));
365: postcset( r , &csetd );
366: setran( ( csetd.csettype ) -> type );
367: (void) put( 2, O_CON24, set.uprbp);
368: (void) put( 2, O_CON24, set.lwrb);
369: (void) put( 2, O_CTTOT,
370: (int)(4 + csetd.singcnt + 2 * csetd.paircnt));
371: }
372: return csetd.csettype;
373: # endif OBJ
374: # ifdef PC
375: if ( precset( r , contype , &csetd ) ) {
376: if ( csetd.csettype == NIL ) {
377: return (NLNIL);
378: }
379: postcset( r , &csetd );
380: } else {
381: putleaf( PCC_ICON , 0 , 0
382: , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
383: , "_CTTOT" );
384: /*
385: * allocate a temporary and use it
386: */
387: tempnlp = tmpalloc(lwidth(csetd.csettype),
388: csetd.csettype, NOREG);
389: putLV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
390: tempnlp -> extra_flags , PCCTM_PTR|PCCT_STRTY );
391: setran( ( csetd.csettype ) -> type );
392: putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 );
393: putop( PCC_CM , PCCT_INT );
394: putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 );
395: putop( PCC_CM , PCCT_INT );
396: postcset( r , &csetd );
397: putop( PCC_CALL , PCCT_INT );
398: }
399: return csetd.csettype;
400: # endif PC
401:
402: /*
403: * Unary plus and minus
404: */
405: case T_PLUS:
406: case T_MINUS:
407: q = rvalue(r->un_expr.expr, NLNIL , RREQ );
408: if (q == NLNIL)
409: return (NLNIL);
410: if (isnta(q, "id")) {
411: error("Operand of %s must be integer or real, not %s", opname, nameof(q));
412: return (NLNIL);
413: }
414: if (r->tag == T_MINUS) {
415: # ifdef OBJ
416: (void) put(1, O_NEG2 + (width(q) >> 2));
417: return (isa(q, "d") ? q : nl+T4INT);
418: # endif OBJ
419: # ifdef PC
420: if (isa(q, "i")) {
421: sconv(p2type(q), PCCT_INT);
422: putop( PCCOM_UNARY PCC_MINUS, PCCT_INT);
423: return nl+T4INT;
424: }
425: putop( PCCOM_UNARY PCC_MINUS, PCCT_DOUBLE);
426: return nl+TDOUBLE;
427: # endif PC
428: }
429: return (q);
430:
431: case T_NOT:
432: q = rvalue(r->un_expr.expr, NLNIL , RREQ );
433: if (q == NLNIL)
434: return (NLNIL);
435: if (isnta(q, "b")) {
436: error("not must operate on a Boolean, not %s", nameof(q));
437: return (NLNIL);
438: }
439: # ifdef OBJ
440: (void) put(1, O_NOT);
441: # endif OBJ
442: # ifdef PC
443: sconv(p2type(q), PCCT_INT);
444: putop( PCC_NOT , PCCT_INT);
445: sconv(PCCT_INT, p2type(q));
446: # endif PC
447: return (nl+T1BOOL);
448:
449: case T_AND:
450: case T_OR:
451: p = rvalue(r->expr_node.lhs, NLNIL , RREQ );
452: # ifdef PC
453: sconv(p2type(p),PCCT_INT);
454: # endif PC
455: p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );
456: # ifdef PC
457: sconv(p2type(p1),PCCT_INT);
458: # endif PC
459: if (p == NLNIL || p1 == NLNIL)
460: return (NLNIL);
461: if (isnta(p, "b")) {
462: error("Left operand of %s must be Boolean, not %s", opname, nameof(p));
463: return (NLNIL);
464: }
465: if (isnta(p1, "b")) {
466: error("Right operand of %s must be Boolean, not %s", opname, nameof(p1));
467: return (NLNIL);
468: }
469: # ifdef OBJ
470: (void) put(1, r->tag == T_AND ? O_AND : O_OR);
471: # endif OBJ
472: # ifdef PC
473: /*
474: * note the use of & and | rather than && and ||
475: * to force evaluation of all the expressions.
476: */
477: putop( r->tag == T_AND ? PCC_AND : PCC_OR , PCCT_INT );
478: sconv(PCCT_INT, p2type(p));
479: # endif PC
480: return (nl+T1BOOL);
481:
482: case T_DIVD:
483: # ifdef OBJ
484: p = rvalue(r->expr_node.lhs, NLNIL , RREQ );
485: p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );
486: # endif OBJ
487: # ifdef PC
488: /*
489: * force these to be doubles for the divide
490: */
491: p = rvalue( r->expr_node.lhs , NLNIL , RREQ );
492: sconv(p2type(p), PCCT_DOUBLE);
493: p1 = rvalue( r->expr_node.rhs , NLNIL , RREQ );
494: sconv(p2type(p1), PCCT_DOUBLE);
495: # endif PC
496: if (p == NLNIL || p1 == NLNIL)
497: return (NLNIL);
498: if (isnta(p, "id")) {
499: error("Left operand of / must be integer or real, not %s", nameof(p));
500: return (NLNIL);
501: }
502: if (isnta(p1, "id")) {
503: error("Right operand of / must be integer or real, not %s", nameof(p1));
504: return (NLNIL);
505: }
506: # ifdef OBJ
507: return gen(NIL, r->tag, width(p), width(p1));
508: # endif OBJ
509: # ifdef PC
510: putop( PCC_DIV , PCCT_DOUBLE );
511: return nl + TDOUBLE;
512: # endif PC
513:
514: case T_MULT:
515: case T_ADD:
516: case T_SUB:
517: # ifdef OBJ
518: /*
519: * get the type of the right hand side.
520: * if it turns out to be a set,
521: * use that type when getting
522: * the type of the left hand side.
523: * and then use the type of the left hand side
524: * when generating code.
525: * this will correctly decide the type of any
526: * empty sets in the tree, since if the empty set
527: * is on the left hand side it will inherit
528: * the type of the right hand side,
529: * and if it's on the right hand side, its type (intset)
530: * will be overridden by the type of the left hand side.
531: * this is an awful lot of tree traversing,
532: * but it works.
533: */
534: codeoff();
535: p1 = rvalue( r->expr_node.rhs , NLNIL , RREQ );
536: codeon();
537: if ( p1 == NLNIL ) {
538: return NLNIL;
539: }
540: if (isa(p1, "t")) {
541: codeoff();
542: contype = rvalue(r->expr_node.lhs, p1, RREQ);
543: codeon();
544: if (contype == NLNIL) {
545: return NLNIL;
546: }
547: }
548: p = rvalue( r->expr_node.lhs , contype , RREQ );
549: p1 = rvalue( r->expr_node.rhs , p , RREQ );
550: if ( p == NLNIL || p1 == NLNIL )
551: return NLNIL;
552: if (isa(p, "id") && isa(p1, "id"))
553: return (gen(NIL, r->tag, width(p), width(p1)));
554: if (isa(p, "t") && isa(p1, "t")) {
555: if (p != p1) {
556: error("Set types of operands of %s must be identical", opname);
557: return (NLNIL);
558: }
559: (void) gen(TSET, r->tag, width(p), 0);
560: return (p);
561: }
562: # endif OBJ
563: # ifdef PC
564: /*
565: * the second pass can't do
566: * long op double or double op long
567: * so we have to know the type of both operands.
568: * also, see the note for obj above on determining
569: * the type of empty sets.
570: */
571: codeoff();
572: p1 = rvalue(r->expr_node.rhs, NLNIL, RREQ);
573: codeon();
574: if ( isa( p1 , "id" ) ) {
575: p = rvalue( r->expr_node.lhs , contype , RREQ );
576: if ( ( p == NLNIL ) || ( p1 == NLNIL ) ) {
577: return NLNIL;
578: }
579: tuac(p, p1, &rettype, (int *) (&ctype));
580: p1 = rvalue( r->expr_node.rhs , contype , RREQ );
581: tuac(p1, p, &rettype, (int *) (&ctype));
582: if ( isa( p , "id" ) ) {
583: putop( (int) mathop[r->tag - T_MULT], (int) ctype);
584: return rettype;
585: }
586: }
587: if ( isa( p1 , "t" ) ) {
588: putleaf( PCC_ICON , 0 , 0
589: , PCCM_ADDTYPE( PCCM_ADDTYPE( PCCTM_PTR | PCCT_STRTY , PCCTM_FTN )
590: , PCCTM_PTR )
591: , setop[ r->tag - T_MULT ] );
592: codeoff();
593: contype = rvalue( r->expr_node.lhs, p1 , LREQ );
594: codeon();
595: if ( contype == NLNIL ) {
596: return NLNIL;
597: }
598: /*
599: * allocate a temporary and use it
600: */
601: tempnlp = tmpalloc(lwidth(contype), contype, NOREG);
602: putLV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
603: tempnlp -> extra_flags , PCCTM_PTR|PCCT_STRTY );
604: p = rvalue( r->expr_node.lhs , contype , LREQ );
605: if ( isa( p , "t" ) ) {
606: putop( PCC_CM , PCCT_INT );
607: if ( p == NLNIL || p1 == NLNIL ) {
608: return NLNIL;
609: }
610: p1 = rvalue( r->expr_node.rhs , p , LREQ );
611: if ( p != p1 ) {
612: error("Set types of operands of %s must be identical", opname);
613: return NLNIL;
614: }
615: putop( PCC_CM , PCCT_INT );
616: putleaf( PCC_ICON , (int) (lwidth(p1)) / sizeof( long ) , 0
617: , PCCT_INT , (char *) 0 );
618: putop( PCC_CM , PCCT_INT );
619: putop( PCC_CALL , PCCTM_PTR | PCCT_STRTY );
620: return p;
621: }
622: }
623: if ( isnta( p1 , "idt" ) ) {
624: /*
625: * find type of left operand for error message.
626: */
627: p = rvalue( r->expr_node.lhs , contype , RREQ );
628: }
629: /*
630: * don't give spurious error messages.
631: */
632: if ( p == NLNIL || p1 == NLNIL ) {
633: return NLNIL;
634: }
635: # endif PC
636: if (isnta(p, "idt")) {
637: error("Left operand of %s must be integer, real or set, not %s", opname, nameof(p));
638: return (NLNIL);
639: }
640: if (isnta(p1, "idt")) {
641: error("Right operand of %s must be integer, real or set, not %s", opname, nameof(p1));
642: return (NLNIL);
643: }
644: error("Cannot mix sets with integers and reals as operands of %s", opname);
645: return (NLNIL);
646:
647: case T_MOD:
648: case T_DIV:
649: p = rvalue(r->expr_node.lhs, NLNIL , RREQ );
650: # ifdef PC
651: sconv(p2type(p), PCCT_INT);
652: # ifdef tahoe
653: /* prepare for ediv workaround, see below. */
654: if (r->tag == T_MOD) {
655: (void) rvalue(r->expr_node.lhs, NLNIL, RREQ);
656: sconv(p2type(p), PCCT_INT);
657: }
658: # endif tahoe
659: # endif PC
660: p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );
661: # ifdef PC
662: sconv(p2type(p1), PCCT_INT);
663: # endif PC
664: if (p == NLNIL || p1 == NLNIL)
665: return (NLNIL);
666: if (isnta(p, "i")) {
667: error("Left operand of %s must be integer, not %s", opname, nameof(p));
668: return (NLNIL);
669: }
670: if (isnta(p1, "i")) {
671: error("Right operand of %s must be integer, not %s", opname, nameof(p1));
672: return (NLNIL);
673: }
674: # ifdef OBJ
675: return (gen(NIL, r->tag, width(p), width(p1)));
676: # endif OBJ
677: # ifdef PC
678: # ifndef tahoe
679: putop( r->tag == T_DIV ? PCC_DIV : PCC_MOD , PCCT_INT );
680: return ( nl + T4INT );
681: # else tahoe
682: putop( PCC_DIV , PCCT_INT );
683: if (r->tag == T_MOD) {
684: /*
685: * avoid f1 bug: PCC_MOD would generate an 'ediv',
686: * which would reuire too many registers to evaluate
687: * things like
688: * var i:boolean;j:integer; i := (j+1) = (j mod 2);
689: * so, instead of
690: * PCC_MOD
691: * / \
692: * p p1
693: * we put
694: * PCC_MINUS
695: * / \
696: * p PCC_MUL
697: * / \
698: * PCC_DIV p1
699: * / \
700: * p p1
701: *
702: * we already have put p, p, p1, PCC_DIV. and now...
703: */
704: rvalue(r->expr_node.rhs, NLNIL , RREQ );
705: sconv(p2type(p1), PCCT_INT);
706: putop( PCC_MUL, PCCT_INT );
707: putop( PCC_MINUS, PCCT_INT );
708: }
709: return ( nl + T4INT );
710: # endif tahoe
711: # endif PC
712:
713: case T_EQ:
714: case T_NE:
715: case T_LT:
716: case T_GT:
717: case T_LE:
718: case T_GE:
719: /*
720: * Since there can be no, a priori, knowledge
721: * of the context type should a constant string
722: * or set arise, we must poke around to find such
723: * a type if possible. Since constant strings can
724: * always masquerade as identifiers, this is always
725: * necessary.
726: * see the note in the obj section of case T_MULT above
727: * for the determination of the base type of empty sets.
728: */
729: codeoff();
730: p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );
731: codeon();
732: if (p1 == NLNIL)
733: return (NLNIL);
734: contype = p1;
735: # ifdef OBJ
736: if (p1->class == STR) {
737: /*
738: * For constant strings we want
739: * the longest type so as to be
740: * able to do padding (more importantly
741: * avoiding truncation). For clarity,
742: * we get this length here.
743: */
744: codeoff();
745: p = rvalue(r->expr_node.lhs, NLNIL , RREQ );
746: codeon();
747: if (p == NLNIL)
748: return (NLNIL);
749: if (width(p) > width(p1))
750: contype = p;
751: }
752: if (isa(p1, "t")) {
753: codeoff();
754: contype = rvalue(r->expr_node.lhs, p1, RREQ);
755: codeon();
756: if (contype == NLNIL) {
757: return NLNIL;
758: }
759: }
760: /*
761: * Now we generate code for
762: * the operands of the relational
763: * operation.
764: */
765: p = rvalue(r->expr_node.lhs, contype , RREQ );
766: if (p == NLNIL)
767: return (NLNIL);
768: p1 = rvalue(r->expr_node.rhs, p , RREQ );
769: if (p1 == NLNIL)
770: return (NLNIL);
771: # endif OBJ
772: # ifdef PC
773: c1 = classify( p1 );
774: if ( c1 == TSET || c1 == TSTR || c1 == TREC ) {
775: putleaf( PCC_ICON , 0 , 0
776: , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
777: , c1 == TSET ? relts[ r->tag - T_EQ ]
778: : relss[ r->tag - T_EQ ] );
779: /*
780: * for [] and strings, comparisons are done on
781: * the maximum width of the two sides.
782: * for other sets, we have to ask the left side
783: * what type it is based on the type of the right.
784: * (this matters for intsets).
785: */
786: if ( c1 == TSTR ) {
787: codeoff();
788: p = rvalue( r->expr_node.lhs , NLNIL , LREQ );
789: codeon();
790: if ( p == NLNIL ) {
791: return NLNIL;
792: }
793: if ( lwidth( p ) > lwidth( p1 ) ) {
794: contype = p;
795: }
796: } else if ( c1 == TSET ) {
797: codeoff();
798: contype = rvalue(r->expr_node.lhs, p1, LREQ);
799: codeon();
800: if (contype == NLNIL) {
801: return NLNIL;
802: }
803: }
804: /*
805: * put out the width of the comparison.
806: */
807: putleaf(PCC_ICON, (int) lwidth(contype), 0, PCCT_INT, (char *) 0);
808: /*
809: * and the left hand side,
810: * for sets, strings, records
811: */
812: p = rvalue( r->expr_node.lhs , contype , LREQ );
813: if ( p == NLNIL ) {
814: return NLNIL;
815: }
816: putop( PCC_CM , PCCT_INT );
817: p1 = rvalue( r->expr_node.rhs , p , LREQ );
818: if ( p1 == NLNIL ) {
819: return NLNIL;
820: }
821: putop( PCC_CM , PCCT_INT );
822: putop( PCC_CALL , PCCT_INT );
823: } else {
824: /*
825: * the easy (scalar or error) case
826: */
827: p = rvalue( r->expr_node.lhs , contype , RREQ );
828: if ( p == NLNIL ) {
829: return NLNIL;
830: }
831: /*
832: * since the second pass can't do
833: * long op double or double op long
834: * we may have to do some coercing.
835: */
836: tuac(p, p1, &rettype, (int *) (&ctype));
837: p1 = rvalue( r->expr_node.rhs , p , RREQ );
838: if ( p1 == NLNIL ) {
839: return NLNIL;
840: }
841: tuac(p1, p, &rettype, (int *) (&ctype));
842: putop((int) relops[ r->tag - T_EQ ] , PCCT_INT );
843: sconv(PCCT_INT, PCCT_CHAR);
844: }
845: # endif PC
846: c = classify(p);
847: c1 = classify(p1);
848: if (nocomp(c) || nocomp(c1))
849: return (NLNIL);
850: # ifdef OBJ
851: g = NIL;
852: # endif
853: switch (c) {
854: case TBOOL:
855: case TCHAR:
856: if (c != c1)
857: goto clash;
858: break;
859: case TINT:
860: case TDOUBLE:
861: if (c1 != TINT && c1 != TDOUBLE)
862: goto clash;
863: break;
864: case TSCAL:
865: if (c1 != TSCAL)
866: goto clash;
867: if (scalar(p) != scalar(p1))
868: goto nonident;
869: break;
870: case TSET:
871: if (c1 != TSET)
872: goto clash;
873: if ( opt( 's' ) &&
874: ( ( r->tag == T_LT) || (r->tag == T_GT) ) &&
875: ( line != nssetline ) ) {
876: nssetline = line;
877: standard();
878: error("%s comparison on sets is non-standard" , opname );
879: }
880: if (p != p1)
881: goto nonident;
882: # ifdef OBJ
883: g = TSET;
884: # endif
885: break;
886: case TREC:
887: if ( c1 != TREC ) {
888: goto clash;
889: }
890: if ( p != p1 ) {
891: goto nonident;
892: }
893: if (r->tag != T_EQ && r->tag != T_NE) {
894: error("%s not allowed on records - only allow = and <>" , opname );
895: return (NLNIL);
896: }
897: # ifdef OBJ
898: g = TREC;
899: # endif
900: break;
901: case TPTR:
902: case TNIL:
903: if (c1 != TPTR && c1 != TNIL)
904: goto clash;
905: if (r->tag != T_EQ && r->tag != T_NE) {
906: error("%s not allowed on pointers - only allow = and <>" , opname );
907: return (NLNIL);
908: }
909: if (p != nl+TNIL && p1 != nl+TNIL && p != p1)
910: goto nonident;
911: break;
912: case TSTR:
913: if (c1 != TSTR)
914: goto clash;
915: if (width(p) != width(p1)) {
916: error("Strings not same length in %s comparison", opname);
917: return (NLNIL);
918: }
919: # ifdef OBJ
920: g = TSTR;
921: # endif OBJ
922: break;
923: default:
924: panic("rval2");
925: }
926: # ifdef OBJ
927: return (gen(g, r->tag, width(p), width(p1)));
928: # endif OBJ
929: # ifdef PC
930: return nl + TBOOL;
931: # endif PC
932: clash:
933: error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname);
934: return (NLNIL);
935: nonident:
936: error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname);
937: return (NLNIL);
938:
939: case T_IN:
940: rt = r->expr_node.rhs;
941: # ifdef OBJ
942: if (rt != TR_NIL && rt->tag == T_CSET) {
943: (void) precset( rt , NLNIL , &csetd );
944: p1 = csetd.csettype;
945: if (p1 == NLNIL)
946: return NLNIL;
947: postcset( rt, &csetd);
948: } else {
949: p1 = stkrval(r->expr_node.rhs, NLNIL , (long) RREQ );
950: rt = TR_NIL;
951: }
952: # endif OBJ
953: # ifdef PC
954: if (rt != TR_NIL && rt->tag == T_CSET) {
955: if ( precset( rt , NLNIL , &csetd ) ) {
956: putleaf( PCC_ICON , 0 , 0
957: , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
958: , "_IN" );
959: } else {
960: putleaf( PCC_ICON , 0 , 0
961: , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
962: , "_INCT" );
963: }
964: p1 = csetd.csettype;
965: if (p1 == NIL)
966: return NLNIL;
967: } else {
968: putleaf( PCC_ICON , 0 , 0
969: , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
970: , "_IN" );
971: codeoff();
972: p1 = rvalue(r->expr_node.rhs, NLNIL , LREQ );
973: codeon();
974: }
975: # endif PC
976: p = stkrval(r->expr_node.lhs, NLNIL , (long) RREQ );
977: if (p == NIL || p1 == NIL)
978: return (NLNIL);
979: if (p1->class != (char) SET) {
980: error("Right operand of 'in' must be a set, not %s", nameof(p1));
981: return (NLNIL);
982: }
983: if (incompat(p, p1->type, r->expr_node.lhs)) {
984: cerror("Index type clashed with set component type for 'in'");
985: return (NLNIL);
986: }
987: setran(p1->type);
988: # ifdef OBJ
989: if (rt == TR_NIL || csetd.comptime)
990: (void) put(4, O_IN, width(p1), set.lwrb, set.uprbp);
991: else
992: (void) put(2, O_INCT,
993: (int)(3 + csetd.singcnt + 2*csetd.paircnt));
994: # endif OBJ
995: # ifdef PC
996: if ( rt == TR_NIL || rt->tag != T_CSET ) {
997: putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 );
998: putop( PCC_CM , PCCT_INT );
999: putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 );
1000: putop( PCC_CM , PCCT_INT );
1001: p1 = rvalue( r->expr_node.rhs , NLNIL , LREQ );
1002: if ( p1 == NLNIL ) {
1003: return NLNIL;
1004: }
1005: putop( PCC_CM , PCCT_INT );
1006: } else if ( csetd.comptime ) {
1007: putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 );
1008: putop( PCC_CM , PCCT_INT );
1009: putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 );
1010: putop( PCC_CM , PCCT_INT );
1011: postcset( r->expr_node.rhs , &csetd );
1012: putop( PCC_CM , PCCT_INT );
1013: } else {
1014: postcset( r->expr_node.rhs , &csetd );
1015: }
1016: putop( PCC_CALL , PCCT_INT );
1017: sconv(PCCT_INT, PCCT_CHAR);
1018: # endif PC
1019: return (nl+T1BOOL);
1020: default:
1021: if (r->expr_node.lhs == TR_NIL)
1022: return (NLNIL);
1023: switch (r->tag) {
1024: default:
1025: panic("rval3");
1026:
1027:
1028: /*
1029: * An octal number
1030: */
1031: case T_BINT:
1032: f.pdouble = a8tol(r->const_node.cptr);
1033: goto conint;
1034:
1035: /*
1036: * A decimal number
1037: */
1038: case T_INT:
1039: f.pdouble = atof(r->const_node.cptr);
1040: conint:
1041: if (f.pdouble > MAXINT || f.pdouble < MININT) {
1042: error("Constant too large for this implementation");
1043: return (NLNIL);
1044: }
1045: l = f.pdouble;
1046: # ifdef OBJ
1047: if (bytes(l, l) <= 2) {
1048: (void) put(2, O_CON2, ( short ) l);
1049: return (nl+T2INT);
1050: }
1051: (void) put(2, O_CON4, l);
1052: return (nl+T4INT);
1053: # endif OBJ
1054: # ifdef PC
1055: switch (bytes(l, l)) {
1056: case 1:
1057: putleaf(PCC_ICON, (int) l, 0, PCCT_CHAR,
1058: (char *) 0);
1059: return nl+T1INT;
1060: case 2:
1061: putleaf(PCC_ICON, (int) l, 0, PCCT_SHORT,
1062: (char *) 0);
1063: return nl+T2INT;
1064: case 4:
1065: putleaf(PCC_ICON, (int) l, 0, PCCT_INT,
1066: (char *) 0);
1067: return nl+T4INT;
1068: }
1069: # endif PC
1070:
1071: /*
1072: * A floating point number
1073: */
1074: case T_FINT:
1075: # ifdef OBJ
1076: (void) put(2, O_CON8, atof(r->const_node.cptr));
1077: # endif OBJ
1078: # ifdef PC
1079: putCON8( atof( r->const_node.cptr ) );
1080: # endif PC
1081: return (nl+TDOUBLE);
1082:
1083: /*
1084: * Constant strings. Note that constant characters
1085: * are constant strings of length one; there is
1086: * no constant string of length one.
1087: */
1088: case T_STRNG:
1089: cp = r->const_node.cptr;
1090: if (cp[1] == 0) {
1091: # ifdef OBJ
1092: (void) put(2, O_CONC, cp[0]);
1093: # endif OBJ
1094: # ifdef PC
1095: putleaf( PCC_ICON , cp[0] , 0 , PCCT_CHAR ,
1096: (char *) 0 );
1097: # endif PC
1098: return (nl+T1CHAR);
1099: }
1100: goto cstrng;
1101: }
1102:
1103: }
1104: }
1105:
1106: /*
1107: * Can a class appear
1108: * in a comparison ?
1109: */
1110: nocomp(c)
1111: int c;
1112: {
1113:
1114: switch (c) {
1115: case TREC:
1116: if ( line != reccompline ) {
1117: reccompline = line;
1118: warning();
1119: if ( opt( 's' ) ) {
1120: standard();
1121: }
1122: error("record comparison is non-standard");
1123: }
1124: break;
1125: case TFILE:
1126: case TARY:
1127: error("%ss may not participate in comparisons", clnames[c]);
1128: return (1);
1129: }
1130: return (NIL);
1131: }
1132:
1133: /*
1134: * this is sort of like gconst, except it works on expression trees
1135: * rather than declaration trees, and doesn't give error messages for
1136: * non-constant things.
1137: * as a side effect this fills in the con structure that gconst uses.
1138: * this returns TRUE or FALSE.
1139: */
1140:
1141: bool
1142: constval(r)
1143: register struct tnode *r;
1144: {
1145: register struct nl *np;
1146: register struct tnode *cn;
1147: char *cp;
1148: int negd, sgnd;
1149: long ci;
1150:
1151: con.ctype = NIL;
1152: cn = r;
1153: negd = sgnd = 0;
1154: loop:
1155: /*
1156: * cn[2] is nil if error recovery generated a T_STRNG
1157: */
1158: if (cn == TR_NIL || cn->expr_node.lhs == TR_NIL)
1159: return FALSE;
1160: switch (cn->tag) {
1161: default:
1162: return FALSE;
1163: case T_MINUS:
1164: negd = 1 - negd;
1165: /* and fall through */
1166: case T_PLUS:
1167: sgnd++;
1168: cn = cn->un_expr.expr;
1169: goto loop;
1170: case T_NIL:
1171: con.cpval = NIL;
1172: con.cival = 0;
1173: con.crval = con.cival;
1174: con.ctype = nl + TNIL;
1175: break;
1176: case T_VAR:
1177: np = lookup(cn->var_node.cptr);
1178: if (np == NLNIL || np->class != CONST) {
1179: return FALSE;
1180: }
1181: if ( cn->var_node.qual != TR_NIL ) {
1182: return FALSE;
1183: }
1184: con.ctype = np->type;
1185: switch (classify(np->type)) {
1186: case TINT:
1187: con.crval = np->range[0];
1188: break;
1189: case TDOUBLE:
1190: con.crval = np->real;
1191: break;
1192: case TBOOL:
1193: case TCHAR:
1194: case TSCAL:
1195: con.cival = np->value[0];
1196: con.crval = con.cival;
1197: break;
1198: case TSTR:
1199: con.cpval = (char *) np->ptr[0];
1200: break;
1201: default:
1202: con.ctype = NIL;
1203: return FALSE;
1204: }
1205: break;
1206: case T_BINT:
1207: con.crval = a8tol(cn->const_node.cptr);
1208: goto restcon;
1209: case T_INT:
1210: con.crval = atof(cn->const_node.cptr);
1211: if (con.crval > MAXINT || con.crval < MININT) {
1212: derror("Constant too large for this implementation");
1213: con.crval = 0;
1214: }
1215: restcon:
1216: ci = con.crval;
1217: #ifndef PI0
1218: if (bytes(ci, ci) <= 2)
1219: con.ctype = nl+T2INT;
1220: else
1221: #endif
1222: con.ctype = nl+T4INT;
1223: break;
1224: case T_FINT:
1225: con.ctype = nl+TDOUBLE;
1226: con.crval = atof(cn->const_node.cptr);
1227: break;
1228: case T_STRNG:
1229: cp = cn->const_node.cptr;
1230: if (cp[1] == 0) {
1231: con.ctype = nl+T1CHAR;
1232: con.cival = cp[0];
1233: con.crval = con.cival;
1234: break;
1235: }
1236: con.ctype = nl+TSTR;
1237: con.cpval = cp;
1238: break;
1239: }
1240: if (sgnd) {
1241: if (isnta(con.ctype, "id")) {
1242: derror("%s constants cannot be signed", nameof(con.ctype));
1243: return FALSE;
1244: } else if (negd)
1245: con.crval = -con.crval;
1246: }
1247: return TRUE;
1248: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.