399 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			399 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/****************************************************************
 | 
						|
Copyright 1990 by AT&T Bell Laboratories and Bellcore.
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this software
 | 
						|
and its documentation for any purpose and without fee is hereby
 | 
						|
granted, provided that the above copyright notice appear in all
 | 
						|
copies and that both that the copyright notice and this
 | 
						|
permission notice and warranty disclaimer appear in supporting
 | 
						|
documentation, and that the names of AT&T Bell Laboratories or
 | 
						|
Bellcore or any of their entities not be used in advertising or
 | 
						|
publicity pertaining to distribution of the software without
 | 
						|
specific, written prior permission.
 | 
						|
 | 
						|
AT&T and Bellcore disclaim all warranties with regard to this
 | 
						|
software, including all implied warranties of merchantability
 | 
						|
and fitness.  In no event shall AT&T or Bellcore be liable for
 | 
						|
any special, indirect or consequential damages or any damages
 | 
						|
whatsoever resulting from loss of use, data or profits, whether
 | 
						|
in an action of contract, negligence or other tortious action,
 | 
						|
arising out of or in connection with the use or performance of
 | 
						|
this software.
 | 
						|
****************************************************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * INTERMEDIATE CODE GENERATION PROCEDURES COMMON TO BOTH
 | 
						|
 * JOHNSON (PORTABLE) AND RITCHIE FAMILIES OF SECOND PASSES
 | 
						|
*/
 | 
						|
 | 
						|
#include "defs.h"
 | 
						|
#include "names.h"		/* For LOCAL_CONST_NAME */
 | 
						|
#include "pccdefs.h"
 | 
						|
#include "p1defs.h"
 | 
						|
 | 
						|
/* Definitions for   putconst()   */
 | 
						|
 | 
						|
#define LIT_CHAR 1
 | 
						|
#define LIT_FLOAT 2
 | 
						|
#define LIT_INT 3
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
char *ops [ ] =
 | 
						|
	{
 | 
						|
	"??", "+", "-", "*", "/", "**", "-",
 | 
						|
	"OR", "AND", "EQV", "NEQV", "NOT",
 | 
						|
	"CONCAT",
 | 
						|
	"<", "==", ">", "<=", "!=", ">=",
 | 
						|
	" of ", " ofC ", " = ", " += ", " *= ", " CONV ", " << ", " % ",
 | 
						|
	" , ", " ? ", " : "
 | 
						|
	" abs ", " min ", " max ", " addr ", " indirect ",
 | 
						|
	" bitor ", " bitand ", " bitxor ", " bitnot ", " >> ",
 | 
						|
	};
 | 
						|
*/
 | 
						|
 | 
						|
/* Each of these values is defined in   pccdefs   */
 | 
						|
 | 
						|
