# include "mfile1" /* this file contains code which is dependent on the target machine */ NODE * cast( p, t ) register NODE *p; TWORD t; { /* cast node p to type t */ p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p ); p->left->op = FREE; p->op = FREE; return( p->right ); } NODE * clocal(p) NODE *p; { /* this is called to do local transformations on an expression tree preparitory to its being written out in intermediate code. */ /* the major essential job is rewriting the automatic variables and arguments in terms of REG and OREG nodes */ /* conversion ops which are not necessary are also clobbered here */ /* in addition, any special features (such as rewriting exclusive or) are easily handled here as well */ register struct symtab *q; register NODE *r; register o; register m, ml; switch( o = p->op ){ case NAME: if( p->rval < 0 ) { /* already processed; ignore... */ return(p); } q = &stab[p->rval]; switch( q->sclass ){ case AUTO: case PARAM: /* fake up a structure reference */ r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 ); r->lval = 0; r->rval = (q->sclass==AUTO?STKREG:ARGREG); p = stref( block( STREF, r, p, 0, 0, 0 ) ); break; case ULABEL: case LABEL: case STATIC: if( q->slevel == 0 ) break; p->lval = 0; p->rval = -q->offset; break; case REGISTER: p->op = REG; p->lval = 0; p->rval = q->offset; break; } break; case LT: case LE: case GT: case GE: if( ISPTR( p->left->type ) || ISPTR( p->right->type ) ){ p->op += (ULT-LT); } break; case PCONV: /* do pointer conversions for char and longs */ ml = p->left->type; if( ( ml==CHAR || ml==UCHAR || ml==LONG || ml==ULONG ) && p->left->op != ICON ) break; /* pointers all have the same representation; the type is inherited */ p->left->type = p->type; p->left->cdim = p->cdim; p->left->csiz = p->csiz; p->op = FREE; return( p->left ); case SCONV: m = (p->type == FLOAT || p->type == DOUBLE ); ml = (p->left->type == FLOAT || p->left->type == DOUBLE ); if( m != ml ) break; /* now, look for conversions downwards */ m = p->type; ml = p->left->type; if( p->left->op == ICON ){ /* simulate the conversion here */ CONSZ val; val = p->left->lval; switch( m ){ case CHAR: p->left->lval = (char) val; break; case UCHAR: p->left->lval = val & 0XFF; break; case UNSIGNED: p->left->lval = val & 0XFFFFL; break; case INT: p->left->lval = (int)val; break; } p->left->type = m; } else { /* meaningful ones are conversion of int to char, int to short, and short to char, and unsigned version of them */ if( m==CHAR || m==UCHAR ){ if( ml==LONG || ml==ULONG ) break; } else if( m==INT || m==UNSIGNED ){ if( ml==LONG || ml==ULONG ) break; } else if( m==LONG || m==ULONG ){ if( ml!=LONG && ml!= ULONG ) break; } } /* clobber conversion */ p->op = FREE; return( p->left ); /* conversion gets clobbered */ case ASSIGN: /* get rid of SCONV for assignments from LONG -> CHAR|INT */ if( p->right->op == SCONV ) { m = p->right->type; ml = p->right->left->type; if( ( m==LONG || m==ULONG ) && ml!=FLOAT && ml!=DOUBLE ) { p->right->op = FREE; p->right = p->right->left; } } break; case PVCONV: case PMCONV: if( p->right->op != ICON ) cerror( "bad conversion", 0); p->op = FREE; return( buildtree( o==PMCONV?MUL:DIV, p->left, p->right ) ); case PLUS: case MINUS: case LS: case MUL: /* optimize address calculations with long indexes */ if( ISPTR( p->type ) || ISARY( p->type ) ) { if( p->left->type==LONG || p->left->type==ULONG ) p->left = cast( p->left, INT ); if( p->right->type==LONG || p->right->type==ULONG ) p->right = cast( p->right, INT ); } break; } return(p); } andable( p ) NODE *p; { return(1); /* all names can have & taken on them */ } cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */ autooff = AUTOINIT; } cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */ if( t==INT || t==UNSIGNED || ISPTR(t) ) return(1); return(0); } NODE * offcon( off, t, d, s ) OFFSZ off; TWORD t; { /* return a node, for structure references, which is suitable for being added to a pointer of type t, in order to be off bits offset into a structure */ register NODE *p; /* t, d, and s are the type, dimension offset, and sizeoffset */ /* in general they are necessary for offcon, but not on H'well */ p = bcon(0); p->lval = off/SZCHAR; return(p); } static inwd /* current bit offsed in word */; static word /* word being built from fields */; incode( p, sz ) register NODE *p; { /* generate initialization code for assigning a constant c to a field of width sz */ /* we assume that the proper alignment has been obtained */ /* inoff is updated to have the proper final value */ /* we also assume sz < SZINT */ if((sz+inwd) > SZINT) cerror("incode: field > int"); word |= p->lval<sname ) ); off = tsize( q->stype, q->dimoff, q->sizoff ); printf( CONFMT, off/SZCHAR ); printf( ".\n" ); } isitlong( cb, ce ){ /* is lastcon to be long or short */ /* cb is the first character of the representation, ce the last */ if( ce == 'l' || ce == 'L' || lastcon >= (1L << (SZINT-1) ) ) return (1); return(0); } isitfloat( s ) char *s; { double atof(); dcon = atof(s); return( FCON ); } ecode( p ) NODE *p; { /* walk the tree and write out the nodes.. */ if( nerrors ) return; p2tree( p ); p2compile( p ); }