* Copyright (c) 1980 The Regents of the University of California.
* This module is believed to contain source code proprietary to AT&T.
* Use and redistribution is subject to the Berkeley Software License
* Agreement and your Software Agreement with AT&T (Western Electric).
static char sccsid
[] = "@(#)putpcc.c 5.3 (Berkeley) 4/12/91";
* Intermediate code generation for S. C. Johnson C compilers
* New version using binary polish postfix intermediate
* University of Utah CS Dept modification history:
* $Header: putpcc.c,v 3.2 85/03/25 09:35:57 root Exp $
* Revision 3.2 85/03/25 09:35:57 root
* fseek return -1 on error.
* Revision 3.1 85/02/27 19:06:55 donn
* Changed to use pcc.h instead of pccdefs.h.
* Revision 2.12 85/02/22 01:05:54 donn
* putaddr() didn't know about intrinsic functions...
* Revision 2.11 84/11/28 21:28:49 donn
* Hacked putop() to handle any character expression being converted to int,
* not just function calls. Previously it bombed on concatenations.
* Revision 2.10 84/11/01 22:07:07 donn
* Yet another try at getting putop() to work right. It appears that the
* second pass can't abide certain explicit conversions (e.g. short to long)
* so the conversion code in putop() tries to remove them. I think this
* version (finally) works.
* Revision 2.9 84/10/29 02:30:57 donn
* Earlier fix to putop() for conversions was insufficient -- we NEVER want to
* see the type of the left operand of the thing left over from stripping off
* Revision 2.8 84/09/18 03:09:21 donn
* Fixed bug in putop() where the left operand of an addrblock was being
* extracted... This caused an extremely obscure conversion error when
* an array of longs was subscripted by a short.
* Revision 2.7 84/08/19 20:10:19 donn
* Removed stuff in putbranch that treats STGARG parameters specially -- the
* bug in the code generation pass that motivated it has been fixed.
* Revision 2.6 84/08/07 21:32:23 donn
* Bumped the size of the buffer for the intermediate code file from 0.5K
* Revision 2.5 84/08/04 20:26:43 donn
* Fixed a goof in the new putbranch() -- it now calls mkaltemp instead of
* mktemp(). Correction due to Jerry Berkman.
* Revision 2.4 84/07/24 19:07:15 donn
* Fixed bug reported by Craig Leres in which putmnmx() mistakenly assumed
* that mkaltemp() returns tempblocks, and tried to free them with frtemp().
* Revision 2.3 84/07/19 17:22:09 donn
* Changed putch1() so that OPPAREN expressions of type CHARACTER are legal.
* Revision 2.2 84/07/19 12:30:38 donn
* Fixed a type clash in Bob Corbett's new putbranch().
* Revision 2.1 84/07/19 12:04:27 donn
* Changed comment headers for UofU.
* Revision 1.8 84/07/19 11:38:23 donn
* Replaced putbranch() routine so that you can ASSIGN into argument variables.
* The code is from Bob Corbett, donated by Jerry Berkman.
* Revision 1.7 84/05/31 00:48:32 donn
* Fixed an extremely obscure bug dealing with the comparison of CHARACTER*1
* expressions -- a foulup in the order of COMOP and the comparison caused
* one operand of the comparison to be garbage.
* Revision 1.6 84/04/16 09:54:19 donn
* Backed out earlier fix for bug where items in the argtemplist were
* (incorrectly) being given away; this is now fixed in mkargtemp().
* Revision 1.5 84/03/23 22:49:48 donn
* Took out the initialization of the subroutine argument temporary list in
* putcall() -- it needs to be done once per statement instead of once per call.
* Revision 1.4 84/03/01 06:48:05 donn
* Fixed bug in Bob Corbett's code for argument temporaries that caused an
* addrblock to get thrown out inadvertently when it was needed for recycling
* Revision 1.3 84/02/26 06:32:38 donn
* Added Berkeley changes to move data definitions around and reduce offsets.
* Revision 1.2 84/02/26 06:27:45 donn
* Added code to catch TTEMP values passed to putx().
Addrp
putcall(), putcxeq(), putcx1(), realpart();
#if HERE==VAX || HERE == TAHOE
static long int p2buff
[PCC_BUFFMAX
];
static long int *p2bufp
= &p2buff
[0];
static long int *p2bufend
= &p2buff
[PCC_BUFFMAX
];
#if TARGET == VAX || TARGET == TAHOE
p2ps("\t.globl\t_%s", s
);
/* put out fake copy of left bracket line, to be redone later */
headoffset
= ftell(textfile
);
p2triple(PCCF_FEXPR
, (strlen(infname
)+ALILONG
-1)/ALILONG
, 0);
/* fake jump to start the optimizer */
putgoto( fudgelabel
= newlabel() );
#if TARGET == VAX || TARGET == TAHOE
/* jump from top to bottom */
if(s
!=CNULL
&& class!=CLBLOCK
)
int proflab
= newlabel();
p2pi("\t.word\tLWM%d", procno
);
fudgelabel
= newlabel());
/* It is necessary to precede each procedure with a "left bracket"
* line that tells pass 2 how many register variables and how
* much automatic space is required for the function. This compiler
* does not know how much automatic space is needed until the
* entire procedure has been processed. Therefore, "puthead"
* is called at the begining to record the current location in textfile,
* then to put out a placeholder left bracket line. This procedure
* repositions the file and rewrites that line, then puts the
* file pointer back to the end of the file.
hereoffset
= ftell(textfile
);
if(fseek(textfile
, headoffset
, 0) == -1)
if(fseek(textfile
, hereoffset
, 0) == -1)
p2triple(PCCF_FEXPR
, 0, lineno
);
/* put out code for if( ! p) goto l */
if( ( k
= (p
= fixtype(p
))->headblock
.vtype
) != TYLOGICAL
)
err("non-logical expression in IF statement");
p2icon( (long int) l
, PCCT_INT
);
/* put out code for goto l */
p2triple(PCC_GOTO
, 1, label
);
/* branch to address constant or integer variable */
p2op(PCC_GOTO
, PCCT_INT
);
p2op(PCCF_FLABEL
, label
);
putcmgo(index
, nlab
, labs
)
struct Labelblock
*labs
[];
int i
, labarray
, skiplabel
;
if(! ISINT(index
->headblock
.vtype
) )
execerr("computed goto index must be integer", CNULL
);
#if TARGET == VAX || TARGET == TAHOE
/* use special case instruction */
casegoto(index
, nlab
, labs
);
prlabel(asmfile
, labarray
);
prcona(asmfile
, (ftnint
) (skiplabel
= newlabel()) );
for(i
= 0 ; i
< nlab
; ++i
)
prcona(asmfile
, (ftnint
)(labs
[i
]->labelno
) );
prcmgoto(index
, nlab
, skiplabel
, labarray
);
switch(type
= p
->constblock
.vtype
)
p2icon(p
->constblock
.constant
.ci
, types2
[type
]);
p2triple(PCC_ICON
, 1, PCCT_INT
|PCCTM_PTR
);
(int) p
->constblock
.constant
.ci
) );
switch(opc
= p
->exprblock
.opcode
)
if( ISCOMPLEX(p
->exprblock
.vtype
) )
if(ISCOMPLEX(p
->exprblock
.leftp
->headblock
.vtype
)
|| ISCOMPLEX(p
->exprblock
.rightp
->headblock
.vtype
) )
if( ISCOMPLEX(p
->exprblock
.leftp
->headblock
.vtype
) ||
ISCOMPLEX(p
->exprblock
.rightp
->headblock
.vtype
) )
if(ISCHAR(p
->exprblock
.leftp
))
if(INT(p
->exprblock
.leftp
->headblock
.vtype
) &&
ISICON(p
->exprblock
.rightp
) &&
( (k
= log2(p
->exprblock
.rightp
->constblock
.constant
.ci
))>0) )
p
->exprblock
.opcode
= OPLSHIFT
;
frexpr(p
->exprblock
.rightp
);
p
->exprblock
.rightp
= ICON(k
);
if( ISCOMPLEX(p
->exprblock
.vtype
) )
if( ISCOMPLEX(p
->exprblock
.vtype
) )
else if( ISCOMPLEX(p
->exprblock
.leftp
->headblock
.vtype
) )
putx( mkconv(p
->exprblock
.vtype
,
realpart(putcx1(p
->exprblock
.leftp
,
putcomma(ncomma
, p
->exprblock
.vtype
, NO
);
putx (p
->exprblock
.leftp
);
* This type is sometimes passed to putx when errors occur
* upstream, I don't know why.
switch(p
->exprblock
.opcode
) /* check for special cases and rewrite */
tt
= pt
= p
->exprblock
.vtype
;
lt
= lp
->headblock
.vtype
;
if (pt
== TYREAL
&& lt
== TYDREAL
)
p2op(PCC_SCONV
, PCCT_FLOAT
);
while(p
->tag
==TEXPR
&& p
->exprblock
.opcode
==OPCONV
&& (
(ISREAL(pt
)&&ISREAL(lt
)) ||
(INT(pt
)&&(ONEOF(lt
,MSKINT
|MSKADDR
|MSKCHAR
|M(TYSUBR
)))) ))
if(pt
==TYINT
&& lt
==TYLONG
)
if(lt
==TYINT
&& pt
==TYLONG
)
if(pt
==TYDREAL
&& lt
==TYREAL
)
lp
->exprblock
.opcode
==OPCONV
&&
lp
->exprblock
.leftp
->headblock
.vtype
==TYDREAL
)
putx(lp
->exprblock
.leftp
);
p2op(PCC_SCONV
, PCCT_FLOAT
);
p2op(PCC_SCONV
, PCCT_DOUBLE
);
if(lt
==TYCHAR
&& lp
->tag
==TEXPR
)
p
->exprblock
.leftp
= (expptr
) putch1(lp
, &ncomma
);
putcomma(ncomma
, pt
, NO
);
lt
= lp
->headblock
.vtype
;
if(p
->tag
==TEXPR
&& p
->exprblock
.opcode
==OPCONV
)
if (types2
[tt
] != types2
[pt
] &&
! ( (ISREAL(tt
)&&ISREAL(pt
)) ||
(INT(tt
)&&(ONEOF(pt
,MSKINT
|MSKADDR
|MSKCHAR
|M(TYSUBR
)))) ))
p2op(PCC_SCONV
,types2
[tt
]);
(lp
->headblock
.vtype
,lp
->headblock
.vleng
);
putx( mkexpr(OPASSIGN
, cpexpr(tp
), lp
) );
#if TARGET == VAX || TARGET == TAHOE
/* take advantage of a glitch in the code generator that does not check
the type clash in an assignment or comparison of an integer zero and
a floating left operand, and generates optimal code for the correct
type. (The PCC has no floating-constant node to encode this correctly.)
if(ISREAL(p
->exprblock
.leftp
->headblock
.vtype
) &&
ISREAL(p
->exprblock
.rightp
->headblock
.vtype
) &&
ISCONST(p
->exprblock
.rightp
) &&
p
->exprblock
.rightp
->constblock
.constant
.cd
[0]==0)
p
->exprblock
.rightp
->constblock
.vtype
= TYINT
;
p
->exprblock
.rightp
->constblock
.constant
.ci
= 0;
if( (k
= ops2
[p
->exprblock
.opcode
]) <= 0)
badop("putop", p
->exprblock
.opcode
);
putx(p
->exprblock
.leftp
);
putx(p
->exprblock
.rightp
);
p2op(k
, types2
[p
->exprblock
.vtype
]);
frexpr(p
->exprblock
.vleng
);
p
= mkconv(t
, fixtype(p
));
(t
==TYLONG
? PCCT_LONG
: (t
==TYREAL
? PCCT_FLOAT
: PCCT_DOUBLE
)) );
(t
==TYSHORT
? PCCT_SHORT
: (t
==TYLONG
? PCCT_LONG
: PCCT_DOUBLE
)) );
if(!ISICON(p
->exprblock
.rightp
) ||
(k
= p
->exprblock
.rightp
->constblock
.constant
.ci
)<2)
fatal("putpower: bad call");
base
= p
->exprblock
.leftp
;
type
= base
->headblock
.vtype
;
if ((k
== 2) && base
->tag
== TADDR
&& ISCONST(base
->addrblock
.memoffset
))
putx( mkexpr(OPSTAR
,cpexpr(base
),cpexpr(base
)));
t1
= mkaltemp(type
, PNULL
);
putassign(cpexpr(t1
), cpexpr(base
) );
for( ; (k
&1)==0 && k
>2 ; k
>>=1 )
putx( mkexpr(OPSTAR
, cpexpr(t1
), cpexpr(t1
)) );
t2
= mkaltemp(type
, PNULL
);
putassign(cpexpr(t2
), cpexpr(t1
));
putx( mkexpr(OPSTAR
, cpexpr(t2
),
mkexpr(OPSTAR
, cpexpr(t1
), cpexpr(t1
)) ));
putcomma(ncomma
, type
, NO
);
LOCAL Addrp
intdouble(p
, ncommap
)
t
= mkaltemp(TYDREAL
, PNULL
);
badtag("putcxeq", p
->tag
);
lp
= putcx1(p
->exprblock
.leftp
, &ncomma
);
rp
= putcx1(p
->exprblock
.rightp
, &ncomma
);
putassign(realpart(lp
), realpart(rp
));
if( ISCOMPLEX(p
->exprblock
.vtype
) )
putassign(imagpart(lp
), imagpart(rp
));
putcomma(ncomma
, TYREAL
, NO
);
putaddr( putcx1(p
, &ncomma
), NO
);
putcomma(ncomma
, TYINT
, NO
);
LOCAL Addrp
putcx1(p
, ncommap
)
if( ISCOMPLEX(p
->constblock
.vtype
) )
p
= (expptr
) putconst(p
);
resp
= mkaltemp(tyint
, PNULL
);
putassign( cpexpr(resp
), p
->addrblock
.memoffset
);
p
->addrblock
.memoffset
= (expptr
)resp
;
if( ISCOMPLEX(p
->exprblock
.vtype
) )
resp
= mkaltemp(TYDREAL
, NO
);
putassign( cpexpr(resp
), p
);
badtag("putcx1", p
->tag
);
opcode
= p
->exprblock
.opcode
;
if(opcode
==OPCALL
|| opcode
==OPCCALL
)
else if(opcode
== OPASSIGN
)
resp
= mkaltemp(p
->exprblock
.vtype
, PNULL
);
if(lp
= putcx1(p
->exprblock
.leftp
, ncommap
) )
if(rp
= putcx1(p
->exprblock
.rightp
, ncommap
) )
putassign( realpart(resp
), mkexpr(OPNEG
, realpart(lp
), ENULL
) );
putassign( imagpart(resp
), mkexpr(OPNEG
, imagpart(lp
), ENULL
) );
putassign( realpart(resp
),
mkexpr(opcode
, realpart(lp
), realpart(rp
) ));
putassign( imagpart(resp
), imagpart(lp
) );
else if(ltype
< TYCOMPLEX
)
putassign( imagpart(resp
), imagpart(rp
) );
else putassign( imagpart(resp
),
mkexpr(OPNEG
, imagpart(rp
), ENULL
) );
putassign( imagpart(resp
),
mkexpr(opcode
, imagpart(lp
), imagpart(rp
) ));
lp
= intdouble(lp
, ncommap
);
putassign( realpart(resp
),
mkexpr(OPSTAR
, cpexpr(lp
), realpart(rp
) ));
putassign( imagpart(resp
),
mkexpr(OPSTAR
, cpexpr(lp
), imagpart(rp
) ));
else if(rtype
< TYCOMPLEX
)
rp
= intdouble(rp
, ncommap
);
putassign( realpart(resp
),
mkexpr(OPSTAR
, cpexpr(rp
), realpart(lp
) ));
putassign( imagpart(resp
),
mkexpr(OPSTAR
, cpexpr(rp
), imagpart(lp
) ));
putassign( realpart(resp
), mkexpr(OPMINUS
,
mkexpr(OPSTAR
, realpart(lp
), realpart(rp
)),
mkexpr(OPSTAR
, imagpart(lp
), imagpart(rp
)) ));
putassign( imagpart(resp
), mkexpr(OPPLUS
,
mkexpr(OPSTAR
, realpart(lp
), imagpart(rp
)),
mkexpr(OPSTAR
, imagpart(lp
), realpart(rp
)) ));
/* fixexpr has already replaced all divisions
* by a complex by a function call
rp
= intdouble(rp
, ncommap
);
putassign( realpart(resp
),
mkexpr(OPSLASH
, realpart(lp
), cpexpr(rp
)) );
putassign( imagpart(resp
),
mkexpr(OPSLASH
, imagpart(lp
), cpexpr(rp
)) );
putassign( realpart(resp
), realpart(lp
) );
if( ISCOMPLEX(lp
->vtype
) )
q
= (expptr
) realpart(rp
);
q
= mkrealcon(TYDREAL
, 0.0);
putassign( imagpart(resp
), q
);
badtag("putcxcmp", p
->tag
);
opcode
= p
->exprblock
.opcode
;
lp
= putcx1(p
->exprblock
.leftp
, &ncomma
);
rp
= putcx1(p
->exprblock
.rightp
, &ncomma
);
q
= mkexpr( opcode
==OPEQ
? OPAND
: OPOR
,
mkexpr(opcode
, realpart(lp
), realpart(rp
)),
mkexpr(opcode
, imagpart(lp
), imagpart(rp
)) );
putcomma(ncomma
, TYINT
, NO
);
LOCAL Addrp
putch1(p
, ncommap
)
switch(p
->exprblock
.opcode
)
t
= putch1(p
->exprblock
.leftp
, ncommap
);
t
= mkaltemp(TYCHAR
, ICON(lencat(p
)) );
q
= (expptr
) cpexpr(p
->headblock
.vleng
);
/* put the correct length on the block */
if(!ISICON(p
->exprblock
.vleng
)
|| p
->exprblock
.vleng
->constblock
.constant
.ci
!=1
|| ! INT(p
->exprblock
.leftp
->headblock
.vtype
) )
fatal("putch1: bad character conversion");
t
= mkaltemp(TYCHAR
, ICON(1) );
putop( mkexpr(OPASSIGN
, cpexpr(t
), p
) );
badop("putch1", p
->exprblock
.opcode
);
badtag("putch1", p
->tag
);
putaddr( putch1(p
, &ncomma
) , NO
);
putcomma(ncomma
, TYCHAR
, YES
);
badtag("putcheq", p
->tag
);
rp
= p
->exprblock
.rightp
;
if( rp
->tag
==TEXPR
&& rp
->exprblock
.opcode
==OPCONCAT
)
else if( ISONE(lp
->headblock
.vleng
) && ISONE(rp
->headblock
.vleng
) )
putaddr( putch1(lp
, &ncomma
) , YES
);
putaddr( putch1(rp
, &ncomma
) , YES
);
putcomma(ncomma
, TYINT
, NO
);
p2op(PCC_ASSIGN
, PCCT_CHAR
);
putx( call2(TYINT
, "s_copy", lp
, rp
) );
putcomma(ncomma
, TYINT
, NO
);
frexpr(p
->exprblock
.vleng
);
badtag("putchcmp", p
->tag
);
rp
= p
->exprblock
.rightp
;
if(ISONE(lp
->headblock
.vleng
) && ISONE(rp
->headblock
.vleng
) )
putaddr( putch1(lp
, &ncomma
) , YES
);
putcomma(ncomma
, TYINT
, NO
);
putaddr( putch1(rp
, &ncomma
) , YES
);
putcomma(ncomma
, TYINT
, NO
);
p2op(ops2
[p
->exprblock
.opcode
], PCCT_CHAR
);
p
->exprblock
.leftp
= call2(TYINT
,"s_cmp", lp
, rp
);
p
->exprblock
.rightp
= ICON(0);
lp
= mkaltmpn(n
, TYLENG
, PNULL
);
cp
= mkaltmpn(n
, TYADDR
, PNULL
);
putct1(rhs
, lp
, cp
, &n
, &ncomma
);
putx( call4(TYSUBR
, "s_cat", lhs
, cp
, lp
, mkconv(TYLONG
, ICON(n
)) ) );
putcomma(ncomma
, TYINT
, NO
);
LOCAL
putct1(q
, lp
, cp
, ip
, ncommap
)
if(q
->tag
==TEXPR
&& q
->exprblock
.opcode
==OPCONCAT
)
putct1(q
->exprblock
.leftp
, lp
, cp
, ip
, ncommap
);
putct1(q
->exprblock
.rightp
, lp
, cp
, ip
, ncommap
);
frexpr(q
->exprblock
.vleng
);
lp1
= (Addrp
) cpexpr(lp
);
lp1
->memoffset
= mkexpr(OPPLUS
,lp1
->memoffset
, ICON(i
*SZLENG
));
cp1
= (Addrp
) cpexpr(cp
);
cp1
->memoffset
= mkexpr(OPPLUS
, cp1
->memoffset
, ICON(i
*SZADDR
));
putassign( lp1
, cpexpr(q
->headblock
.vleng
) );
putassign( cp1
, addrof(putch1(q
,ncommap
)) );
ftnint offset
, simoffset();
if( p
->tag
==TERROR
|| (p
->memoffset
!=NULL
&& ISERROR(p
->memoffset
)) )
if (p
->tag
!= TADDR
) badtag ("putaddr",p
->tag
);
funct
= (p
->vclass
==CLPROC
? PCCTM_FTN
<<2 : 0);
offp
= (p
->memoffset
? (expptr
) cpexpr(p
->memoffset
) : (expptr
)NULL
);
offp
= mkexpr(OPSTAR
, ICON(FUDGEOFFSET
), offp
);
offset
= simoffset( &offp
);
offp
= mkconv(TYINT
, offp
);
offp
= mkconv(TYINT
, offp
);
&& (p
->vstg
== STGBSS
|| p
->vstg
== STGEQUIV
)
&& offset
>= -32768 && offset
<= 32767)
p2ldisp(offset
, memname(p
->vstg
, p
->memno
), type2
);
p2reg(LVARREG
, type2
| PCCTM_PTR
);
p2triple(PCC_ICON
, 1, PCCT_INT
);
p2ndisp(memname(p
->vstg
, p
->memno
));
p2op(PCC_PLUS
, type2
| PCCTM_PTR
);
p2op(PCC_PLUS
, type2
| PCCTM_PTR
);
p2oreg(offset
, AUTOREG
, type2
);
if(!indir
&& !offp
&& !offset
)
p2reg(AUTOREG
, type2
| PCCTM_PTR
);
p2reg(AUTOREG
, type2
| PCCTM_PTR
);
p2icon(offset
, PCCT_INT
);
p2icon(offset
, PCCT_INT
);
p2op(PCC_PLUS
, type2
| PCCTM_PTR
);
p2op(PCC_PLUS
, type2
| PCCTM_PTR
);
(ftnint
) (FUDGEOFFSET
*p
->memno
),
ARGREG
, type2
| PCCTM_PTR
| funct
);
p2icon(offset
, PCCT_INT
);
p2op(PCC_PLUS
, type2
| PCCTM_PTR
);
p2op(PCC_PLUS
, type2
| PCCTM_PTR
);
(ftnint
) (FUDGEOFFSET
*p
->memno
),
p2reg(ARGREG
, type2
| PCCTM_PTR
);
(ftnint
) (FUDGEOFFSET
*p
->memno
), PCCT_INT
);
p2op(PCC_PLUS
, type2
| PCCTM_PTR
);
putmem(p
, PCC_ICON
, offset
);
p2op(PCC_PLUS
, type2
| PCCTM_PTR
);
putmem(p
, (indir
? PCC_NAME
: PCC_ICON
), offset
);
fatal("attempt to take address of a register");
p2oreg(offset
, p
->memno
, type2
);
p2reg(p
->memno
, type2
| PCCTM_PTR
);
badstg("putaddr", p
->vstg
);
LOCAL
putmem(p
, class, offset
)
funct
= (p
->headblock
.vclass
==CLPROC
? PCCTM_FTN
<<2 : 0);
type2
= types2
[p
->headblock
.vtype
];
if(p
->headblock
.vclass
== CLPROC
)
name
= memname(p
->addrblock
.vstg
, p
->addrblock
.memno
);
p2triple(PCC_ICON
, name
[0]!='\0', type2
|PCCTM_PTR
);
p2triple(PCC_NAME
, offset
!=0, type2
);
chainp arglist
, charsp
, cp
;
int type
, type2
, ctype
, qtype
, indir
;
type2
= types2
[type
= p
->vtype
];
indir
= (p
->opcode
== OPCCALL
);
arglist
= p
->rightp
->listblock
.listp
;
free( (charptr
) (p
->rightp
) );
for(cp
= arglist
; cp
; cp
= cp
->nextp
)
q
= (expptr
) (cp
->datap
);
q
= (expptr
) putconst(q
);
if( ISCHAR(q
) && q
->headblock
.vclass
!=CLPROC
)
mkchain(cpexpr(q
->headblock
.vleng
),
fval
= mkargtemp(TYCHAR
, p
->vleng
);
err("adjustable character function");
else if( ISCOMPLEX(type
) )
fval
= mkargtemp(type
, PNULL
);
ctype
= (fval
? PCCT_INT
: type2
);
putaddr( cpexpr(fval
), NO
);
putx( mkconv(TYLENG
,p
->vleng
) );
for(cp
= arglist
; cp
; cp
= cp
->nextp
)
q
= (expptr
) (cp
->datap
);
if(q
->tag
==TADDR
&& (indir
|| q
->addrblock
.vstg
!=STGREG
) )
putaddr(q
, indir
&& q
->addrblock
.vtype
!=TYCHAR
);
else if( ISCOMPLEX(q
->headblock
.vtype
) )
t
= mkargtemp(qtype
= q
->headblock
.vtype
,
putassign( cpexpr(t
), q
);
for(cp
= charsp
; cp
; cp
= cp
->nextp
)
putx( mkconv(TYLENG
,cp
->datap
) );
if(indir
&& ctype
==PCCT_FLOAT
) /* function opcodes */
p2op(PCC_FORTCALL
, ctype
);
p2op(n
>0 ? PCC_CALL
: PCC_UCALL
, ctype
);
badtag("putmnmx", p
->tag
);
type
= p
->exprblock
.vtype
;
op
= (p
->exprblock
.opcode
==OPMIN
? OPLT
: OPGT
);
p0
= p
->exprblock
.leftp
->listblock
.listp
;
free( (charptr
) (p
->exprblock
.leftp
) );
sp
= mkaltemp(type
, PNULL
);
tp
= mkaltemp(type
, PNULL
);
qp
= mkexpr(OPCOLON
, cpexpr(tp
), cpexpr(sp
));
qp
= mkexpr(OPQUEST
, mkexpr(op
, cpexpr(tp
),cpexpr(sp
)), qp
);
putassign( cpexpr(sp
), p0
->datap
);
for(p1
= p0
->nextp
; p1
; p1
= p1
->nextp
)
putassign( cpexpr(tp
), p1
->datap
);
putassign( cpexpr(sp
), cpexpr(qp
) );
putcomma(ncomma
, type
, NO
);
LOCAL
putcomma(n
, type
, indir
)
register expptr p
, lp
, rp
;
if( ! ISINT(p
->headblock
.vtype
) )
if(p
->tag
==TEXPR
&& p
->exprblock
.opcode
==OPSTAR
)
rp
= p
->exprblock
.rightp
;
if(ISICON(rp
) && lp
->tag
==TEXPR
&&
lp
->exprblock
.opcode
==OPPLUS
&& ISICON(lp
->exprblock
.rightp
))
p
->exprblock
.opcode
= OPPLUS
;
lp
->exprblock
.opcode
= OPSTAR
;
prod
= rp
->constblock
.constant
.ci
*
lp
->exprblock
.rightp
->constblock
.constant
.ci
;
lp
->exprblock
.rightp
->constblock
.constant
.ci
= rp
->constblock
.constant
.ci
;
rp
->constblock
.constant
.ci
= prod
;
if(p
->tag
==TEXPR
&& p
->exprblock
.opcode
==OPPLUS
&&
ISICON(p
->exprblock
.rightp
))
rp
= p
->exprblock
.rightp
;
offset
+= rp
->constblock
.constant
.ci
;
offset
+= p
->constblock
.constant
.ci
;
p2triple(PCC_ICON
, 0, type
);
p2oreg(offset
, reg
, type
)
p2triple(PCC_OREG
, reg
, type
);
p2triple(PCC_REG
, reg
, type
);
p2triple(PCCF_FTEXT
, (strlen(s
) + ALILONG
-1)/ALILONG
, 0);
union { long int word
; char str
[SZLONG
]; } u
;
word
= PCCM_TRIPLE(op
, var
, type
);
/* arbitrary length names, terminated by a null,
# define WL sizeof(long int)
union { long int word
; char str
[WL
]; } w
;
/* standard intermediate, names are 8 characters long */
union { long int word
[2]; char str
[8]; } u
;
u
.word
[0] = u
.word
[1] = 0;
for(i
= 0 ; i
<8 && *s
; ++i
)
write(fileno(textfile
), p2buff
, (p2bufp
-p2buff
)*sizeof(long int));
p2ldisp(offset
, vname
, type
)
sprintf(buff
, "%s-v.%d", vname
, bsslabel
);
p2triple(PCC_OREG
, LVARREG
, type
);
sprintf(buff
, "%s-v.%d", vname
, bsslabel
);