int ops2 [ ] =
 | 
						|
{
 | 
						|
	P2BAD, P2PLUS, P2MINUS, P2STAR, P2SLASH, P2BAD, P2NEG,
 | 
						|
	P2OROR, P2ANDAND, P2EQ, P2NE, P2NOT,
 | 
						|
	P2BAD,
 | 
						|
	P2LT, P2EQ, P2GT, P2LE, P2NE, P2GE,
 | 
						|
	P2CALL, P2CALL, P2ASSIGN, P2PLUSEQ, P2STAREQ, P2CONV, P2LSHIFT, P2MOD,
 | 
						|
	P2COMOP, P2QUEST, P2COLON,
 | 
						|
	1, P2BAD, P2BAD, P2BAD, P2BAD,
 | 
						|
	P2BITOR, P2BITAND, P2BITXOR, P2BITNOT, P2RSHIFT,
 | 
						|
	P2BAD, P2BAD, P2BAD, P2BAD, P2BAD, P2BAD, P2BAD, P2BAD, P2BAD,
 | 
						|
	P2BAD, P2BAD, P2BAD, P2BAD,
 | 
						|
	1,1,1,1,1, /* OPNEG1, OPDMIN, OPDMAX, OPASSIGNI, OPIDENTITY */
 | 
						|
	1,1,1,1	/* OPCHARCAST, OPDABS, OPMIN2, OPMAX2 */
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
int types2 [ ] =
 | 
						|
{
 | 
						|
	P2BAD, P2INT|P2PTR, P2SHORT, P2LONG, P2REAL, P2DREAL,
 | 
						|
	P2REAL, P2DREAL, P2LONG, P2CHAR, P2INT, P2BAD
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
setlog()
 | 
						|
{
 | 
						|
	types2[TYLOGICAL] = types2[tylogical];
 | 
						|
	typesize[TYLOGICAL] = typesize[tylogical];
 | 
						|
	typealign[TYLOGICAL] = typealign[tylogical];
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void putex1(p)
 | 
						|
expptr p;
 | 
						|
{
 | 
						|
/* Write the expression to the p1 file */
 | 
						|
 | 
						|
	p = (expptr) putx (fixtype (p));
 | 
						|
	p1_expr (p);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
expptr putassign(lp, rp)
 | 
						|
expptr lp, rp;
 | 
						|
{
 | 
						|
	return putx(fixexpr((Exprp)mkexpr(OPASSIGN, lp, rp)));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void puteq(lp, rp)
 | 
						|
expptr lp, rp;
 | 
						|
{
 | 
						|
	putexpr(mkexpr(OPASSIGN, lp, rp) );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* put code for  a *= b */
 | 
						|
 | 
						|
expptr putsteq(a, b)
 | 
						|
Addrp a, b;
 | 
						|
{
 | 
						|
	return putx( fixexpr((Exprp)
 | 
						|
		mkexpr(OPSTAREQ, cpexpr((expptr)a), cpexpr((expptr)b))));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
Addrp mkfield(res, f, ty)
 | 
						|
register Addrp res;
 | 
						|
char *f;
 | 
						|
int ty;
 | 
						|
{
 | 
						|
    res -> vtype = ty;
 | 
						|
    res -> Field = f;
 | 
						|
    return res;
 | 
						|
} /* mkfield */
 | 
						|
 | 
						|
 | 
						|
Addrp realpart(p)
 | 
						|
register Addrp p;
 | 
						|
{
 | 
						|
	register Addrp q;
 | 
						|
	expptr mkrealcon();
 | 
						|
 | 
						|
	if (p -> uname_tag == UNAM_CONST && ISCOMPLEX (p->vtype)) {
 | 
						|
		return (Addrp)mkrealcon (p -> vtype + TYREAL - TYCOMPLEX,
 | 
						|
			p->user.kludge.vstg1 ? p->user.Const.cds[0]
 | 
						|
				: cds(dtos(p->user.Const.cd[0]),CNULL));
 | 
						|
	} /* if p -> uname_tag */
 | 
						|
 | 
						|
	q = (Addrp) cpexpr((expptr) p);
 | 
						|
	if( ISCOMPLEX(p->vtype) )
 | 
						|
		q = mkfield (q, "r", p -> vtype + TYREAL - TYCOMPLEX);
 | 
						|
 | 
						|
	return(q);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
expptr imagpart(p)
 | 
						|
register Addrp p;
 | 
						|
{
 | 
						|
	register Addrp q;
 | 
						|
	expptr mkrealcon();
 | 
						|
 | 
						|
	if( ISCOMPLEX(p->vtype) )
 | 
						|
	{
 | 
						|
		if (p -> uname_tag == UNAM_CONST)
 | 
						|
			return mkrealcon (p -> vtype + TYREAL - TYCOMPLEX,
 | 
						|
				p->user.kludge.vstg1 ? p->user.Const.cds[1]
 | 
						|
				: cds(dtos(p->user.Const.cd[1]),CNULL));
 | 
						|
		q = (Addrp) cpexpr((expptr) p);
 | 
						|
		q = mkfield (q, "i", p -> vtype + TYREAL - TYCOMPLEX);
 | 
						|
		return( (expptr) q );
 | 
						|
	}
 | 
						|
	else
 | 
						|
 | 
						|
/* Cast an integer type onto a Double Real type */
 | 
						|
 | 
						|
		return( mkrealcon( ISINT(p->vtype) ? TYDREAL : p->vtype , "0"));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* ncat -- computes the number of adjacent concatenation operations */
 | 
						|
 | 
						|
ncat(p)
 | 
						|
register expptr p;
 | 
						|
{
 | 
						|
	if(p->tag==TEXPR && p->exprblock.opcode==OPCONCAT)
 | 
						|
		return( ncat(p->exprblock.leftp) + ncat(p->exprblock.rightp) );
 | 
						|
	else	return(1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* lencat -- returns the length of the concatenated string.  Each
 | 
						|
   substring must have a static (i.e. compile-time) fixed length */
 | 
						|
 | 
						|
ftnint lencat(p)
 | 
						|
register expptr p;
 | 
						|
{
 | 
						|
	if(p->tag==TEXPR && p->exprblock.opcode==OPCONCAT)
 | 
						|
		return( lencat(p->exprblock.leftp) + lencat(p->exprblock.rightp) );
 | 
						|
	else if( p->headblock.vleng!=NULL && ISICON(p->headblock.vleng) )
 | 
						|
		return(p->headblock.vleng->constblock.Const.ci);
 | 
						|
	else if(p->tag==TADDR && p->addrblock.varleng!=0)
 | 
						|
		return(p->addrblock.varleng);
 | 
						|
	else
 | 
						|
	{
 | 
						|
		err("impossible element in concatenation");
 | 
						|
		return(0);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* putconst -- Creates a new Addrp value which maps onto the input
 | 
						|
   constant value.  The Addrp doesn't retain the value of the constant,
 | 
						|
   instead that value is copied into a table of constants (called
 | 
						|
   litpool,   for pool of literal values).  The only way to retrieve the
 | 
						|
   actual value of the constant is to look at the   memno   field of the
 | 
						|
   Addrp result.  You know that the associated literal is the one referred
 | 
						|
   to by   q   when   (q -> memno == litp -> litnum).
 | 
						|
*/
 | 
						|
 | 
						|
Addrp putconst(p)
 | 
						|
register Constp p;
 | 
						|
{
 | 
						|
	register Addrp q;
 | 
						|
	struct Literal *litp, *lastlit;
 | 
						|
	int k, len, type;
 | 
						|
	int litflavor;
 | 
						|
	double cd[2];
 | 
						|
	ftnint nblanks;
 | 
						|
	char *strp;
 | 
						|
	char cdsbuf0[64], cdsbuf1[64], *ds[2];
 | 
						|
 | 
						|
	if (p->tag != TCONST)
 | 
						|
		badtag("putconst", p->tag);
 | 
						|
 | 
						|
	q = ALLOC(Addrblock);
 | 
						|
	q->tag = TADDR;
 | 
						|
	type = p->vtype;
 | 
						|
	q->vtype = ( type==TYADDR ? tyint : type );
 | 
						|
	q->vleng = (expptr) cpexpr(p->vleng);
 | 
						|
	q->vstg = STGCONST;
 | 
						|
 | 
						|
/* Create the new label for the constant.  This is wasteful of labels
 | 
						|
   because when the constant value already exists in the literal pool,
 | 
						|
   this label gets thrown away and is never reclaimed.  It might be
 | 
						|
   cleaner to move this down past the first   switch()   statement below */
 | 
						|
 | 
						|
	q->memno = newlabel();
 | 
						|
	q->memoffset = ICON(0);
 | 
						|
	q -> uname_tag = UNAM_CONST;
 | 
						|
 | 
						|
/* Copy the constant info into the Addrblock; do this by copying the
 | 
						|
   largest storage elts */
 | 
						|
 | 
						|
	q -> user.Const = p -> Const;
 | 
						|
	q->user.kludge.vstg1 = p->vstg;	/* distinguish string from binary fp */
 | 
						|
 | 
						|
	/* check for value in literal pool, and update pool if necessary */
 | 
						|
 | 
						|
	k = 1;
 | 
						|
	switch(type)
 | 
						|
	{
 | 
						|
	case TYCHAR:
 | 
						|
		if (halign) {
 | 
						|
			strp = p->Const.ccp;
 | 
						|
			nblanks = p->Const.ccp1.blanks;
 | 
						|
			len = p->vleng->constblock.Const.ci;
 | 
						|
			litflavor = LIT_CHAR;
 | 
						|
			goto loop;
 | 
						|
			}
 | 
						|
		else
 | 
						|
			q->memno = BAD_MEMNO;
 | 
						|
		break;
 | 
						|
	case TYCOMPLEX:
 | 
						|
	case TYDCOMPLEX:
 | 
						|
		k = 2;
 | 
						|
		if (p->vstg)
 | 
						|
			cd[1] = atof(ds[1] = p->Const.cds[1]);
 | 
						|
		else
 | 
						|
			ds[1] = cds(dtos(cd[1] = p->Const.cd[1]), cdsbuf1);
 | 
						|
	case TYREAL:
 | 
						|
	case TYDREAL:
 | 
						|
		litflavor = LIT_FLOAT;
 | 
						|
		if (p->vstg)
 | 
						|
			cd[0] = atof(ds[0] = p->Const.cds[0]);
 | 
						|
		else
 | 
						|
			ds[0] = cds(dtos(cd[0] = p->Const.cd[0]), cdsbuf0);
 | 
						|
		goto loop;
 | 
						|
 | 
						|
	case TYLOGICAL:
 | 
						|
		type = tylogical;
 | 
						|
		goto lit_int_flavor;
 | 
						|
	case TYLONG:
 | 
						|
		type = tyint;
 | 
						|
	case TYSHORT:
 | 
						|
 lit_int_flavor:
 | 
						|
		litflavor = LIT_INT;
 | 
						|
 | 
						|
/* Scan the literal pool for this constant value.  If this same constant
 | 
						|
   has been assigned before, use the same label.  Note that this routine
 | 
						|
   does NOT consider two differently-typed constants with the same bit
 | 
						|
   pattern to be the same constant */
 | 
						|
 | 
						|
 loop:
 | 
						|
		lastlit = litpool + nliterals;
 | 
						|
		for(litp = litpool ; litp<lastlit ; ++litp)
 | 
						|
 | 
						|
/* Remove this type checking to ensure that all bit patterns are reused */
 | 
						|
 | 
						|
			if(type == litp->littype) switch(litflavor)
 | 
						|
			{
 | 
						|
			case LIT_CHAR:
 | 
						|
				if (len == (int)litp->litval.litival2[0]
 | 
						|
				&& nblanks == litp->litval.litival2[1]
 | 
						|
				&& !memcmp(strp, litp->cds[0], len)) {
 | 
						|
					q->memno = litp->litnum;
 | 
						|
					frexpr((expptr)p);
 | 
						|
					return(q);
 | 
						|
					}
 | 
						|
				break;
 | 
						|
			case LIT_FLOAT:
 | 
						|
				if(cd[0] == litp->litval.litdval[0]
 | 
						|
				&& !strcmp(ds[0], litp->cds[0])
 | 
						|
				&& (k == 1 ||
 | 
						|
				    cd[1] == litp->litval.litdval[1]
 | 
						|
				    && !strcmp(ds[1], litp->cds[1]))) {
 | 
						|
ret:
 | 
						|
					q->memno = litp->litnum;
 | 
						|
					frexpr((expptr)p);
 | 
						|
					return(q);
 | 
						|
					}
 | 
						|
				break;
 | 
						|
 | 
						|
			case LIT_INT:
 | 
						|
				if(p->Const.ci == litp->litval.litival)
 | 
						|
					goto ret;
 | 
						|
				break;
 | 
						|
			}
 | 
						|
 | 
						|
/* If there's room in the literal pool, add this new value to the pool */
 | 
						|
 | 
						|
		if(nliterals < maxliterals)
 | 
						|
		{
 | 
						|
			++nliterals;
 | 
						|
 | 
						|
			/* litp   now points to the next free elt */
 | 
						|
 | 
						|
			litp->littype = type;
 | 
						|
			litp->litnum = q->memno;
 | 
						|
			switch(litflavor)
 | 
						|
			{
 | 
						|
			case LIT_CHAR:
 | 
						|
				litp->litval.litival2[0] = len;
 | 
						|
				litp->litval.litival2[1] = nblanks;
 | 
						|
				q->user.Const.ccp = litp->cds[0] =
 | 
						|
					memcpy(gmem(len,0), strp, len);
 | 
						|
				break;
 | 
						|
 | 
						|
			case LIT_FLOAT:
 | 
						|
				litp->litval.litdval[0] = cd[0];
 | 
						|
				litp->cds[0] = copys(ds[0]);
 | 
						|
				if (k == 2) {
 | 
						|
					litp->litval.litdval[1] = cd[1];
 | 
						|
					litp->cds[1] = copys(ds[1]);
 | 
						|
					}
 | 
						|
				break;
 | 
						|
 | 
						|
			case LIT_INT:
 | 
						|
				litp->litval.litival = p->Const.ci;
 | 
						|
				break;
 | 
						|
			} /* switch (litflavor) */
 | 
						|
		}
 | 
						|
		else
 | 
						|
			many("literal constants", 'L', maxliterals);
 | 
						|
 | 
						|
		break;
 | 
						|
	case TYADDR:
 | 
						|
	    break;
 | 
						|
	default:
 | 
						|
		badtype ("putconst", p -> vtype);
 | 
						|
		break;
 | 
						|
	} /* switch */
 | 
						|
 | 
						|
	if (type != TYCHAR || halign)
 | 
						|
	    frexpr((expptr)p);
 | 
						|
	return( q );
 | 
						|
}
 |