117738Sralph #ifndef lint
2*34250Sdonn static char *sccsid ="@(#)local.c 1.17 (Berkeley) 05/11/88";
317738Sralph #endif lint
417738Sralph
518555Sralph # include "pass1.h"
69701Slinton
79701Slinton /* this file contains code which is dependent on the target machine */
89701Slinton
99701Slinton NODE *
clocal(p)1032916Sdonn clocal(p) register NODE *p; {
119701Slinton
129701Slinton /* this is called to do local transformations on
139701Slinton an expression tree preparitory to its being
149701Slinton written out in intermediate code.
159701Slinton */
169701Slinton
179701Slinton /* the major essential job is rewriting the
189701Slinton automatic variables and arguments in terms of
199701Slinton REG and OREG nodes */
209701Slinton /* conversion ops which are not necessary are also clobbered here */
219701Slinton /* in addition, any special features (such as rewriting
229701Slinton exclusive or) are easily handled here as well */
239701Slinton
249701Slinton register struct symtab *q;
259701Slinton register NODE *r;
2632916Sdonn register int o;
2732916Sdonn register int m, ml;
289701Slinton
299701Slinton switch( o = p->in.op ){
309701Slinton
319701Slinton case NAME:
329701Slinton if( p->tn.rval < 0 ) { /* already processed; ignore... */
339701Slinton return(p);
349701Slinton }
359701Slinton q = &stab[p->tn.rval];
369701Slinton switch( q->sclass ){
379701Slinton
389701Slinton case AUTO:
399701Slinton case PARAM:
409701Slinton /* fake up a structure reference */
419701Slinton r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 );
429701Slinton r->tn.lval = 0;
439701Slinton r->tn.rval = (q->sclass==AUTO?STKREG:ARGREG);
449701Slinton p = stref( block( STREF, r, p, 0, 0, 0 ) );
459701Slinton break;
469701Slinton
479701Slinton case ULABEL:
489701Slinton case LABEL:
499701Slinton case STATIC:
509701Slinton if( q->slevel == 0 ) break;
519701Slinton p->tn.lval = 0;
529701Slinton p->tn.rval = -q->offset;
539701Slinton break;
549701Slinton
559701Slinton case REGISTER:
569701Slinton p->in.op = REG;
579701Slinton p->tn.lval = 0;
589701Slinton p->tn.rval = q->offset;
599701Slinton break;
609701Slinton
619701Slinton }
629701Slinton break;
639701Slinton
6432916Sdonn case LT:
6532916Sdonn case LE:
6632916Sdonn case GT:
6732916Sdonn case GE:
6832916Sdonn if( ISPTR( p->in.left->in.type ) || ISPTR( p->in.right->in.type ) ){
6932916Sdonn p->in.op += (ULT-LT);
7032916Sdonn }
7132916Sdonn break;
7232916Sdonn
739701Slinton case PCONV:
749701Slinton /* do pointer conversions for char and longs */
759701Slinton ml = p->in.left->in.type;
769701Slinton if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) break;
779701Slinton
789701Slinton /* pointers all have the same representation; the type is inherited */
799701Slinton
809701Slinton p->in.left->in.type = p->in.type;
819701Slinton p->in.left->fn.cdim = p->fn.cdim;
829701Slinton p->in.left->fn.csiz = p->fn.csiz;
839701Slinton p->in.op = FREE;
849701Slinton return( p->in.left );
859701Slinton
869701Slinton case SCONV:
8732916Sdonn m = p->in.type;
8832916Sdonn ml = p->in.left->in.type;
8932916Sdonn if(m == ml)
9032916Sdonn goto clobber;
9117738Sralph o = p->in.left->in.op;
9232916Sdonn if(m == FLOAT || m == DOUBLE) {
9332916Sdonn if(o==SCONV &&
9432916Sdonn ml == DOUBLE &&
9532916Sdonn p->in.left->in.left->in.type==m) {
9632916Sdonn p->in.op = p->in.left->in.op = FREE;
9732916Sdonn return(p->in.left->in.left);
9832916Sdonn }
9932916Sdonn /* see makety() for constant conversions */
10032916Sdonn break;
10132916Sdonn }
10232916Sdonn if(ml == FLOAT || ml == DOUBLE){
10332916Sdonn if(o != FCON && o != DCON)
10432916Sdonn break;
10532916Sdonn ml = ISUNSIGNED(m) ? UNSIGNED : INT; /* LONG? */
10632916Sdonn r = block( ICON, (NODE *)NULL, (NODE *)NULL, ml, 0, 0 );
10717738Sralph if( o == FCON )
10832916Sdonn r->tn.lval = ml == INT ?
10932916Sdonn (int) p->in.left->fpn.fval :
11032916Sdonn (unsigned) p->in.left->fpn.fval;
11117738Sralph else
11232916Sdonn r->tn.lval = ml == INT ?
11332916Sdonn (int) p->in.left->dpn.dval :
11432916Sdonn (unsigned) p->in.left->dpn.dval;
11517738Sralph r->tn.rval = NONAME;
11617738Sralph p->in.left->in.op = FREE;
11717738Sralph p->in.left = r;
11832916Sdonn o = ICON;
11932916Sdonn if( m == ml )
12032916Sdonn goto clobber;
12117738Sralph }
1229701Slinton /* now, look for conversions downwards */
1239701Slinton
12432916Sdonn if( o == ICON ){ /* simulate the conversion here */
1259701Slinton CONSZ val;
1269701Slinton val = p->in.left->tn.lval;
1279701Slinton switch( m ){
1289701Slinton case CHAR:
1299701Slinton p->in.left->tn.lval = (char) val;
1309701Slinton break;
1319701Slinton case UCHAR:
1329701Slinton p->in.left->tn.lval = val & 0XFF;
1339701Slinton break;
1349701Slinton case USHORT:
1359701Slinton p->in.left->tn.lval = val & 0XFFFFL;
1369701Slinton break;
1379701Slinton case SHORT:
1389701Slinton p->in.left->tn.lval = (short)val;
1399701Slinton break;
1409701Slinton case UNSIGNED:
1419701Slinton p->in.left->tn.lval = val & 0xFFFFFFFFL;
1429701Slinton break;
1439701Slinton case INT:
1449701Slinton p->in.left->tn.lval = (int)val;
1459701Slinton break;
1469701Slinton }
1479701Slinton p->in.left->in.type = m;
1489701Slinton }
14932916Sdonn else
15016181Sralph break;
1519701Slinton
15232916Sdonn clobber:
1539701Slinton p->in.op = FREE;
1549701Slinton return( p->in.left ); /* conversion gets clobbered */
1559701Slinton
1569701Slinton case PVCONV:
1579701Slinton case PMCONV:
1589701Slinton if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0);
1599701Slinton p->in.op = FREE;
1609701Slinton return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) );
1619701Slinton
1629701Slinton case RS:
1639701Slinton case ASG RS:
1649701Slinton /* convert >> to << with negative shift count */
1659701Slinton /* only if type of left operand is not unsigned */
1669701Slinton
1679701Slinton if( ISUNSIGNED(p->in.left->in.type) ) break;
16817738Sralph if( p->in.right->in.op != UNARY MINUS )
16917738Sralph p->in.right = buildtree( UNARY MINUS, p->in.right, NIL );
17017738Sralph else {
17117738Sralph r = p->in.right;
17217738Sralph p->in.right = p->in.right->in.left;
17317738Sralph r->in.op = FREE;
17417738Sralph }
1759701Slinton if( p->in.op == RS ) p->in.op = LS;
1769701Slinton else p->in.op = ASG LS;
1779701Slinton break;
1789701Slinton
1799701Slinton case FLD:
1809701Slinton /* make sure that the second pass does not make the
1819701Slinton descendant of a FLD operator into a doubly indexed OREG */
1829701Slinton
1839701Slinton if( p->in.left->in.op == UNARY MUL
1849701Slinton && (r=p->in.left->in.left)->in.op == PCONV)
1859701Slinton if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS )
1869701Slinton if( ISPTR(r->in.type) ) {
1879701Slinton if( ISUNSIGNED(p->in.left->in.type) )
188*34250Sdonn p->in.left->in.type = UCHAR;
1899701Slinton else
190*34250Sdonn p->in.left->in.type = CHAR;
1919701Slinton }
1929701Slinton break;
1939701Slinton }
1949701Slinton
1959701Slinton return(p);
1969701Slinton }
1979701Slinton
19832915Sdonn /*ARGSUSED*/
andable(p)1999701Slinton andable( p ) NODE *p; {
2009701Slinton return(1); /* all names can have & taken on them */
2019701Slinton }
2029701Slinton
cendarg()2039701Slinton cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
2049701Slinton autooff = AUTOINIT;
2059701Slinton }
2069701Slinton
cisreg(t)2079701Slinton cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */
2089701Slinton
2099701Slinton #ifdef TRUST_REG_CHAR_AND_REG_SHORT
2109701Slinton if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */
2119701Slinton || t==CHAR || t==UCHAR || t==SHORT /* tbl */
2129701Slinton || t==USHORT || ISPTR(t)) return(1); /* tbl */
2139701Slinton #else
2149701Slinton if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* wnj */
21517738Sralph #ifdef SPRECC
21617738Sralph || t==FLOAT
21717738Sralph #endif
2189701Slinton || ISPTR(t)) return (1); /* wnj */
2199701Slinton #endif
2209701Slinton return(0);
2219701Slinton }
2229701Slinton
22332915Sdonn /*ARGSUSED*/
2249701Slinton NODE *
offcon(off,t,d,s)2259701Slinton offcon( off, t, d, s ) OFFSZ off; TWORD t; {
2269701Slinton
2279701Slinton /* return a node, for structure references, which is suitable for
2289701Slinton being added to a pointer of type t, in order to be off bits offset
2299701Slinton into a structure */
2309701Slinton
2319701Slinton register NODE *p;
2329701Slinton
2339701Slinton /* t, d, and s are the type, dimension offset, and sizeoffset */
23432915Sdonn /* in general they are necessary for offcon, but not on VAX */
2359701Slinton
2369701Slinton p = bcon(0);
2379701Slinton p->tn.lval = off/SZCHAR;
2389701Slinton return(p);
2399701Slinton
2409701Slinton }
2419701Slinton
2429701Slinton
2439701Slinton static inwd /* current bit offsed in word */;
24432916Sdonn static CONSZ word /* word being built from fields */;
2459701Slinton
incode(p,sz)2469701Slinton incode( p, sz ) register NODE *p; {
2479701Slinton
2489701Slinton /* generate initialization code for assigning a constant c
2499701Slinton to a field of width sz */
2509701Slinton /* we assume that the proper alignment has been obtained */
2519701Slinton /* inoff is updated to have the proper final value */
2529701Slinton /* we also assume sz < SZINT */
2539701Slinton
254*34250Sdonn inoff += sz;
25532916Sdonn if(nerrors) return;
2569701Slinton if((sz+inwd) > SZINT) cerror("incode: field > int");
2579701Slinton word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd);
2589701Slinton inwd += sz;
2599701Slinton if(inoff%SZINT == 0) {
26032916Sdonn printf( " .long 0x%lx\n", word);
2619701Slinton word = inwd = 0;
2629701Slinton }
2639701Slinton }
2649701Slinton
fincode(d,sz)2659701Slinton fincode( d, sz ) double d; {
2669701Slinton /* output code to initialize space of size sz to the value d */
2679701Slinton /* the proper alignment has been obtained */
2689701Slinton /* inoff is updated to have the proper final value */
2699701Slinton /* on the target machine, write it out in octal! */
2709701Slinton
2719701Slinton
272*34250Sdonn if(!nerrors)
2739701Slinton printf(" %s 0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float",
2749701Slinton sz == SZDOUBLE ? 'd' : 'f', d);
2759701Slinton inoff += sz;
2769701Slinton }
2779701Slinton
cinit(p,sz)2789701Slinton cinit( p, sz ) NODE *p; {
27918437Smckusick NODE *l;
28018437Smckusick
28118437Smckusick /*
28218437Smckusick * as a favor (?) to people who want to write
28318437Smckusick * int i = 9600/134.5;
28418437Smckusick * we will, under the proper circumstances, do
28532916Sdonn * a coercion here.
28618437Smckusick */
28718437Smckusick switch (p->in.type) {
28818437Smckusick case INT:
28918437Smckusick case UNSIGNED:
29018437Smckusick l = p->in.left;
29118555Sralph if (l->in.op != SCONV ||
29218555Sralph (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON))
29318555Sralph break;
29418437Smckusick l->in.op = FREE;
29518437Smckusick l = l->in.left;
29618555Sralph l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) :
29718555Sralph (long)(l->fpn.fval);
29818437Smckusick l->tn.rval = NONAME;
29918437Smckusick l->tn.op = ICON;
30018437Smckusick l->tn.type = INT;
30118437Smckusick p->in.left = l;
30218437Smckusick break;
30318437Smckusick }
30418437Smckusick /* arrange for the initialization of p into a space of size sz */
3059701Slinton /* the proper alignment has been opbtained */
3069701Slinton /* inoff is updated to have the proper final value */
3079701Slinton ecode( p );
3089701Slinton inoff += sz;
3099701Slinton }
3109701Slinton
vfdzero(n)3119701Slinton vfdzero( n ){ /* define n bits of zeros in a vfd */
3129701Slinton
3139701Slinton if( n <= 0 ) return;
3149701Slinton
315*34250Sdonn inoff += n;
31632914Sdonn if (nerrors) return;
3179701Slinton inwd += n;
3189701Slinton if( inoff%ALINT ==0 ) {
31932916Sdonn printf( " .long 0x%lx\n", word );
3209701Slinton word = inwd = 0;
3219701Slinton }
3229701Slinton }
3239701Slinton
3249701Slinton char *
exname(p)3259701Slinton exname( p ) char *p; {
3269701Slinton /* make a name look like an external name in the local machine */
3279701Slinton
3289701Slinton #ifndef FLEXNAMES
3299701Slinton static char text[NCHNAM+1];
3309701Slinton #else
3319701Slinton static char text[BUFSIZ+1];
3329701Slinton #endif
3339701Slinton
33432916Sdonn register int i;
3359701Slinton
3369701Slinton text[0] = '_';
3379701Slinton #ifndef FLEXNAMES
33824417Smckusick for( i=1; *p&&i<NCHNAM; ++i )
3399701Slinton #else
34024417Smckusick for( i=1; *p; ++i )
3419701Slinton #endif
3429701Slinton text[i] = *p++;
3439701Slinton
3449701Slinton text[i] = '\0';
3459701Slinton #ifndef FLEXNAMES
3469701Slinton text[NCHNAM] = '\0'; /* truncate */
3479701Slinton #endif
3489701Slinton
3499701Slinton return( text );
3509701Slinton }
3519701Slinton
ctype(type)35217738Sralph ctype( type ) TWORD type;
35317738Sralph { /* map types which are not defined on the local machine */
3549701Slinton switch( BTYPE(type) ){
3559701Slinton
3569701Slinton case LONG:
3579701Slinton MODTYPE(type,INT);
3589701Slinton break;
3599701Slinton
3609701Slinton case ULONG:
3619701Slinton MODTYPE(type,UNSIGNED);
3629701Slinton }
3639701Slinton return( type );
3649701Slinton }
3659701Slinton
noinit()36617738Sralph noinit() { /* curid is a variable which is defined but
3679701Slinton is not initialized (and not a function );
3689701Slinton This routine returns the stroage class for an uninitialized declaration */
3699701Slinton
3709701Slinton return(EXTERN);
3719701Slinton
3729701Slinton }
3739701Slinton
commdec(id)3749701Slinton commdec( id ){ /* make a common declaration for id, if reasonable */
3759701Slinton register struct symtab *q;
3769701Slinton OFFSZ off, tsize();
3779701Slinton
37832914Sdonn if (nerrors) return;
3799701Slinton q = &stab[id];
3809701Slinton printf( " .comm %s,", exname( q->sname ) );
3819701Slinton off = tsize( q->stype, q->dimoff, q->sizoff );
3829701Slinton printf( CONFMT, off/SZCHAR );
38332916Sdonn putchar( '\n' );
3849701Slinton }
3859701Slinton
prtdcon(p)38632916Sdonn prtdcon(p)
38732916Sdonn register NODE *p;
38832916Sdonn {
38932916Sdonn register int o = p->in.op;
39032916Sdonn int i;
3919701Slinton
39232916Sdonn if (o != DCON && o != FCON)
39332916Sdonn return;
39432916Sdonn /*
39532916Sdonn * Clobber constants of value zero so
39632916Sdonn * we can generate more efficient code.
39732916Sdonn */
39832916Sdonn if ((o == DCON && p->dpn.dval == 0) ||
39932916Sdonn (o == FCON && p->fpn.fval == 0)) {
40032916Sdonn p->in.op = ICON;
40132916Sdonn p->tn.rval = NONAME;
40232916Sdonn return;
4039701Slinton }
40432916Sdonn locctr(DATA);
40532916Sdonn defalign(o == DCON ? ALDOUBLE : ALFLOAT);
40632916Sdonn deflab(i = getlab());
40732916Sdonn if (o == FCON)
40832916Sdonn fincode(p->fpn.fval, SZFLOAT);
40932916Sdonn else
41032916Sdonn fincode(p->dpn.dval, SZDOUBLE);
41132916Sdonn p->tn.lval = 0;
41232916Sdonn p->tn.rval = -i;
41332916Sdonn p->in.type = (o == DCON ? DOUBLE : FLOAT);
41432916Sdonn p->in.op = NAME;
41532916Sdonn }
4169701Slinton
ecode(p)4179701Slinton ecode( p ) NODE *p; {
4189701Slinton
4199701Slinton /* walk the tree and write out the nodes.. */
4209701Slinton
4219701Slinton if( nerrors ) return;
4229701Slinton p2tree( p );
4239701Slinton p2compile( p );
4249701Slinton }
4259701Slinton
4269701Slinton #ifndef ONEPASS
tlen(p)4279701Slinton tlen(p) NODE *p;
4289701Slinton {
4299701Slinton switch(p->in.type) {
4309701Slinton case CHAR:
4319701Slinton case UCHAR:
4329701Slinton return(1);
4339701Slinton
4349701Slinton case SHORT:
4359701Slinton case USHORT:
43632919Sdonn return(SZSHORT/SZCHAR);
4379701Slinton
4389701Slinton case DOUBLE:
43932919Sdonn return(SZDOUBLE/SZCHAR);
4409701Slinton
4419701Slinton default:
44232919Sdonn return(SZINT/SZCHAR);
4439701Slinton }
4449701Slinton }
4459701Slinton #endif
446