|
|
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.1 (Berkeley) 6/5/85";
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: # endif PC
653: p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );
654: # ifdef PC
655: sconv(p2type(p1), PCCT_INT);
656: # endif PC
657: if (p == NLNIL || p1 == NLNIL)
658: return (NLNIL);
659: if (isnta(p, "i")) {
660: error("Left operand of %s must be integer, not %s", opname, nameof(p));
661: return (NLNIL);
662: }
663: if (isnta(p1, "i")) {
664: error("Right operand of %s must be integer, not %s", opname, nameof(p1));
665: return (NLNIL);
666: }
667: # ifdef OBJ
668: return (gen(NIL, r->tag, width(p), width(p1)));
669: # endif OBJ
670: # ifdef PC
671: putop( r->tag == T_DIV ? PCC_DIV : PCC_MOD , PCCT_INT );
672: return ( nl + T4INT );
673: # endif PC
674:
675: case T_EQ:
676: case T_NE:
677: case T_LT:
678: case T_GT:
679: case T_LE:
680: case T_GE:
681: /*
682: * Since there can be no, a priori, knowledge
683: * of the context type should a constant string
684: * or set arise, we must poke around to find such
685: * a type if possible. Since constant strings can
686: * always masquerade as identifiers, this is always
687: * necessary.
688: * see the note in the obj section of case T_MULT above
689: * for the determination of the base type of empty sets.
690: */
691: codeoff();
692: p1 = rvalue(r->expr_node.rhs, NLNIL , RREQ );
693: codeon();
694: if (p1 == NLNIL)
695: return (NLNIL);
696: contype = p1;
697: # ifdef OBJ
698: if (p1->class == STR) {
699: /*
700: * For constant strings we want
701: * the longest type so as to be
702: * able to do padding (more importantly
703: * avoiding truncation). For clarity,
704: * we get this length here.
705: */
706: codeoff();
707: p = rvalue(r->expr_node.lhs, NLNIL , RREQ );
708: codeon();
709: if (p == NLNIL)
710: return (NLNIL);
711: if (width(p) > width(p1))
712: contype = p;
713: }
714: if (isa(p1, "t")) {
715: codeoff();
716: contype = rvalue(r->expr_node.lhs, p1, RREQ);
717: codeon();
718: if (contype == NLNIL) {
719: return NLNIL;
720: }
721: }
722: /*
723: * Now we generate code for
724: * the operands of the relational
725: * operation.
726: */
727: p = rvalue(r->expr_node.lhs, contype , RREQ );
728: if (p == NLNIL)
729: return (NLNIL);
730: p1 = rvalue(r->expr_node.rhs, p , RREQ );
731: if (p1 == NLNIL)
732: return (NLNIL);
733: # endif OBJ
734: # ifdef PC
735: c1 = classify( p1 );
736: if ( c1 == TSET || c1 == TSTR || c1 == TREC ) {
737: putleaf( PCC_ICON , 0 , 0
738: , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
739: , c1 == TSET ? relts[ r->tag - T_EQ ]
740: : relss[ r->tag - T_EQ ] );
741: /*
742: * for [] and strings, comparisons are done on
743: * the maximum width of the two sides.
744: * for other sets, we have to ask the left side
745: * what type it is based on the type of the right.
746: * (this matters for intsets).
747: */
748: if ( c1 == TSTR ) {
749: codeoff();
750: p = rvalue( r->expr_node.lhs , NLNIL , LREQ );
751: codeon();
752: if ( p == NLNIL ) {
753: return NLNIL;
754: }
755: if ( lwidth( p ) > lwidth( p1 ) ) {
756: contype = p;
757: }
758: } else if ( c1 == TSET ) {
759: codeoff();
760: contype = rvalue(r->expr_node.lhs, p1, LREQ);
761: codeon();
762: if (contype == NLNIL) {
763: return NLNIL;
764: }
765: }
766: /*
767: * put out the width of the comparison.
768: */
769: putleaf(PCC_ICON, (int) lwidth(contype), 0, PCCT_INT, (char *) 0);
770: /*
771: * and the left hand side,
772: * for sets, strings, records
773: */
774: p = rvalue( r->expr_node.lhs , contype , LREQ );
775: if ( p == NLNIL ) {
776: return NLNIL;
777: }
778: putop( PCC_CM , PCCT_INT );
779: p1 = rvalue( r->expr_node.rhs , p , LREQ );
780: if ( p1 == NLNIL ) {
781: return NLNIL;
782: }
783: putop( PCC_CM , PCCT_INT );
784: putop( PCC_CALL , PCCT_INT );
785: } else {
786: /*
787: * the easy (scalar or error) case
788: */
789: p = rvalue( r->expr_node.lhs , contype , RREQ );
790: if ( p == NLNIL ) {
791: return NLNIL;
792: }
793: /*
794: * since the second pass can't do
795: * long op double or double op long
796: * we may have to do some coercing.
797: */
798: tuac(p, p1, &rettype, (int *) (&ctype));
799: p1 = rvalue( r->expr_node.rhs , p , RREQ );
800: if ( p1 == NLNIL ) {
801: return NLNIL;
802: }
803: tuac(p1, p, &rettype, (int *) (&ctype));
804: putop((int) relops[ r->tag - T_EQ ] , PCCT_INT );
805: sconv(PCCT_INT, PCCT_CHAR);
806: }
807: # endif PC
808: c = classify(p);
809: c1 = classify(p1);
810: if (nocomp(c) || nocomp(c1))
811: return (NLNIL);
812: # ifdef OBJ
813: g = NIL;
814: # endif
815: switch (c) {
816: case TBOOL:
817: case TCHAR:
818: if (c != c1)
819: goto clash;
820: break;
821: case TINT:
822: case TDOUBLE:
823: if (c1 != TINT && c1 != TDOUBLE)
824: goto clash;
825: break;
826: case TSCAL:
827: if (c1 != TSCAL)
828: goto clash;
829: if (scalar(p) != scalar(p1))
830: goto nonident;
831: break;
832: case TSET:
833: if (c1 != TSET)
834: goto clash;
835: if ( opt( 's' ) &&
836: ( ( r->tag == T_LT) || (r->tag == T_GT) ) &&
837: ( line != nssetline ) ) {
838: nssetline = line;
839: standard();
840: error("%s comparison on sets is non-standard" , opname );
841: }
842: if (p != p1)
843: goto nonident;
844: # ifdef OBJ
845: g = TSET;
846: # endif
847: break;
848: case TREC:
849: if ( c1 != TREC ) {
850: goto clash;
851: }
852: if ( p != p1 ) {
853: goto nonident;
854: }
855: if (r->tag != T_EQ && r->tag != T_NE) {
856: error("%s not allowed on records - only allow = and <>" , opname );
857: return (NLNIL);
858: }
859: # ifdef OBJ
860: g = TREC;
861: # endif
862: break;
863: case TPTR:
864: case TNIL:
865: if (c1 != TPTR && c1 != TNIL)
866: goto clash;
867: if (r->tag != T_EQ && r->tag != T_NE) {
868: error("%s not allowed on pointers - only allow = and <>" , opname );
869: return (NLNIL);
870: }
871: if (p != nl+TNIL && p1 != nl+TNIL && p != p1)
872: goto nonident;
873: break;
874: case TSTR:
875: if (c1 != TSTR)
876: goto clash;
877: if (width(p) != width(p1)) {
878: error("Strings not same length in %s comparison", opname);
879: return (NLNIL);
880: }
881: # ifdef OBJ
882: g = TSTR;
883: # endif OBJ
884: break;
885: default:
886: panic("rval2");
887: }
888: # ifdef OBJ
889: return (gen(g, r->tag, width(p), width(p1)));
890: # endif OBJ
891: # ifdef PC
892: return nl + TBOOL;
893: # endif PC
894: clash:
895: error("%ss and %ss cannot be compared - operator was %s", clnames[c], clnames[c1], opname);
896: return (NLNIL);
897: nonident:
898: error("%s types must be identical in comparisons - operator was %s", clnames[c1], opname);
899: return (NLNIL);
900:
901: case T_IN:
902: rt = r->expr_node.rhs;
903: # ifdef OBJ
904: if (rt != TR_NIL && rt->tag == T_CSET) {
905: (void) precset( rt , NLNIL , &csetd );
906: p1 = csetd.csettype;
907: if (p1 == NLNIL)
908: return NLNIL;
909: postcset( rt, &csetd);
910: } else {
911: p1 = stkrval(r->expr_node.rhs, NLNIL , (long) RREQ );
912: rt = TR_NIL;
913: }
914: # endif OBJ
915: # ifdef PC
916: if (rt != TR_NIL && rt->tag == T_CSET) {
917: if ( precset( rt , NLNIL , &csetd ) ) {
918: putleaf( PCC_ICON , 0 , 0
919: , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
920: , "_IN" );
921: } else {
922: putleaf( PCC_ICON , 0 , 0
923: , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
924: , "_INCT" );
925: }
926: p1 = csetd.csettype;
927: if (p1 == NIL)
928: return NLNIL;
929: } else {
930: putleaf( PCC_ICON , 0 , 0
931: , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
932: , "_IN" );
933: codeoff();
934: p1 = rvalue(r->expr_node.rhs, NLNIL , LREQ );
935: codeon();
936: }
937: # endif PC
938: p = stkrval(r->expr_node.lhs, NLNIL , (long) RREQ );
939: if (p == NIL || p1 == NIL)
940: return (NLNIL);
941: if (p1->class != (char) SET) {
942: error("Right operand of 'in' must be a set, not %s", nameof(p1));
943: return (NLNIL);
944: }
945: if (incompat(p, p1->type, r->expr_node.lhs)) {
946: cerror("Index type clashed with set component type for 'in'");
947: return (NLNIL);
948: }
949: setran(p1->type);
950: # ifdef OBJ
951: if (rt == TR_NIL || csetd.comptime)
952: (void) put(4, O_IN, width(p1), set.lwrb, set.uprbp);
953: else
954: (void) put(2, O_INCT,
955: (int)(3 + csetd.singcnt + 2*csetd.paircnt));
956: # endif OBJ
957: # ifdef PC
958: if ( rt == TR_NIL || rt->tag != T_CSET ) {
959: putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 );
960: putop( PCC_CM , PCCT_INT );
961: putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 );
962: putop( PCC_CM , PCCT_INT );
963: p1 = rvalue( r->expr_node.rhs , NLNIL , LREQ );
964: if ( p1 == NLNIL ) {
965: return NLNIL;
966: }
967: putop( PCC_CM , PCCT_INT );
968: } else if ( csetd.comptime ) {
969: putleaf( PCC_ICON , set.lwrb , 0 , PCCT_INT , (char *) 0 );
970: putop( PCC_CM , PCCT_INT );
971: putleaf( PCC_ICON , set.uprbp , 0 , PCCT_INT , (char *) 0 );
972: putop( PCC_CM , PCCT_INT );
973: postcset( r->expr_node.rhs , &csetd );
974: putop( PCC_CM , PCCT_INT );
975: } else {
976: postcset( r->expr_node.rhs , &csetd );
977: }
978: putop( PCC_CALL , PCCT_INT );
979: sconv(PCCT_INT, PCCT_CHAR);
980: # endif PC
981: return (nl+T1BOOL);
982: default:
983: if (r->expr_node.lhs == TR_NIL)
984: return (NLNIL);
985: switch (r->tag) {
986: default:
987: panic("rval3");
988:
989:
990: /*
991: * An octal number
992: */
993: case T_BINT:
994: f.pdouble = a8tol(r->const_node.cptr);
995: goto conint;
996:
997: /*
998: * A decimal number
999: */
1000: case T_INT:
1001: f.pdouble = atof(r->const_node.cptr);
1002: conint:
1003: if (f.pdouble > MAXINT || f.pdouble < MININT) {
1004: error("Constant too large for this implementation");
1005: return (NLNIL);
1006: }
1007: l = f.pdouble;
1008: # ifdef OBJ
1009: if (bytes(l, l) <= 2) {
1010: (void) put(2, O_CON2, ( short ) l);
1011: return (nl+T2INT);
1012: }
1013: (void) put(2, O_CON4, l);
1014: return (nl+T4INT);
1015: # endif OBJ
1016: # ifdef PC
1017: switch (bytes(l, l)) {
1018: case 1:
1019: putleaf(PCC_ICON, (int) l, 0, PCCT_CHAR,
1020: (char *) 0);
1021: return nl+T1INT;
1022: case 2:
1023: putleaf(PCC_ICON, (int) l, 0, PCCT_SHORT,
1024: (char *) 0);
1025: return nl+T2INT;
1026: case 4:
1027: putleaf(PCC_ICON, (int) l, 0, PCCT_INT,
1028: (char *) 0);
1029: return nl+T4INT;
1030: }
1031: # endif PC
1032:
1033: /*
1034: * A floating point number
1035: */
1036: case T_FINT:
1037: # ifdef OBJ
1038: (void) put(2, O_CON8, atof(r->const_node.cptr));
1039: # endif OBJ
1040: # ifdef PC
1041: putCON8( atof( r->const_node.cptr ) );
1042: # endif PC
1043: return (nl+TDOUBLE);
1044:
1045: /*
1046: * Constant strings. Note that constant characters
1047: * are constant strings of length one; there is
1048: * no constant string of length one.
1049: */
1050: case T_STRNG:
1051: cp = r->const_node.cptr;
1052: if (cp[1] == 0) {
1053: # ifdef OBJ
1054: (void) put(2, O_CONC, cp[0]);
1055: # endif OBJ
1056: # ifdef PC
1057: putleaf( PCC_ICON , cp[0] , 0 , PCCT_CHAR ,
1058: (char *) 0 );
1059: # endif PC
1060: return (nl+T1CHAR);
1061: }
1062: goto cstrng;
1063: }
1064:
1065: }
1066: }
1067:
1068: /*
1069: * Can a class appear
1070: * in a comparison ?
1071: */
1072: nocomp(c)
1073: int c;
1074: {
1075:
1076: switch (c) {
1077: case TREC:
1078: if ( line != reccompline ) {
1079: reccompline = line;
1080: warning();
1081: if ( opt( 's' ) ) {
1082: standard();
1083: }
1084: error("record comparison is non-standard");
1085: }
1086: break;
1087: case TFILE:
1088: case TARY:
1089: error("%ss may not participate in comparisons", clnames[c]);
1090: return (1);
1091: }
1092: return (NIL);
1093: }
1094:
1095: /*
1096: * this is sort of like gconst, except it works on expression trees
1097: * rather than declaration trees, and doesn't give error messages for
1098: * non-constant things.
1099: * as a side effect this fills in the con structure that gconst uses.
1100: * this returns TRUE or FALSE.
1101: */
1102:
1103: bool
1104: constval(r)
1105: register struct tnode *r;
1106: {
1107: register struct nl *np;
1108: register struct tnode *cn;
1109: char *cp;
1110: int negd, sgnd;
1111: long ci;
1112:
1113: con.ctype = NIL;
1114: cn = r;
1115: negd = sgnd = 0;
1116: loop:
1117: /*
1118: * cn[2] is nil if error recovery generated a T_STRNG
1119: */
1120: if (cn == TR_NIL || cn->expr_node.lhs == TR_NIL)
1121: return FALSE;
1122: switch (cn->tag) {
1123: default:
1124: return FALSE;
1125: case T_MINUS:
1126: negd = 1 - negd;
1127: /* and fall through */
1128: case T_PLUS:
1129: sgnd++;
1130: cn = cn->un_expr.expr;
1131: goto loop;
1132: case T_NIL:
1133: con.cpval = NIL;
1134: con.cival = 0;
1135: con.crval = con.cival;
1136: con.ctype = nl + TNIL;
1137: break;
1138: case T_VAR:
1139: np = lookup(cn->var_node.cptr);
1140: if (np == NLNIL || np->class != CONST) {
1141: return FALSE;
1142: }
1143: if ( cn->var_node.qual != TR_NIL ) {
1144: return FALSE;
1145: }
1146: con.ctype = np->type;
1147: switch (classify(np->type)) {
1148: case TINT:
1149: con.crval = np->range[0];
1150: break;
1151: case TDOUBLE:
1152: con.crval = np->real;
1153: break;
1154: case TBOOL:
1155: case TCHAR:
1156: case TSCAL:
1157: con.cival = np->value[0];
1158: con.crval = con.cival;
1159: break;
1160: case TSTR:
1161: con.cpval = (char *) np->ptr[0];
1162: break;
1163: default:
1164: con.ctype = NIL;
1165: return FALSE;
1166: }
1167: break;
1168: case T_BINT:
1169: con.crval = a8tol(cn->const_node.cptr);
1170: goto restcon;
1171: case T_INT:
1172: con.crval = atof(cn->const_node.cptr);
1173: if (con.crval > MAXINT || con.crval < MININT) {
1174: derror("Constant too large for this implementation");
1175: con.crval = 0;
1176: }
1177: restcon:
1178: ci = con.crval;
1179: #ifndef PI0
1180: if (bytes(ci, ci) <= 2)
1181: con.ctype = nl+T2INT;
1182: else
1183: #endif
1184: con.ctype = nl+T4INT;
1185: break;
1186: case T_FINT:
1187: con.ctype = nl+TDOUBLE;
1188: con.crval = atof(cn->const_node.cptr);
1189: break;
1190: case T_STRNG:
1191: cp = cn->const_node.cptr;
1192: if (cp[1] == 0) {
1193: con.ctype = nl+T1CHAR;
1194: con.cival = cp[0];
1195: con.crval = con.cival;
1196: break;
1197: }
1198: con.ctype = nl+TSTR;
1199: con.cpval = cp;
1200: break;
1201: }
1202: if (sgnd) {
1203: if (isnta(con.ctype, "id")) {
1204: derror("%s constants cannot be signed", nameof(con.ctype));
1205: return FALSE;
1206: } else if (negd)
1207: con.crval = -con.crval;
1208: }
1209: return TRUE;
1210: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.