325 lines
		
	
	
	
		
			7.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			325 lines
		
	
	
	
		
			7.5 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.
 | 
						|
****************************************************************/
 | 
						|
 | 
						|
#include "defs.h"
 | 
						|
#include "pccdefs.h"
 | 
						|
#include "output.h"
 | 
						|
 | 
						|
int regnum[] =  {
 | 
						|
	11, 10, 9, 8, 7, 6 };
 | 
						|
 | 
						|
/* Put out a constant integer */
 | 
						|
 | 
						|
prconi(fp, n)
 | 
						|
FILEP fp;
 | 
						|
ftnint n;
 | 
						|
{
 | 
						|
	fprintf(fp, "\t%ld\n", n);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Put out a constant address */
 | 
						|
 | 
						|
prcona(fp, a)
 | 
						|
FILEP fp;
 | 
						|
ftnint a;
 | 
						|
{
 | 
						|
	fprintf(fp, "\tL%ld\n", a);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
prconr(fp, x, k)
 | 
						|
 FILEP fp;
 | 
						|
 int k;
 | 
						|
 Constp x;
 | 
						|
{
 | 
						|
	char *x0, *x1;
 | 
						|
	char cdsbuf0[64], cdsbuf1[64];
 | 
						|
 | 
						|
	if (k > 1) {
 | 
						|
		if (x->vstg) {
 | 
						|
			x0 = x->Const.cds[0];
 | 
						|
			x1 = x->Const.cds[1];
 | 
						|
			}
 | 
						|
		else {
 | 
						|
			x0 = cds(dtos(x->Const.cd[0]), cdsbuf0);
 | 
						|
			x1 = cds(dtos(x->Const.cd[1]), cdsbuf1);
 | 
						|
			}
 | 
						|
		fprintf(fp, "\t%s %s\n", x0, x1);
 | 
						|
		}
 | 
						|
	else
 | 
						|
		fprintf(fp, "\t%s\n", x->vstg ? x->Const.cds[0]
 | 
						|
				: cds(dtos(x->Const.cd[0]), cdsbuf0));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
char *memname(stg, mem)
 | 
						|
 int stg;
 | 
						|
 long mem;
 | 
						|
{
 | 
						|
	static char s[20];
 | 
						|
 | 
						|
	switch(stg)
 | 
						|
	{
 | 
						|
	case STGCOMMON:
 | 
						|
	case STGEXT:
 | 
						|
		sprintf(s, "_%s", extsymtab[mem].cextname);
 | 
						|
		break;
 | 
						|
 | 
						|
	case STGBSS:
 | 
						|
	case STGINIT:
 | 
						|
		sprintf(s, "v.%ld", mem);
 | 
						|
		break;
 | 
						|
 | 
						|
	case STGCONST:
 | 
						|
		sprintf(s, "L%ld", mem);
 | 
						|
		break;
 | 
						|
 | 
						|
	case STGEQUIV:
 | 
						|
		sprintf(s, "q.%ld", mem+eqvstart);
 | 
						|
		break;
 | 
						|
 | 
						|
	default:
 | 
						|
		badstg("memname", stg);
 | 
						|
	}
 | 
						|
	return(s);
 | 
						|
}
 | 
						|
 | 
						|
/* make_int_expr -- takes an arbitrary expression, and replaces all
 | 
						|
   occurrences of arguments with indirection */
 | 
						|
 | 
						|
expptr make_int_expr (e)
 | 
						|
expptr e;
 | 
						|
{
 | 
						|
    if (e != ENULL)
 | 
						|
	switch (e -> tag) {
 | 
						|
	    case TADDR:
 | 
						|
	        if (e -> addrblock.vstg == STGARG)
 | 
						|
		    e = mkexpr (OPWHATSIN, e, ENULL);
 | 
						|
	        break;
 | 
						|
	    case TEXPR:
 | 
						|
	        e -> exprblock.leftp = make_int_expr (e -> exprblock.leftp);
 | 
						|
	        e -> exprblock.rightp = make_int_expr (e -> exprblock.rightp);
 | 
						|
	        break;
 | 
						|
	    default:
 | 
						|
	        break;
 | 
						|
	} /* switch */
 | 
						|
 | 
						|
    return e;
 | 
						|
} /* make_int_expr */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* prune_left_conv -- used in prolog() to strip type cast away from
 | 
						|
   left-hand side of parameter adjustments.  This is necessary to avoid
 | 
						|
   error messages from cktype() */
 | 
						|
 | 
						|
expptr prune_left_conv (e)
 | 
						|
expptr e;
 | 
						|
{
 | 
						|
    struct Exprblock *leftp;
 | 
						|
 | 
						|
    if (e && e -> tag == TEXPR && e -> exprblock.leftp &&
 | 
						|
	    e -> exprblock.leftp -> tag == TEXPR) {
 | 
						|
	leftp = &(e -> exprblock.leftp -> exprblock);
 | 
						|
	if (leftp -> opcode == OPCONV) {
 | 
						|
	    e -> exprblock.leftp = leftp -> leftp;
 | 
						|
	    free ((charptr) leftp);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    return e;
 | 
						|
} /* prune_left_conv */
 | 
						|
 | 
						|
 | 
						|
 static int wrote_comment;
 | 
						|
 static FILE *comment_file;
 | 
						|
 | 
						|
 static void
 | 
						|
write_comment()
 | 
						|
{
 | 
						|
	if (!wrote_comment) {
 | 
						|
		wrote_comment = 1;
 | 
						|
		nice_printf (comment_file, "/* Parameter adjustments */\n");
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 static int *
 | 
						|
count_args()
 | 
						|
{
 | 
						|
	register int *ac;
 | 
						|
	register chainp cp;
 | 
						|
	register struct Entrypoint *ep;
 | 
						|
	register Namep q;
 | 
						|
 | 
						|
	ac = (int *)ckalloc(nallargs*sizeof(int));
 | 
						|
 | 
						|
	for(ep = entries; ep; ep = ep->entnextp)
 | 
						|
		for(cp = ep->arglist; cp; cp = cp->nextp)
 | 
						|
			if (q = (Namep)cp->datap)
 | 
						|
				ac[q->argno]++;
 | 
						|
	return ac;
 | 
						|
	}
 | 
						|
 | 
						|
prolog(outfile, p)
 | 
						|
 FILE *outfile;
 | 
						|
 register chainp p;
 | 
						|
{
 | 
						|
	int addif, addif0, i, nd, size;
 | 
						|
	int *ac;
 | 
						|
	register Namep q;
 | 
						|
	register struct Dimblock *dp;
 | 
						|
 | 
						|
	if(procclass == CLBLOCK)
 | 
						|
		return;
 | 
						|
	wrote_comment = 0;
 | 
						|
	comment_file = outfile;
 | 
						|
	ac = 0;
 | 
						|
 | 
						|
/* Compute the base addresses and offsets for the array parameters, and
 | 
						|
   assign these values to local variables */
 | 
						|
 | 
						|
	addif = addif0 = nentry > 1;
 | 
						|
	for(; p ; p = p->nextp)
 | 
						|
	{
 | 
						|
	    q = (Namep) p->datap;
 | 
						|
	    if(dp = q->vdim)	/* if this param is an array ... */
 | 
						|
	    {
 | 
						|
		expptr Q, expr;
 | 
						|
 | 
						|
		/* See whether to protect the following with an if. */
 | 
						|
		/* This only happens when there are multiple entries. */
 | 
						|
 | 
						|
		nd = dp->ndim - 1;
 | 
						|
		if (addif0) {
 | 
						|
			if (!ac)
 | 
						|
				ac = count_args();
 | 
						|
			if (ac[q->argno] == nentry)
 | 
						|
				addif = 0;
 | 
						|
			else if (dp->basexpr
 | 
						|
				    || dp->baseoffset->constblock.Const.ci)
 | 
						|
				addif = 1;
 | 
						|
			else for(addif = i = 0; i <= nd; i++)
 | 
						|
				if (dp->dims[i].dimexpr
 | 
						|
				&& (i < nd || !q->vlastdim)) {
 | 
						|
					addif = 1;
 | 
						|
					break;
 | 
						|
					}
 | 
						|
			if (addif) {
 | 
						|
				write_comment();
 | 
						|
				nice_printf(outfile, "if (%s) {\n", /*}*/
 | 
						|
						q->cvarname);
 | 
						|
				next_tab(outfile);
 | 
						|
				}
 | 
						|
			}
 | 
						|
		for(i = 0 ; i <= nd; ++i)
 | 
						|
 | 
						|
/* Store the variable length of each dimension (which is fixed upon
 | 
						|
   runtime procedure entry) into a local variable */
 | 
						|
 | 
						|
		    if ((Q = dp->dims[i].dimexpr)
 | 
						|
			&& (i < nd || !q->vlastdim)) {
 | 
						|
			expr = (expptr)cpexpr(Q);
 | 
						|
			write_comment();
 | 
						|
			out_and_free_statement (outfile, mkexpr (OPASSIGN,
 | 
						|
				fixtype(cpexpr(dp->dims[i].dimsize)), expr));
 | 
						|
		    } /* if dp -> dims[i].dimexpr */
 | 
						|
 | 
						|
/* size   will equal the size of a single element, or -1 if the type is
 | 
						|
   variable length character type */
 | 
						|
 | 
						|
		size = typesize[ q->vtype ];
 | 
						|
		if(q->vtype == TYCHAR)
 | 
						|
		    if( ISICON(q->vleng) )
 | 
						|
			size *= q->vleng->constblock.Const.ci;
 | 
						|
		    else
 | 
						|
			size = -1;
 | 
						|
 | 
						|
		/* Fudge the argument pointers for arrays so subscripts
 | 
						|
		 * are 0-based. Not done if array bounds are being checked.
 | 
						|
		 */
 | 
						|
		if(dp->basexpr) {
 | 
						|
 | 
						|
/* Compute the base offset for this procedure */
 | 
						|
 | 
						|
		    write_comment();
 | 
						|
		    out_and_free_statement (outfile, mkexpr (OPASSIGN,
 | 
						|
			    cpexpr(fixtype(dp->baseoffset)),
 | 
						|
			    cpexpr(fixtype(dp->basexpr))));
 | 
						|
		} /* if dp -> basexpr */
 | 
						|
 | 
						|
		if(! checksubs) {
 | 
						|
		    if(dp->basexpr) {
 | 
						|
			expptr tp;
 | 
						|
 | 
						|
/* If the base of this array has a variable adjustment ... */
 | 
						|
 | 
						|
			tp = (expptr) cpexpr (dp -> baseoffset);
 | 
						|
			if(size < 0 || q -> vtype == TYCHAR)
 | 
						|
			    tp = mkexpr (OPSTAR, tp, cpexpr (q -> vleng));
 | 
						|
 | 
						|
			write_comment();
 | 
						|
			tp = mkexpr (OPMINUSEQ,
 | 
						|
				mkconv (TYADDR, (expptr)p->datap),
 | 
						|
				mkconv(TYINT, fixtype
 | 
						|
				(fixtype (tp))));
 | 
						|
/* Avoid type clash by removing the type conversion */
 | 
						|
			tp = prune_left_conv (tp);
 | 
						|
			out_and_free_statement (outfile, tp);
 | 
						|
		    } else if(dp->baseoffset->constblock.Const.ci != 0) {
 | 
						|
 | 
						|
/* if the base of this array has a nonzero constant adjustment ... */
 | 
						|
 | 
						|
			expptr tp;
 | 
						|
 | 
						|
			write_comment();
 | 
						|
			if(size > 0 && q -> vtype != TYCHAR) {
 | 
						|
			    tp = prune_left_conv (mkexpr (OPMINUSEQ,
 | 
						|
				    mkconv (TYADDR, (expptr)p->datap),
 | 
						|
				    mkconv (TYINT, fixtype
 | 
						|
				    (cpexpr (dp->baseoffset)))));
 | 
						|
			    out_and_free_statement (outfile, tp);
 | 
						|
			} else {
 | 
						|
			    tp = prune_left_conv (mkexpr (OPMINUSEQ,
 | 
						|
				    mkconv (TYADDR, (expptr)p->datap),
 | 
						|
				    mkconv (TYINT, fixtype
 | 
						|
				    (mkexpr (OPSTAR, cpexpr (dp -> baseoffset),
 | 
						|
				    cpexpr (q -> vleng))))));
 | 
						|
			    out_and_free_statement (outfile, tp);
 | 
						|
			} /* else */
 | 
						|
		    } /* if dp -> baseoffset -> const */
 | 
						|
		} /* if !checksubs */
 | 
						|
 | 
						|
		if (addif) {
 | 
						|
			nice_printf(outfile, /*{*/ "}\n");
 | 
						|
			prev_tab(outfile);
 | 
						|
			}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	if (wrote_comment)
 | 
						|
	    nice_printf (outfile, "\n/* Function Body */\n");
 | 
						|
	if (ac)
 | 
						|
		free((char *)ac);
 | 
						|
} /* prolog */
 |