326 lines
7.5 KiB
C
326 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 */
|