1 /* $Id: putscj.c,v 1.18 2008/12/19 08:08:48 ragge Exp $ */
3 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * Redistributions of source code and documentation must retain the above
10 * copyright notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed or owned by Caldera
18 * Neither the name of Caldera International, Inc. nor the names of other
19 * contributors may be used to endorse or promote products derived from
20 * this software without specific prior written permission.
22 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
23 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
27 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
35 /* INTERMEDIATE CODE GENERATION FOR S C JOHNSON C COMPILERS */
36 /* NEW VERSION USING BINARY POLISH POSTFIX INTERMEDIATE */
46 LOCAL
struct bigblock
*putcall(struct bigblock
*p
);
47 LOCAL NODE
*putmnmx(struct bigblock
*p
);
48 LOCAL NODE
*putmem(bigptr
, int, ftnint
);
49 LOCAL NODE
*putaddr(struct bigblock
*, int);
50 LOCAL
void putct1(bigptr
, struct bigblock
*, struct bigblock
*, int *);
51 LOCAL
int ncat(bigptr p
);
52 LOCAL NODE
*putcat(struct bigblock
*, bigptr
);
53 LOCAL NODE
*putchcmp(struct bigblock
*p
);
54 LOCAL NODE
*putcheq(struct bigblock
*p
);
55 LOCAL NODE
*putcxcmp(struct bigblock
*p
);
56 LOCAL
struct bigblock
*putcx1(bigptr
);
57 LOCAL NODE
*putcxop(bigptr p
);
58 LOCAL
struct bigblock
*putcxeq(struct bigblock
*p
);
59 LOCAL NODE
*putpower(bigptr p
);
60 LOCAL NODE
*putop(bigptr p
);
61 LOCAL NODE
*putchop(bigptr p
);
62 LOCAL
struct bigblock
*putch1(bigptr
);
63 LOCAL
struct bigblock
*intdouble(struct bigblock
*);
68 static NODE
*callval
; /* to get return value right */
71 #define XINT(z) ONEOF(z, MSKINT|MSKCHAR)
72 #define P2TYPE(x) (types2[(x)->vtype])
73 #define P2OP(x) (ops2[(x)->b_expr.opcode])
84 pass2_compile(ipnode(p
));
88 putassign(bigptr lp
, bigptr rp
)
90 return putx(fixexpr(mkexpr(OPASSIGN
, lp
, rp
)));
97 struct interpass_prolog
*ipp
= ckalloc(sizeof(struct interpass_prolog
));
104 fatal1("puthead %s in procedure", s
);
110 for (i
= 0; i
< NIPPREGS
; i
++)
111 ipp
->ipp_regs
[i
] = 0; /* no regs used yet */
112 ipp
->ipp_autos
= 0; /* no autos used yet */
113 ipp
->ipp_name
= copys(s
); /* function name */
114 ipp
->ipp_type
= INT
; /* type not known yet? */
115 ipp
->ipp_vis
= 1; /* always visible */
116 ipp
->ip_tmpnum
= 0; /* no temp nodes used in F77 yet */
117 ipp
->ip_lblnum
= olbl
; /* # used labels so far */
118 ipp
->ipp_ip
.ip_lbl
= lbl1
; /* first label, for optim */
119 ipp
->ipp_ip
.type
= IP_PROLOG
;
120 pass2_compile((struct interpass
*)ipp
);
124 /* It is necessary to precede each procedure with a "left bracket"
125 * line that tells pass 2 how many register variables and how
126 * much automatic space is required for the function. This compiler
127 * does not know how much automatic space is needed until the
128 * entire procedure has been processed. Therefore, "puthead"
129 * is called at the begining to record the current location in textfile,
130 * then to put out a placeholder left bracket line. This procedure
131 * repositions the file and rewrites that line, then puts the
132 * file pointer back to the end of the file.
138 struct interpass_prolog
*ipp
= ckalloc(sizeof(struct interpass_prolog
));
142 fatal1("puteof outside procedure");
143 for (i
= 0; i
< NIPPREGS
; i
++)
144 ipp
->ipp_regs
[i
] = 0;
145 ipp
->ipp_autos
= autoleng
;
146 ipp
->ipp_name
= copys(inproc
);
147 ipp
->ipp_type
= INT
; /* XXX should set the correct type */
150 ipp
->ip_lblnum
= lastlabno
;
151 ipp
->ipp_ip
.ip_lbl
= retlabel
;
152 ipp
->ipp_ip
.type
= IP_EPILOG
;
153 printf("\t.text\n"); /* XXX */
154 pass2_compile((struct interpass
*)ipp
);
172 /* put out code for if( ! p) goto l */
174 putif(bigptr p
, int l
)
179 if( ( k
= (p
= fixtype(p
))->vtype
) != TYLOGICAL
) {
181 err("non-logical expression in IF statement");
185 if (p1
->n_op
== EQ
&& p1
->n_right
->n_op
== ICON
&&
186 p1
->n_right
->n_lval
== 0 && logop(p1
->n_left
->n_op
)) {
187 /* created by OPOR */
188 NODE
*q
= p1
->n_left
;
189 q
->n_op
= negrel
[q
->n_op
- EQ
];
194 if (logop(p1
->n_op
) == 0)
195 p1
= mkbinode(NE
, p1
, mklnode(ICON
, 0, 0, INT
), INT
);
196 if (p1
->n_left
->n_op
== ICON
) {
197 /* change constants to right */
198 NODE
*p2
= p1
->n_left
;
199 p1
->n_left
= p1
->n_right
;
201 if (p1
->n_op
!= EQ
&& p1
->n_op
!= NE
)
202 p1
->n_op
= negrel
[p1
->n_op
- EQ
];
204 p1
->n_op
= negrel
[p1
->n_op
- EQ
];
205 p1
= mkbinode(CBRANCH
, p1
, mklnode(ICON
, l
, 0, INT
), INT
);
212 prarif(bigptr p
, int neg
, int zer
, int pos
)
214 bigptr x1
= fmktemp(p
->vtype
, NULL
);
216 putexpr(mkexpr(OPASSIGN
, cpexpr(x1
), p
));
217 putif(mkexpr(OPGE
, cpexpr(x1
), MKICON(0)), neg
);
218 putif(mkexpr(OPLE
, x1
, MKICON(0)), pos
);
222 /* put out code for goto l */
228 p
= mkunode(GOTO
, mklnode(ICON
, label
, 0, INT
), 0, INT
);
233 /* branch to address constant or integer variable */
235 putbranch(struct bigblock
*q
)
239 p
= mkunode(GOTO
, putex1(q
), 0, INT
);
244 * put out label l: in text segment
249 struct interpass
*ip
= ckalloc(sizeof(struct interpass
));
251 ip
->type
= IP_DEFLAB
;
259 * Called from inner routines. Generates a NODE tree and writes it out.
272 putcmgo(bigptr x
, int nlab
, struct labelblock
*labels
[])
277 if (!ISINT(x
->vtype
)) {
278 execerr("computed goto index must be integer", NULL
);
282 y
= fmktemp(x
->vtype
, NULL
);
283 putexpr(mkexpr(OPASSIGN
, cpexpr(y
), x
));
284 #ifdef notyet /* target-specific computed goto */
285 vaxgoto(y
, nlab
, labels
);
288 * Primitive implementation, should use table here.
290 for(i
= 0 ; i
< nlab
; ++i
)
291 putif(mkexpr(OPNE
, cpexpr(y
), MKICON(i
+1)), labels
[i
]->labelno
);
297 * Convert a f77 tree statement to something that looks like a
298 * pcc expression tree.
304 NODE
*p
= NULL
; /* XXX */
310 printf("putx %p\n", q
);
321 switch(type
= q
->vtype
) {
326 p
= mklnode(ICON
, q
->b_const
.fconst
.ci
,
332 p
= mklnode(ICON
, 0, 0, types2
[type
]);
333 p
->n_name
= copys(memname(STGCONST
,
334 (int)q
->b_const
.fconst
.ci
));
339 p
= putx(putconst(q
));
345 switch(opc
= q
->b_expr
.opcode
) {
348 if( ISCOMPLEX(q
->vtype
) )
362 if (ISCOMPLEX(q
->b_expr
.leftp
->vtype
) ||
363 ISCOMPLEX(q
->b_expr
.rightp
->vtype
)) {
365 } else if (ISCHAR(q
))
373 if (ISCOMPLEX(q
->b_expr
.leftp
->vtype
) ||
374 ISCOMPLEX(q
->b_expr
.rightp
->vtype
) ) {
382 if(ISCHAR(q
->b_expr
.leftp
))
393 /* m * (2**k) -> m<<k */
394 if (XINT(q
->b_expr
.leftp
->vtype
) &&
395 ISICON(q
->b_expr
.rightp
) &&
396 ((k
= flog2(q
->b_expr
.rightp
->b_const
.fconst
.ci
))>0) ) {
397 q
->b_expr
.opcode
= OPLSHIFT
;
398 frexpr(q
->b_expr
.rightp
);
399 q
->b_expr
.rightp
= MKICON(k
);
409 if( ISCOMPLEX(q
->vtype
) )
416 if( ISCOMPLEX(q
->vtype
) )
418 else if (ISCOMPLEX(q
->b_expr
.leftp
->vtype
)) {
419 p
= putx(mkconv(q
->vtype
,
420 realpart(putcx1(q
->b_expr
.leftp
))));
427 /* Create logical AND */
428 x1
= fmktemp(TYLOGICAL
, NULL
);
429 putexpr(mkexpr(OPASSIGN
, cpexpr(x1
),
432 putif(q
->b_expr
.leftp
, k
);
433 putif(q
->b_expr
.rightp
, k
);
434 putexpr(mkexpr(OPASSIGN
, cpexpr(x1
),
440 case OPNOT
: /* Logical NOT */
441 x1
= fmktemp(TYLOGICAL
, NULL
);
442 putexpr(mkexpr(OPASSIGN
, cpexpr(x1
),
445 putif(q
->b_expr
.leftp
, k
);
446 putexpr(mkexpr(OPASSIGN
, cpexpr(x1
),
452 case OPOR
: /* Create logical OR */
453 x1
= fmktemp(TYLOGICAL
, NULL
);
454 putexpr(mkexpr(OPASSIGN
, cpexpr(x1
),
457 putif(mkexpr(OPEQ
, q
->b_expr
.leftp
,
459 putif(mkexpr(OPEQ
, q
->b_expr
.rightp
,
461 putexpr(mkexpr(OPASSIGN
, cpexpr(x1
),
468 for (x1
= q
; x1
->b_expr
.opcode
== OPCOMMA
;
469 x1
= x1
->b_expr
.leftp
)
470 putexpr(x1
->b_expr
.rightp
);
488 fatal1("putx: invalid opcode %d", opc
);
497 fatal1("putx: impossible tag %d", q
->tag
);
512 printf("putop %p\n", q
);
516 switch(q
->b_expr
.opcode
) { /* check for special cases and rewrite */
519 lp
= q
->b_expr
.leftp
;
521 while(q
->tag
==TEXPR
&& q
->b_expr
.opcode
==OPCONV
&&
522 ((ISREAL(pt
)&&ISREAL(lt
)) ||
523 (XINT(pt
)&&(ONEOF(lt
,MSKINT
|MSKADDR
))) )) {
524 if(lp
->tag
!= TEXPR
) {
525 if(pt
==TYINT
&& lt
==TYLONG
)
527 if(lt
==TYINT
&& pt
==TYLONG
)
533 lp
= q
->b_expr
.leftp
;
536 if(q
->tag
==TEXPR
&& q
->b_expr
.opcode
==OPCONV
)
542 lp
= q
->b_expr
.leftp
;
543 if(lp
->tag
!= TADDR
) {
544 tp
= fmktemp(lp
->vtype
, lp
->vleng
);
545 p
= putx(mkexpr(OPASSIGN
, cpexpr(tp
), lp
));
554 if ((k
= ops2
[q
->b_expr
.opcode
]) <= 0)
555 fatal1("putop: invalid opcode %d (%d)", q
->b_expr
.opcode
, k
);
556 p
= putx(q
->b_expr
.leftp
);
558 p
= mkbinode(k
, p
, putx(q
->b_expr
.rightp
), types2
[q
->vtype
]);
560 p
= mkunode(k
, p
, 0, types2
[q
->vtype
]);
569 * Put return values into correct register.
572 putforce(int t
, bigptr p
)
576 p
= mkconv(t
, fixtype(p
));
578 p1
= mkunode(FORCE
, p1
, 0,
579 (t
==TYSHORT
? SHORT
: (t
==TYLONG
? LONG
: LDOUBLE
)));
588 struct bigblock
*t1
, *t2
;
589 ftnint k
= 0; /* XXX gcc */
592 if(!ISICON(p
->b_expr
.rightp
) ||
593 (k
= p
->b_expr
.rightp
->b_const
.fconst
.ci
)<2)
594 fatal("putpower: bad call");
595 base
= p
->b_expr
.leftp
;
597 t1
= fmktemp(type
, NULL
);
599 p3
= putassign(cpexpr(t1
), cpexpr(base
) );
602 for( ; (k
&1)==0 && k
>2 ; k
>>=1 ) {
603 p3
= putassign(cpexpr(t1
),
604 mkexpr(OPSTAR
, cpexpr(t1
), cpexpr(t1
)));
609 p3
= putx(mkexpr(OPSTAR
, cpexpr(t1
), cpexpr(t1
)));
611 t2
= fmktemp(type
, NULL
);
612 p3
= putassign(cpexpr(t2
), cpexpr(t1
));
615 for(k
>>=1 ; k
>1 ; k
>>=1) {
616 p3
= putassign(cpexpr(t1
),
617 mkexpr(OPSTAR
, cpexpr(t1
), cpexpr(t1
)));
620 p3
= putassign(cpexpr(t2
),
621 mkexpr(OPSTAR
, cpexpr(t2
), cpexpr(t1
)));
625 p3
= putx( mkexpr(OPSTAR
, cpexpr(t2
),
626 mkexpr(OPSTAR
, cpexpr(t1
), cpexpr(t1
)) ));
635 LOCAL
struct bigblock
*
636 intdouble(struct bigblock
*p
)
640 t
= fmktemp(TYDREAL
, NULL
);
642 sendp2(putassign(cpexpr(t
), p
));
646 LOCAL
struct bigblock
*
647 putcxeq(struct bigblock
*q
)
649 struct bigblock
*lp
, *rp
;
651 lp
= putcx1(q
->b_expr
.leftp
);
652 rp
= putcx1(q
->b_expr
.rightp
);
653 sendp2(putassign(realpart(lp
), realpart(rp
)));
654 if( ISCOMPLEX(q
->vtype
) ) {
655 sendp2(putassign(imagpart(lp
), imagpart(rp
)));
669 p
= putaddr(putcx1(q
), NO
);
673 LOCAL
struct bigblock
*
676 struct bigblock
*q
, *lp
, *rp
;
677 register struct bigblock
*resp
;
682 ltype
= rtype
= 0; /* XXX gcc */
688 if( ISCOMPLEX(qq
->vtype
) )
693 if( ! addressable(qq
) ) {
694 resp
= fmktemp(tyint
, NULL
);
695 p
= putassign( cpexpr(resp
), qq
->b_addr
.memoffset
);
697 qq
->b_addr
.memoffset
= resp
;
702 if( ISCOMPLEX(qq
->vtype
) )
704 resp
= fmktemp(TYDREAL
, NO
);
705 p
= putassign( cpexpr(resp
), qq
);
710 fatal1("putcx1: bad tag %d", qq
->tag
);
713 opcode
= qq
->b_expr
.opcode
;
714 if(opcode
==OPCALL
|| opcode
==OPCCALL
) {
718 } else if(opcode
== OPASSIGN
) {
719 return( putcxeq(qq
) );
722 resp
= fmktemp(qq
->vtype
, NULL
);
723 if((lp
= putcx1(qq
->b_expr
.leftp
) ))
725 if((rp
= putcx1(qq
->b_expr
.rightp
) ))
736 p
= putassign(realpart(resp
),
737 mkexpr(OPNEG
, realpart(lp
), NULL
));
739 p
= putassign(imagpart(resp
),
740 mkexpr(OPNEG
, imagpart(lp
), NULL
));
746 p
= putassign( realpart(resp
),
747 mkexpr(opcode
, realpart(lp
), realpart(rp
) ));
749 if(rtype
< TYCOMPLEX
) {
750 p
= putassign(imagpart(resp
), imagpart(lp
) );
751 } else if(ltype
< TYCOMPLEX
) {
753 p
= putassign( imagpart(resp
), imagpart(rp
) );
755 p
= putassign( imagpart(resp
),
756 mkexpr(OPNEG
, imagpart(rp
), NULL
) );
758 p
= putassign( imagpart(resp
),
759 mkexpr(opcode
, imagpart(lp
), imagpart(rp
) ));
764 if(ltype
< TYCOMPLEX
) {
767 p
= putassign( realpart(resp
),
768 mkexpr(OPSTAR
, cpexpr(lp
), realpart(rp
) ));
770 p
= putassign( imagpart(resp
),
771 mkexpr(OPSTAR
, cpexpr(lp
), imagpart(rp
) ));
772 } else if(rtype
< TYCOMPLEX
) {
775 p
= putassign( realpart(resp
),
776 mkexpr(OPSTAR
, cpexpr(rp
), realpart(lp
) ));
778 p
= putassign( imagpart(resp
),
779 mkexpr(OPSTAR
, cpexpr(rp
), imagpart(lp
) ));
781 p
= putassign( realpart(resp
), mkexpr(OPMINUS
,
782 mkexpr(OPSTAR
, realpart(lp
), realpart(rp
)),
783 mkexpr(OPSTAR
, imagpart(lp
), imagpart(rp
)) ));
785 p
= putassign( imagpart(resp
), mkexpr(OPPLUS
,
786 mkexpr(OPSTAR
, realpart(lp
), imagpart(rp
)),
787 mkexpr(OPSTAR
, imagpart(lp
), realpart(rp
)) ));
793 /* fixexpr has already replaced all divisions
794 * by a complex by a function call
798 p
= putassign( realpart(resp
),
799 mkexpr(OPSLASH
, realpart(lp
), cpexpr(rp
)) );
801 p
= putassign( imagpart(resp
),
802 mkexpr(OPSLASH
, imagpart(lp
), cpexpr(rp
)) );
807 p
= putassign( realpart(resp
), realpart(lp
) );
808 if( ISCOMPLEX(lp
->vtype
) )
813 q
= mkrealcon(TYDREAL
, 0.0);
815 p
= putassign( imagpart(resp
), q
);
820 fatal1("putcx1 of invalid opcode %d", opcode
);
831 putcxcmp(struct bigblock
*p
)
835 struct bigblock
*lp
, *rp
;
838 opcode
= p
->b_expr
.opcode
;
839 lp
= putcx1(p
->b_expr
.leftp
);
840 rp
= putcx1(p
->b_expr
.rightp
);
842 q
= mkexpr( opcode
==OPEQ
? OPAND
: OPOR
,
843 mkexpr(opcode
, realpart(lp
), realpart(rp
)),
844 mkexpr(opcode
, imagpart(lp
), imagpart(rp
)) );
845 p1
= putx( fixexpr(q
) );
853 LOCAL
struct bigblock
*
860 return( putconst(p
) );
866 switch(p
->b_expr
.opcode
) {
874 t
= fmktemp(TYCHAR
, cpexpr(p
->vleng
) );
875 sendp2(putcat( cpexpr(t
), p
));
879 if(!ISICON(p
->vleng
) ||
880 p
->vleng
->b_const
.fconst
.ci
!=1
881 || ! XINT(p
->b_expr
.leftp
->vtype
) )
882 fatal("putch1: bad character conversion");
883 t
= fmktemp(TYCHAR
, MKICON(1) );
884 sendp2(putassign( cpexpr(t
), p
));
887 fatal1("putch1: invalid opcode %d", p
->b_expr
.opcode
);
888 t
= NULL
; /* XXX gcc */
893 fatal1("putch1: bad tag %d", p
->tag
);
896 return NULL
; /* XXX gcc */
907 p1
= putaddr( putch1(p
) , NO
);
913 * Assign a character to another.
916 putcheq(struct bigblock
*p
)
920 if( p
->b_expr
.rightp
->tag
==TEXPR
&&
921 p
->b_expr
.rightp
->b_expr
.opcode
==OPCONCAT
)
922 p3
= putcat(p
->b_expr
.leftp
, p
->b_expr
.rightp
);
923 else if( ISONE(p
->b_expr
.leftp
->vleng
) &&
924 ISONE(p
->b_expr
.rightp
->vleng
) ) {
925 p1
= putaddr( putch1(p
->b_expr
.leftp
) , YES
);
926 p2
= putaddr( putch1(p
->b_expr
.rightp
) , YES
);
927 p3
= mkbinode(ASSIGN
, p1
, p2
, CHAR
);
929 p3
= putx(call2(TYINT
, "s_copy",
930 p
->b_expr
.leftp
, p
->b_expr
.rightp
));
940 * Compare character(s) code.
943 putchcmp(struct bigblock
*p
)
947 if(ISONE(p
->b_expr
.leftp
->vleng
) && ISONE(p
->b_expr
.rightp
->vleng
) ) {
948 p1
= putaddr( putch1(p
->b_expr
.leftp
) , YES
);
949 p2
= putaddr( putch1(p
->b_expr
.rightp
) , YES
);
950 p3
= mkbinode(ops2
[p
->b_expr
.opcode
], p1
, p2
, CHAR
);
953 p
->b_expr
.leftp
= call2(TYINT
,"s_cmp",
954 p
->b_expr
.leftp
, p
->b_expr
.rightp
);
955 p
->b_expr
.rightp
= MKICON(0);
962 putcat(bigptr lhs
, bigptr rhs
)
966 struct bigblock
*lp
, *cp
;
969 lp
= mktmpn(n
, TYLENG
, NULL
);
970 cp
= mktmpn(n
, TYADDR
, NULL
);
973 putct1(rhs
, lp
, cp
, &n
);
975 p3
= putx( call4(TYSUBR
, "s_cat", lhs
, cp
, lp
, MKICON(n
) ) );
982 if(p
->tag
==TEXPR
&& p
->b_expr
.opcode
==OPCONCAT
)
983 return( ncat(p
->b_expr
.leftp
) + ncat(p
->b_expr
.rightp
) );
989 putct1(bigptr q
, bigptr lp
, bigptr cp
, int *ip
)
993 struct bigblock
*lp1
, *cp1
;
995 if(q
->tag
==TEXPR
&& q
->b_expr
.opcode
==OPCONCAT
) {
996 putct1(q
->b_expr
.leftp
, lp
, cp
, ip
);
997 putct1(q
->b_expr
.rightp
, lp
, cp
, ip
);
1003 lp1
->b_addr
.memoffset
=
1004 mkexpr(OPPLUS
, lp1
->b_addr
.memoffset
, MKICON(i
*FSZLENG
));
1006 cp1
->b_addr
.memoffset
=
1007 mkexpr(OPPLUS
, cp1
->b_addr
.memoffset
, MKICON(i
*FSZADDR
));
1008 p
= putassign( lp1
, cpexpr(q
->vleng
) );
1010 p
= putassign( cp1
, addrof(putch1(q
)) );
1016 * Create a tree that can later be converted to an OREG.
1019 oregtree(int off
, int reg
, int type
)
1023 p
= mklnode(REG
, 0, reg
, INCREF(type
));
1024 q
= mklnode(ICON
, off
, 0, INT
);
1025 return mkunode(UMUL
, mkbinode(PLUS
, p
, q
, INCREF(type
)), 0, type
);
1029 putaddr(bigptr q
, int indir
)
1031 int type
, type2
, funct
;
1036 p
= p1
= p2
= NULL
; /* XXX */
1039 type2
= types2
[type
];
1040 funct
= (q
->vclass
==CLPROC
? FTN
<<TSHIFT
: 0);
1042 offp
= (q
->b_addr
.memoffset
? cpexpr(q
->b_addr
.memoffset
) : NULL
);
1044 offset
= simoffset(&offp
);
1046 offp
= mkconv(TYINT
, offp
);
1050 if(indir
&& !offp
) {
1051 p
= oregtree(offset
, AUTOREG
, type2
);
1055 if(!indir
&& !offp
&& !offset
) {
1056 p
= mklnode(REG
, 0, AUTOREG
, INCREF(type2
));
1060 p
= mklnode(REG
, 0, AUTOREG
, INCREF(type2
));
1064 p2
= mklnode(ICON
, offset
, 0, INT
);
1066 p1
= mklnode(ICON
, offset
, 0, INT
);
1068 p1
= mkbinode(PLUS
, p1
, p2
, INCREF(type2
));
1069 p
= mkbinode(PLUS
, p
, p1
, INCREF(type2
));
1071 p
= mkunode(UMUL
, p
, 0, type2
);
1075 p
= oregtree(ARGOFFSET
+ (ftnint
)(q
->b_addr
.memno
),
1076 ARGREG
, INCREF(type2
)|funct
);
1081 p2
= mklnode(ICON
, offset
, 0, INT
);
1083 p1
= mkbinode(PLUS
, p1
, p2
, INCREF(type2
));
1087 p
= mkbinode(PLUS
, p
, p1
, INCREF(type2
));
1089 p
= mkunode(UMUL
, p
, 0, type2
);
1094 p
= oregtree(ARGOFFSET
+ (ftnint
)(q
->b_addr
.memno
),
1095 ARGREG
, INCREF(type2
)|funct
);
1097 fatal1("faddrnode: STGLENG: fixme!");
1099 p2op(P2PLUS
, types2
[TYLENG
] | P2PTR
);
1100 p2reg(ARGREG
, types2
[TYLENG
] | P2PTR
);
1102 (ftnint
) (FUDGEOFFSET
*p
->b_addr
.memno
), P2INT
);
1116 p2
= putmem(q
, ICON
, offset
);
1117 p
= mkbinode(PLUS
, p1
, p2
, INCREF(type2
));
1119 p
= mkunode(UMUL
, p
, 0, type2
);
1121 p
= putmem(q
, (indir
? NAME
: ICON
), offset
);
1126 p
= mklnode(REG
, 0, q
->b_addr
.memno
, type2
);
1128 fatal("attempt to take address of a register");
1132 fatal1("putaddr: invalid vstg %d", q
->vstg
);
1139 putmem(bigptr q
, int class, ftnint offset
)
1144 type2
= types2
[q
->vtype
];
1145 if(q
->vclass
== CLPROC
)
1146 type2
|= (FTN
<<TSHIFT
);
1149 p
= mklnode(class, offset
, 0, type2
);
1150 p
->n_name
= copys(memname(q
->vstg
, q
->b_addr
.memno
));
1156 LOCAL
struct bigblock
*
1157 putcall(struct bigblock
*qq
)
1159 chainp arglist
, charsp
, cp
;
1163 struct bigblock
*fval
;
1164 int type
, type2
, ctype
, indir
;
1167 lp
= p2
= NULL
; /* XXX */
1169 type2
= types2
[type
= qq
->vtype
];
1171 indir
= (qq
->b_expr
.opcode
== OPCCALL
);
1175 if(qq
->b_expr
.rightp
) {
1176 arglist
= qq
->b_expr
.rightp
->b_list
.listp
;
1177 ckfree(qq
->b_expr
.rightp
);
1181 for(cp
= arglist
; cp
; cp
= cp
->chain
.nextp
)
1185 q
= cp
->chain
.datap
;
1186 if(q
->tag
== TCONST
)
1187 cp
->chain
.datap
= q
= putconst(q
);
1189 charsp
= hookup(charsp
,
1190 mkchain(cpexpr(q
->vleng
), 0) );
1192 } else if(q
->vclass
== CLPROC
) {
1193 charsp
= hookup(charsp
,
1194 mkchain( MKICON(0) , 0));
1200 if(type
== TYCHAR
) {
1201 if( ISICON(qq
->vleng
) ) {
1202 fval
= fmktemp(TYCHAR
, qq
->vleng
);
1205 err("adjustable character function");
1208 } else if(ISCOMPLEX(type
)) {
1209 fval
= fmktemp(type
, NULL
);
1214 ctype
= (fval
? P2INT
: type2
);
1215 p1
= putaddr(qq
->b_expr
.leftp
, NO
);
1219 lp
= putaddr( cpexpr(fval
), NO
);
1221 lp
= mkbinode(CM
, lp
, putx(cpexpr(qq
->vleng
)), INT
);
1224 for(cp
= arglist
; cp
; cp
= cp
->chain
.nextp
) {
1225 q
= cp
->chain
.datap
;
1226 if(q
->tag
==TADDR
&& (indir
|| q
->vstg
!=STGREG
) )
1227 p2
= putaddr(q
, indir
&& q
->vtype
!=TYCHAR
);
1228 else if( ISCOMPLEX(q
->vtype
) )
1230 else if (ISCHAR(q
) ) {
1232 } else if( ! ISERROR(q
) ) {
1236 t
= fmktemp(q
->vtype
, q
->vleng
);
1237 p2
= putassign( cpexpr(t
), q
);
1239 p2
= putaddr(t
, NO
);
1246 lp
= mkbinode(CM
, lp
, p2
, INT
);
1251 for(cp
= charsp
; cp
; cp
= cp
->chain
.nextp
) {
1252 p2
= putx( mkconv(TYLENG
,cp
->chain
.datap
) );
1253 lp
= mkbinode(CM
, lp
, p2
, INT
);
1257 callval
= mkbinode(CALL
, p1
, lp
, ctype
);
1259 callval
= mkunode(UCALL
, p1
, 0, ctype
);
1265 * Write out code to do min/max calculations.
1266 * Note that these operators may have multiple arguments in fortran.
1269 putmnmx(struct bigblock
*p
)
1274 struct bigblock
*tp
;
1277 op
= (p
->b_expr
.opcode
==OPMIN
? LT
: GT
);
1278 p0
= p
->b_expr
.leftp
->b_list
.listp
;
1279 ckfree(p
->b_expr
.leftp
);
1283 * Store first value in a temporary, then compare it with
1284 * each following value and save that if needed.
1286 tp
= fmktemp(type
, NULL
);
1287 sendp2(putassign(cpexpr(tp
), p0
->chain
.datap
));
1289 for(p1
= p0
->chain
.nextp
; p1
; p1
= p1
->chain
.nextp
) {
1290 n1
= putx(cpexpr(tp
));
1291 n2
= putx(cpexpr(p1
->chain
.datap
));
1293 sendp2(mkbinode(CBRANCH
, mkbinode(op
, n1
, n2
, INT
),
1294 mklnode(ICON
, lab
, 0, INT
), INT
));
1295 sendp2(putassign(cpexpr(tp
), p1
->chain
.datap
));
1302 simoffset(bigptr
*p0
)
1304 ftnint offset
, prod
;
1312 if( ! ISINT(p
->vtype
) )
1315 if(p
->tag
==TEXPR
&& p
->b_expr
.opcode
==OPSTAR
) {
1316 lp
= p
->b_expr
.leftp
;
1317 rp
= p
->b_expr
.rightp
;
1318 if(ISICON(rp
) && lp
->tag
==TEXPR
&&
1319 lp
->b_expr
.opcode
==OPPLUS
&& ISICON(lp
->b_expr
.rightp
)) {
1320 p
->b_expr
.opcode
= OPPLUS
;
1321 lp
->b_expr
.opcode
= OPSTAR
;
1322 prod
= rp
->b_const
.fconst
.ci
*
1323 lp
->b_expr
.rightp
->b_const
.fconst
.ci
;
1324 lp
->b_expr
.rightp
->b_const
.fconst
.ci
=
1325 rp
->b_const
.fconst
.ci
;
1326 rp
->b_const
.fconst
.ci
= prod
;
1330 if(p
->tag
==TEXPR
&& p
->b_expr
.opcode
==OPPLUS
&&
1331 ISICON(p
->b_expr
.rightp
)) {
1332 rp
= p
->b_expr
.rightp
;
1333 lp
= p
->b_expr
.leftp
;
1334 offset
+= rp
->b_const
.fconst
.ci
;
1340 if(p
->tag
== TCONST
) {
1341 offset
+= p
->b_const
.fconst
.ci
;
1350 * F77 uses ckalloc() (malloc) for NODEs.
1355 NODE
*p
= ckalloc(sizeof(NODE
));
1361 static char *tagnam
[] = {
1362 "NONE", "NAME", "CONST", "EXPR", "ADDR", "PRIM", "LIST", "IMPLDO", "ERROR",
1364 static char *typnam
[] = {
1365 "unknown", "addr", "short", "long", "real", "dreal", "complex", "dcomplex",
1366 "logical", "char", "subr", "error",
1368 static char *classnam
[] = {
1369 "unknown", "param", "var", "entry", "main", "block", "proc",
1371 static char *stgnam
[] = {
1372 "unknown", "arg", "auto", "bss", "init", "const", "intr", "stfunct",
1373 "common", "equiv", "reg", "leng",
1378 * Print out a f77 tree, for diagnostic purposes.
1381 fprint(bigptr p
, int indx
)
1397 printf("%p) %s, ", p
, tagnam
[p
->tag
]);
1399 printf("type=%s, ", typnam
[p
->vtype
]);
1401 printf("class=%s, ", classnam
[p
->vclass
]);
1403 printf("stg=%s, ", stgnam
[p
->vstg
]);
1408 printf("OP %s\n", ops
[p
->b_expr
.opcode
]);
1409 lp
= p
->b_expr
.leftp
;
1410 rp
= p
->b_expr
.rightp
;
1413 printf("memno=%d\n", p
->b_addr
.memno
);
1415 rp
= p
->b_addr
.memoffset
;
1423 printf("val=%ld\n", p
->b_const
.fconst
.ci
);
1432 lp
= p
->b_prim
.namep
;
1433 rp
= p
->b_prim
.argsp
;
1434 printf("fcharp=%p, lcharp=%p\n", p
->b_prim
.fcharp
, p
->b_prim
.lcharp
);
1437 printf("name=%s\n", p
->b_name
.varname
);
1441 for (bp
= &p
->b_list
.listp
->chain
; bp
; bp
= &bp
->nextp
->chain
)
1442 fprint(bp
->datap
, indx
+1);