537 lines
9.2 KiB
C
537 lines
9.2 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[] = "$Id$" ;
|
|
#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)
|
|
{
|
|
C_loc((arith)BEMINTSIZE);
|
|
C_loc((arith)BEMFLTSIZE);
|
|
C_cif ();
|
|
} else {
|
|
if (debug)
|
|
print("type n=%d o=%d\n",newtype,oldtype);
|
|
error("conversion error");
|
|
}
|
|
break;
|
|
case FLOATTYPE:
|
|
case DOUBLETYPE:
|
|
if ( newtype==INTTYPE)
|
|
{
|
|
/* rounded ! */
|
|
C_cal("_cint");
|
|
C_asp((arith)BEMFLTSIZE);
|
|
C_lfr((arith)BEMINTSIZE);
|
|
break;
|
|
} else if ( newtype==FLOATTYPE || newtype==DOUBLETYPE)
|
|
break;
|
|
default:
|
|
if (debug)
|
|
print("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) print("extra convert %d %d %d\n",oldtype,newtype,topstack);
|
|
/* save top in dummy */
|
|
|
|
switch( topstack)
|
|
{
|
|
case INTTYPE:
|
|
C_ste_dnam("dummy1",(arith)0);
|
|
break;
|
|
case FLOATTYPE:
|
|
case DOUBLETYPE:
|
|
/* rounded ! */
|
|
C_lae_dnam("dummy1",(arith)0);
|
|
C_sti((arith)BEMFLTSIZE);
|
|
break;
|
|
default:
|
|
error("conversion error");
|
|
return;
|
|
}
|
|
/* now its on top of the stack */
|
|
|
|
conversion(oldtype,newtype);
|
|
/* restore top */
|
|
|
|
switch( topstack)
|
|
{
|
|
case INTTYPE:
|
|
C_loe_dnam("dummy1",(arith)0);
|
|
break;
|
|
case FLOATTYPE:
|
|
case DOUBLETYPE:
|
|
/* rounded ! */
|
|
C_lae_dnam("dummy1",(arith)0);
|
|
C_loi((arith)BEMFLTSIZE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
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:
|
|
C_com((arith)BEMINTSIZE);
|
|
break;
|
|
case ANDSYM:
|
|
C_and((arith)BEMINTSIZE);
|
|
break;
|
|
case ORSYM:
|
|
C_ior((arith)BEMINTSIZE);
|
|
break;
|
|
case XORSYM:
|
|
C_xor((arith)BEMINTSIZE);
|
|
break;
|
|
case EQVSYM:
|
|
C_xor((arith)BEMINTSIZE);
|
|
C_com((arith)BEMINTSIZE);
|
|
break;
|
|
case IMPSYM:
|
|
/* implies */
|
|
C_com((arith)BEMINTSIZE);
|
|
C_and((arith)BEMINTSIZE);
|
|
C_com((arith)BEMINTSIZE);
|
|
break;
|
|
default:
|
|
error("boolop:unexpected");
|
|
}
|
|
|
|
return(INTTYPE);
|
|
}
|
|
|
|
|
|
|
|
genbool(operator)
|
|
int operator;
|
|
{
|
|
int l1,l2;
|
|
|
|
l1= genlabel();
|
|
l2= genlabel();
|
|
|
|
switch(operator)
|
|
{
|
|
case '<': C_zlt((label)l1); break;
|
|
case '>': C_zgt((label)l1); break;
|
|
case '=': C_zeq((label)l1); break;
|
|
case NESYM: C_zne((label)l1); break;
|
|
case LESYM: C_zle((label)l1); break;
|
|
case GESYM: C_zge((label)l1); break;
|
|
default: error("relop:unexpected operator");
|
|
}
|
|
|
|
C_loc((arith)0);
|
|
C_bra((label)l2);
|
|
C_df_ilb((label)l1);
|
|
C_loc((arith)-1);
|
|
C_df_ilb((label)l2);
|
|
}
|
|
|
|
|
|
|
|
relop( ltype,rtype,operator)
|
|
int ltype,rtype,operator;
|
|
{
|
|
int result;
|
|
|
|
if (debug) print("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)
|
|
C_cmi((arith)BEMINTSIZE);
|
|
else if ( result==FLOATTYPE || result==DOUBLETYPE)
|
|
C_cmf((arith)BEMFLTSIZE);
|
|
else if ( result==STRINGTYPE)
|
|
{
|
|
C_cal("_strcomp");
|
|
C_asp((arith)(2*BEMPTRSIZE));
|
|
C_lfr((arith)BEMINTSIZE);
|
|
} else error("relop:unexpected");
|
|
/* handle the relational operators */
|
|
genbool(operator);
|
|
return(INTTYPE);
|
|
}
|
|
|
|
|
|
|
|
plusmin(ltype,rtype,operator)
|
|
int ltype,rtype,operator;
|
|
{
|
|
int result;
|
|
|
|
result= exprtype(ltype,rtype);
|
|
if ( result== STRINGTYPE)
|
|
{
|
|
if ( operator== '+')
|
|
{
|
|
C_cal("_concat");
|
|
C_asp((arith)(2*BEMPTRSIZE));
|
|
C_lfr((arith)BEMPTRSIZE);
|
|
} else error("illegal operator");
|
|
} else {
|
|
extraconvert(ltype,result,rtype);
|
|
conversion(rtype,result);
|
|
if ( result== INTTYPE)
|
|
{
|
|
if ( operator=='+')
|
|
C_adi((arith)BEMINTSIZE);
|
|
else C_sbi((arith)BEMINTSIZE);
|
|
} else {
|
|
if ( operator=='+')
|
|
C_adf((arith)BEMFLTSIZE);
|
|
else C_sbf((arith)BEMFLTSIZE);
|
|
}
|
|
}
|
|
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);
|
|
C_dvf((arith)BEMFLTSIZE);
|
|
} else
|
|
if ( operator=='\\')
|
|
C_dvi((arith)BEMINTSIZE);
|
|
else
|
|
if ( operator=='*')
|
|
C_mli((arith)BEMINTSIZE);
|
|
else
|
|
if ( operator==MODSYM)
|
|
C_rmi((arith)BEMINTSIZE);
|
|
else error("illegal operator");
|
|
} else {
|
|
if ( operator=='/')
|
|
C_dvf((arith)BEMFLTSIZE);
|
|
else
|
|
if ( operator=='*')
|
|
C_mlf((arith)BEMFLTSIZE);
|
|
else error("illegal operator");
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
|
|
|
|
negate(type)
|
|
int type;
|
|
{
|
|
switch(type)
|
|
{
|
|
case INTTYPE:
|
|
C_ngi((arith)BEMINTSIZE);
|
|
break;
|
|
case DOUBLETYPE:
|
|
case FLOATTYPE:
|
|
C_ngf((arith)BEMFLTSIZE);
|
|
break;
|
|
default:
|
|
error("Illegal operator");
|
|
}
|
|
return(type);
|
|
}
|
|
|
|
|
|
|
|
#ifdef ___
|
|
power(ltype,rtype)
|
|
int ltype,rtype;
|
|
{
|
|
int resulttype = exprtype(ltype, rtype);
|
|
|
|
extraconvert(ltype,resulttype,rtype);
|
|
conversion(rtype,resulttype);
|
|
switch(resulttype) {
|
|
case INTTYPE:
|
|
C_cal("_ipower");
|
|
break;
|
|
case DOUBLETYPE:
|
|
case FLOATTYPE:
|
|
C_cal("_power");
|
|
break;
|
|
default:
|
|
error("Illegal operator");
|
|
}
|
|
C_asp((arith)(2*typestring(resulttype)));
|
|
C_lfr((arith)typestring(resulttype));
|
|
return(resulttype);
|
|
}
|
|
#else
|
|
power(ltype,rtype)
|
|
int ltype,rtype;
|
|
{
|
|
extraconvert(ltype,DOUBLETYPE,rtype);
|
|
conversion(rtype,DOUBLETYPE);
|
|
C_cal("_power");
|
|
C_asp((arith)(2*BEMFLTSIZE));
|
|
C_lfr((arith)BEMFLTSIZE);
|
|
return(DOUBLETYPE);
|
|
}
|
|
#endif
|
|
|
|
|
|
int typesize(ltype)
|
|
int ltype;
|
|
{
|
|
switch( ltype)
|
|
{
|
|
case INTTYPE:
|
|
return(BEMINTSIZE);
|
|
case FLOATTYPE:
|
|
case DOUBLETYPE:
|
|
return(BEMFLTSIZE);
|
|
case STRINGTYPE:
|
|
return(BEMPTRSIZE);
|
|
default:
|
|
error("typesize:unexpected");
|
|
if (debug) print("type received %d\n",ltype);
|
|
}
|
|
return(BEMINTSIZE);
|
|
}
|
|
|
|
|
|
|
|
int typestring(type)
|
|
int type;
|
|
{
|
|
switch(type)
|
|
{
|
|
case INTTYPE:
|
|
return(BEMINTSIZE);
|
|
case FLOATTYPE:
|
|
case DOUBLETYPE:
|
|
return(BEMFLTSIZE);
|
|
case STRINGTYPE:
|
|
return(BEMPTRSIZE);
|
|
default:
|
|
error("typestring: unexpected type");
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
|
|
loadvar(type)
|
|
int type;
|
|
{
|
|
/* load a simple variable its address is on the stack*/
|
|
C_loi((arith)typestring(type));
|
|
}
|
|
|
|
|
|
|
|
loadint(value)
|
|
int value;
|
|
{
|
|
C_loc((arith)value);
|
|
return(INTTYPE);
|
|
}
|
|
|
|
|
|
|
|
loaddbl(value)
|
|
char *value;
|
|
{
|
|
int index;
|
|
|
|
index=genlabel();
|
|
C_df_dlb((label)index);
|
|
C_bss_fcon((arith)BEMFLTSIZE,value,(arith)BEMFLTSIZE,1);
|
|
C_lae_dlb((label)index,(arith)0);
|
|
C_loi((arith)BEMFLTSIZE);
|
|
return(DOUBLETYPE);
|
|
}
|
|
|
|
|
|
|
|
loadstr(value)
|
|
int value;
|
|
{
|
|
C_lae_dlb((label)value,(arith)0);
|
|
}
|
|
|
|
|
|
|
|
loadaddr(s)
|
|
Symbol *s;
|
|
{
|
|
extern Symbol *fcn;
|
|
int i,j;
|
|
arith sum;
|
|
|
|
if (debug) print("load %s %d\n",s->symname,s->symtype);
|
|
if ( s->symalias>0)
|
|
C_lae_dlb((label)s->symalias,(arith)0);
|
|
else {
|
|
j= -s->symalias;
|
|
if (debug) print("load parm %d\n",j);
|
|
/* first count the sizes. */
|
|
sum = 0;
|
|
for(i=fcn->dimensions;i>j;i--)
|
|
sum += typesize(fcn->dimlimit[i-1]);
|
|
C_lal(sum);
|
|
}
|
|
return(s->symtype);
|
|
}
|
|
|
|
|
|
|
|
/* This is a new routine */
|
|
save_address()
|
|
{
|
|
C_lae_dnam("dummy3",(arith)0);
|
|
C_sti((arith)BEMPTRSIZE);
|
|
}
|
|
|
|
|
|
|
|
assign(type,lt)
|
|
int type,lt;
|
|
{
|
|
extern int e1,e2;
|
|
|
|
conversion(lt,type);
|
|
C_lae_dnam("dummy3",(arith)0); /* Statement added by us */
|
|
C_loi((arith)BEMPTRSIZE);
|
|
/* address is on stack already */
|
|
C_sti((arith)typestring(type));
|
|
}
|
|
|
|
|
|
|
|
storevar(lab,type)
|
|
int lab,type;
|
|
{
|
|
/*store value back */
|
|
C_lae_dlb((label)lab,(arith)0);
|
|
C_sti((arith)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]= 0;
|
|
arraystk[dimtop]= s;
|
|
C_lae_dlb((label)s->symalias,(arith)0);
|
|
}
|
|
|
|
|
|
|
|
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>=s->dimensions)
|
|
{
|
|
error("too many indices");
|
|
dimstk[dimtop]=0;
|
|
return;
|
|
}
|
|
conversion(type,INTTYPE);
|
|
C_lae_dlb((label)s->dimalias[dim],(arith)0);
|
|
C_aar((arith)BEMINTSIZE);
|
|
dimstk[dimtop]++;
|
|
}
|
|
|
|
|
|
|