/* $OpenBSD: local.c,v 1.1 2007/10/07 17:58:52 otto Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code and documentation must retain the above * copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditionsand the following disclaimer in the * documentation and/or other materials provided with the distribution. * All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed or owned by Caldera * International, Inc. * Neither the name of Caldera International, Inc. nor the names of other * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ # 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 PCONV: /* do pointer conversions for char and longs */ ml = p->left->type; if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->left->op != ICON ) break; /* pointers all have the same representation; the type is inherited */ inherit: 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 USHORT: p->left->lval = val & 0XFFFFL; break; case SHORT: p->left->lval = (short)val; break; case UNSIGNED: p->left->lval = val & 0xFFFFFFFFL; 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!=CHAR && ml!= UCHAR ) break; } else if( m==SHORT || m==USHORT ){ if( ml!=CHAR && ml!=UCHAR && ml!=SHORT && ml!=USHORT ) break; } } /* clobber conversion */ if( tlen(p) == tlen(p->left) ) goto inherit; p->op = FREE; return( p->left ); /* conversion gets clobbered */ 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 RS: case ASG RS: /* convert >> to << with negative shift count */ /* only if type of left operand is not unsigned */ if( ISUNSIGNED(p->left->type) ) break; p->right = buildtree( UNARY MINUS, p->right, NIL ); if( p->op == RS ) p->op = LS; else p->op = ASG LS; 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 || t==LONG || t==ULONG /* tbl */ || t==CHAR || t==UCHAR || t==SHORT || t==USHORT /* tbl */ || ISPTR(t)) return(1); /* tbl */ 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); } 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 */ inoff += sz; if (sz>SZSHORT) printf(" .long %d:%d\n", sz, p->lval); else if (sz>SZCHAR) printf(" .word %d:%d\n", sz, p->lval); else printf(" .byte %d:%d\n", sz, p->lval); } fincode( d, sz ) double d; { /* output code to initialize space of size sz to the value d */ /* the proper alignment has been obtained */ /* inoff is updated to have the proper final value */ /* on the target machine, write it out in octal! */ printf(" %s 0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float", sz == SZDOUBLE ? 'd' : 'f', d); inoff += sz; } cinit( p, sz ) NODE *p; { /* arrange for the initialization of p into a space of size sz */ /* the proper alignment has been opbtained */ /* inoff is updated to have the proper final value */ ecode( p ); inoff += sz; } vfdzero( n ){ /* define n bits of zeros in a vfd */ register i; if( n <= 0 ) return; inoff += n; i = n; while (i>=SZCHAR) { printf(" .byte 0\n"); i -= SZCHAR; } if (i) printf(" .byte %d:0\n", i); } char * exname( p ) char *p; { /* make a name look like an external name in the local machine */ static char text[NCHNAM+1]; register i; text[0] = '_'; for( i=1; *p&&isname ) ); 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 ); } #include "a.out.h" int ddebug; int gdebug; outstab(p) struct symtab *p; { register TWORD ptype; register char *pname; register char pclass; register int poffset; if (!gdebug) return; ptype = p->stype; pname = p->sname; pclass = p->sclass; poffset = p->offset; if (ISFTN(ptype)) { return; } switch (pclass) { case AUTO: pstab(pname, N_LSYM); printf("0,%d,%d\n", ptype, (-poffset)/SZCHAR); poffs(p); return; case EXTDEF: case EXTERN: pstab(pname, N_GSYM); printf("0,%d,0\n", ptype); poffs(p); return; case STATIC: pstab(pname, N_STSYM); if (p->slevel > 1) { printf("0,%d,L%d\n", ptype, poffset); } else { printf("0,%d,%s\n", ptype, exname(pname)); } poffs(p); return; case REGISTER: pstab(pname, N_RSYM); printf("0,%d,%d\n", ptype, poffset); poffs(p); return; case MOS: case MOU: pstab(pname, N_SSYM); printf("0,%d,%d\n", ptype, poffset/SZCHAR); poffs(p); return; case PARAM: /* parameter stab entries are processed in dclargs() */ return; default: if (ddebug) printf(" No .stab for %.8s\n", pname); } } pstab(name, type) char *name; int type; { register int i; register char c; if (!gdebug) return; printf(" .stab "); for(i=0; i<8; i++) if (c = name[i]) printf("'%c,", c); else printf("0,"); printf("0%o,", type); } poffs(p) register struct symtab *p; { int s; if (!gdebug) return; if ((s = dimtab[p->sizoff]/SZCHAR) > 1) { pstab(p->sname, N_LENG); printf("1,0,%d\n", s); } } char NULLNAME[8]; int labelno; int fdefflag; psline() { static int lastlineno; register char *cp, *cq; register int i; if (!gdebug) return; cq = ititle; cp = ftitle; while ( *cq ) if ( *cp++ != *cq++ ) goto neq; if ( *cp == '\0' ) goto eq; neq: for (i=0; i<100; i++) ititle[i] = '\0'; cp = ftitle; cq = ititle; while ( *cp ) *cq++ = *cp++; *cq = '\0'; *--cq = '\0'; for ( cp = ititle+1; *(cp-1); cp += 8 ) { pstab(cp, N_SOL); if (gdebug) printf("0,0,LL%d\n", labelno); } *cq = '"'; printf("LL%d:\n", labelno++); eq: if (lineno == lastlineno) return; lastlineno = lineno; if (fdefflag) { pstab(NULLNAME, N_SLINE); printf("0,%d,LL%d\n", lineno, labelno); printf("LL%d:\n", labelno++); } } plcstab(level) { if (!gdebug) return; pstab(NULLNAME, N_LBRAC); printf("0,%d,LL%d\n", level, labelno); printf("LL%d:\n", labelno++); } prcstab(level) { if (!gdebug) return; pstab(NULLNAME, N_RBRAC); printf("0,%d,LL%d\n", level, labelno); printf("LL%d:\n", labelno++); } pfstab(sname) char *sname; { if (!gdebug) return; pstab(sname, N_FUN); printf("0,%d,_%.7s\n", lineno, sname); } #ifndef ONEPASS tlen(p) NODE *p; { switch(p->type) { case CHAR: case UCHAR: return(1); case SHORT: case USHORT: return(2); case DOUBLE: return(8); default: return(4); } } #endif