From 889e37dec41b08089fc6d47c4d2dce8f7983c716 Mon Sep 17 00:00:00 2001 From: Oliver Lehmann Date: Wed, 27 Jun 1990 15:21:40 +0000 Subject: [PATCH] add LCC - a better C-Compiler for WEGA --- WEGA/contrib/lcc/cmd/comp/common/trees.c | 2235 ++++++++++++++++++++++ 1 file changed, 2235 insertions(+) create mode 100644 WEGA/contrib/lcc/cmd/comp/common/trees.c diff --git a/WEGA/contrib/lcc/cmd/comp/common/trees.c b/WEGA/contrib/lcc/cmd/comp/common/trees.c new file mode 100644 index 0000000..c181f69 --- /dev/null +++ b/WEGA/contrib/lcc/cmd/comp/common/trees.c @@ -0,0 +1,2235 @@ +# include "mfile1.h" +static TWORD orgtleft; +static int convasgflg; + +/* some special actions, used in finding the type of nodes */ +# define NCVT 01 +# define PUN 02 +# define TYPL 04 +# define TYPR 010 +# define TYMATCH 040 +# define LVAL 0100 +# define CVTO 0200 +# define CVTL 0400 +# define CVTR 01000 +# define PTMATCH 02000 +# define OTHER 04000 +# define NCVTR 010000 + +/* node conventions: +** +** NAME: rval>0 is stab index for external +** rval<0 is -inlabel number +** lval is offset in address units +** (NAME really means "STATIC VARIABLE") +** ICON: lval has the value +** rval has the STAB index, or - label number, +** if a name whose address is in the constant +** rval = NONAME means no name +** VAUTO: automatic name: lval has offset in address units +** VPARAM: parameter: lval has offset in address units +** REG: rval is reg. number +** +*/ + +TWORD +indtype( t ) +register TWORD t; +{ + /* return the type of an intermediate expression of type t */ + switch( t ) + { + + case CHAR: + case SHORT: + return( INT ); + + case UCHAR: + case USHORT: + return( UNSIGNED ); + + case FLOAT: + return( DOUBLE ); + + } + return( t ); +} + +int bdebug = 0; +extern ddebug; + +# ifndef XI +NODE * +xicolon( l, r1, r2 ) register NODE *l, *r1, *r2; + +{ + uerror( "syntax error: colon in subscript" ); + tfree( r2 ); + return( buildtree( LB, l, r1 ) ); +} +# endif + +NODE * +buildtree( o, l, r ) +register NODE *l, *r; +register o; +{ + register NODE *p, *q; + register actions; + register opty; + register struct symtab *sp; + register NODE *lr, *ll; + int i; + +# ifndef NODBG + if( bdebug ) + printf( "buildtree( %s, %d, %d )\n", opst[o], l-node, r-node ); +# endif + + /* special case to recognize subscripting explicitly */ + +# ifdef XI + if( o == LB && l->tn.type == LONG ) + return( xicolon( l, r, (NODE *) 0 ) ); +# endif + + if( o == LB ) return( buildtree( STAR, buildtree( PLUS, l, r ), NIL ) ); + opty = optype(o); + + /* check for constants */ + + if( o == NOT && l->in.op == ICON && hflag ) + { + werror( "constant argument to NOT" ); + } + + else if( o==UNARY MINUS && l->in.op==FCON ) + { + l->fpn.dval = -l->fpn.dval; + return(l); + } + + else if( o==QUEST && l->in.op==ICON && l->tn.rval==NONAME ) + { + l->in.op = FREE; + r->in.op = FREE; + if( l->tn.lval ) + { + tfree( r->in.right ); + return( r->in.left ); + } + else + { + tfree( r->in.left ); + return( r->in.right ); + } + } + + else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) + goto ccwarn; + + else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ) + { + + switch( o ) + { + + case ULT: + case UGT: + case ULE: + case UGE: + case LT: + case GT: + case LE: + case GE: + case EQ: + case NE: + case ANDAND: + case OROR: + case CBRANCH: + +ccwarn: + if( hflag ) werror( "constant in conditional context" ); + } + } + + /* we make a real node, and look for shrinking later */ + + p = block( o, l, r, INT, 0, INT ); + + actions = opact(p); +# ifdef MYOPACT + actions = MYOPACT(p,actions); +# endif + + if( actions&LVAL ) + { + /* check left descendent */ + if( notlval(p->in.left) ) + { + uerror( "illegal lhs of assignment operator" ); + } + } + + if( actions & NCVTR ) + { + p->in.left = pconvert( p->in.left ); + } + else if( !(actions & NCVT ) ) + { + switch( opty ) + { + + case BITYPE: + p->in.right = pconvert( p->in.right ); + case UTYPE: + if( !(actions&LVAL) ) + p->in.left = pconvert( p->in.left ); + + } + } + + if( (actions&PUN) && (o!=CAST||cflag) ) + { + chkpun(p); + } + + if( actions & (TYPL|TYPR) ) + { + + q = (actions&TYPL) ? p->in.left : p->in.right; + + p->in.type = q->in.type; + p->fn.cdim = q->fn.cdim; + p->fn.csiz = q->fn.csiz; + } + + if( actions & CVTL ) p = convert( p, CVTL ); + if( actions & CVTR ) p = convert( p, CVTR ); + + if( actions & TYMATCH ) p = tymatch(p); +/* hier z.B. (int a) -= (unsigned b) => in (unsigned -=) umgebaut und convasgflg gesetzt fuer Ruecknahme, s. vor return(p) +*/ + + if( actions & PTMATCH ) p = ptmatch(p); + + if( actions & SPFLG ) p = clocal(p); + + if( actions & OTHER ) + { + l = p->in.left; + r = p->in.right; + + switch(o) + { + + case NAME: + sp = &stab[idname]; + if( sp->stype == UNDEF ) + { + lerror( "%s undefined", sp->sname ); + /* make p look reasonable */ + p->in.type = p->fn.cdim = p->fn.csiz = INT; + p->tn.rval = idname; + p->tn.lval = 0; + defid( p, SNULL ); + break; + } + p->in.type = sp->stype; + p->fn.cdim = sp->dimoff; + p->fn.csiz = sp->sizoff; + /* special case: MOETY is really an ICON... */ + if( p->in.type == MOETY ) + { + p->tn.rval = NONAME; + p->tn.lval = sp->offset; + p->fn.cdim = 0; + p->in.type = ENUMTY; + p->in.op = ICON; + } + else + { + switch( sp->sclass ) + { + + case AUTO: + p->in.op = VAUTO; + p->tn.rval = NONAME; + p->tn.lval = BITOOR(sp->offset); + break; + + case PARAM: + p->in.op = VPARAM; + p->tn.rval = NONAME; + p->tn.lval = BITOOR(sp->offset); + break; + + case REGISTER: + p->in.op = REG; + p->tn.lval = 0; + p->tn.rval = sp->offset; + break; + + case ULABEL: + case LABEL: + case STATIC: + if( sp->slevel != 0 ) + { + p->tn.lval = 0; + p->tn.rval = -sp->offset; + break; + } + /* FALLTHRU */ + + default: + p->tn.lval = 0; + p->tn.rval = idname; + } + } + break; + + case ICON: + p->in.type = INT; + p->fn.cdim = 0; + p->fn.csiz = INT; + break; + + case STRING: + p->in.op = NAME; + p->in.type = CHAR+ARY; + p->tn.lval = 0; + p->tn.rval = NOLAB; + p->fn.cdim = curdim; + p->fn.csiz = CHAR; + break; + + case FCON: + p->tn.lval = 0; + p->tn.rval = 0; + p->in.type = DOUBLE; + p->fn.cdim = 0; + p->fn.csiz = DOUBLE; + break; + + case STREF: + /* p->x turned into *(p+offset) */ + /* rhs must be a name; check correctness */ + + i = r->tn.rval; + if(i<0 || i>=SYMTSZ || ((sp= &stab[i])->sclass != MOS && + sp->sclass != MOU && !(sp->sclass&FIELD)) ) + { + uerror( "structure/union member required" ); + break; + } + else + /* if this name is non-unique, find right one */ + if( stab[i].sflags&SNONUNIQ && (l->in.type==PTR+STRTY || + l->in.type == PTR+UNIONTY) && + (l->fn.csiz+1) >= 0 ) + { + /* nonunique name && structure defined */ + char * memnam, * tabnam; + OFFSZ j; + OFFSZ memi; + j=dimtab[l->fn.csiz+1]; + for( ; (memi=dimtab[j]) >= 0; ++j ) + { + tabnam = stab[memi].sname; + memnam = stab[i].sname; +# ifndef NODBG + if( ddebug>1 ) + { + printf("member %s==%s?\n", + memnam, tabnam); + } +# endif + if( stab[memi].sflags & SNONUNIQ ) + { + if ( memnam != tabnam ) + continue; + r->tn.rval = i = memi; + break; + } + continue; + } + if( memi < 0 ) + lerror("illegal member use: %s", + stab[i].sname); + } + else + { + register j; + if( l->in.type != PTR+STRTY && + l->in.type != PTR+UNIONTY ) + { + if( stab[i].sflags & SNONUNIQ ) + { + uerror( + "nonunique name demands struct/union or struct/union pointer" ); + } + else werror( + "struct/union or struct/union pointer required" ); + } + else if( (j=l->fn.csiz+1)<0 ) + cerror( "undefined structure or union"); + else if( !chkstr( i, dimtab[j], + DECREF(l->in.type) ) ) + { + werror( "illegal member use: %s", + stab[i].sname ); + } + } + p = stref( p ); + break; + + case STAR: + if( l->in.op == UNARY AND ) + { + p->in.op = l->in.op = FREE; + p = l->in.left; + } + if( !ISPTR(l->in.type) ) uerror("illegal indirection"); + p->in.type = DECREF(l->in.type); + p->fn.cdim = l->fn.cdim; + p->fn.csiz = l->fn.csiz; + break; + + case UNARY AND: + switch( l->in.op ) + { + + case STAR: + p->in.op = l->in.op = FREE; + p = l->in.left; + case NAME: + case VAUTO: + case VPARAM: + case RNODE: + case STCALL: + case UNARY STCALL: + p->in.type = INCREF( l->in.type ); + p->fn.cdim = l->fn.cdim; + p->fn.csiz = l->fn.csiz; + break; + + case COMOP: + lr = buildtree( UNARY AND, l->in.right, NIL ); + p->in.op = l->in.op = FREE; + p = buildtree( COMOP, l->in.left, lr ); + break; + + case QUEST: + lr = buildtree( UNARY AND, + l->in.right->in.right, NIL ); + ll = buildtree( UNARY AND, + l->in.right->in.left, NIL ); + p->in.op = l->in.op = l->in.right->in.op = FREE; + p = buildtree( QUEST, l->in.left, + buildtree( COLON, ll, lr ) ); + break; + + default: + uerror( "unacceptable operand of &" ); + break; + } + break; + + case RETURN: + case ASSIGN: + case CAST: + /* structure assignment */ + /* take the addresses of the two sides; then make an + ** operator using STASG and + ** the addresses of left and right + */ + + { + register TWORD t; + register d, s; + OFFSZ sz; + + if( l->fn.csiz != r->fn.csiz ) + uerror( + "assignment of different structures" ); + + r = buildtree( UNARY AND, r, NIL ); + l = buildtree( UNARY AND, l, NIL ); + t = r->in.type; + d = r->fn.cdim; + s = r->fn.csiz; +#ifdef ENDSTRUCT + sz = tsize( STRTY, d, s ); + l = aadjust( l, sz ); + r = aadjust( r, sz ); +#endif + + l = block( STASG, l, r, t, d, s ); + + if( o == RETURN ) + { + p->in.op = FREE; + p = l; + break; + } + + p->in.op = STAR; + p->in.left = clocal(l); + p->in.right = NIL; + break; + } + case COLON: + /* structure colon */ + + if( l->fn.csiz != r->fn.csiz ) + uerror( "type clash in conditional" ); + break; + + case CALL: + i = 0; + p->in.right = r = strargs( p->in.right, &i ); + if( i > maxarg ) maxarg = i; + case UNARY CALL: + if( !ISPTR(l->in.type)) uerror("illegal function"); + p->in.type = DECREF(l->in.type); + if( !ISFTN(p->in.type)) uerror("illegal function"); + p->in.type = DECREF( p->in.type ); + p->fn.cdim = l->fn.cdim; + p->fn.csiz = l->fn.csiz; + if( l->in.op == UNARY AND && + l->in.left->in.op == NAME && + l->in.left->tn.rval >= 0 && + l->in.left->tn.rval != NONAME && + ((i=stab[l->in.left->tn.rval].sclass)==FORTRAN + || i == UFORTRAN ) ) + { + p->in.op += (FORTCALL-CALL); + } + if( p->in.type == STRTY || p->in.type == UNIONTY ) + { + /* function returning structure */ + /* function really returns ptr with * */ + +# ifdef ARGSRET + /* set aside argument space for return val */ + i = tsize( p->in.type, p->fn.cdim, p->fn.csiz ); + /* alignment??? */ + if( i > maxarg ) maxarg = i; +# endif + p->in.op += STCALL-CALL; + p->in.type = INCREF( p->in.type ); + p = buildtree( STAR, p, NIL ); + break; + } + + /* fix up type of return value from call */ + { + register TWORD t; + t = indtype( p->tn.type ); + if( t != p->tn.type ) + { + p->fn.csiz = p->tn.type = t; + } + } +# ifdef ARGALLRET + /* set aside argument space for return val */ + i = tsize( p->in.type, p->fn.cdim, p->fn.csiz ); + /* alignment??? */ + if( i > maxarg ) maxarg = i; +# endif + break; + + default: + cerror( "other code %d", o ); + } + + } + + if( actions & CVTO ) p = oconvert(p); + p = clocal(conval(p)); + +# ifndef NODBG + if( bdebug ) eprint(p); +# endif + if( convasgflg && asgop(p->in.op) && p->in.left->in.op==CONV ) + p = makety(p,orgtleft,0,(int)orgtleft); + return(p); + +} + +NODE * +strargs( p, off ) +register NODE *p; +register *off; +{ + /* rewrite arguments */ + /* allocate the arguments at *off, and update *off */ + register TWORD t; + + t = p->fn.type; + if( p->in.op == CM ) + { + p->in.left = strargs( p->in.left, off ); + p->in.right = strargs( p->in.right, off ); + return( p ); + } + + p = block( STARG, p, NIL, t, p->fn.cdim, p->fn.csiz ); + if( t == STRTY || t == UNIONTY ) + { + p->in.left = buildtree( UNARY AND, p->in.left, NIL ); + } + else + { + p->in.op = FUNARG; + } + SETOFF( *off, talign( t, p->fn.csiz ) ); + p->tn.rval = *off; + *off += tsize( t, p->fn.cdim, p->fn.csiz ); + return( clocal(p) ); +} + +chkstr( i, j, type ) +register TWORD type; +register i; +OFFSZ j; +{ + /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */ + /* i has been checked to contain a MOS or MOU */ + /* j is the index in dimtab of the members... */ + register k, kk; + + extern int ddebug; + +# ifndef NODBG + if( ddebug > 1 ) printf( "chkstr( %s(%d), %ld )\n", stab[i].sname, i, j ); +# endif + if( (k = j) < 0 ) uerror( "undefined structure or union" ); + else + { + for( ; (kk = dimtab[k] ) >= 0; ++k ) + { + if( kk >= SYMTSZ ) + { + cerror( "gummy structure" ); + return(1); + } + if( kk == i ) return( 1 ); + switch( stab[kk].stype ) + { + + case STRTY: + case UNIONTY: + if( type == STRTY ) continue; /* no recursive looking for strs */ + if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ) + { + if( stab[kk].sname[0] == '$' ) return(0); /* $FAKE */ + werror( + "illegal member use: perhaps %s.%s?", + stab[kk].sname, stab[i].sname); + return(1); + } + } + } + } + return( 0 ); +} + +NODE * +conval( p ) +register NODE *p; +{ + register NODE *l, *r; + register o, i, f, u; + register CONSZ val; + + f = (p->tn.type==FLOAT || p->tn.type == DOUBLE); + u = ISUNSIGNED(p->tn.type); + + switch( optype(o = p->tn.op) ) + { + case BITYPE: + l = p->in.left; + r = p->in.right; + break; + + case UTYPE: + r = l = p->in.left; + break; + + case LTYPE: + return( p ); + } + + if( l->tn.op != ( f ? FCON : ICON ) ) return( p ); + if( r->tn.op != ( f ? FCON : ICON ) ) return( p ); + + if( !f ) + { + /* weed out unprofitable cases */ + val = r->tn.lval; + if( l->tn.rval != NONAME && r->tn.rval != NONAME ) return(p); + if( r->tn.rval != NONAME && o!=PLUS ) return(p); + if( l->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(p); + } + else if( logop(o) ) return( p ); + + switch( o ) + { + + case PLUS: + if( f ) + { + l->fpn.dval += r->fpn.dval; + break; + } + l->tn.lval += val; + if( l->tn.rval == NONAME ) + { + l->tn.rval = r->tn.rval; + l->in.type = r->in.type; + } + break; + + case MINUS: + if( f ) l->fpn.dval -= r->fpn.dval; + else l->tn.lval -= val; + break; + + case MUL: + if( f ) l->fpn.dval *= r->fpn.dval; + else l->tn.lval *= val; + break; + + case DIV: + if( f ) + { + if( r->fpn.dval == 0. ) uerror( "division by 0" ); + else l->fpn.dval /= r->fpn.dval; + } + else + { + if( val == 0 ) uerror( "division by 0" ); + else if( u ) + l->tn.lval = (unsigned long)l->tn.lval / val; + else l->tn.lval /= val; + } + break; + + case MOD: + if( val == 0 ) uerror( "division by 0" ); + else if( u ) l->tn.lval = (unsigned long)l->tn.lval % val; + else l->tn.lval %= val; + break; + + case AND: + l->tn.lval &= val; + break; + + case OR: + l->tn.lval |= val; + break; + + case ER: + l->tn.lval ^= val; + break; + + case LS: + i = val; + l->tn.lval = l->tn.lval << i; + break; + + case RS: + i = val; + if( u ) l->tn.lval = (unsigned long)l->tn.lval >> i; + else l->tn.lval = l->tn.lval >> i; + break; + + case UNARY MINUS: + if( f ) l->fpn.dval = -l->fpn.dval; + else l->tn.lval = - l->tn.lval; + break; + + case COMPL: + l->tn.lval = ~l->tn.lval; + break; + + case NOT: + if( l->tn.type == FLOAT || l->tn.type == DOUBLE ) + { + l->tn.op = ICON; + l->tn.lval = !l->fpn.dval; + } + else l->tn.lval = !l->tn.lval; + break; + + case LT: + l->tn.lval = l->tn.lval < val; + break; + + case LE: + l->tn.lval = l->tn.lval <= val; + break; + + case GT: + l->tn.lval = l->tn.lval > val; + break; + + case GE: + l->tn.lval = l->tn.lval >= val; + break; + + case ULT: + l->tn.lval = (l->tn.lval-val)<0; + break; + + case ULE: + l->tn.lval = (l->tn.lval-val)<=0; + break; + + case UGE: + l->tn.lval = (l->tn.lval-val)>=0; + break; + + case UGT: + l->tn.lval = (l->tn.lval-val)>0; + break; + + case EQ: + l->tn.lval = l->tn.lval == val; + break; + + case NE: + l->tn.lval = l->tn.lval != val; + break; + + default: + return(p); + } + + if( l != r ) r->tn.op = FREE; /* don't clobber unary answer */ + l = makety( l, p->tn.type, p->fn.cdim, p->fn.csiz ); + p->tn.op = FREE; + return( l ); +} + +chkpun(p) +register NODE *p; +{ + /* checks p for the existance of a pun */ + /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, + ** or relational + */ + + /* one case is when enumerations are used: this applies only to lint */ + /* in the other case, one operand is a pointer, the other integer */ + /* we check that this integer is in fact a constant zero... */ + /* if it is, we redo the type of the 0 to match the other side */ + + /* with ASSIGN, assignment of pointer to integer is illegal */ + /* this falls out, because the LHS is never 0 */ + + register NODE *q1, *q2; + register t1, t2; + register d1, d2; + + q1 = p->in.left; + q2 = p->in.right; + t1 = q1->in.type; + t2 = q2->in.type; + + if( t1==ENUMTY || t2==ENUMTY ) + { + /* check for enumerations */ + if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) + { + uerror( "illegal comparison of enums" ); + return; + } + if( t1==ENUMTY && t2==ENUMTY && q1->fn.csiz==q2->fn.csiz ) + return; + werror( "enumeration type clash, operator %s", opst[p->in.op] ); + return; + } + + if( ISPTR(t1) || ISARY(t1) ) + { /* switch roles: q1 should be non-pointer */ + q1 = q2; + q2 = p->in.left; + } + + if( !ISPTR(q1->in.type) && !ISARY(q1->in.type) ) + { + if( q1->in.op == ICON && q1->tn.lval == 0 && q1->tn.rval == NONAME ) + { /* make the 0 have the type of the other side */ + q1->fn.type = q2->fn.type; + q1->fn.cdim = q2->fn.cdim; + q1->fn.csiz = q2->fn.type; + } + else + { + combo( "pointer/integer", p ); + } + return; + } + else + { /* q1 and q2 still mean left and right */ + d1 = q1->fn.cdim; + d2 = q2->fn.cdim; + for( ;; ) + { + if( t1 == t2 ) + { + ; + if(q1->fn.csiz!=q2->fn.csiz) + { + combo( "structure pointer", p ); + } + return; + } + if( ISARY(t1) || ISPTR(t1) ) + { + if( !ISARY(t2) && !ISPTR(t2) ) break; + if( ISARY(t1) && ISARY(t2) && + dimtab[d1] != dimtab[d2] ) + { + combo( "array size", p ); + return; + } + if( ISARY(t1) ) ++d1; + if( ISARY(t2) ) ++d2; + } + else break; + t1 = DECREF(t1); + t2 = DECREF(t2); + } + if ( BTYPE(t1) == VOID || BTYPE(t2) == VOID ) return; + combo( "pointer", p ); + } +} + +combo( s, p ) +char *s; +NODE *p; +{ + char buf[100]; + sprintf( buf, "illegal %s combination, op %s", s, opst[p->tn.op] ); + werror( buf ); +} + +NODE * +stref( p ) +register NODE *p; +{ + register TWORD t; + register d, s, dsc, align; + register OFFSZ off; + register struct symtab *q; + + /* make p->x */ + /* this is also used to reference automatic variables */ + + q = &stab[p->in.right->tn.rval]; + p->in.right->in.op = FREE; + p->in.op = FREE; + p = pconvert( p->in.left ); + + /* make p look like ptr to x */ + + if( !ISPTR(p->in.type)) + { + p->in.type = PTR+UNIONTY; + } + + t = INCREF( q->stype ); + d = q->dimoff; + s = q->sizoff; + + p = makety( p, t, d, s ); + + /* compute the offset to be added */ + + off = q->offset; + dsc = q->sclass; + + if( dsc & FIELD ) + { + /* normalize offset */ + switch(q->stype) + { + + case CHAR: + case UCHAR: + align = ALCHAR; + s = CHAR; + break; + + case SHORT: + case USHORT: + align = ALSHORT; + s = SHORT; + break; + + case ENUMTY: + case INT: + case UNSIGNED: + align = ALINT; + s = INT; + break; + +# ifdef LONGFIELDS + case LONG: + case ULONG: + align = ALLONG; + s = LONG; + break; +# endif + + default: + cerror( "undefined bit field type" ); + } + off = (off/align)*align; + } + if( off != 0 ) + p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) ); + + p = buildtree( STAR, p, NIL ); + + /* if field, build field info */ + + if( dsc & FIELD ) + { + p = block( FLD, p, NIL, q->stype, 0, q->sizoff ); + p->tn.rval = PKFIELD(dsc&FLDSIZ,((int)(q->offset)%align)&077 ); + } + + return( clocal(p) ); +} + +notlval(p) +register NODE *p; +{ + + /* return 0 if p an lvalue, 1 otherwise */ + +again: + switch( p->in.op ) + { + + case FLD: + p = p->in.left; + goto again; + + case STAR: + /* fix the &(a=b) bug, given that a and b are structures */ + if( p->in.left->in.op == STASG ) return( 1 ); + case NAME: + case VAUTO: + case VPARAM: + case RNODE: + case QNODE: + case SNODE: + if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1); + case REG: + return(0); + + default: + return(1); + + } + +} + +NODE * +bcon( i ) +{ + /* make a constant node with value i */ + register NODE *p; + + p = block( ICON, NIL, NIL, INT, 0, INT ); + p->tn.lval = i; + p->tn.rval = NONAME; + return( clocal(p) ); +} + +NODE * +bpsize(p) +register NODE *p; +{ + return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) ); +} + +OFFSZ +psize( p ) +register NODE *p; +{ + /* p is a node of type pointer; psize returns the + ** size of the thing pointed to + */ + + if( !ISPTR(p->in.type) ) + { + uerror( "pointer required"); + return( SZINT ); + } + /* note: no pointers to fields */ + return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) ); +} + +NODE * +unconvert( p, q ) +register NODE *p, *q; +{ + /* p is divided by the size of q */ + /* q had better have type pointer */ + +# ifdef MYPDIV + return( clocal( block( PDIV, p, bpsize(q), INT, 0, INT ) ) ); +# else +/* 10.4. + p = makety( p, PTRTYPE, 0, PTRTYPE ); + p = clocal( buildtree( DIV, p, bpsize(q) ) ); + + return( makety( p, PTRTYPE, 0, PTRTYPE ) ); +*/ + p = makety( p, INT, 0, INT ); + p = clocal( buildtree( DIV, p, bpsize(q) ) ); + + return( makety( p, INT, 0, INT ) ); +# endif +} + +NODE * +convert( p, f ) +register NODE *p; +register f; +{ + /* convert an operand of p + ** f is either CVTL or CVTR + ** operand has type int, and is converted by the size of the other side + */ + + register NODE *q, *r; + + if( f == CVTL ) + { + q = p->in.left; + r = bpsize( p->in.right ); + } + else + { + q = p->in.right; + r = bpsize( p->in.left ); + } +# ifdef MYPMUL + r = clocal( block( PMUL, q, r, PTRTYPE, 0, PTRTYPE ) ); +# else + /* if PTRTYPE is defined, make q this size; then, the MUL will be */ +/*11.4. + q = makety( q, PTRTYPE, 0, PTRTYPE ); +*/ + q = makety( q, INT, 0, INT ); + r = clocal( buildtree( MUL, q, r ) ); +# endif + if( f == CVTL ) + p->in.left = r; + else + p->in.right = r; + return(p); + +} + +econvert( p ) +register NODE *p; +{ + + /* change enums to ints, or appropriate types */ + + register TWORD ty; + + if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) + { + if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR; + else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT; + else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT; + else ty = LONG; + ty = ctype( ty ); + p->fn.csiz = ty; + MODTYPE(p->in.type,ty); + if( p->in.op == ICON && ty != LONG ) + p->in.type = p->fn.csiz = INT; + } +} + +NODE * +pconvert( p ) +register NODE *p; +{ + register TWORD t; + + /* if p should be changed into a pointer, do so */ + /* also, widen p so it can be used as an operand */ + + if( ISARY( p->in.type) ) + { + p->in.type = DECREF( p->in.type ); + ++p->fn.cdim; + return( buildtree( UNARY AND, p, NIL ) ); + } + if( ISFTN( p->in.type) ) + return( buildtree( UNARY AND, p, NIL ) ); + + t = indtype( p->tn.type ); + if( t == p->tn.type ) return( p ); + if( p->tn.op == CONV && cbigger( p ) ) + { + p->tn.type = p->fn.csiz = t; + } + else p = makety( p, t, 0, (int) t ); + return( p ); +} + +bigsize( t ) +TWORD t; +{ + /* return a type size for t */ + switch( t ) + { + + case CHAR: + case UCHAR: + return( SZCHAR ); + + case SHORT: + case USHORT: + return( SZSHORT ); + + case VOID: + case INT: + case UNSIGNED: + return( SZINT ); + + case LONG: + case ULONG: + return( SZLONG ); + + case FLOAT: + return( SZLONG+1 ); /* must appear > long */ + case DOUBLE: + return( SZLONG+2 ); + + } + + if( ISPTR(t) || ISARY(t) ) return( SZPOINT ); + cerror( "bad bigsize: 0%o", t ); +/*NOTREACHED*/ +} + +cbigger( p ) +register NODE *p; +{ + /* returns 1 if the conversion op p makes things bigger */ + + if( p->tn.op != CONV ) cerror( "cbigger" ); + return( bigsize( p->tn.type ) > bigsize( p->in.left->tn.type ) ); +} + +NODE * +oconvert(p) +register NODE *p; + +{ + /* convert the result itself: used for pointer and unsigned */ + register TWORD t; + + switch(p->in.op) + { + + case LE: + case LT: + case GE: + case GT: + t = p->in.left->in.type; + if( ISUNSIGNED(t) || ISPTR(t) || ISARY(t) ) + { + p->in.op += (ULE-LE); + } + else + { + t = p->in.right->in.type; + if( ISUNSIGNED(t) || ISPTR(t) || ISARY(t) ) + { + p->in.op += (ULE-LE); + } + } + case EQ: + case NE: + case ULE: + case ULT: + case UGE: + case UGT: + return( p ); + + case MINUS: + return( unconvert( p, p->in.left ) ); + } + + cerror( "illegal oconvert: %d", p->in.op ); + + return(p); +} + +NODE * +ptmatch(p) +register NODE *p; +{ + + /* makes the operands of p agree; they are + ** either pointers or integers, by this time + */ + /* with MINUS, the sizes must be the same */ + /* with COLON, the types must be the same */ + + register TWORD t1, t2, t; + register o, d2, d, s2, s; + + o = p->in.op; + t = t1 = p->in.left->in.type; + t2 = p->in.right->in.type; + d = p->in.left->fn.cdim; + d2 = p->in.right->fn.cdim; + s = p->in.left->fn.csiz; + s2 = p->in.right->fn.csiz; + + switch( o ) + { + + case ASSIGN: + case RETURN: + case CAST: + break; + + case MINUS: + if( psize(p->in.left) != psize(p->in.right) ) + { + uerror( "illegal pointer subtraction"); + } +/* 10.4. p->tn.type = p->fn.csiz = PTRTYPE; +*/ + p->tn.type = p->fn.csiz = INT; + p->fn.cdim = 0; + return( clocal(p) ); + + case COLON: + if(t1 == t2) + break; + if(ISPTR(t1) && ISPTR(t2) && + (BTYPE(t1)==VOID || BTYPE(t2)==VOID)) + break; + else + uerror( "illegal types in :"); + break; + + default: + if( !ISPTR(t1) ) + { + t = t2; + d = d2; + s = s2; + break; + } + if( !ISPTR(t2) ) + { + break; + } + + /* both are pointers */ + if( talign(t2,s2) < talign(t,s) ) + { + t = t2; + s = s2; + } + break; + } + + p->in.left = makety( p->in.left, t, d, s ); + p->in.right = makety( p->in.right, t, d, s ); + if( !logop(o) ) + { + p->in.type = t; + p->fn.cdim = d; + p->fn.csiz = s; + } + + return(clocal(p)); +} + +int tdebug = 0; + +NODE * +tymatch(p) +register NODE *p; +{ + + /* satisfy the types of various arithmetic binary ops */ + + /* rules are: + ** if any float or doubles, make double + ** if any longs, make long + ** if any ints, make int + ** if any shorts, make short + ** otherwise, make char + ** if either operand is unsigned, the result is... + ** if a simple assignment, type = type of lhs + ** if an asg. op, type = type of original lhs + ** (under CONV, if any) + */ + + register o; + register TWORD t1, t2; + TWORD t, tu; + register NODE *l, *r; + int u; + + o = p->in.op; + + convasgflg = 0; + orgtleft = t1 = (l=p->in.left)->in.type; + t2 = (r=p->in.right)->in.type; + + /* constants have a kind of "flexible" type */ + + if( r->tn.op == ICON && r->tn.rval == NONAME && + (t1==CHAR || t1==UCHAR || t1==SHORT || t1==USHORT) ) + { + /* if the constant retains its value when cast to the + ** type of the lhs, assume it has the lhs type + */ + if( r->tn.lval == ccast( r->tn.lval, t1 ) ) + { + r->in.type = t2 = t1; + r->fn.cdim = l->fn.cdim; + r->fn.csiz = l->fn.csiz; + } + } + + /* this is the opposite case from the above (it is too early + to assume that constants are on the right) */ + + if( l->tn.op == ICON && l->tn.rval == NONAME && + (t2==CHAR || t2==UCHAR || t2==SHORT || t2==USHORT) ) + { + /* if the constant retains its value when cast to the + ** type of the rhs, assume it has the rhs type + */ + if( l->tn.lval == ccast( l->tn.lval, t2 ) ) + { + l->in.type = t1 = t2; + l->fn.cdim = r->fn.cdim; + l->fn.csiz = r->fn.csiz; + } + } + if( (t1==VOID || t2==VOID) && o!=CAST ) + uerror("void type illegal in expression"); + + u = 0; + if( ISUNSIGNED(t1) ) + { + u = 1; + t1 = DEUNSIGN(t1); + } + if( ISUNSIGNED(t2) ) + { + u = 1; + t2 = DEUNSIGN(t2); + } + + if( t1==DOUBLE || t1==FLOAT || t2==DOUBLE || t2==FLOAT ) t = DOUBLE; + else if( t1==LONG || t2==LONG ) t = LONG; + else if( t1==INT || t2==INT ) t = INT; + else if( t1==SHORT || t2==SHORT ) t = SHORT; + else t = CHAR; + + if( o == ASSIGN || o == CAST || o == RETURN ) + { + tu = t1; + if( o == RETURN ) + { + if( tu==FLOAT ) tu = DOUBLE; + else if( tu==CHAR || tu==SHORT ) tu = INT; + } + t = t1 = tu; /* t1 set to avoid lhs conversion */ + if( ISUNSIGNED(l->tn.type) ) u=1; + else u=0; + t2 = r->tn.type; /* back to reality... */ + } + tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t; + + if( tu != t1 ) p->in.left = makety( l, tu, 0, (int)tu ); + if( tu != t2 ) p->in.right = makety( r, tu, 0, (int)tu ); + + if( !logop(o) ) /* the type of the node = type of the operation */ + { + p->in.type = tu; + p->fn.cdim = 0; + p->fn.csiz = t; + } + + if( asgop(o) && p->in.left->tn.op == CONV ) + { + /* original, unconverted type */ + /* this will get rewritten to A = A op B, in most cases */ + /* if the op is an unsigned op, change the lhs to unsigned */ + convasgflg = 1; + l = p->in.left->in.left; + tu = l->in.type; + if( u && (UNSIGNABLE(tu)) ) tu = ENUNSIGN(tu); + p->in.type = l->in.type = tu; + p->fn.cdim = l->fn.cdim; + p->fn.csiz = l->fn.csiz; + } + +# ifndef NODBG + if( tdebug ) + { + printf( "tymatch(%lx): %x '%s' %x => %x\n",p,t1,opst[o],t2,tu ); + e2print(p); + } +# endif + + return(p); +} + +NODE * +makety( p, t, d, s ) +register NODE *p; +register TWORD t; +register d,s; +{ + /* make p into type t by inserting a conversion */ + register TWORD pt; + + pt = p->in.type; + + if( pt == ENUMTY && p->in.op == ICON ) + { + econvert(p); + pt = p->in.type; + } + if( t == pt ) + { +rew: + p->fn.type = t; + p->fn.cdim = d; + p->fn.csiz = s; + +/* for really heavy debugging + printf( "block( %s, %d, %d, 0%o, %d, %d ) yields %d\n", + opst[o], l-node, r-node, t, d, s, p-node ); +*/ + + return( p ); + } + + if( t & TMASK ) + { + /* non-simple type */ + if( ISPTR(pt) +# ifdef TWOPTRS + && TWOPTRS(t) == TWOPTRS(pt) +# endif + ) + { + /* don't generate CONV: just rewrite type */ + goto rew; + } + + return( block( CONV, p, NIL, t, d, s ) ); + } + + if( p->in.op == ICON && p->tn.rval==NONAME ) + { + if( t==DOUBLE||t==FLOAT ) + { + p->in.op = FCON; + if( ISUNSIGNED(pt) ) + { + p->fpn.dval = /* (unsigned CONSZ) */ p->tn.lval; + } + else + { + p->fpn.dval = p->tn.lval; + } + goto rew; + } + p->tn.lval = ccast( p->tn.lval, t ); + goto rew; + } + return( block( CONV, p, NIL, t, d, s ) ); +} + +NODE * +block( o, l, r, t, d, s ) +register NODE *l, *r; +register TWORD t; +register o,d,s; +{ + + register NODE *p; + + p = talloc(); + p->in.op = o; + p->in.left = l; + p->in.right = r; + p->in.type = t; + p->fn.cdim = d; + p->fn.csiz = s; + return(p); +} + +icons(p) +register NODE *p; +{ + /* if p is an integer constant, return its value */ + register val; + + if( p->in.op != ICON ) + { + uerror( "constant expected"); + val = 1; + } + else + { + val = p->tn.lval; + if( val != p->tn.lval ) +/* + if((p->tn.lval & 0xffff0000) && + (p->tn.lval & 0xffff0000) != 0xffff0000) +*/ + uerror( "warning: constant too big for compiler" ); + } + tfree( p ); + return(val); +} + +/* the intent of this table is to examine the +** operators, and to check them for +** correctness. +** +** The table is searched for the op and the +** modified type (where this is one of the +** types INT (includes char and short), LONG, +** DOUBLE (includes FLOAT), and POINTER +** +** The default action is to make the node type integer +** +** The actions taken include: +** PUN check for puns +** CVTL convert the left operand +** CVTR convert the right operand +** TYPL the type is determined by the left operand +** TYPR the type is determined by the right operand +** TYMATCH force type of left and right to match, by inserting conversions +** PTMATCH like TYMATCH, but for pointers +** LVAL left operand must be lval +** CVTO convert the op +** NCVT do not convert the operands +** OTHER handled by code +** NCVTR convert the left operand, not the right... +** +*/ + +# define MINT 01 /* integer */ +# define MDBI 02 /* integer or double */ +# define MSTR 04 /* structure */ +# define MPTR 010 /* pointer */ +# define MPTI 020 /* pointer or integer */ +# define MENU 040 /* enumeration variable or member */ + +opact( p ) +register NODE *p; +{ + register mt12, mt1, mt2, o; + + mt12 = 0; + + switch( optype(o=p->in.op) ) + { + + case BITYPE: + mt12=mt2 = moditype( p->in.right->in.type ); + case UTYPE: + mt12 &= (mt1 = moditype( p->in.left->in.type )); + + } + + switch( o ) + { + + case NAME : + case STRING : + case ICON : + case FCON : + case CALL : + case UNARY CALL: + case STAR: + { + return( OTHER ); + } + case UNARY MINUS: + if( mt1 & MDBI ) return( TYPL ); + break; + + case COMPL: + if( mt1 & MINT ) return( TYPL ); + break; + + case UNARY AND: + { + return( NCVT+OTHER ); + } + case INIT: + case CM: + return( 0 ); + case NOT: + case CBRANCH: + case ANDAND: + case OROR: + return( NCVT ); + + case MUL: + case DIV: + if( mt12 & MDBI ) return( TYMATCH ); + break; + + case MOD: + case AND: + case OR: + case ER: + case LS: + case RS: + if( mt12 & MINT ) return( TYMATCH ); + break; + + case EQ: + case NE: + case LT: + case LE: + case GT: + case GE: + if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT ); + if( mt12 & MDBI ) return( TYMATCH+CVTO+NCVT ); + else if( mt12 & MPTR ) return( PTMATCH+PUN+CVTO ); + else if( mt12 & MPTI ) return( PTMATCH+PUN+CVTO ); + else break; + + case QUEST: + case COMOP: + return( TYPR+NCVTR ); + + case STREF: + return( NCVTR+OTHER ); + + case COLON: + if( mt12 & MENU ) return( NCVT+PUN+PTMATCH ); + else if( mt12 & MDBI ) return( TYMATCH ); + else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); + else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN ); + else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN ); + else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); + break; + + case ASSIGN: + case RETURN: + if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); + case CAST: + if(o==CAST && mt1==0)return(TYPL+TYMATCH); + if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); + else if( (mt1&MENU)||(mt2&MENU) ) + { + return( LVAL+NCVT+TYPL+PTMATCH+PUN ); + } + else if( mt12 == 0 ) break; + else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); + else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); + break; + + case ASG MUL: + case ASG DIV: + if( mt12 & MDBI ) return( LVAL+TYMATCH ); + break; + + case ASG MOD: + case ASG AND: + case ASG OR: + case ASG ER: + case ASG LS: + case ASG RS: + if( mt12 & MINT ) return( LVAL+TYMATCH ); + break; + + case ASG PLUS: + case ASG MINUS: + case INCR: + case DECR: + if( mt12 & MDBI ) return( TYMATCH+LVAL ); + else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR ); + break; + + case MINUS: + if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN ); + if( mt2 & MPTR ) break; + case PLUS: + if( mt12 & MDBI ) return( TYMATCH ); + else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR ); + else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL ); + + /* special operators */ + case UOP0: + case UOP1: + case UOP2: + case UOP3: + case UOP4: + case UOP5: + case UOP6: + case UOP7: + case UOP8: + case UOP9: + return( TYPL ); + } + lerror( "operands of %s have incompatible types", opst[o] ); + return( NCVT ); +} + +moditype( ty ) +register TWORD ty; +{ + + switch( ty ) + { + + case UNDEF: + case VOID: + return(0); /* type is void */ + case ENUMTY: + case MOETY: + return( MENU ); + + case STRTY: + case UNIONTY: + return( MSTR ); + + case CHAR: + case SHORT: + case UCHAR: + case USHORT: + return( MINT|MPTI|MDBI ); + + case UNSIGNED: + case ULONG: + case INT: + case LONG: + return( MINT|MDBI|MPTI ); + + case FLOAT: + case DOUBLE: + return( MDBI ); + + default: + return( MPTR|MPTI ); + } +} + +# ifndef MYCCAST +CONSZ +ccast( v, t ) +register CONSZ v; +register TWORD t; +{ + /* cast value v into simple type t */ + /* must be done as it would be on the target machine */ + + switch( t ) + { + + case CHAR: +# ifdef CHSIGN + if( v&ONEBIT(SZCHAR-1) ) + { + return( v | ~BITMASK(SZCHAR) ); + } +# endif + case UCHAR: + return( v & BITMASK(SZCHAR) ); + + case SHORT: + if( v&ONEBIT(SZSHORT-1) ) + { + return( v | ~BITMASK(SZSHORT) ); + } + case USHORT: + return( v & BITMASK(SZSHORT) ); + + case INT: + if( v&ONEBIT(SZINT-1) ) + { + return( v | ~BITMASK(SZINT) ); + } + case UNSIGNED: + return( v & BITMASK(SZINT) ); + + default: + return( v ); + } +} +# endif + + +NODE * +doszof( p ) +register NODE *p; +{ + /* do sizeof p */ + register i; + + /* whatever is the meaning of this if it is a bitfield? */ + i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; + + tfree(p); + if( i <= 0 ) werror( "sizeof returns 0" ); + p = bcon(i); + p->tn.type = UNSIGNED; /* damn dmr anyhow! */ + return( p ); +} + +# ifndef NODBG +eprint(p) +NODE *p; +{ + printf("\n++++++++\n"); + e1print(p,"T"); + printf("---------\n"); +} +e1print( p ,s) +register NODE *p; +char *s; +{ + register ty, d; + static down = 0; + + ty = optype( p->tn.op ); + + if( ty == BITYPE ) + { + ++down; + e1print( p->in.right ,"R"); + --down; + } + + for( d=down; d>1; d -= 2 ) printf( "\t" ); + if( d ) printf( " " ); + + printf("%s=%d) %s, ", s, (int) (p-node), opst[p->in.op] ); + if( ty == LTYPE ) + { + printf( "lval=%ld", p->tn.lval ); + printf( ", rval=%d, ", p->tn.rval ); + } + printf("type="); + tprint( p->in.type ); + printf( ", dim=%d, siz=%d\n", p->fn.cdim, p->fn.csiz ); + if( ty != LTYPE ) + { + ++down; + e1print( p->in.left ,"L"); + --down; + } +} + +tprint( t ) +register TWORD t; +{ + /* output a nice description of the type of t */ + static char * tnames[] = + { + "undef", + "farg", + "char", + "short", + "int", + "long", + "float", + "double", + "strty", + "unionty", + "enumty", + "moety", + "uchar", + "ushort", + "unsigned", + "ulong", + "?", "?" + }; + + for(;; t = DECREF(t) ) + { + if( ISPTR(t) ) printf( "PTR " ); + else if( ISFTN(t) ) printf( "FTN " ); + else if( ISARY(t) ) printf( "ARY " ); + else + { + printf( "%s", tnames[BTYPE(t)] ); + return; + } + } +} +# endif + +# ifndef MYLOCCTR +locctr(l) +register l; +{ + register temp, lt; + /* look in locnames; print out the location counter name */ + /* null means use the next; all null, don't print */ + for( lt=l; lt<=STRNG && !locnames[lt]; ++lt ) + { + /* EMPTY */ + } + if( lt == curloc ) return( lt ); + temp = curloc; + if( lt > STRNG ) lt = l; +/* + else printf( locnames[lt] ); + Fuer variable Segmentnamen bei Daten geaendert !!!!!!! +*/ + else + printf(locnames[lt], datanm); + curloc = lt; + return( temp ); +} +# endif + +# ifndef NOFLOAT + +prtdcon( p ) +register NODE *p; +{ + register i; + register TWORD t; + register NODE *hp; + + if( p->in.op == CBRANCH && optype((hp=p->in.left)->in.op) == BITYPE ) { + if( hp->in.right->in.op==FCON && hp->in.right->fpn.dval==0 ) { + hp->in.right->in.op = FREE; + hp->in.right = bcon(0); + } + else + if( hp->in.left->in.op==FCON && hp->in.left->fpn.dval==0 ) { + hp->in.left->in.op = FREE; + hp->in.left = bcon(0); + } + } + if( p->in.op == FCON ) + { + locctr( DATA ); + t = p->tn.type; + defalign( t==DOUBLE?ALDOUBLE:ALFLOAT ); + deflab( i = getlab() ); + fincode( p->fpn.dval, t==DOUBLE?SZDOUBLE:SZFLOAT ); + p->tn.lval = 0; + p->tn.rval = -i; + p->in.op = NAME; + } + if( (i = optype(p->in.op)) == BITYPE ) prtdcon( p->in.right ); + if( i != LTYPE ) prtdcon( p->in.left ); +} +# endif + +# ifndef MYLABELS +getlab() +{ + static crslab = 10; + return( ++crslab ); +} +# endif + +int edebug = 0; +ecomp( p ) +register NODE *p; +{ +# ifndef NODBG + if( edebug ) eprint(p); +# endif + if( !reached ) + { + werror( "statement not reached" ); + reached = 1; + } +# ifdef CLOCAL + p = clocal(p); +# endif + p = optim(p); +# ifndef NOFLOAT + prtdcon(p); +# endif + locctr( PROG ); + ecode(p); + tfree(p); +} + +# ifndef MYECODE +ecode( p ) +register NODE *p; +{ + /* standard version of writing the tree nodes */ + if( nerrors ) return; +# ifdef SDB + sdbline(); +# endif + + p2tree( p ); + p2compile( p ); +} +# endif + +# ifdef STDPRTREE /****************************************/ + +# ifndef RNODNAME +# define RNODNAME LABFMT +# endif + +# ifndef ONEPASS + +prtree(p) register NODE *p; { + + register struct symtab *q; + register ty; + +# ifdef MYPRTREE + MYPRTREE(p); /* local action can be taken here; then return... */ +#endif + + ty = optype(p->in.op); + + printf( "%d\t", p->in.op ); + + if( ty == LTYPE ) { + printf( CONFMT, p->tn.lval ); + printf( "\t" ); + } + if( ty != BITYPE ) { + if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" ); + else printf( "%d\t", p->tn.rval ); + } + + printf( "%o\t", p->in.type ); + + /* handle special cases */ + + switch( p->in.op ){ + + case NAME: + case ICON: + /* print external name */ + if( p->tn.rval == NONAME ) printf( "\n" ); + else if( p->tn.rval >= 0 ){ + q = &stab[p->tn.rval]; + printf( "%.8s\n", exname(q->sname) ); + } + else { /* label */ + printf( LABFMT, -p->tn.rval ); + printf("\n"); + } + break; + + case STARG: + case STASG: + case STCALL: + case UNARY STCALL: + /* print out size */ + /* use lhs size, in order to avoid hassles with the structure `.' operator */ + + /* note: p->in.left not a field... */ + printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) ); + printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) ); + break; + + default: + printf( "\n" ); + } + + if( ty != LTYPE ) prtree( p->in.left ); + if( ty == BITYPE ) prtree( p->in.right ); + + } + +# endif not defined ONEPASS + +p2tree(p) +register NODE *p; +{ + register ty; + register NODE *l; + register o; + char temp[32]; /* place to dump label stuff */ + +# ifdef MYP2TREE + MYP2TREE(p); /* local action can be taken here; then return... */ +# endif + + /* this routine sits painfully between pass1 and pass2 */ + ty = optype(o=p->in.op); + p->tn.goal = 0; /* an illegal goal, just to clear it out */ + p->tn.type = ttype( p->tn.type ); /* type gets second-pass (bits) */ + switch( o ) + { + + case TEMP: + case NAME: + case ICON: + case VAUTO: + case VPARAM: + if( p->tn.rval == NONAME ) + p->in.name = (char *) 0; + else if( p->tn.rval >= 0 ) + { + /* copy name from exname */ + register char *cp; + cp = exname( stab[p->tn.rval].sname ); + p->in.name = tstr( cp ); + } + else if( p->tn.rval == - strftn ) + { + sprintf( temp, RNODNAME, -p->tn.rval ); + p->in.name = tstr( temp ); + } + else + { + sprintf( temp, LABFMT, -p->tn.rval ); + p->in.name = tstr( temp ); + } + break; + + case STARG: + case STASG: + case STCALL: + case UNARY STCALL: + /* set up size parameters */ + l = p->in.left; + p->stn.stsize = tsize(STRTY,l->fn.cdim,l->fn.csiz); + p->stn.stalign = talign(STRTY,l->fn.csiz); + break; + /* this should do something only if temporary regs are + /* built into the tree by machine-dependent actions */ + case REG: + rbusy( p->tn.rval, p->in.type ); + default: + p->in.name = (char *) 0; + } + + if( ty != LTYPE ) p2tree( p->in.left ); + if( ty == BITYPE ) p2tree( p->in.right ); +} + +# endif /******************************************/