19411d0f5Sralph #ifndef lint
2*10cfdb8aSbostic static char *sccsid ="@(#)trees.c 4.37 (Berkeley) 06/18/90";
39411d0f5Sralph #endif
49411d0f5Sralph
5c975fa10Sralph # include "pass1.h"
685b1171fSralph
7d0dde492Smckusick # include <setjmp.h>
8d0dde492Smckusick
99411d0f5Sralph int bdebug = 0;
109411d0f5Sralph int adebug = 0;
119411d0f5Sralph extern ddebug;
129411d0f5Sralph extern eprint();
139411d0f5Sralph
1485b1171fSralph /* corrections when in violation of lint */
1585b1171fSralph
1685b1171fSralph /* some special actions, used in finding the type of nodes */
1785b1171fSralph # define NCVT 01
1885b1171fSralph # define PUN 02
1985b1171fSralph # define TYPL 04
2085b1171fSralph # define TYPR 010
2185b1171fSralph # define TYMATCH 040
2285b1171fSralph # define LVAL 0100
2385b1171fSralph # define CVTO 0200
2485b1171fSralph # define CVTL 0400
2585b1171fSralph # define CVTR 01000
2685b1171fSralph # define PTMATCH 02000
2785b1171fSralph # define OTHER 04000
2885b1171fSralph # define NCVTR 010000
2985b1171fSralph
309411d0f5Sralph #ifndef BUG1
printact(t,acts)319411d0f5Sralph printact(t, acts)
329411d0f5Sralph NODE *t;
339411d0f5Sralph int acts;
349411d0f5Sralph {
359411d0f5Sralph static struct actions {
369411d0f5Sralph int a_bit;
379411d0f5Sralph char *a_name;
389411d0f5Sralph } actions[] = {
399411d0f5Sralph { PUN, "PUN" },
409411d0f5Sralph { CVTL, "CVTL" },
419411d0f5Sralph { CVTR, "CVTR" },
429411d0f5Sralph { TYPL, "TYPL" },
439411d0f5Sralph { TYPR, "TYPR" },
449411d0f5Sralph { TYMATCH, "TYMATCH" },
459411d0f5Sralph { PTMATCH, "PTMATCH" },
469411d0f5Sralph { LVAL, "LVAL" },
479411d0f5Sralph { CVTO, "CVTO" },
489411d0f5Sralph { NCVT, "NCVT" },
499411d0f5Sralph { OTHER, "OTHER" },
509411d0f5Sralph { NCVTR, "NCVTR" },
519411d0f5Sralph { 0 }
529411d0f5Sralph };
539411d0f5Sralph register struct actions *p;
549411d0f5Sralph char *sep = " ";
559411d0f5Sralph
569411d0f5Sralph printf("actions");
579411d0f5Sralph for (p = actions; p->a_name; p++)
589411d0f5Sralph if (p->a_bit & acts) {
599411d0f5Sralph printf("%s%s", sep, p->a_name);
609411d0f5Sralph sep = "|";
619411d0f5Sralph }
629411d0f5Sralph if (!bdebug) {
639411d0f5Sralph printf(" for:\n");
649411d0f5Sralph fwalk(t, eprint, 0);
659411d0f5Sralph } else
669411d0f5Sralph putchar('\n');
679411d0f5Sralph }
689411d0f5Sralph #endif
699411d0f5Sralph
7085b1171fSralph /* node conventions:
7185b1171fSralph
7285b1171fSralph NAME: rval>0 is stab index for external
7385b1171fSralph rval<0 is -inlabel number
7485b1171fSralph lval is offset in bits
7585b1171fSralph ICON: lval has the value
7685b1171fSralph rval has the STAB index, or - label number,
7785b1171fSralph if a name whose address is in the constant
7885b1171fSralph rval = NONAME means no name
7985b1171fSralph REG: rval is reg. identification cookie
8085b1171fSralph
8185b1171fSralph */
8285b1171fSralph
8385b1171fSralph NODE *
buildtree(o,l,r)8485b1171fSralph buildtree( o, l, r ) register NODE *l, *r; {
8585b1171fSralph register NODE *p, *q;
8685b1171fSralph register actions;
8785b1171fSralph register opty;
8885b1171fSralph register struct symtab *sp;
8985b1171fSralph register NODE *lr, *ll;
909411d0f5Sralph NODE *fixargs();
9185b1171fSralph int i;
9285b1171fSralph
9385b1171fSralph # ifndef BUG1
9485b1171fSralph if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
9585b1171fSralph # endif
9685b1171fSralph opty = optype(o);
9785b1171fSralph
9885b1171fSralph /* check for constants */
9985b1171fSralph
10085b1171fSralph if( opty == UTYPE && l->in.op == ICON ){
10185b1171fSralph
10285b1171fSralph switch( o ){
10385b1171fSralph
10485b1171fSralph case NOT:
10585b1171fSralph if( hflag ) werror( "constant argument to NOT" );
10685b1171fSralph case UNARY MINUS:
10785b1171fSralph case COMPL:
10885b1171fSralph if( conval( l, o, l ) ) return(l);
10985b1171fSralph break;
11085b1171fSralph
11185b1171fSralph }
11285b1171fSralph }
11385b1171fSralph
114007a19b4Sdonn else if( opty == UTYPE && (l->in.op == FCON || l->in.op == DCON) ){
1159411d0f5Sralph
116007a19b4Sdonn switch( o ){
117007a19b4Sdonn
118007a19b4Sdonn case NOT:
119007a19b4Sdonn if( hflag ) werror( "constant argument to NOT" );
120007a19b4Sdonn if( l->in.op == FCON )
121007a19b4Sdonn l->tn.lval = l->fpn.fval == 0.0;
122007a19b4Sdonn else
123007a19b4Sdonn l->tn.lval = l->dpn.dval == 0.0;
124007a19b4Sdonn l->tn.rval = NONAME;
125007a19b4Sdonn l->in.op = ICON;
126007a19b4Sdonn l->fn.csiz = l->in.type = INT;
127007a19b4Sdonn l->fn.cdim = 0;
128007a19b4Sdonn return(l);
129007a19b4Sdonn case UNARY MINUS:
130007a19b4Sdonn if( l->in.op == FCON )
131007a19b4Sdonn l->fpn.fval = -l->fpn.fval;
132007a19b4Sdonn else
1339411d0f5Sralph l->dpn.dval = -l->dpn.dval;
13485b1171fSralph return(l);
13585b1171fSralph }
136007a19b4Sdonn }
13785b1171fSralph
13885b1171fSralph else if( o==QUEST && l->in.op==ICON ) {
13985b1171fSralph l->in.op = FREE;
14085b1171fSralph r->in.op = FREE;
14185b1171fSralph if( l->tn.lval ){
14285b1171fSralph tfree( r->in.right );
14385b1171fSralph return( r->in.left );
14485b1171fSralph }
14585b1171fSralph else {
14685b1171fSralph tfree( r->in.left );
14785b1171fSralph return( r->in.right );
14885b1171fSralph }
14985b1171fSralph }
15085b1171fSralph
15185b1171fSralph else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
15285b1171fSralph
15385b1171fSralph else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
15485b1171fSralph
15585b1171fSralph switch( o ){
15685b1171fSralph
15785b1171fSralph case ULT:
15885b1171fSralph case UGT:
15985b1171fSralph case ULE:
16085b1171fSralph case UGE:
16185b1171fSralph case LT:
16285b1171fSralph case GT:
16385b1171fSralph case LE:
16485b1171fSralph case GE:
16585b1171fSralph case EQ:
16685b1171fSralph case NE:
167eb7dc8d0Sdonn if( l->in.type == ENUMTY && r->in.type == ENUMTY ){
168eb7dc8d0Sdonn p = block( o, l, r, INT, 0, INT );
1692a1a76a1Sdonn chkpun( p );
170eb7dc8d0Sdonn p->in.op = FREE;
171eb7dc8d0Sdonn }
1722a1a76a1Sdonn
17385b1171fSralph case ANDAND:
17485b1171fSralph case OROR:
17585b1171fSralph case CBRANCH:
17685b1171fSralph
17785b1171fSralph ccwarn:
17885b1171fSralph if( hflag ) werror( "constant in conditional context" );
17985b1171fSralph
18085b1171fSralph case PLUS:
18185b1171fSralph case MINUS:
18285b1171fSralph case MUL:
18385b1171fSralph case DIV:
18485b1171fSralph case MOD:
18585b1171fSralph case AND:
18685b1171fSralph case OR:
18785b1171fSralph case ER:
18885b1171fSralph case LS:
18985b1171fSralph case RS:
19085b1171fSralph if( conval( l, o, r ) ) {
19185b1171fSralph r->in.op = FREE;
19285b1171fSralph return(l);
19385b1171fSralph }
19485b1171fSralph break;
19585b1171fSralph }
19685b1171fSralph }
197d0dde492Smckusick else if (opty == BITYPE &&
198d0dde492Smckusick (l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
199d0dde492Smckusick (r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
200d0dde492Smckusick if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
201d0dde492Smckusick extern int fpe_count;
202d0dde492Smckusick extern jmp_buf gotfpe;
2039411d0f5Sralph
204d0dde492Smckusick fpe_count = 0;
205d0dde492Smckusick if (setjmp(gotfpe))
206d0dde492Smckusick goto treatfpe;
2079411d0f5Sralph if (l->in.op == ICON)
2089411d0f5Sralph l->dpn.dval = l->tn.lval;
209d0dde492Smckusick else if (l->in.op == FCON)
210d0dde492Smckusick l->dpn.dval = l->fpn.fval;
2119411d0f5Sralph if (r->in.op == ICON)
2129411d0f5Sralph r->dpn.dval = r->tn.lval;
213d0dde492Smckusick else if (r->in.op == FCON)
214d0dde492Smckusick r->dpn.dval = r->fpn.fval;
21585b1171fSralph switch (o) {
2169411d0f5Sralph
21785b1171fSralph case PLUS:
2189411d0f5Sralph l->dpn.dval += r->dpn.dval;
219d0dde492Smckusick break;
2209411d0f5Sralph
22185b1171fSralph case MINUS:
2229411d0f5Sralph l->dpn.dval -= r->dpn.dval;
223d0dde492Smckusick break;
2249411d0f5Sralph
22585b1171fSralph case MUL:
2269411d0f5Sralph l->dpn.dval *= r->dpn.dval;
227d0dde492Smckusick break;
2289411d0f5Sralph
22985b1171fSralph case DIV:
2309411d0f5Sralph if (r->dpn.dval == 0)
2319411d0f5Sralph uerror("division by 0.");
2329411d0f5Sralph else
2339411d0f5Sralph l->dpn.dval /= r->dpn.dval;
234d0dde492Smckusick break;
235d0dde492Smckusick }
236d0dde492Smckusick treatfpe:
237d0dde492Smckusick if (fpe_count > 0) {
238d0dde492Smckusick uerror("floating point exception in constant expression");
239d0dde492Smckusick l->dpn.dval = 1.0; /* Fairly harmless */
240d0dde492Smckusick }
241d0dde492Smckusick fpe_count = -1;
242d0dde492Smckusick l->in.op = DCON;
243d0dde492Smckusick l->in.type = l->fn.csiz = DOUBLE;
244d0dde492Smckusick r->in.op = FREE;
24585b1171fSralph return (l);
24685b1171fSralph }
24785b1171fSralph }
24885b1171fSralph
249d0dde492Smckusick /* it's real; we must make a new node */
25085b1171fSralph
25185b1171fSralph p = block( o, l, r, INT, 0, INT );
25285b1171fSralph
25385b1171fSralph actions = opact(p);
2549411d0f5Sralph #ifndef BUG1
2559411d0f5Sralph if (adebug)
2569411d0f5Sralph printact(p, actions);
2579411d0f5Sralph #endif
25885b1171fSralph
25985b1171fSralph if( actions&LVAL ){ /* check left descendent */
26085b1171fSralph if( notlval(p->in.left) ) {
26109ddf2aaSdonn uerror( "illegal lvalue operand of assignment operator" );
26285b1171fSralph }
26385b1171fSralph }
26485b1171fSralph
26585b1171fSralph if( actions & NCVTR ){
26685b1171fSralph p->in.left = pconvert( p->in.left );
26785b1171fSralph }
26885b1171fSralph else if( !(actions & NCVT ) ){
26985b1171fSralph switch( opty ){
27085b1171fSralph
27185b1171fSralph case BITYPE:
27285b1171fSralph p->in.right = pconvert( p->in.right );
27385b1171fSralph case UTYPE:
27485b1171fSralph p->in.left = pconvert( p->in.left );
27585b1171fSralph
27685b1171fSralph }
27785b1171fSralph }
27885b1171fSralph
27985b1171fSralph if( (actions&PUN) && (o!=CAST||cflag) ){
28085b1171fSralph chkpun(p);
28185b1171fSralph }
28285b1171fSralph
28385b1171fSralph if( actions & (TYPL|TYPR) ){
28485b1171fSralph
28585b1171fSralph q = (actions&TYPL) ? p->in.left : p->in.right;
28685b1171fSralph
28785b1171fSralph p->in.type = q->in.type;
28885b1171fSralph p->fn.cdim = q->fn.cdim;
28985b1171fSralph p->fn.csiz = q->fn.csiz;
29085b1171fSralph }
29185b1171fSralph
29285b1171fSralph if( actions & CVTL ) p = convert( p, CVTL );
29385b1171fSralph if( actions & CVTR ) p = convert( p, CVTR );
29485b1171fSralph if( actions & TYMATCH ) p = tymatch(p);
29585b1171fSralph if( actions & PTMATCH ) p = ptmatch(p);
29685b1171fSralph
29785b1171fSralph if( actions & OTHER ){
29885b1171fSralph l = p->in.left;
29985b1171fSralph r = p->in.right;
30085b1171fSralph
30185b1171fSralph switch(o){
30285b1171fSralph
30385b1171fSralph case NAME:
30485b1171fSralph sp = &stab[idname];
30585b1171fSralph if( sp->stype == UNDEF ){
30685b1171fSralph #ifndef FLEXNAMES
30785b1171fSralph uerror( "%.8s undefined", sp->sname );
30885b1171fSralph #else
30985b1171fSralph uerror( "%s undefined", sp->sname );
31085b1171fSralph #endif
31185b1171fSralph /* make p look reasonable */
312007a19b4Sdonn p->in.type = p->fn.csiz = INT;
313007a19b4Sdonn p->fn.cdim = 0;
31485b1171fSralph p->tn.rval = idname;
31585b1171fSralph p->tn.lval = 0;
31685b1171fSralph defid( p, SNULL );
31785b1171fSralph break;
31885b1171fSralph }
31985b1171fSralph p->in.type = sp->stype;
32085b1171fSralph p->fn.cdim = sp->dimoff;
32185b1171fSralph p->fn.csiz = sp->sizoff;
32285b1171fSralph p->tn.lval = 0;
32385b1171fSralph p->tn.rval = idname;
32485b1171fSralph /* special case: MOETY is really an ICON... */
32585b1171fSralph if( p->in.type == MOETY ){
32685b1171fSralph p->tn.rval = NONAME;
32785b1171fSralph p->tn.lval = sp->offset;
32885b1171fSralph p->fn.cdim = 0;
32985b1171fSralph p->in.type = ENUMTY;
33085b1171fSralph p->in.op = ICON;
33185b1171fSralph }
33285b1171fSralph break;
33385b1171fSralph
33485b1171fSralph case ICON:
33585b1171fSralph p->in.type = INT;
33685b1171fSralph p->fn.cdim = 0;
33785b1171fSralph p->fn.csiz = INT;
33885b1171fSralph break;
33985b1171fSralph
34085b1171fSralph case STRING:
34185b1171fSralph p->in.op = NAME;
34285b1171fSralph p->in.type = CHAR+ARY;
34385b1171fSralph p->tn.lval = 0;
34485b1171fSralph p->tn.rval = NOLAB;
34585b1171fSralph p->fn.cdim = curdim;
34685b1171fSralph p->fn.csiz = CHAR;
34785b1171fSralph break;
34885b1171fSralph
34985b1171fSralph case FCON:
35085b1171fSralph p->tn.lval = 0;
35185b1171fSralph p->tn.rval = 0;
3529411d0f5Sralph p->in.type = FLOAT;
3539411d0f5Sralph p->fn.cdim = 0;
3549411d0f5Sralph p->fn.csiz = FLOAT;
3559411d0f5Sralph break;
3569411d0f5Sralph
3579411d0f5Sralph case DCON:
3589411d0f5Sralph p->tn.lval = 0;
3599411d0f5Sralph p->tn.rval = 0;
36085b1171fSralph p->in.type = DOUBLE;
36185b1171fSralph p->fn.cdim = 0;
36285b1171fSralph p->fn.csiz = DOUBLE;
36385b1171fSralph break;
36485b1171fSralph
36585b1171fSralph case STREF:
36685b1171fSralph /* p->x turned into *(p+offset) */
36785b1171fSralph /* rhs must be a name; check correctness */
36885b1171fSralph
36985b1171fSralph i = r->tn.rval;
37085b1171fSralph if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
37185b1171fSralph uerror( "member of structure or union required" );
37285b1171fSralph }else
37385b1171fSralph /* if this name is non-unique, find right one */
37485b1171fSralph if( stab[i].sflags & SNONUNIQ &&
37585b1171fSralph (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
37685b1171fSralph (l->fn.csiz +1) >= 0 ){
37785b1171fSralph /* nonunique name && structure defined */
37885b1171fSralph char * memnam, * tabnam;
37985b1171fSralph int j;
38085b1171fSralph int memi;
38185b1171fSralph j=dimtab[l->fn.csiz+1];
38285b1171fSralph for( ; (memi=dimtab[j]) >= 0; ++j ){
38385b1171fSralph tabnam = stab[memi].sname;
38485b1171fSralph memnam = stab[i].sname;
38585b1171fSralph # ifndef BUG1
38685b1171fSralph if( ddebug>1 ){
38785b1171fSralph #ifndef FLEXNAMES
38885b1171fSralph printf("member %.8s==%.8s?\n",
38985b1171fSralph #else
39085b1171fSralph printf("member %s==%s?\n",
39185b1171fSralph #endif
39285b1171fSralph memnam, tabnam);
39385b1171fSralph }
39485b1171fSralph # endif
39585b1171fSralph if( stab[memi].sflags & SNONUNIQ ){
39685b1171fSralph #ifndef FLEXNAMES
397eb7dc8d0Sdonn register k;
39885b1171fSralph for( k=0; k<NCHNAM; ++k ){
39985b1171fSralph if(*memnam++!=*tabnam)
40085b1171fSralph goto next;
40185b1171fSralph if(!*tabnam++) break;
40285b1171fSralph }
40385b1171fSralph #else
40485b1171fSralph if (memnam != tabnam)
40585b1171fSralph goto next;
40685b1171fSralph #endif
40785b1171fSralph r->tn.rval = i = memi;
40885b1171fSralph break;
40985b1171fSralph }
41085b1171fSralph next: continue;
41185b1171fSralph }
41285b1171fSralph if( memi < 0 )
41385b1171fSralph #ifndef FLEXNAMES
41485b1171fSralph uerror("illegal member use: %.8s",
41585b1171fSralph #else
41685b1171fSralph uerror("illegal member use: %s",
41785b1171fSralph #endif
41885b1171fSralph stab[i].sname);
41985b1171fSralph }
42085b1171fSralph else {
42185b1171fSralph register j;
42285b1171fSralph if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
42385b1171fSralph if( stab[i].sflags & SNONUNIQ ){
42485b1171fSralph uerror( "nonunique name demands struct/union or struct/union pointer" );
42585b1171fSralph }
42685b1171fSralph else werror( "struct/union or struct/union pointer required" );
42785b1171fSralph }
42885b1171fSralph else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
42985b1171fSralph else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
43085b1171fSralph #ifndef FLEXNAMES
43185b1171fSralph werror( "illegal member use: %.8s", stab[i].sname );
43285b1171fSralph #else
43385b1171fSralph werror( "illegal member use: %s", stab[i].sname );
43485b1171fSralph #endif
43585b1171fSralph }
43685b1171fSralph }
43785b1171fSralph
43885b1171fSralph p = stref( p );
43985b1171fSralph break;
44085b1171fSralph
44185b1171fSralph case UNARY MUL:
44285b1171fSralph if( l->in.op == UNARY AND ){
44385b1171fSralph p->in.op = l->in.op = FREE;
44485b1171fSralph p = l->in.left;
44585b1171fSralph }
44685b1171fSralph if( !ISPTR(l->in.type))uerror("illegal indirection");
44785b1171fSralph p->in.type = DECREF(l->in.type);
44885b1171fSralph p->fn.cdim = l->fn.cdim;
44985b1171fSralph p->fn.csiz = l->fn.csiz;
45085b1171fSralph break;
45185b1171fSralph
45285b1171fSralph case UNARY AND:
45385b1171fSralph switch( l->in.op ){
45485b1171fSralph
45585b1171fSralph case UNARY MUL:
45685b1171fSralph p->in.op = l->in.op = FREE;
45785b1171fSralph p = l->in.left;
45885b1171fSralph case NAME:
45985b1171fSralph p->in.type = INCREF( l->in.type );
46085b1171fSralph p->fn.cdim = l->fn.cdim;
46185b1171fSralph p->fn.csiz = l->fn.csiz;
46285b1171fSralph break;
46385b1171fSralph
46485b1171fSralph case COMOP:
46585b1171fSralph lr = buildtree( UNARY AND, l->in.right, NIL );
46685b1171fSralph p->in.op = l->in.op = FREE;
46785b1171fSralph p = buildtree( COMOP, l->in.left, lr );
46885b1171fSralph break;
46985b1171fSralph
47085b1171fSralph case QUEST:
47185b1171fSralph lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
47285b1171fSralph ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
47385b1171fSralph p->in.op = l->in.op = l->in.right->in.op = FREE;
47485b1171fSralph p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
47585b1171fSralph break;
47685b1171fSralph
47785b1171fSralph # ifdef ADDROREG
47885b1171fSralph case OREG:
47985b1171fSralph /* OREG was built in clocal()
48085b1171fSralph * for an auto or formal parameter
48185b1171fSralph * now its address is being taken
48285b1171fSralph * local code must unwind it
48385b1171fSralph * back to PLUS/MINUS REG ICON
48485b1171fSralph * according to local conventions
48585b1171fSralph */
48685b1171fSralph {
48785b1171fSralph extern NODE * addroreg();
48885b1171fSralph p->in.op = FREE;
48985b1171fSralph p = addroreg( l );
49085b1171fSralph }
49185b1171fSralph break;
49285b1171fSralph
49385b1171fSralph # endif
49485b1171fSralph default:
49585b1171fSralph uerror( "unacceptable operand of &" );
49685b1171fSralph break;
49785b1171fSralph }
49885b1171fSralph break;
49985b1171fSralph
50085b1171fSralph case LS:
50185b1171fSralph case RS:
502007a19b4Sdonn if( l->in.type == CHAR || l->in.type == SHORT )
503007a19b4Sdonn p->in.type = INT;
504007a19b4Sdonn else if( l->in.type == UCHAR || l->in.type == USHORT )
505007a19b4Sdonn p->in.type = UNSIGNED;
506007a19b4Sdonn else
507007a19b4Sdonn p->in.type = l->in.type;
50885b1171fSralph case ASG LS:
50985b1171fSralph case ASG RS:
510007a19b4Sdonn if( r->in.type != INT )
511007a19b4Sdonn p->in.right = r = makety(r, INT, 0, INT );
51285b1171fSralph break;
51385b1171fSralph
51485b1171fSralph case RETURN:
51585b1171fSralph case ASSIGN:
51685b1171fSralph case CAST:
51785b1171fSralph /* structure assignment */
51885b1171fSralph /* take the addresses of the two sides; then make an
51985b1171fSralph /* operator using STASG and
52085b1171fSralph /* the addresses of left and right */
52185b1171fSralph
52285b1171fSralph {
52385b1171fSralph register TWORD t;
52485b1171fSralph register d, s;
52585b1171fSralph
52685b1171fSralph if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );
52785b1171fSralph
52885b1171fSralph r = buildtree( UNARY AND, r, NIL );
52985b1171fSralph t = r->in.type;
53085b1171fSralph d = r->fn.cdim;
53185b1171fSralph s = r->fn.csiz;
53285b1171fSralph
53385b1171fSralph l = block( STASG, l, r, t, d, s );
53485b1171fSralph
53585b1171fSralph if( o == RETURN ){
53685b1171fSralph p->in.op = FREE;
53785b1171fSralph p = l;
53885b1171fSralph break;
53985b1171fSralph }
54085b1171fSralph
54185b1171fSralph p->in.op = UNARY MUL;
54285b1171fSralph p->in.left = l;
54385b1171fSralph p->in.right = NIL;
54485b1171fSralph break;
54585b1171fSralph }
54685b1171fSralph case COLON:
54785b1171fSralph /* structure colon */
54885b1171fSralph
54985b1171fSralph if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
55085b1171fSralph break;
55185b1171fSralph
55285b1171fSralph case CALL:
5539411d0f5Sralph p->in.right = r = fixargs( p->in.right );
55485b1171fSralph case UNARY CALL:
55585b1171fSralph if( !ISPTR(l->in.type)) uerror("illegal function");
55685b1171fSralph p->in.type = DECREF(l->in.type);
55785b1171fSralph if( !ISFTN(p->in.type)) uerror("illegal function");
55885b1171fSralph p->in.type = DECREF( p->in.type );
55985b1171fSralph p->fn.cdim = l->fn.cdim;
56085b1171fSralph p->fn.csiz = l->fn.csiz;
56185b1171fSralph if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
56285b1171fSralph l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
56385b1171fSralph ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
56485b1171fSralph p->in.op += (FORTCALL-CALL);
56585b1171fSralph }
56685b1171fSralph if( p->in.type == STRTY || p->in.type == UNIONTY ){
56785b1171fSralph /* function returning structure */
56885b1171fSralph /* make function really return ptr to str., with * */
56985b1171fSralph
57085b1171fSralph p->in.op += STCALL-CALL;
57185b1171fSralph p->in.type = INCREF( p->in.type );
57285b1171fSralph p = buildtree( UNARY MUL, p, NIL );
57385b1171fSralph
57485b1171fSralph }
57585b1171fSralph break;
57685b1171fSralph
57785b1171fSralph default:
57885b1171fSralph cerror( "other code %d", o );
57985b1171fSralph }
58085b1171fSralph
58185b1171fSralph }
58285b1171fSralph
58385b1171fSralph if( actions & CVTO ) p = oconvert(p);
58485b1171fSralph p = clocal(p);
58585b1171fSralph
58685b1171fSralph # ifndef BUG1
58785b1171fSralph if( bdebug ) fwalk( p, eprint, 0 );
58885b1171fSralph # endif
58985b1171fSralph
59085b1171fSralph return(p);
59185b1171fSralph
59285b1171fSralph }
59385b1171fSralph
594d0dde492Smckusick int fpe_count = -1;
595d0dde492Smckusick jmp_buf gotfpe;
596d0dde492Smckusick
597*10cfdb8aSbostic void
fpe()598d0dde492Smckusick fpe() {
599d0dde492Smckusick if (fpe_count < 0)
600d0dde492Smckusick cerror("floating point exception");
601d0dde492Smckusick ++fpe_count;
602d0dde492Smckusick longjmp(gotfpe, 1);
603d0dde492Smckusick }
604d0dde492Smckusick
6059411d0f5Sralph /*
6069411d0f5Sralph * Rewrite arguments in a function call.
6079411d0f5Sralph * Structure arguments are massaged, single
6089411d0f5Sralph * precision floating point constants are
6099411d0f5Sralph * cast to double (to eliminate convert code).
6109411d0f5Sralph */
61185b1171fSralph NODE *
fixargs(p)6129411d0f5Sralph fixargs( p ) register NODE *p; {
6139411d0f5Sralph int o = p->in.op;
61485b1171fSralph
6159411d0f5Sralph if( o == CM ){
6169411d0f5Sralph p->in.left = fixargs( p->in.left );
6179411d0f5Sralph p->in.right = fixargs( p->in.right );
61885b1171fSralph return( p );
61985b1171fSralph }
62085b1171fSralph
62185b1171fSralph if( p->in.type == STRTY || p->in.type == UNIONTY ){
62285b1171fSralph p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
62385b1171fSralph p->in.left = buildtree( UNARY AND, p->in.left, NIL );
62485b1171fSralph p = clocal(p);
62585b1171fSralph }
6269411d0f5Sralph else if( o == FCON )
6279411d0f5Sralph p = makety(p, DOUBLE, 0, 0);
62885b1171fSralph return( p );
62985b1171fSralph }
63085b1171fSralph
chkstr(i,j,type)63185b1171fSralph chkstr( i, j, type ) TWORD type; {
63285b1171fSralph /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
63385b1171fSralph /* i has been checked to contain a MOS or MOU */
63485b1171fSralph /* j is the index in dimtab of the members... */
63585b1171fSralph int k, kk;
63685b1171fSralph
63785b1171fSralph extern int ddebug;
63885b1171fSralph
63985b1171fSralph # ifndef BUG1
64085b1171fSralph #ifndef FLEXNAMES
64185b1171fSralph if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
64285b1171fSralph #else
64385b1171fSralph if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
64485b1171fSralph #endif
64585b1171fSralph # endif
64685b1171fSralph if( (k = j) < 0 ) uerror( "undefined structure or union" );
64785b1171fSralph else {
64885b1171fSralph for( ; (kk = dimtab[k] ) >= 0; ++k ){
64985b1171fSralph if( kk >= SYMTSZ ){
65085b1171fSralph cerror( "gummy structure" );
65185b1171fSralph return(1);
65285b1171fSralph }
65385b1171fSralph if( kk == i ) return( 1 );
65485b1171fSralph switch( stab[kk].stype ){
65585b1171fSralph
65685b1171fSralph case STRTY:
65785b1171fSralph case UNIONTY:
65885b1171fSralph if( type == STRTY ) continue; /* no recursive looking for strs */
65985b1171fSralph if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
66085b1171fSralph if( stab[kk].sname[0] == '$' ) return(0); /* $FAKE */
66185b1171fSralph werror(
66285b1171fSralph #ifndef FLEXNAMES
66385b1171fSralph "illegal member use: perhaps %.8s.%.8s?",
66485b1171fSralph #else
66585b1171fSralph "illegal member use: perhaps %s.%s?",
66685b1171fSralph #endif
66785b1171fSralph stab[kk].sname, stab[i].sname );
66885b1171fSralph return(1);
66985b1171fSralph }
67085b1171fSralph }
67185b1171fSralph }
67285b1171fSralph }
67385b1171fSralph return( 0 );
67485b1171fSralph }
67585b1171fSralph
conval(p,o,q)67685b1171fSralph conval( p, o, q ) register NODE *p, *q; {
67785b1171fSralph /* apply the op o to the lval part of p; if binary, rhs is val */
67897187f20Sdonn /* works only on integer constants */
67997187f20Sdonn NODE *r;
68085b1171fSralph int i, u;
68185b1171fSralph CONSZ val;
6829d332cffSdonn TWORD utype;
68385b1171fSralph
68485b1171fSralph val = q->tn.lval;
68585b1171fSralph u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
68685b1171fSralph if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
68785b1171fSralph
68885b1171fSralph if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
68985b1171fSralph if( q->tn.rval != NONAME && o!=PLUS ) return(0);
69085b1171fSralph if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
69185b1171fSralph
6929d332cffSdonn /* usual type conversions -- handle casts of constants */
6935d572d7fSdonn #define ISLONG(t) ((t) == LONG || (t) == ULONG)
6945d572d7fSdonn if (ISLONG(p->in.type) || ISLONG(q->in.type))
6955d572d7fSdonn utype = u ? ULONG : LONG;
6965d572d7fSdonn else
6979d332cffSdonn utype = u ? UNSIGNED : INT;
6989d332cffSdonn if( !ISPTR(p->in.type) && p->in.type != utype )
6999d332cffSdonn p = makety(p, utype, 0, (int)utype);
7009d332cffSdonn if( q->in.type != utype )
7019d332cffSdonn q = makety(q, utype, 0, (int)utype);
70297187f20Sdonn
70385b1171fSralph switch( o ){
70485b1171fSralph
70585b1171fSralph case PLUS:
70685b1171fSralph p->tn.lval += val;
70785b1171fSralph if( p->tn.rval == NONAME ){
70885b1171fSralph p->tn.rval = q->tn.rval;
70985b1171fSralph p->in.type = q->in.type;
71085b1171fSralph }
71185b1171fSralph break;
71285b1171fSralph case MINUS:
71385b1171fSralph p->tn.lval -= val;
71485b1171fSralph break;
71585b1171fSralph case MUL:
7162a1a76a1Sdonn p->tn.lval *= val;
71785b1171fSralph break;
71885b1171fSralph case DIV:
71985b1171fSralph if( val == 0 ) uerror( "division by 0" );
7209411d0f5Sralph else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
72185b1171fSralph else p->tn.lval /= val;
72285b1171fSralph break;
72385b1171fSralph case MOD:
72485b1171fSralph if( val == 0 ) uerror( "division by 0" );
7259411d0f5Sralph else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
72685b1171fSralph else p->tn.lval %= val;
72785b1171fSralph break;
72885b1171fSralph case AND:
72985b1171fSralph p->tn.lval &= val;
73085b1171fSralph break;
73185b1171fSralph case OR:
73285b1171fSralph p->tn.lval |= val;
73385b1171fSralph break;
73485b1171fSralph case ER:
73585b1171fSralph p->tn.lval ^= val;
73685b1171fSralph break;
73785b1171fSralph case LS:
73885b1171fSralph i = val;
73985b1171fSralph p->tn.lval = p->tn.lval << i;
74085b1171fSralph break;
74185b1171fSralph case RS:
74285b1171fSralph i = val;
7439411d0f5Sralph if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
7449411d0f5Sralph else p->tn.lval = p->tn.lval >> i;
74585b1171fSralph break;
74685b1171fSralph
74785b1171fSralph case UNARY MINUS:
74885b1171fSralph p->tn.lval = - p->tn.lval;
74985b1171fSralph break;
75085b1171fSralph case COMPL:
75185b1171fSralph p->tn.lval = ~p->tn.lval;
75285b1171fSralph break;
75385b1171fSralph case NOT:
75485b1171fSralph p->tn.lval = !p->tn.lval;
75585b1171fSralph break;
75685b1171fSralph case LT:
75785b1171fSralph p->tn.lval = p->tn.lval < val;
75885b1171fSralph break;
75985b1171fSralph case LE:
76085b1171fSralph p->tn.lval = p->tn.lval <= val;
76185b1171fSralph break;
76285b1171fSralph case GT:
76385b1171fSralph p->tn.lval = p->tn.lval > val;
76485b1171fSralph break;
76585b1171fSralph case GE:
76685b1171fSralph p->tn.lval = p->tn.lval >= val;
76785b1171fSralph break;
76885b1171fSralph case ULT:
7695eb997faSdonn p->tn.lval = p->tn.lval < (unsigned) val;
77085b1171fSralph break;
77185b1171fSralph case ULE:
7725eb997faSdonn p->tn.lval = p->tn.lval <= (unsigned) val;
7732a1a76a1Sdonn break;
7742a1a76a1Sdonn case UGT:
7755eb997faSdonn p->tn.lval = p->tn.lval > (unsigned) val;
7765eb997faSdonn break;
7775eb997faSdonn case UGE:
7785eb997faSdonn p->tn.lval = p->tn.lval >= (unsigned) val;
77985b1171fSralph break;
78085b1171fSralph case EQ:
78185b1171fSralph p->tn.lval = p->tn.lval == val;
78285b1171fSralph break;
78385b1171fSralph case NE:
78485b1171fSralph p->tn.lval = p->tn.lval != val;
78585b1171fSralph break;
78685b1171fSralph default:
78785b1171fSralph return(0);
78885b1171fSralph }
78985b1171fSralph return(1);
79085b1171fSralph }
79185b1171fSralph
chkpun(p)79285b1171fSralph chkpun(p) register NODE *p; {
79385b1171fSralph
79485b1171fSralph /* checks p for the existance of a pun */
79585b1171fSralph
79685b1171fSralph /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
79785b1171fSralph
79885b1171fSralph /* one case is when enumerations are used: this applies only to lint */
79985b1171fSralph /* in the other case, one operand is a pointer, the other integer type */
80085b1171fSralph /* we check that this integer is in fact a constant zero... */
80185b1171fSralph
80285b1171fSralph /* in the case of ASSIGN, any assignment of pointer to integer is illegal */
80385b1171fSralph /* this falls out, because the LHS is never 0 */
80485b1171fSralph
80585b1171fSralph register NODE *q;
80685b1171fSralph register t1, t2;
80785b1171fSralph register d1, d2;
80858dcaca6Sdonn int ref1, ref2;
80985b1171fSralph
81085b1171fSralph t1 = p->in.left->in.type;
81185b1171fSralph t2 = p->in.right->in.type;
81285b1171fSralph
81385b1171fSralph if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
8146c817b2bSdonn /* rob pike says this is obnoxious...
8152a1a76a1Sdonn if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE )
8166c817b2bSdonn werror( "comparison of enums" ); */
8176c817b2bSdonn if( t1==ENUMTY && t2==ENUMTY ) {
8186c817b2bSdonn if ( p->in.left->fn.csiz!=p->in.right->fn.csiz )
81985b1171fSralph werror( "enumeration type clash, operator %s", opst[p->in.op] );
82085b1171fSralph return;
82185b1171fSralph }
8226c817b2bSdonn if ( t1 == ENUMTY ) t1 = INT;
8236c817b2bSdonn if ( t2 == ENUMTY ) t2 = INT;
8246c817b2bSdonn }
82585b1171fSralph
82658dcaca6Sdonn ref1 = ISPTR(t1) || ISARY(t1);
82758dcaca6Sdonn ref2 = ISPTR(t2) || ISARY(t2);
82885b1171fSralph
82958dcaca6Sdonn if( ref1 ^ ref2 ){
83058dcaca6Sdonn if( ref1 ) q = p->in.right;
83158dcaca6Sdonn else q = p->in.left;
83285b1171fSralph if( q->in.op != ICON || q->tn.lval != 0 ){
83385b1171fSralph werror( "illegal combination of pointer and integer, op %s",
83485b1171fSralph opst[p->in.op] );
83585b1171fSralph }
83685b1171fSralph }
83758dcaca6Sdonn else if( ref1 ){
8387cd1d6a9Sdonn if( t1 == t2 ) {
8397cd1d6a9Sdonn if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
8407cd1d6a9Sdonn werror( "illegal structure pointer combination" );
8417cd1d6a9Sdonn return;
8427cd1d6a9Sdonn }
84385b1171fSralph d1 = p->in.left->fn.cdim;
84485b1171fSralph d2 = p->in.right->fn.cdim;
84585b1171fSralph for( ;; ){
8467cd1d6a9Sdonn if( ISARY(t1) ){
8477cd1d6a9Sdonn if( dimtab[d1] != dimtab[d2] ){
84885b1171fSralph werror( "illegal array size combination" );
84985b1171fSralph return;
85085b1171fSralph }
8517cd1d6a9Sdonn ++d1;
8527cd1d6a9Sdonn ++d2;
85385b1171fSralph }
8547cd1d6a9Sdonn else if( !ISPTR(t1) ) break;
85585b1171fSralph t1 = DECREF(t1);
85685b1171fSralph }
8577cd1d6a9Sdonn }
858007a19b4Sdonn else if( t1 != INCREF(UNDEF) && t2 != INCREF(UNDEF) )
85985b1171fSralph werror( "illegal pointer combination" );
86085b1171fSralph }
86185b1171fSralph
86285b1171fSralph }
86385b1171fSralph
86485b1171fSralph NODE *
stref(p)86585b1171fSralph stref( p ) register NODE *p; {
86685b1171fSralph
86785b1171fSralph TWORD t;
86885b1171fSralph int d, s, dsc, align;
86985b1171fSralph OFFSZ off;
87085b1171fSralph register struct symtab *q;
87185b1171fSralph
87285b1171fSralph /* make p->x */
87385b1171fSralph /* this is also used to reference automatic variables */
87485b1171fSralph
87585b1171fSralph q = &stab[p->in.right->tn.rval];
87685b1171fSralph p->in.right->in.op = FREE;
87785b1171fSralph p->in.op = FREE;
87885b1171fSralph p = pconvert( p->in.left );
87985b1171fSralph
88085b1171fSralph /* make p look like ptr to x */
88185b1171fSralph
88285b1171fSralph if( !ISPTR(p->in.type)){
88385b1171fSralph p->in.type = PTR+UNIONTY;
88485b1171fSralph }
88585b1171fSralph
88685b1171fSralph t = INCREF( q->stype );
88785b1171fSralph d = q->dimoff;
88885b1171fSralph s = q->sizoff;
88985b1171fSralph
89085b1171fSralph p = makety( p, t, d, s );
89185b1171fSralph
89285b1171fSralph /* compute the offset to be added */
89385b1171fSralph
89485b1171fSralph off = q->offset;
89585b1171fSralph dsc = q->sclass;
89685b1171fSralph
89785b1171fSralph if( dsc & FIELD ) { /* normalize offset */
89885b1171fSralph align = ALINT;
89985b1171fSralph s = INT;
90085b1171fSralph off = (off/align)*align;
90185b1171fSralph }
90285b1171fSralph if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
90385b1171fSralph
90485b1171fSralph p = buildtree( UNARY MUL, p, NIL );
90585b1171fSralph
90685b1171fSralph /* if field, build field info */
90785b1171fSralph
90885b1171fSralph if( dsc & FIELD ){
90985b1171fSralph p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
91085b1171fSralph p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
91185b1171fSralph }
91285b1171fSralph
91385b1171fSralph return( clocal(p) );
91485b1171fSralph }
91585b1171fSralph
notlval(p)91685b1171fSralph notlval(p) register NODE *p; {
91785b1171fSralph
91885b1171fSralph /* return 0 if p an lvalue, 1 otherwise */
91985b1171fSralph
92085b1171fSralph again:
92185b1171fSralph
92285b1171fSralph switch( p->in.op ){
92385b1171fSralph
92485b1171fSralph case FLD:
92585b1171fSralph p = p->in.left;
92685b1171fSralph goto again;
92785b1171fSralph
92885b1171fSralph case UNARY MUL:
92985b1171fSralph /* fix the &(a=b) bug, given that a and b are structures */
93085b1171fSralph if( p->in.left->in.op == STASG ) return( 1 );
93185b1171fSralph /* and the f().a bug, given that f returns a structure */
93285b1171fSralph if( p->in.left->in.op == UNARY STCALL ||
93385b1171fSralph p->in.left->in.op == STCALL ) return( 1 );
93485b1171fSralph case NAME:
93585b1171fSralph case OREG:
93685b1171fSralph if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
93785b1171fSralph case REG:
93885b1171fSralph return(0);
93985b1171fSralph
94085b1171fSralph default:
94185b1171fSralph return(1);
94285b1171fSralph
94385b1171fSralph }
94485b1171fSralph
94585b1171fSralph }
94685b1171fSralph
94785b1171fSralph NODE *
bcon(i)94885b1171fSralph bcon( i ){ /* make a constant node with value i */
94985b1171fSralph register NODE *p;
95085b1171fSralph
95185b1171fSralph p = block( ICON, NIL, NIL, INT, 0, INT );
95285b1171fSralph p->tn.lval = i;
95385b1171fSralph p->tn.rval = NONAME;
95485b1171fSralph return( clocal(p) );
95585b1171fSralph }
95685b1171fSralph
95785b1171fSralph NODE *
bpsize(p)95885b1171fSralph bpsize(p) register NODE *p; {
95985b1171fSralph return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
96085b1171fSralph }
96185b1171fSralph
96285b1171fSralph OFFSZ
psize(p)96385b1171fSralph psize( p ) NODE *p; {
96485b1171fSralph /* p is a node of type pointer; psize returns the
96585b1171fSralph size of the thing pointed to */
96685b1171fSralph
96785b1171fSralph if( !ISPTR(p->in.type) ){
96885b1171fSralph uerror( "pointer required");
96985b1171fSralph return( SZINT );
97085b1171fSralph }
97185b1171fSralph /* note: no pointers to fields */
97285b1171fSralph return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
97385b1171fSralph }
97485b1171fSralph
97585b1171fSralph NODE *
convert(p,f)97685b1171fSralph convert( p, f ) register NODE *p; {
97785b1171fSralph /* convert an operand of p
97885b1171fSralph f is either CVTL or CVTR
97985b1171fSralph operand has type int, and is converted by the size of the other side
98085b1171fSralph */
98185b1171fSralph
98285b1171fSralph register NODE *q, *r;
98385b1171fSralph
98485b1171fSralph q = (f==CVTL)?p->in.left:p->in.right;
98585b1171fSralph
98685b1171fSralph r = block( PMCONV,
98785b1171fSralph q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
98885b1171fSralph r = clocal(r);
98985b1171fSralph if( f == CVTL )
99085b1171fSralph p->in.left = r;
99185b1171fSralph else
99285b1171fSralph p->in.right = r;
99385b1171fSralph return(p);
99485b1171fSralph
99585b1171fSralph }
99685b1171fSralph
9975b9e3d1eSdonn #ifndef econvert
econvert(p)99885b1171fSralph econvert( p ) register NODE *p; {
99985b1171fSralph
100085b1171fSralph /* change enums to ints, or appropriate types */
100185b1171fSralph
100285b1171fSralph register TWORD ty;
100385b1171fSralph
100485b1171fSralph if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
100585b1171fSralph if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
100685b1171fSralph else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
100785b1171fSralph else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
100885b1171fSralph else ty = LONG;
100985b1171fSralph ty = ctype( ty );
101085b1171fSralph p->fn.csiz = ty;
101185b1171fSralph MODTYPE(p->in.type,ty);
101285b1171fSralph if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
101385b1171fSralph }
101485b1171fSralph }
10155b9e3d1eSdonn #endif
101685b1171fSralph
101785b1171fSralph NODE *
pconvert(p)101885b1171fSralph pconvert( p ) register NODE *p; {
101985b1171fSralph
102085b1171fSralph /* if p should be changed into a pointer, do so */
102185b1171fSralph
102285b1171fSralph if( ISARY( p->in.type) ){
102385b1171fSralph p->in.type = DECREF( p->in.type );
102485b1171fSralph ++p->fn.cdim;
102585b1171fSralph return( buildtree( UNARY AND, p, NIL ) );
102685b1171fSralph }
102785b1171fSralph if( ISFTN( p->in.type) )
102885b1171fSralph return( buildtree( UNARY AND, p, NIL ) );
102985b1171fSralph
103085b1171fSralph return( p );
103185b1171fSralph }
103285b1171fSralph
103385b1171fSralph NODE *
oconvert(p)103485b1171fSralph oconvert(p) register NODE *p; {
103585b1171fSralph /* convert the result itself: used for pointer and unsigned */
103685b1171fSralph
103785b1171fSralph switch(p->in.op) {
103885b1171fSralph
103985b1171fSralph case LE:
104085b1171fSralph case LT:
104185b1171fSralph case GE:
104285b1171fSralph case GT:
104385b1171fSralph if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE);
104485b1171fSralph case EQ:
104585b1171fSralph case NE:
104685b1171fSralph return( p );
104785b1171fSralph
104885b1171fSralph case MINUS:
104985b1171fSralph return( clocal( block( PVCONV,
105085b1171fSralph p, bpsize(p->in.left), INT, 0, INT ) ) );
105185b1171fSralph }
105285b1171fSralph
105385b1171fSralph cerror( "illegal oconvert: %d", p->in.op );
105485b1171fSralph
105585b1171fSralph return(p);
105685b1171fSralph }
105785b1171fSralph
105885b1171fSralph NODE *
ptmatch(p)105985b1171fSralph ptmatch(p) register NODE *p; {
106085b1171fSralph
106185b1171fSralph /* makes the operands of p agree; they are
106285b1171fSralph either pointers or integers, by this time */
106385b1171fSralph /* with MINUS, the sizes must be the same */
106485b1171fSralph /* with COLON, the types must be the same */
106585b1171fSralph
106685b1171fSralph TWORD t1, t2, t;
106785b1171fSralph int o, d2, d, s2, s;
106885b1171fSralph
106985b1171fSralph o = p->in.op;
107085b1171fSralph t = t1 = p->in.left->in.type;
107185b1171fSralph t2 = p->in.right->in.type;
107285b1171fSralph d = p->in.left->fn.cdim;
107385b1171fSralph d2 = p->in.right->fn.cdim;
107485b1171fSralph s = p->in.left->fn.csiz;
107585b1171fSralph s2 = p->in.right->fn.csiz;
107685b1171fSralph
107785b1171fSralph switch( o ){
107885b1171fSralph
107985b1171fSralph case ASSIGN:
108085b1171fSralph case RETURN:
108185b1171fSralph case CAST:
108285b1171fSralph { break; }
108385b1171fSralph
108485b1171fSralph case MINUS:
108585b1171fSralph { if( psize(p->in.left) != psize(p->in.right) ){
108685b1171fSralph uerror( "illegal pointer subtraction");
108785b1171fSralph }
108885b1171fSralph break;
108985b1171fSralph }
109085b1171fSralph case COLON:
109185b1171fSralph { if( t1 != t2 ) uerror( "illegal types in :");
109285b1171fSralph break;
109385b1171fSralph }
109485b1171fSralph default: /* must work harder: relationals or comparisons */
109585b1171fSralph
109685b1171fSralph if( !ISPTR(t1) ){
109785b1171fSralph t = t2;
109885b1171fSralph d = d2;
109985b1171fSralph s = s2;
110085b1171fSralph break;
110185b1171fSralph }
110285b1171fSralph if( !ISPTR(t2) ){
110385b1171fSralph break;
110485b1171fSralph }
110585b1171fSralph
110685b1171fSralph /* both are pointers */
110785b1171fSralph if( talign(t2,s2) < talign(t,s) ){
110885b1171fSralph t = t2;
110985b1171fSralph s = s2;
111085b1171fSralph }
111185b1171fSralph break;
111285b1171fSralph }
111385b1171fSralph
111485b1171fSralph p->in.left = makety( p->in.left, t, d, s );
111585b1171fSralph p->in.right = makety( p->in.right, t, d, s );
111685b1171fSralph if( o!=MINUS && !logop(o) ){
111785b1171fSralph
111885b1171fSralph p->in.type = t;
111985b1171fSralph p->fn.cdim = d;
112085b1171fSralph p->fn.csiz = s;
112185b1171fSralph }
112285b1171fSralph
112385b1171fSralph return(clocal(p));
112485b1171fSralph }
112585b1171fSralph
112685b1171fSralph int tdebug = 0;
112785b1171fSralph
112885b1171fSralph NODE *
tymatch(p)112985b1171fSralph tymatch(p) register NODE *p; {
113085b1171fSralph
113185b1171fSralph /* satisfy the types of various arithmetic binary ops */
113285b1171fSralph
113385b1171fSralph /* rules are:
11345b9e3d1eSdonn if assignment, type of LHS
113585b1171fSralph if any float or doubles, make double
113685b1171fSralph if any longs, make long
113785b1171fSralph otherwise, make int
113885b1171fSralph if either operand is unsigned, the result is...
113985b1171fSralph */
114085b1171fSralph
114185b1171fSralph register TWORD t1, t2, t, tu;
114285b1171fSralph register o, u;
114385b1171fSralph
114485b1171fSralph o = p->in.op;
114585b1171fSralph
114685b1171fSralph t1 = p->in.left->in.type;
114785b1171fSralph t2 = p->in.right->in.type;
114885b1171fSralph if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
114985b1171fSralph uerror("void type illegal in expression");
115085b1171fSralph
115185b1171fSralph u = 0;
115285b1171fSralph if( ISUNSIGNED(t1) ){
115385b1171fSralph u = 1;
115485b1171fSralph t1 = DEUNSIGN(t1);
115585b1171fSralph }
115685b1171fSralph if( ISUNSIGNED(t2) ){
115785b1171fSralph u = 1;
115885b1171fSralph t2 = DEUNSIGN(t2);
115985b1171fSralph }
116085b1171fSralph
116185b1171fSralph if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
116285b1171fSralph if( t2 == CHAR || t2 == SHORT ) t2 = INT;
116385b1171fSralph
11649411d0f5Sralph #ifdef SPRECC
11659411d0f5Sralph if( t1 == DOUBLE || t2 == DOUBLE )
11669411d0f5Sralph t = DOUBLE;
11679411d0f5Sralph else if( t1 == FLOAT || t2 == FLOAT )
11689411d0f5Sralph t = FLOAT;
11699411d0f5Sralph #else
11709411d0f5Sralph if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
11719411d0f5Sralph t = DOUBLE;
11729411d0f5Sralph #endif
117385b1171fSralph else if( t1==LONG || t2==LONG ) t = LONG;
117485b1171fSralph else t = INT;
117585b1171fSralph
11764306b042Sdonn if( o == ASSIGN || o == CAST || o == RETURN )
11774306b042Sdonn {
117885b1171fSralph tu = p->in.left->in.type;
117985b1171fSralph t = t1;
118085b1171fSralph }
118185b1171fSralph else {
118285b1171fSralph tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
118385b1171fSralph }
118485b1171fSralph
118585b1171fSralph /* because expressions have values that are at least as wide
118685b1171fSralph as INT or UNSIGNED, the only conversions needed
118785b1171fSralph are those involving FLOAT/DOUBLE, and those
118885b1171fSralph from LONG to INT and ULONG to UNSIGNED */
118985b1171fSralph
119066edcb48Sdonn if( (t != t1 || (u && !ISUNSIGNED(p->in.left->in.type))) && ! asgop(o) )
11915b9e3d1eSdonn p->in.left = makety( p->in.left, tu, 0, (int)tu );
119285b1171fSralph
119366edcb48Sdonn if( t != t2 || (u && !ISUNSIGNED(p->in.right->in.type)) || o==CAST)
11942a1a76a1Sdonn if ( tu == ENUMTY ) {/* always asgop */
11952a1a76a1Sdonn p->in.right = makety( p->in.right, INT, 0, INT );
11962a1a76a1Sdonn p->in.right->in.type = tu;
11972a1a76a1Sdonn p->in.right->fn.cdim = p->in.left->fn.cdim;
11982a1a76a1Sdonn p->in.right->fn.csiz = p->in.left->fn.csiz;
11992a1a76a1Sdonn }
12002a1a76a1Sdonn else
12015b9e3d1eSdonn p->in.right = makety( p->in.right, tu, 0, (int)tu );
120285b1171fSralph
120385b1171fSralph if( asgop(o) ){
120485b1171fSralph p->in.type = p->in.left->in.type;
120585b1171fSralph p->fn.cdim = p->in.left->fn.cdim;
120685b1171fSralph p->fn.csiz = p->in.left->fn.csiz;
120785b1171fSralph }
120885b1171fSralph else if( !logop(o) ){
120985b1171fSralph p->in.type = tu;
121085b1171fSralph p->fn.cdim = 0;
121185b1171fSralph p->fn.csiz = t;
121285b1171fSralph }
121385b1171fSralph
121485b1171fSralph # ifndef BUG1
121585b1171fSralph if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
121685b1171fSralph # endif
121785b1171fSralph
121885b1171fSralph return(p);
121985b1171fSralph }
122085b1171fSralph
122185b1171fSralph NODE *
makety(p,t,d,s)122285b1171fSralph makety( p, t, d, s ) register NODE *p; TWORD t; {
122385b1171fSralph /* make p into type t by inserting a conversion */
122485b1171fSralph
122585b1171fSralph if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
122685b1171fSralph if( t == p->in.type ){
122785b1171fSralph p->fn.cdim = d;
122885b1171fSralph p->fn.csiz = s;
122985b1171fSralph return( p );
123085b1171fSralph }
123185b1171fSralph
123285b1171fSralph if( t & TMASK ){
123385b1171fSralph /* non-simple type */
12344a7a2b7bSralph return( block( PCONV, p, NIL, t, d, s ) );
123585b1171fSralph }
123685b1171fSralph
123785b1171fSralph if( p->in.op == ICON ){
12389411d0f5Sralph if (t == DOUBLE) {
12399411d0f5Sralph p->in.op = DCON;
12409411d0f5Sralph if (ISUNSIGNED(p->in.type))
1241c202b11fSbostic p->dpn.dval = (U_CONSZ) p->tn.lval;
12429411d0f5Sralph else
12439411d0f5Sralph p->dpn.dval = p->tn.lval;
12449411d0f5Sralph p->in.type = p->fn.csiz = t;
12459411d0f5Sralph return (clocal(p));
12469411d0f5Sralph }
12479411d0f5Sralph if (t == FLOAT) {
124885b1171fSralph p->in.op = FCON;
124985b1171fSralph if( ISUNSIGNED(p->in.type) ){
1250c202b11fSbostic p->fpn.fval = (U_CONSZ) p->tn.lval;
125185b1171fSralph }
125285b1171fSralph else {
12539411d0f5Sralph p->fpn.fval = p->tn.lval;
125485b1171fSralph }
125585b1171fSralph
125685b1171fSralph p->in.type = p->fn.csiz = t;
125785b1171fSralph return( clocal(p) );
125885b1171fSralph }
125985b1171fSralph }
12609411d0f5Sralph else if (p->in.op == FCON && t == DOUBLE) {
12619411d0f5Sralph double db;
12629411d0f5Sralph
12639411d0f5Sralph p->in.op = DCON;
12649411d0f5Sralph db = p->fpn.fval;
12659411d0f5Sralph p->dpn.dval = db;
12669411d0f5Sralph p->in.type = p->fn.csiz = t;
12679411d0f5Sralph return (clocal(p));
12689411d0f5Sralph } else if (p->in.op == DCON && t == FLOAT) {
12699411d0f5Sralph float fl;
12709411d0f5Sralph
12719411d0f5Sralph p->in.op = FCON;
12729411d0f5Sralph fl = p->dpn.dval;
12739411d0f5Sralph #ifdef notdef
12749411d0f5Sralph if (fl != p->dpn.dval)
12759411d0f5Sralph werror("float conversion loses precision");
12769411d0f5Sralph #endif
12779411d0f5Sralph p->fpn.fval = fl;
12789411d0f5Sralph p->in.type = p->fn.csiz = t;
12799411d0f5Sralph return (clocal(p));
12809411d0f5Sralph }
128185b1171fSralph
12821e9f4dc5Sralph return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
128385b1171fSralph
128485b1171fSralph }
128585b1171fSralph
128685b1171fSralph NODE *
block(o,l,r,t,d,s)128785b1171fSralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
128885b1171fSralph
128985b1171fSralph register NODE *p;
129085b1171fSralph
129185b1171fSralph p = talloc();
129285b1171fSralph p->in.op = o;
129385b1171fSralph p->in.left = l;
129485b1171fSralph p->in.right = r;
129585b1171fSralph p->in.type = t;
129685b1171fSralph p->fn.cdim = d;
129785b1171fSralph p->fn.csiz = s;
129885b1171fSralph return(p);
129985b1171fSralph }
130085b1171fSralph
icons(p)130185b1171fSralph icons(p) register NODE *p; {
130285b1171fSralph /* if p is an integer constant, return its value */
130385b1171fSralph int val;
130485b1171fSralph
130585b1171fSralph if( p->in.op != ICON ){
130685b1171fSralph uerror( "constant expected");
130785b1171fSralph val = 1;
130885b1171fSralph }
130985b1171fSralph else {
131085b1171fSralph val = p->tn.lval;
131185b1171fSralph if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
131285b1171fSralph }
131385b1171fSralph tfree( p );
131485b1171fSralph return(val);
131585b1171fSralph }
131685b1171fSralph
131785b1171fSralph /* the intent of this table is to examine the
131885b1171fSralph operators, and to check them for
131985b1171fSralph correctness.
132085b1171fSralph
132185b1171fSralph The table is searched for the op and the
132285b1171fSralph modified type (where this is one of the
132385b1171fSralph types INT (includes char and short), LONG,
132485b1171fSralph DOUBLE (includes FLOAT), and POINTER
132585b1171fSralph
132685b1171fSralph The default action is to make the node type integer
132785b1171fSralph
132885b1171fSralph The actions taken include:
132985b1171fSralph PUN check for puns
133085b1171fSralph CVTL convert the left operand
133185b1171fSralph CVTR convert the right operand
133285b1171fSralph TYPL the type is determined by the left operand
133385b1171fSralph TYPR the type is determined by the right operand
133485b1171fSralph TYMATCH force type of left and right to match, by inserting conversions
133585b1171fSralph PTMATCH like TYMATCH, but for pointers
133685b1171fSralph LVAL left operand must be lval
133785b1171fSralph CVTO convert the op
133885b1171fSralph NCVT do not convert the operands
133985b1171fSralph OTHER handled by code
134085b1171fSralph NCVTR convert the left operand, not the right...
134185b1171fSralph
134285b1171fSralph */
134385b1171fSralph
134485b1171fSralph # define MINT 01 /* integer */
134585b1171fSralph # define MDBI 02 /* integer or double */
134685b1171fSralph # define MSTR 04 /* structure */
134785b1171fSralph # define MPTR 010 /* pointer */
134885b1171fSralph # define MPTI 020 /* pointer or integer */
134985b1171fSralph # define MENU 040 /* enumeration variable or member */
1350d0dde492Smckusick # define MVOID 0100000 /* void type */
135185b1171fSralph
opact(p)135285b1171fSralph opact( p ) NODE *p; {
135385b1171fSralph
135485b1171fSralph register mt12, mt1, mt2, o;
135585b1171fSralph
1356d0dde492Smckusick mt1 = mt2 = mt12 = 0;
135785b1171fSralph
135885b1171fSralph switch( optype(o=p->in.op) ){
135985b1171fSralph
136085b1171fSralph case BITYPE:
1361d0dde492Smckusick mt2 = moditype( p->in.right->in.type );
136285b1171fSralph case UTYPE:
1363d0dde492Smckusick mt1 = moditype( p->in.left->in.type );
1364d0dde492Smckusick break;
136585b1171fSralph
136685b1171fSralph }
136785b1171fSralph
1368d0dde492Smckusick if( ((mt1 | mt2) & MVOID) &&
1369d0dde492Smckusick o != COMOP &&
13704a39ba84Sdonn o != COLON &&
13714a39ba84Sdonn !(o == QUEST && (mt1 & MVOID) == 0) &&
1372d0dde492Smckusick !(o == CAST && (mt1 & MVOID)) ){
1373d0dde492Smckusick /* if lhs of RETURN is void, grammar will complain */
1374d0dde492Smckusick if( o != RETURN )
1375d0dde492Smckusick uerror( "value of void expression used" );
1376d0dde492Smckusick return( NCVT );
1377d0dde492Smckusick }
1378d0dde492Smckusick mt12 = mt1 & mt2;
1379d0dde492Smckusick
138085b1171fSralph switch( o ){
138185b1171fSralph
138285b1171fSralph case NAME :
138385b1171fSralph case STRING :
138485b1171fSralph case ICON :
138585b1171fSralph case FCON :
13869411d0f5Sralph case DCON :
138785b1171fSralph case CALL :
138885b1171fSralph case UNARY CALL:
138985b1171fSralph case UNARY MUL:
139085b1171fSralph { return( OTHER ); }
139185b1171fSralph case UNARY MINUS:
139258dcaca6Sdonn if( mt1 & MENU ) return( 0 );
139385b1171fSralph if( mt1 & MDBI ) return( TYPL );
139485b1171fSralph break;
139585b1171fSralph
139685b1171fSralph case COMPL:
139758dcaca6Sdonn if( mt1 & MENU ) return( 0 );
139885b1171fSralph if( mt1 & MINT ) return( TYPL );
139985b1171fSralph break;
140085b1171fSralph
140185b1171fSralph case UNARY AND:
1402007a19b4Sdonn return( NCVT+OTHER );
140385b1171fSralph case INIT:
140485b1171fSralph case CM:
1405e3d916c2Sralph return( 0 );
1406e3d916c2Sralph
140785b1171fSralph case NOT:
140885b1171fSralph case CBRANCH:
1409e3d916c2Sralph if( mt1 & MSTR ) break;
1410e3d916c2Sralph return( 0 );
1411e3d916c2Sralph
141285b1171fSralph case ANDAND:
141385b1171fSralph case OROR:
1414e3d916c2Sralph if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
141585b1171fSralph return( 0 );
141685b1171fSralph
141785b1171fSralph case MUL:
141885b1171fSralph case DIV:
141985b1171fSralph if( mt12 & MDBI ) return( TYMATCH );
142085b1171fSralph break;
142185b1171fSralph
142285b1171fSralph case MOD:
142385b1171fSralph case AND:
142485b1171fSralph case OR:
142585b1171fSralph case ER:
142685b1171fSralph if( mt12 & MINT ) return( TYMATCH );
142785b1171fSralph break;
142885b1171fSralph
142985b1171fSralph case LS:
143085b1171fSralph case RS:
1431007a19b4Sdonn if( mt12 & MINT ) return( OTHER );
143285b1171fSralph break;
143385b1171fSralph
143485b1171fSralph case EQ:
143585b1171fSralph case NE:
143685b1171fSralph case LT:
143785b1171fSralph case LE:
143885b1171fSralph case GT:
143985b1171fSralph case GE:
144058dcaca6Sdonn if( mt12 & MENU ) return( TYMATCH+NCVT+PUN );
144158dcaca6Sdonn if( mt12 & MDBI ) return( TYMATCH+NCVT+CVTO );
144285b1171fSralph else if( mt12 & MPTR ) return( PTMATCH+PUN );
144385b1171fSralph else if( mt12 & MPTI ) return( PTMATCH+PUN );
144485b1171fSralph else break;
144585b1171fSralph
144685b1171fSralph case QUEST:
144785b1171fSralph case COMOP:
144885b1171fSralph if( mt2&MENU ) return( TYPR+NCVTR );
144985b1171fSralph return( TYPR );
145085b1171fSralph
145185b1171fSralph case STREF:
145285b1171fSralph return( NCVTR+OTHER );
145385b1171fSralph
145485b1171fSralph case FORCE:
145585b1171fSralph return( TYPL );
145685b1171fSralph
145785b1171fSralph case COLON:
145858dcaca6Sdonn if( mt12 & MENU ) return( NCVT+PUN+TYMATCH );
145958dcaca6Sdonn else if( mt12 & MDBI ) return( NCVT+TYMATCH );
146085b1171fSralph else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
146185b1171fSralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
146285b1171fSralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
146385b1171fSralph else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
14644a39ba84Sdonn else if( mt12 == MVOID ) return( NCVT+TYPL );
146585b1171fSralph break;
146685b1171fSralph
146785b1171fSralph case ASSIGN:
146885b1171fSralph case RETURN:
146985b1171fSralph if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
147058dcaca6Sdonn else if( mt12 & MENU ) return( LVAL+NCVT+TYPL+TYMATCH+PUN );
147185b1171fSralph case CAST:
14721b8d7ffdSdonn if(o==CAST && mt1==MVOID)return(TYPL+TYMATCH);
147358dcaca6Sdonn else if( mt12 & MDBI ) return( TYPL+LVAL+NCVT+TYMATCH );
14741b8d7ffdSdonn else if( mt2 == MVOID &&
147578bda08aSmckusick ( p->in.right->in.op == CALL ||
147678bda08aSmckusick p->in.right->in.op == UNARY CALL)) break;
1477a30a413aSdonn else if( (mt1 & MPTR) && (mt2 & MPTI) )
1478a30a413aSdonn return( LVAL+PTMATCH+PUN );
147985b1171fSralph else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
148085b1171fSralph break;
148185b1171fSralph
148285b1171fSralph case ASG LS:
148385b1171fSralph case ASG RS:
148485b1171fSralph if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
148585b1171fSralph break;
148685b1171fSralph
148785b1171fSralph case ASG MUL:
148885b1171fSralph case ASG DIV:
148985b1171fSralph if( mt12 & MDBI ) return( LVAL+TYMATCH );
149085b1171fSralph break;
149185b1171fSralph
149285b1171fSralph case ASG MOD:
149385b1171fSralph case ASG AND:
149485b1171fSralph case ASG OR:
149585b1171fSralph case ASG ER:
149685b1171fSralph if( mt12 & MINT ) return( LVAL+TYMATCH );
149785b1171fSralph break;
149885b1171fSralph
149985b1171fSralph case ASG PLUS:
150085b1171fSralph case ASG MINUS:
150185b1171fSralph case INCR:
150285b1171fSralph case DECR:
150385b1171fSralph if( mt12 & MDBI ) return( TYMATCH+LVAL );
150485b1171fSralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
150585b1171fSralph break;
150685b1171fSralph
150785b1171fSralph case MINUS:
150885b1171fSralph if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
150985b1171fSralph if( mt2 & MPTR ) break;
151085b1171fSralph case PLUS:
151185b1171fSralph if( mt12 & MDBI ) return( TYMATCH );
151285b1171fSralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
151385b1171fSralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
151485b1171fSralph
151585b1171fSralph }
1516d0dde492Smckusick if( mt12 == MSTR )
1517d0dde492Smckusick uerror( "%s is not a permitted struct/union operation", opst[o] );
1518d0dde492Smckusick else
151985b1171fSralph uerror( "operands of %s have incompatible types", opst[o] );
152085b1171fSralph return( NCVT );
152185b1171fSralph }
152285b1171fSralph
moditype(ty)152385b1171fSralph moditype( ty ) TWORD ty; {
152485b1171fSralph
152585b1171fSralph switch( ty ){
152685b1171fSralph
152785b1171fSralph case UNDEF:
1528d0dde492Smckusick return( MVOID );
152985b1171fSralph case ENUMTY:
153085b1171fSralph case MOETY:
15312a1a76a1Sdonn return( MENU|MINT|MDBI|MPTI ); /* enums are ints */
153285b1171fSralph
153385b1171fSralph case STRTY:
153485b1171fSralph case UNIONTY:
153585b1171fSralph return( MSTR );
153685b1171fSralph
153785b1171fSralph case CHAR:
153885b1171fSralph case SHORT:
153985b1171fSralph case UCHAR:
154085b1171fSralph case USHORT:
154185b1171fSralph return( MINT|MPTI|MDBI );
154285b1171fSralph case UNSIGNED:
154385b1171fSralph case ULONG:
154485b1171fSralph case INT:
154585b1171fSralph case LONG:
154685b1171fSralph return( MINT|MDBI|MPTI );
154785b1171fSralph case FLOAT:
154885b1171fSralph case DOUBLE:
154985b1171fSralph return( MDBI );
155085b1171fSralph default:
155185b1171fSralph return( MPTR|MPTI );
155285b1171fSralph
155385b1171fSralph }
155485b1171fSralph }
155585b1171fSralph
155685b1171fSralph NODE *
doszof(p)155785b1171fSralph doszof( p ) register NODE *p; {
155885b1171fSralph /* do sizeof p */
155985b1171fSralph int i;
156085b1171fSralph
156185b1171fSralph /* whatever is the meaning of this if it is a bitfield? */
156285b1171fSralph i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
156385b1171fSralph
156485b1171fSralph tfree(p);
156585b1171fSralph if( i <= 0 ) werror( "sizeof returns 0" );
156685b1171fSralph return( bcon( i ) );
156785b1171fSralph }
156885b1171fSralph
156985b1171fSralph # ifndef BUG2
eprint(p,down,a,b)157085b1171fSralph eprint( p, down, a, b ) register NODE *p; int *a, *b; {
157185b1171fSralph register ty;
157285b1171fSralph
157385b1171fSralph *a = *b = down+1;
157485b1171fSralph while( down > 1 ){
157585b1171fSralph printf( "\t" );
157685b1171fSralph down -= 2;
157785b1171fSralph }
157885b1171fSralph if( down ) printf( " " );
157985b1171fSralph
158085b1171fSralph ty = optype( p->in.op );
158185b1171fSralph
158285b1171fSralph printf("%o) %s, ", p, opst[p->in.op] );
158385b1171fSralph if( ty == LTYPE ){
158485b1171fSralph printf( CONFMT, p->tn.lval );
158585b1171fSralph printf( ", %d, ", p->tn.rval );
158685b1171fSralph }
158785b1171fSralph tprint( p->in.type );
158885b1171fSralph printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
158985b1171fSralph }
159085b1171fSralph # endif
159185b1171fSralph
1592bd26bb5eSdonn #ifndef PRTDCON
prtdcon(p)159385b1171fSralph prtdcon( p ) register NODE *p; {
15949411d0f5Sralph int o = p->in.op, i;
159585b1171fSralph
15969411d0f5Sralph if( o == DCON || o == FCON ){
15977b5a1073Sdonn (void) locctr( DATA );
15989411d0f5Sralph defalign( o == DCON ? ALDOUBLE : ALFLOAT );
159985b1171fSralph deflab( i = getlab() );
16009411d0f5Sralph if( o == FCON )
16019411d0f5Sralph fincode( p->fpn.fval, SZFLOAT );
16029411d0f5Sralph else
16039411d0f5Sralph fincode( p->dpn.dval, SZDOUBLE );
160485b1171fSralph p->tn.lval = 0;
160585b1171fSralph p->tn.rval = -i;
16069411d0f5Sralph p->in.type = (o == DCON ? DOUBLE : FLOAT);
160785b1171fSralph p->in.op = NAME;
160885b1171fSralph }
160985b1171fSralph }
1610bd26bb5eSdonn #endif PRTDCON
161185b1171fSralph
161285b1171fSralph
161385b1171fSralph int edebug = 0;
ecomp(p)161485b1171fSralph ecomp( p ) register NODE *p; {
161585b1171fSralph # ifndef BUG2
161685b1171fSralph if( edebug ) fwalk( p, eprint, 0 );
161785b1171fSralph # endif
161885b1171fSralph if( !reached ){
161985b1171fSralph werror( "statement not reached" );
162085b1171fSralph reached = 1;
162185b1171fSralph }
162285b1171fSralph p = optim(p);
162385b1171fSralph walkf( p, prtdcon );
16247b5a1073Sdonn (void) locctr( PROG );
162585b1171fSralph ecode( p );
162685b1171fSralph tfree(p);
162785b1171fSralph }
162885b1171fSralph
162985b1171fSralph # ifdef STDPRTREE
163085b1171fSralph # ifndef ONEPASS
163185b1171fSralph
prtree(p)163285b1171fSralph prtree(p) register NODE *p; {
163385b1171fSralph
163485b1171fSralph register struct symtab *q;
163585b1171fSralph register ty;
163685b1171fSralph
163785b1171fSralph # ifdef MYPRTREE
163885b1171fSralph MYPRTREE(p); /* local action can be taken here; then return... */
163985b1171fSralph #endif
164085b1171fSralph
164185b1171fSralph ty = optype(p->in.op);
164285b1171fSralph
164385b1171fSralph printf( "%d\t", p->in.op );
164485b1171fSralph
164585b1171fSralph if( ty == LTYPE ) {
164685b1171fSralph printf( CONFMT, p->tn.lval );
164785b1171fSralph printf( "\t" );
164885b1171fSralph }
164985b1171fSralph if( ty != BITYPE ) {
165085b1171fSralph if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
165185b1171fSralph else printf( "%d\t", p->tn.rval );
165285b1171fSralph }
165385b1171fSralph
165485b1171fSralph printf( "%o\t", p->in.type );
165585b1171fSralph
165685b1171fSralph /* handle special cases */
165785b1171fSralph
165885b1171fSralph switch( p->in.op ){
165985b1171fSralph
166085b1171fSralph case NAME:
166185b1171fSralph case ICON:
166285b1171fSralph /* print external name */
166385b1171fSralph if( p->tn.rval == NONAME ) printf( "\n" );
166485b1171fSralph else if( p->tn.rval >= 0 ){
166585b1171fSralph q = &stab[p->tn.rval];
166685b1171fSralph printf( "%s\n", exname(q->sname) );
166785b1171fSralph }
166885b1171fSralph else { /* label */
166985b1171fSralph printf( LABFMT, -p->tn.rval );
167085b1171fSralph }
167185b1171fSralph break;
167285b1171fSralph
167385b1171fSralph case STARG:
167485b1171fSralph case STASG:
167585b1171fSralph case STCALL:
167685b1171fSralph case UNARY STCALL:
167785b1171fSralph /* print out size */
167885b1171fSralph /* use lhs size, in order to avoid hassles with the structure `.' operator */
167985b1171fSralph
168085b1171fSralph /* note: p->in.left not a field... */
168185b1171fSralph printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
168285b1171fSralph printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
168385b1171fSralph break;
168485b1171fSralph
168585b1171fSralph default:
168685b1171fSralph printf( "\n" );
168785b1171fSralph }
168885b1171fSralph
168985b1171fSralph if( ty != LTYPE ) prtree( p->in.left );
169085b1171fSralph if( ty == BITYPE ) prtree( p->in.right );
169185b1171fSralph
169285b1171fSralph }
169385b1171fSralph
169485b1171fSralph # else
169585b1171fSralph
p2tree(p)169685b1171fSralph p2tree(p) register NODE *p; {
169785b1171fSralph register ty;
169885b1171fSralph
169985b1171fSralph # ifdef MYP2TREE
170085b1171fSralph MYP2TREE(p); /* local action can be taken here; then return... */
170185b1171fSralph # endif
170285b1171fSralph
170385b1171fSralph ty = optype(p->in.op);
170485b1171fSralph
170585b1171fSralph switch( p->in.op ){
170685b1171fSralph
170785b1171fSralph case NAME:
170885b1171fSralph case ICON:
170985b1171fSralph #ifndef FLEXNAMES
171085b1171fSralph if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
171185b1171fSralph #else
171285b1171fSralph if( p->tn.rval == NONAME ) p->in.name = "";
171385b1171fSralph #endif
171485b1171fSralph else if( p->tn.rval >= 0 ){ /* copy name from exname */
171585b1171fSralph register char *cp;
171685b1171fSralph cp = exname( stab[p->tn.rval].sname );
171785b1171fSralph #ifndef FLEXNAMES
17187b5a1073Sdonn {
17197b5a1073Sdonn register i;
17207b5a1073Sdonn for( i=0; i<NCHNAM; ++i )
17217b5a1073Sdonn p->in.name[i] = *cp++;
17227b5a1073Sdonn }
172385b1171fSralph #else
172485b1171fSralph p->in.name = tstr(cp);
172585b1171fSralph #endif
172685b1171fSralph }
172785b1171fSralph #ifndef FLEXNAMES
172885b1171fSralph else sprintf( p->in.name, LABFMT, -p->tn.rval );
172985b1171fSralph #else
173085b1171fSralph else {
173185b1171fSralph char temp[32];
173285b1171fSralph sprintf( temp, LABFMT, -p->tn.rval );
173385b1171fSralph p->in.name = tstr(temp);
173485b1171fSralph }
173585b1171fSralph #endif
173685b1171fSralph break;
173785b1171fSralph
173885b1171fSralph case STARG:
173985b1171fSralph case STASG:
174085b1171fSralph case STCALL:
174185b1171fSralph case UNARY STCALL:
174285b1171fSralph /* set up size parameters */
174385b1171fSralph p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
174485b1171fSralph p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
174585b1171fSralph break;
174685b1171fSralph
174785b1171fSralph case REG:
174885b1171fSralph rbusy( p->tn.rval, p->in.type );
174985b1171fSralph default:
175085b1171fSralph #ifndef FLEXNAMES
175185b1171fSralph p->in.name[0] = '\0';
175285b1171fSralph #else
175385b1171fSralph p->in.name = "";
175485b1171fSralph #endif
175585b1171fSralph }
175685b1171fSralph
175785b1171fSralph p->in.rall = NOPREF;
175885b1171fSralph
175985b1171fSralph if( ty != LTYPE ) p2tree( p->in.left );
176085b1171fSralph if( ty == BITYPE ) p2tree( p->in.right );
176185b1171fSralph }
176285b1171fSralph
176385b1171fSralph # endif
176485b1171fSralph # endif
1765