444 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			444 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
						|
 */
 | 
						|
#include "bem.h"
 | 
						|
 | 
						|
#ifndef NORSCID
 | 
						|
static char rcs_id[] = "$Header$" ;
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
/* Here you find all routines to evaluate expressions and
 | 
						|
   generate code for assignment statements
 | 
						|
*/
 | 
						|
 | 
						|
exprtype(ltype,rtype)
 | 
						|
int	ltype,rtype;
 | 
						|
{
 | 
						|
	/* determine the result type of an expression */
 | 
						|
	if( ltype== STRINGTYPE || rtype==STRINGTYPE)
 | 
						|
	{
 | 
						|
		if( ltype!=rtype)
 | 
						|
			error("type conflict, string expected");
 | 
						|
		return( STRINGTYPE);
 | 
						|
	}
 | 
						|
	/* take maximum */
 | 
						|
	if( ltype<rtype) return(rtype);
 | 
						|
	return(ltype);
 | 
						|
}
 | 
						|
 | 
						|
conversion(oldtype,newtype)
 | 
						|
int oldtype,newtype;
 | 
						|
{
 | 
						|
	/* the value on top of the stack should be converted */
 | 
						|
	if( oldtype==newtype) return;
 | 
						|
	switch( oldtype)
 | 
						|
	{
 | 
						|
	case INTTYPE:
 | 
						|
		if( newtype==FLOATTYPE || newtype==DOUBLETYPE)
 | 
						|
		{
 | 
						|
			emcode("loc",EMINTSIZE);
 | 
						|
			emcode("loc",EMFLTSIZE);
 | 
						|
			emcode("cif","");
 | 
						|
		}else{
 | 
						|
			if(debug) 
 | 
						|
				printf("type n=%d o=%d\n",newtype,oldtype);
 | 
						|
			error("conversion error");
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case FLOATTYPE:
 | 
						|
	case DOUBLETYPE:
 | 
						|
		if( newtype==INTTYPE)
 | 
						|
		{
 | 
						|
			/* rounded ! */
 | 
						|
			emcode("cal","$_cint");
 | 
						|
			emcode("asp",EMFLTSIZE);
 | 
						|
			emcode("lfr",EMINTSIZE);
 | 
						|
			break;
 | 
						|
		}else
 | 
						|
		if( newtype== FLOATTYPE || newtype==DOUBLETYPE)
 | 
						|
			break;
 | 
						|
	default:
 | 
						|
		if(debug) 
 | 
						|
			printf("type n=%d o=%d\n",newtype,oldtype);
 | 
						|
		error("conversion error");
 | 
						|
	}
 | 
						|
}
 | 
						|
extraconvert(oldtype,newtype,topstack)
 | 
						|
int oldtype,newtype,topstack;
 | 
						|
{
 | 
						|
	/* the value below the top of the stack should be converted */
 | 
						|
	if( oldtype==newtype ) return;
 | 
						|
	if( debug) printf("extra convert %d %d %d\n",oldtype,newtype,topstack);
 | 
						|
	/* save top in dummy */
 | 
						|
	switch( topstack)
 | 
						|
	{
 | 
						|
	case INTTYPE:
 | 
						|
		emcode("ste","dummy1");
 | 
						|
		break;
 | 
						|
	case FLOATTYPE:
 | 
						|
	case DOUBLETYPE:
 | 
						|
		/* rounded ! */
 | 
						|
		emcode("lae","dummy1");
 | 
						|
		emcode("sti",EMFLTSIZE);
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		error("conversion error");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	/* now its on top of the stack */
 | 
						|
	conversion(oldtype,newtype);
 | 
						|
	/* restore top */
 | 
						|
	switch( topstack)
 | 
						|
	{
 | 
						|
	case INTTYPE:
 | 
						|
		emcode("loe","dummy1");
 | 
						|
		break;
 | 
						|
	case FLOATTYPE:
 | 
						|
	case DOUBLETYPE:
 | 
						|
		/* rounded ! */
 | 
						|
		emcode("lae","dummy1");
 | 
						|
		emcode("loi",EMFLTSIZE);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
boolop(ltype,rtype,operator)
 | 
						|
int	ltype,rtype,operator;
 | 
						|
{
 | 
						|
	if( operator != NOTSYM)
 | 
						|
	{
 | 
						|
		extraconvert(ltype,INTTYPE,rtype);
 | 
						|
		conversion(rtype,INTTYPE);
 | 
						|
	} else conversion(ltype,INTTYPE);
 | 
						|
	switch( operator)
 | 
						|
	{
 | 
						|
	case NOTSYM:	emcode("com",EMINTSIZE); break;
 | 
						|
	case ANDSYM:	emcode("and",EMINTSIZE); break;
 | 
						|
	case ORSYM:	emcode("ior",EMINTSIZE); break;
 | 
						|
	case XORSYM:	emcode("xor",EMINTSIZE); break;
 | 
						|
	case EQVSYM:
 | 
						|
		emcode("xor",EMINTSIZE);
 | 
						|
		emcode("com",EMINTSIZE);
 | 
						|
		break;
 | 
						|
	case IMPSYM:
 | 
						|
		/* implies */
 | 
						|
		emcode("com",EMINTSIZE);
 | 
						|
		emcode("and",EMINTSIZE);
 | 
						|
		emcode("com",EMINTSIZE);
 | 
						|
		break;
 | 
						|
	default:	error("boolop:unexpected");
 | 
						|
	}
 | 
						|
	return(INTTYPE);
 | 
						|
}
 | 
						|
genbool(opcode)
 | 
						|
char *opcode;
 | 
						|
{
 | 
						|
	int l1,l2;
 | 
						|
	l1= genlabel();
 | 
						|
	l2= genlabel();
 | 
						|
	emcode(opcode,instrlabel(l1));
 | 
						|
	emcode("loc",itoa(0));
 | 
						|
	emcode("bra",instrlabel(l2));
 | 
						|
	fprintf(Tmpfile,"%d\n",l1); emlinecount++;
 | 
						|
	emcode("loc",itoa(-1));
 | 
						|
	fprintf(Tmpfile,"%d\n",l2); emlinecount++;
 | 
						|
}
 | 
						|
relop( ltype,rtype,operator)
 | 
						|
int	ltype,rtype,operator;
 | 
						|
{
 | 
						|
	int	result;
 | 
						|
	if(debug) printf("relop %d %d op=%d\n",ltype,rtype,operator);
 | 
						|
	result= exprtype(ltype,rtype);
 | 
						|
	extraconvert(ltype,result,rtype);
 | 
						|
	conversion(rtype,result);
 | 
						|
	/* compare the objects */
 | 
						|
	if( result== INTTYPE)
 | 
						|
		emcode("cmi", EMINTSIZE);
 | 
						|
	else
 | 
						|
	if( result==FLOATTYPE || result==DOUBLETYPE)
 | 
						|
		emcode("cmf",EMFLTSIZE);
 | 
						|
	else
 | 
						|
	if( result==STRINGTYPE)
 | 
						|
	{
 | 
						|
		emcode("cal","$_strcomp");
 | 
						|
		emcode("asp",EMPTRSIZE);
 | 
						|
		emcode("asp",EMPTRSIZE);
 | 
						|
		emcode("lfr",EMINTSIZE);
 | 
						|
	} else	error("relop:unexpected");
 | 
						|
	/* handle the relational operators */
 | 
						|
	switch(operator)
 | 
						|
	{
 | 
						|
	case '<':	genbool("zlt"); break;
 | 
						|
	case '>':	genbool("zgt"); break;
 | 
						|
	case '=':	genbool("zeq"); break;
 | 
						|
	case NESYM:	genbool("zne"); break;
 | 
						|
	case LESYM:	genbool("zle"); break;
 | 
						|
	case GESYM:	genbool("zge"); break;
 | 
						|
	default:	error("relop:unexpected operator");
 | 
						|
	}
 | 
						|
	return(INTTYPE);
 | 
						|
}
 | 
						|
plusmin(ltype,rtype,operator)
 | 
						|
int	ltype,rtype,operator;
 | 
						|
{
 | 
						|
	int result;
 | 
						|
	result= exprtype(ltype,rtype);
 | 
						|
 | 
						|
	if( result== STRINGTYPE)
 | 
						|
	{
 | 
						|
		if( operator== '+')
 | 
						|
		{
 | 
						|
			emcode("cal","$_concat");
 | 
						|
			emcode("asp",EMPTRSIZE);
 | 
						|
			emcode("asp",EMPTRSIZE);
 | 
						|
			emcode("lfr",EMPTRSIZE);
 | 
						|
		} else error("illegal operator");
 | 
						|
	} else {
 | 
						|
		extraconvert(ltype,result,rtype);
 | 
						|
		conversion(rtype,result);
 | 
						|
		if( result== INTTYPE)
 | 
						|
		{
 | 
						|
			if( operator=='+') 
 | 
						|
				emcode("adi",EMINTSIZE);
 | 
						|
			else	emcode("sbi",EMINTSIZE);
 | 
						|
		} else{
 | 
						|
			if( operator=='+') 
 | 
						|
				emcode("adf",EMFLTSIZE);
 | 
						|
			else	emcode("sbf",EMFLTSIZE);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return(result);
 | 
						|
}
 | 
						|
muldiv(ltype,rtype,operator)
 | 
						|
int	ltype,rtype,operator;
 | 
						|
{
 | 
						|
	int result;
 | 
						|
 | 
						|
	result= exprtype(ltype,rtype);
 | 
						|
	if(operator==MODSYM || operator== '\\') result=INTTYPE;
 | 
						|
	extraconvert(ltype,result,rtype);
 | 
						|
	conversion(rtype,result);
 | 
						|
	if( result== INTTYPE)
 | 
						|
	{
 | 
						|
		if( operator=='/') 
 | 
						|
		{
 | 
						|
			result= DOUBLETYPE;
 | 
						|
			extraconvert(ltype,result,rtype);
 | 
						|
			conversion(rtype,result);
 | 
						|
			emcode("dvf",EMFLTSIZE);
 | 
						|
		} else
 | 
						|
		if( operator=='\\')
 | 
						|
			emcode("dvi",EMINTSIZE);
 | 
						|
		else
 | 
						|
		if( operator=='*') 
 | 
						|
			emcode("mli",EMINTSIZE);
 | 
						|
		else	
 | 
						|
		if( operator==MODSYM)
 | 
						|
			emcode("rmi",EMINTSIZE);
 | 
						|
		else	error("illegal operator");
 | 
						|
	} else{
 | 
						|
		if( operator=='/') 
 | 
						|
			emcode("dvf",EMFLTSIZE);
 | 
						|
		else
 | 
						|
		if( operator=='*') 
 | 
						|
			emcode("mlf",EMFLTSIZE);
 | 
						|
		else	error("illegal operator");
 | 
						|
	}
 | 
						|
	return(result);
 | 
						|
}
 | 
						|
negate(type)
 | 
						|
int type;
 | 
						|
{
 | 
						|
	switch(type)
 | 
						|
	{
 | 
						|
	case INTTYPE:
 | 
						|
		emcode("ngi",EMINTSIZE); break;
 | 
						|
	case DOUBLETYPE:
 | 
						|
	case FLOATTYPE:
 | 
						|
		emcode("ngf",EMFLTSIZE); break;
 | 
						|
	default:
 | 
						|
		error("Illegal operator");
 | 
						|
	}
 | 
						|
	return(type);
 | 
						|
}
 | 
						|
power(ltype,rtype)
 | 
						|
int	ltype,rtype;
 | 
						|
{
 | 
						|
	extraconvert(ltype,DOUBLETYPE,rtype);
 | 
						|
	conversion(rtype,DOUBLETYPE);
 | 
						|
	emcode("cal","$_power");
 | 
						|
	emcode("asp",EMFLTSIZE);
 | 
						|
	emcode("asp",EMFLTSIZE);
 | 
						|
	emcode("lfr",EMFLTSIZE);
 | 
						|
	return(DOUBLETYPE);
 | 
						|
}
 | 
						|
char *typesize(ltype)
 | 
						|
int ltype;
 | 
						|
{
 | 
						|
	switch( ltype)
 | 
						|
	{
 | 
						|
	case INTTYPE:
 | 
						|
		return(EMINTSIZE);
 | 
						|
	case FLOATTYPE:
 | 
						|
	case DOUBLETYPE:
 | 
						|
		return(EMFLTSIZE);
 | 
						|
	case STRINGTYPE:
 | 
						|
		return(EMPTRSIZE);
 | 
						|
	default:
 | 
						|
		error("typesize:unexpected");
 | 
						|
		if(debug) printf("type received %d\n",ltype);
 | 
						|
	}
 | 
						|
	return(EMINTSIZE);
 | 
						|
}
 | 
						|
/*
 | 
						|
loadptr(s)
 | 
						|
Symbol *s;
 | 
						|
{
 | 
						|
	if( POINTERSIZE==WORDSIZE)
 | 
						|
		fprintf(Tmpfile," loe l%d\n",s->symalias);
 | 
						|
	else 
 | 
						|
	if( POINTERSIZE== 2*WORDSIZE)
 | 
						|
		fprintf(Tmpfile," lde l%d\n",s->symalias);
 | 
						|
	else error("loadptr:unexpected pointersize");
 | 
						|
}
 | 
						|
*/
 | 
						|
char *typestring(type)
 | 
						|
int type;
 | 
						|
{
 | 
						|
	switch(type)
 | 
						|
	{
 | 
						|
	case INTTYPE:
 | 
						|
		return(EMINTSIZE);
 | 
						|
	case FLOATTYPE:
 | 
						|
	case DOUBLETYPE:
 | 
						|
		return(EMFLTSIZE);
 | 
						|
	case STRINGTYPE:
 | 
						|
		return(EMPTRSIZE);
 | 
						|
	default:
 | 
						|
		error("typestring: unexpected type");
 | 
						|
	}
 | 
						|
	return("0");
 | 
						|
}
 | 
						|
loadvar(type)
 | 
						|
int type;
 | 
						|
{
 | 
						|
	/* load a simple variable  its address is on the stack*/
 | 
						|
	emcode("loi",typestring(type));
 | 
						|
}
 | 
						|
loadint(value)
 | 
						|
int value;
 | 
						|
{
 | 
						|
	emcode("loc",itoa(value));
 | 
						|
	return(INTTYPE);
 | 
						|
}
 | 
						|
loaddbl(value)
 | 
						|
double value;
 | 
						|
{
 | 
						|
	int index;
 | 
						|
	index= genlabel();
 | 
						|
	fprintf(emfile,"l%d\n bss 8,%fF8,1\n",index,value);
 | 
						|
	emcode("lae",datalabel(index));
 | 
						|
	emcode("loi",EMFLTSIZE);
 | 
						|
	return(DOUBLETYPE);
 | 
						|
}
 | 
						|
loadstr(value)
 | 
						|
int value;
 | 
						|
{
 | 
						|
	emcode("lae",datalabel(value));
 | 
						|
}
 | 
						|
loadaddr(s)
 | 
						|
Symbol *s;
 | 
						|
{
 | 
						|
	extern Symbol *fcn;
 | 
						|
	int i,j;
 | 
						|
 | 
						|
	if(debug) printf("load %s %d\n",s->symname,s->symtype);
 | 
						|
	if( s->symalias>0)
 | 
						|
		emcode("lae",datalabel(s->symalias));
 | 
						|
	else{	
 | 
						|
		j= -s->symalias;
 | 
						|
		if(debug) printf("load parm %d\n",j);
 | 
						|
		fprintf(Tmpfile," lal ");
 | 
						|
		for(i=fcn->dimensions;i>j;i--)
 | 
						|
			fprintf(Tmpfile,"%s+",typesize(fcn->dimlimit[i-1]));
 | 
						|
		fprintf(Tmpfile,"0\n");
 | 
						|
		emlinecount++;
 | 
						|
		/*
 | 
						|
		emcode("lal",datalabel(fcn->dimalias[-s->symalias]));
 | 
						|
		*/
 | 
						|
	}
 | 
						|
	return(s->symtype);
 | 
						|
}
 | 
						|
assign(type,lt)
 | 
						|
int type,lt;
 | 
						|
{
 | 
						|
	extern int e1,e2;
 | 
						|
	conversion(lt,type);
 | 
						|
	exchange(e1,e2);
 | 
						|
	/* address is on stack already */
 | 
						|
	emcode("sti",typestring(type) );
 | 
						|
}
 | 
						|
storevar(lab,type)
 | 
						|
int lab,type;
 | 
						|
{
 | 
						|
	/*store value back */
 | 
						|
	emcode("lae",datalabel(lab));
 | 
						|
	emcode("sti",typestring(type));
 | 
						|
}
 | 
						|
 | 
						|
/* maintain a stack of array references */
 | 
						|
int	dimstk[MAXDIMENSIONS], dimtop= -1;
 | 
						|
Symbol  *arraystk[MAXDIMENSIONS];
 | 
						|
 | 
						|
newarrayload(s)
 | 
						|
Symbol *s;
 | 
						|
{
 | 
						|
	if( dimtop<MAXDIMENSIONS) dimtop++;
 | 
						|
	if( s->dimensions==0)
 | 
						|
	{
 | 
						|
		s->dimensions=1;
 | 
						|
		defarray(s);
 | 
						|
	}
 | 
						|
	dimstk[dimtop]= s->dimensions;
 | 
						|
	arraystk[dimtop]= s;
 | 
						|
	emcode("lae",datalabel(s->symalias));
 | 
						|
}
 | 
						|
endarrayload()
 | 
						|
{
 | 
						|
	return(arraystk[dimtop--]->symtype);
 | 
						|
}
 | 
						|
loadarray(type)
 | 
						|
int	type;
 | 
						|
{
 | 
						|
	int	dim;
 | 
						|
	Symbol	*s;
 | 
						|
 | 
						|
	if( dimtop<0 || dimtop>=MAXDIMENSIONS)
 | 
						|
		fatal("too many nested array references");
 | 
						|
	/* index expression is on top of stack */
 | 
						|
	s=arraystk[dimtop];
 | 
						|
	dim= dimstk[dimtop];
 | 
						|
	if( dim==0)
 | 
						|
	{
 | 
						|
		error("too many indices");
 | 
						|
		dimstk[dim--]=0;
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	conversion(type,INTTYPE);
 | 
						|
	dim--;
 | 
						|
	/* first check index range */
 | 
						|
	fprintf(Tmpfile," lae r%d\n",s->dimalias[dim]);
 | 
						|
	emlinecount++;
 | 
						|
	emcode("rck",EMINTSIZE);
 | 
						|
	emcode("lae",datalabel(s->dimalias[dim]));
 | 
						|
	emcode("aar",EMINTSIZE);
 | 
						|
	dimstk[dimtop]--;
 | 
						|
}
 | 
						|
storearray(type)
 | 
						|
{
 | 
						|
	/* used only in let statement */
 | 
						|
	extern int e1,e2;
 | 
						|
	exchange(e1,e2);
 | 
						|
	emcode("sti",typestring(type));
 | 
						|
}
 |