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