static char sccsid
[] = "@(#)local.c 1.4 (Berkeley) %G%";
/* this file contains code which is dependent on the target machine */
clocal(p
) register NODE
*p
; {
/* this is called to do local transformations on
an expression tree preparitory to its being
written out in intermediate code.
/* the major essential job is rewriting the
automatic variables and arguments in terms of
/* conversion ops which are not necessary are also clobbered here */
/* in addition, any special features (such as rewriting
exclusive or) are easily handled here as well */
register struct symtab
*q
;
if( p
->tn
.rval
< 0 ) { /* already processed; ignore... */
/* fake up a structure reference */
r
= block( REG
, NIL
, NIL
, PTR
+STRTY
, 0, 0 );
p
= stref( block( STREF
, r
, p
, 0, 0, 0 ) );
if( q
->slevel
== 0 ) break;
if( m
==CHAR
|| m
==SHORT
)
else if( m
==UCHAR
|| m
==USHORT
)
if( ISPTR( p
->in
.left
->in
.type
) || ISPTR( p
->in
.right
->in
.type
) ){
/* do pointer conversions for char and longs */
ml
= p
->in
.left
->in
.type
;
if( ( ml
==CHAR
|| ml
==UCHAR
|| ml
==SHORT
|| ml
==USHORT
) && p
->in
.left
->in
.op
!= ICON
) break;
/* pointers all have the same representation; the type is inherited */
p
->in
.left
->in
.type
= p
->in
.type
;
p
->in
.left
->fn
.cdim
= p
->fn
.cdim
;
p
->in
.left
->fn
.csiz
= p
->fn
.csiz
;
ml
= p
->in
.left
->in
.type
;
if(m
== FLOAT
|| m
== DOUBLE
) {
if(p
->in
.left
->in
.op
==SCONV
&&
p
->in
.left
->in
.left
->in
.type
==m
) {
p
->in
.op
= p
->in
.left
->in
.op
= FREE
;
return(p
->in
.left
->in
.left
);
if(p
->in
.left
->in
.op
==FCON
)
if(ml
== FLOAT
|| ml
== DOUBLE
){
if (p
->in
.left
->in
.op
== FCON
){
p
->in
.left
->in
.op
= FREE
;
p
->tn
.lval
= p
->in
.left
->fpn
.fval
;
/* now, look for conversions downwards */
if( p
->in
.left
->in
.op
== ICON
){ /* simulate the conversion here */
val
= p
->in
.left
->tn
.lval
;
p
->in
.left
->tn
.lval
= (char) val
;
p
->in
.left
->tn
.lval
= val
& 0XFF;
p
->in
.left
->tn
.lval
= val
& 0XFFFFL
;
p
->in
.left
->tn
.lval
= (short)val
;
p
->in
.left
->tn
.lval
= val
& 0xFFFFFFFFL
;
p
->in
.left
->tn
.lval
= (int)val
;
/* meaningful ones are conversion of int to char, int to short,
and short to char, and unsigned versions thereof */
if( m
==CHAR
|| m
==UCHAR
){
if( ml
!=CHAR
&& ml
!= UCHAR
) break;
else if( m
==SHORT
|| m
==USHORT
){
if( ml
!=CHAR
&& ml
!=UCHAR
&& ml
!=SHORT
&& ml
!=USHORT
) break;
if( tlen(p
) == tlen(p
->in
.left
) ) goto inherit
;
return( p
->in
.left
); /* conversion gets clobbered */
case QUEST
: /* the right side should be COLON */
if((r
= p
->in
.right
)->in
.op
== SCONV
) {
p
->in
.right
= r
->in
.left
;
p
->in
.type
= r
->in
.left
->in
.type
;
if( p
->in
.right
->in
.op
!= ICON
) cerror( "bad conversion", 0);
return( buildtree( o
==PMCONV
?MUL
:DIV
, p
->in
.left
, p
->in
.right
) );
/* make sure that the second pass does not make the
descendant of a FLD operator into a doubly indexed OREG */
if( p
->in
.left
->in
.op
== UNARY MUL
&& (r
=p
->in
.left
->in
.left
)->in
.op
== PCONV
)
if( r
->in
.left
->in
.op
== PLUS
|| r
->in
.left
->in
.op
== MINUS
)
if( ISPTR(r
->in
.type
) ) {
if( ISUNSIGNED(p
->in
.left
->in
.type
) )
p
->in
.left
->in
.type
= UNSIGNED
;
p
->in
.left
->in
.type
= INT
;
case FORTCALL
: /* arg must be FLOAT */
if((r
= p
->in
.right
)->in
.type
!= FLOAT
)
p
->in
.right
= clocal(makety(r
, FLOAT
, 0, FLOAT
));
/* if both sides are FLOAT, so is the op */
if(optype(o
)!=LTYPE
&& p
->in
.left
->in
.type
==DOUBLE
&&
(o
==UNARY MINUS
|| optype(o
)==BITYPE
&& p
->in
.right
->in
.type
==DOUBLE
)) {
if(r
->in
.op
==SCONV
&& r
->in
.left
->in
.type
==FLOAT
) {
if(r
->in
.op
==SCONV
&& r
->in
.left
->in
.type
==FLOAT
) {
p
->in
.right
= r
->in
.left
;
} else if(r
->in
.op
==FCON
)
} else if(optype(o
)==BITYPE
&& r
->in
.op
==FCON
) {
if(!(r
->in
.op
==SCONV
&& r
->in
.left
->in
.type
==FLOAT
))
p
->in
.right
= r
->in
.left
;
p
->in
.left
->in
.type
= FLOAT
;
} else { /* usually logop */
return(1); /* all names can have & taken on them */
cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */
cisreg( t
) TWORD t
; { /* is an automatic variable of type t OK for a register variable */
if( t
==INT
|| t
==UNSIGNED
|| t
==LONG
|| t
==ULONG
/* tbl */
|| t
==CHAR
|| t
==UCHAR
|| t
==SHORT
|| t
==USHORT
/* tbl */
|| ISPTR(t
) || t
== FLOAT
) return (1); /* wnj */
offcon( off
, t
, d
, s
) OFFSZ off
; TWORD t
; {
/* return a node, for structure references, which is suitable for
being added to a pointer of type t, in order to be off bits offset
/* t, d, and s are the type, dimension offset, and sizeoffset */
/* in general they are necessary for offcon, but not on H'well */
static inwd
/* current bit offsed in word */;
static CONSZ word
/* word being built from fields */;
incode( p
, sz
) register NODE
*p
; {
/* generate initialization code for assigning a constant c
to a field of width sz */
/* we assume that the proper alignment has been obtained */
/* inoff is updated to have the proper final value */
/* we also assume sz < SZINT */
if(inwd
> SZINT
) cerror("incode: field > int");
word
|= (p
->tn
.lval
&((1L<<sz
)-1)) << (SZINT
-inwd
);
printf( " .long 0x%X\n", word
);
fincode( d
, sz
) double d
; register int sz
; {
* output code to initialize space of size sz to the value d
* the proper alignment has been obtained
* inoff is updated to have the proper final value.
if(sz
== SZFLOAT
) { /* force rounding */
printf(" .long 0x%04x%04x", x
->sh
[0], x
->sh
[1]);
printf(", 0x%04x%04x", x
->sh
[2], x
->sh
[3]);
printf(" # .double %.17g\n", d
);
printf(" # .float %.8g\n", d
);
cinit( p
, sz
) NODE
*p
; {
* as a favor (?) to people who want to write
* we will, under the proper circumstances, do
(l
->in
.left
->tn
.op
!= DCON
&& l
->in
.left
->tn
.op
!= FCON
))
l
->tn
.lval
= l
->tn
.op
== DCON
? (long)(l
->dpn
.dval
) :
/* arrange for the initialization of p into a space of
/* the proper alignment has been opbtained */
/* inoff is updated to have the proper final value */
vfdzero( n
){ /* define n bits of zeros in a vfd */
printf( " .long 0x%X\n", word
);
/* make a name look like an external name in the local machine */
static char text
[NCHNAM
+1];
static char text
[BUFSIZ
+1];
for( i
=1; *p
&&i
<NCHNAM
; ++i
)
text
[NCHNAM
] = '\0'; /* truncate */
ctype( type
)TWORD type
;{ /* map types which are not defined on the local machine */
noinit() { /* curid is a variable which is defined but
is not initialized (and not a function );
This routine returns the stroage class for an uninitialized declaration */
commdec( id
){ /* make a common declaration for id, if reasonable */
register struct symtab
*q
;
printf( " .comm %s,", exname( q
->sname
) );
off
= tsize( q
->stype
, q
->dimoff
, q
->sizoff
);
printf( "%d\n" /*CONFMT*/, off
/SZCHAR
);
register int o
= p
->in
.op
;
if (o
!= DCON
&& o
!= FCON
)
* Clobber constants of value zero so
* we can generate more efficient code.
if ((o
== DCON
&& p
->dpn
.dval
== 0) ||
(o
== FCON
&& p
->fpn
.fval
== 0)) {
defalign(o
== DCON
? ALDOUBLE
: ALFLOAT
);
fincode(p
->fpn
.fval
, SZFLOAT
);
fincode(p
->dpn
.dval
, SZDOUBLE
);
p
->in
.type
= (o
== DCON
? DOUBLE
: FLOAT
);
isitfloat( s
) char *s
; {
/* avoid floating point exception for double -> float conversions */
/* walk the tree and write out the nodes.. */