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));
 | |
| }
 |