1 /* $Id: reader.c,v 1.268.2.1 2011/03/15 17:23:18 ragge Exp $ */
3 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. 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 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
36 * Redistributions of source code and documentation must retain the above
37 * copyright notice, this list of conditions and the following disclaimer.
38 * Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditionsand the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed or owned by Caldera
45 * Neither the name of Caldera International, Inc. nor the names of other
46 * contributors may be used to endorse or promote products derived from
47 * this software without specific prior written permission.
49 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
50 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
51 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
52 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
54 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
58 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
59 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 * POSSIBILITY OF SUCH DAMAGE.
64 * Everything is entered via pass2_compile(). No functions are
65 * allowed to recurse back into pass2_compile().
74 /* some storage declarations */
77 int x2debug
, udebug
, odebug
;
80 int p2autooff
, p2maxautooff
;
84 struct interpass prepole
;
86 void saveip(struct interpass
*ip
);
87 void deltemp(NODE
*p
, void *);
88 static void cvtemps(struct interpass
*ipole
, int op
, int off
);
90 static void fixxasm(struct p2env
*);
92 static void gencode(NODE
*p
, int cookie
);
93 static void genxasm(NODE
*p
);
100 extern int getlab(void);
103 if (p2env
.epp
->ip_lblnum
!= rv
)
104 comperr("getlab2 error: %d != %d", p2env
.epp
->ip_lblnum
, rv
);
106 p2env
.epp
->ip_lblnum
++;
111 static int *lbldef
, *lbluse
;
113 cktree(NODE
*p
, void *arg
)
118 cerror("%p) op %d slipped through", p
, p
->n_op
);
119 if (BTYPE(p
->n_type
) > MAXTYPES
)
120 cerror("%p) type %x slipped through", p
, p
->n_type
);
121 if (p
->n_op
== CBRANCH
) {
122 if (!logop(p
->n_left
->n_op
))
123 cerror("%p) not logop branch", p
);
124 i
= (int)p
->n_right
->n_lval
;
125 if (i
< p2env
.ipp
->ip_lblnum
|| i
>= p2env
.epp
->ip_lblnum
)
126 cerror("%p) label %d outside boundaries %d-%d",
127 p
, i
, p2env
.ipp
->ip_lblnum
, p2env
.epp
->ip_lblnum
);
128 lbluse
[i
-p2env
.ipp
->ip_lblnum
] = 1;
130 if ((dope
[p
->n_op
] & ASGOPFLG
) && p
->n_op
!= RETURN
)
131 cerror("%p) asgop %d slipped through", p
, p
->n_op
);
132 if (p
->n_op
== TEMP
&&
133 (regno(p
) < p2env
.ipp
->ip_tmpnum
|| regno(p
) >= p2env
.epp
->ip_tmpnum
))
134 cerror("%p) temporary %d outside boundaries %d-%d",
135 p
, regno(p
), p2env
.ipp
->ip_tmpnum
, p2env
.epp
->ip_tmpnum
);
136 if (p
->n_op
== GOTO
&& p
->n_left
->n_op
== ICON
) {
137 i
= (int)p
->n_left
->n_lval
;
138 if (i
< p2env
.ipp
->ip_lblnum
|| i
>= p2env
.epp
->ip_lblnum
)
139 cerror("%p) label %d outside boundaries %d-%d",
140 p
, i
, p2env
.ipp
->ip_lblnum
, p2env
.epp
->ip_lblnum
);
141 lbluse
[i
-p2env
.ipp
->ip_lblnum
] = 1;
146 * Check that the trees are in a suitable state for pass2.
149 sanitychecks(struct p2env
*p2e
)
151 struct interpass
*ip
;
156 lbldef
= tmpcalloc(sizeof(int) * (p2e
->epp
->ip_lblnum
- p2e
->ipp
->ip_lblnum
));
157 lbluse
= tmpcalloc(sizeof(int) * (p2e
->epp
->ip_lblnum
- p2e
->ipp
->ip_lblnum
));
159 DLIST_FOREACH(ip
, &p2env
.ipole
, qelem
) {
160 if (ip
->type
== IP_DEFLAB
) {
162 if (i
< p2e
->ipp
->ip_lblnum
|| i
>= p2e
->epp
->ip_lblnum
)
163 cerror("label %d outside boundaries %d-%d",
164 i
, p2e
->ipp
->ip_lblnum
, p2e
->epp
->ip_lblnum
);
165 lbldef
[i
-p2e
->ipp
->ip_lblnum
] = 1;
167 if (ip
->type
== IP_NODE
)
168 walkf(ip
->ip_node
, cktree
, 0);
170 for (i
= 0; i
< (p2e
->epp
->ip_lblnum
- p2e
->ipp
->ip_lblnum
); i
++)
171 if (lbluse
[i
] != 0 && lbldef
[i
] == 0)
172 cerror("internal label %d not defined",
173 i
+ p2e
->ipp
->ip_lblnum
);
182 * Look if a temporary comes from a on-stack argument, in that case
183 * use the already existing stack position instead of moving it to
184 * a new place, and remove the move-to-temp statement.
187 stkarg(int tnr
, int *soff
)
189 struct p2env
*p2e
= &p2env
;
190 struct interpass
*ip
;
193 ip
= DLIST_NEXT((struct interpass
*)p2e
->ipp
, qelem
);
194 while (ip
->type
!= IP_DEFLAB
) /* search for first DEFLAB */
195 ip
= DLIST_NEXT(ip
, qelem
);
197 ip
= DLIST_NEXT(ip
, qelem
); /* first NODE */
199 for (; ip
->type
!= IP_DEFLAB
; ip
= DLIST_NEXT(ip
, qelem
)) {
200 if (ip
->type
!= IP_NODE
)
205 continue; /* XXX - hack for x86 PIC */
207 if (p
->n_op
!= ASSIGN
|| p
->n_left
->n_op
!= TEMP
)
210 if (p
->n_op
!= ASSIGN
|| p
->n_left
->n_op
!= TEMP
)
211 continue; /* unknown tree */
213 if (p
->n_right
->n_op
!= OREG
&& p
->n_right
->n_op
!= UMUL
)
214 continue; /* arg in register */
215 if (tnr
!= regno(p
->n_left
))
216 continue; /* wrong assign */
218 if (p
->n_op
== UMUL
&&
219 p
->n_left
->n_op
== PLUS
&&
220 p
->n_left
->n_left
->n_op
== REG
&&
221 p
->n_left
->n_right
->n_op
== ICON
)
222 *soff
= (int)p
->n_left
->n_right
->n_lval
;
223 else if (p
->n_op
== OREG
)
224 *soff
= (int)p
->n_lval
;
226 comperr("stkarg: bad arg");
228 DLIST_REMOVE(ip
, qelem
);
235 * See if an ADDROF is somewhere inside the expression tree.
236 * If so, fill in the offset table.
239 findaof(NODE
*p
, void *arg
)
244 if (p
->n_op
!= ADDROF
|| p
->n_left
->n_op
!= TEMP
)
246 tnr
= regno(p
->n_left
);
248 return; /* already gotten stack address */
249 if (stkarg(tnr
, &aof
[tnr
]))
250 return; /* argument was on stack */
251 aof
[tnr
] = BITOOR(freetemp(szty(p
->n_left
->n_type
)));
255 * Check if a node has side effects.
283 * Delete statements with no meaning (like a+b; or 513.4;)
288 struct interpass
*ip
;
291 if (optype(p
->n_op
) == LTYPE
) {
295 if (isuseless(p
) == 0)
298 if (optype(p
->n_op
) == UTYPE
) {
301 return deluseless(l
);
304 /* Be sure that both leaves may be valid */
305 l
= deluseless(p
->n_left
);
306 r
= deluseless(p
->n_right
);
310 DLIST_INSERT_AFTER(&prepole
, ip
, qelem
);
320 * Receives interpass structs from pass1.
323 pass2_compile(struct interpass
*ip
)
325 void deljumps(struct p2env
*);
326 struct p2env
*p2e
= &p2env
;
330 if (ip
->type
== IP_PROLOG
) {
331 memset(p2e
, 0, sizeof(struct p2env
));
332 p2e
->ipp
= (struct interpass_prolog
*)ip
;
333 DLIST_INIT(&p2e
->ipole
, qelem
);
335 DLIST_INSERT_BEFORE(&p2e
->ipole
, ip
, qelem
);
336 if (ip
->type
!= IP_EPILOG
)
341 printf("Entering pass2\n");
342 printip(&p2e
->ipole
);
346 p2e
->epp
= (struct interpass_prolog
*)DLIST_PREV(&p2e
->ipole
, qelem
);
347 p2maxautooff
= p2autooff
= p2e
->epp
->ipp_autos
;
352 myreader(&p2e
->ipole
); /* local massage of input */
355 * Do initial modification of the trees. Two loops;
356 * - first, search for ADDROF of TEMPs, these must be
357 * converterd to OREGs on stack.
358 * - second, do the actual conversions, in case of not xtemps
359 * convert all temporaries to stack references.
362 if (p2e
->epp
->ip_tmpnum
!= p2e
->ipp
->ip_tmpnum
) {
363 addrp
= tmpcalloc(sizeof(int) *
364 (p2e
->epp
->ip_tmpnum
- p2e
->ipp
->ip_tmpnum
));
365 addrp
-= p2e
->ipp
->ip_tmpnum
;
369 DLIST_FOREACH(ip
, &p2e
->ipole
, qelem
) {
370 if (ip
->type
== IP_NODE
)
371 walkf(ip
->ip_node
, findaof
, addrp
);
374 DLIST_FOREACH(ip
, &p2e
->ipole
, qelem
)
375 if (ip
->type
== IP_NODE
)
376 walkf(ip
->ip_node
, deltemp
, addrp
);
381 printf("Efter ADDROF/TEMP\n");
382 printip(&p2e
->ipole
);
386 DLIST_INIT(&prepole
, qelem
);
387 DLIST_FOREACH(ip
, &p2e
->ipole
, qelem
) {
388 if (ip
->type
!= IP_NODE
)
391 if ((ip
->ip_node
= deluseless(ip
->ip_node
)) == NULL
) {
392 DLIST_REMOVE(ip
, qelem
);
393 } else while (!DLIST_ISEMPTY(&prepole
, qelem
)) {
394 struct interpass
*tipp
;
396 tipp
= DLIST_NEXT(&prepole
, qelem
);
397 DLIST_REMOVE(tipp
, qelem
);
398 DLIST_INSERT_BEFORE(ip
, tipp
, qelem
);
402 fixxasm(p2e
); /* setup for extended asm */
407 if (xssaflag
&& xtemps
&& xdeljumps
)
410 DLIST_FOREACH(ip
, &p2e
->ipole
, qelem
)
415 emit(struct interpass
*ip
)
426 canon(p
); /* may convert stuff after genregs */
428 printf("emit IP_NODE:\n");
429 fwalk(p
, e2print
, 0);
433 /* Only emit branch insn if RESCC */
434 /* careful when an OPLOG has been elided */
435 if (p
->n_left
->n_su
== 0 && p
->n_left
->n_left
!= NULL
) {
436 op
= &table
[TBLIDX(p
->n_left
->n_left
->n_su
)];
439 op
= &table
[TBLIDX(p
->n_left
->n_su
)];
442 if (op
->rewrite
& RESCC
) {
445 cbgen(o
, p
->n_right
->n_lval
);
451 gencode(p
->n_left
, INREGS
);
457 if (p
->n_op
!= REG
|| p
->n_type
!= VOID
) /* XXX */
458 gencode(p
, FOREFF
); /* Emit instructions */
464 prologue((struct interpass_prolog
*)ip
);
467 eoftn((struct interpass_prolog
*)ip
);
468 p2maxautooff
= p2autooff
= AUTOINIT
/SZCHAR
;
474 printf("%s", ip
->ip_asm
);
477 cerror("emit %d", ip
->type
);
502 * print a nice-looking description of cookie
510 if (cookie
& SPECIAL
) {
519 snprintf(buf
, sizeof(buf
), "SPECIAL+%d", cookie
& ~SPECIAL
);
526 for (i
= 0; cnames
[i
]; ++i
) {
527 if (cookie
& (1<<i
)) {
529 strlcat(buf
, "|", sizeof(buf
));
531 strlcat(buf
, cnames
[i
], sizeof(buf
));
539 geninsn(NODE
*p
, int cookie
)
546 printf("geninsn(%p, %s)\n", p
, prcook(cookie
));
547 fwalk(p
, e2print
, 0);
552 cookie
&= ~QUIET
; /* XXX - should not be necessary */
554 again
: switch (o
= p
->n_op
) {
567 if (p2
->n_op
== ICON
&& p2
->n_lval
== 0 && *p2
->n_name
== 0 &&
568 (dope
[p1
->n_op
] & (FLOFLG
|DIVFLG
|SIMPFLG
|SHFFLG
))) {
569 #ifdef mach_pdp11 /* XXX all targets? */
570 if ((rv
= geninsn(p1
, FORCC
|QUIET
)) != FFAIL
)
573 if (findops(p1
, FORCC
) > 0)
590 rv
= findops(p
, cookie
);
595 if ((rv
= findmops(p
, cookie
)) != FFAIL
)
600 rv
= findasg(p
, cookie
);
603 case UMUL
: /* May turn into an OREG */
604 rv
= findumul(p
, cookie
);
613 rv
= findleaf(p
, cookie
);
618 /* CALL arguments are handled special */
619 for (p1
= p
->n_right
; p1
->n_op
== CM
; p1
= p1
->n_left
)
620 (void)geninsn(p1
->n_right
, FOREFF
);
621 (void)geninsn(p1
, FOREFF
);
635 rv
= finduni(p
, cookie
);
641 p1
->n_label
= (int)p2
->n_lval
;
642 (void)geninsn(p1
, FORCC
);
646 case FORCE
: /* XXX needed? */
647 (void)geninsn(p
->n_left
, INREGS
);
648 p
->n_su
= 0; /* su calculations traverse left */
652 for (p1
= p
->n_left
; p1
->n_op
== CM
; p1
= p1
->n_left
)
653 (void)geninsn(p1
->n_right
, FOREFF
);
654 (void)geninsn(p1
, FOREFF
);
655 break; /* all stuff already done? */
658 /* generate code for correct class here */
660 geninsn(p
->n_left
, 1 << p
->n_label
);
665 comperr("geninsn: bad op %s, node %p", opst
[o
], p
);
667 if (rv
== FFAIL
&& !q
)
668 comperr("Cannot generate code, node %p op %s", p
,opst
[p
->n_op
]);
673 printf("geninsn(%p, %s) rv %d\n", p
, prcook(cookie
), rv
);
674 fwalk(p
, e2print
, 0);
681 * Store a given subtree in a temporary location.
682 * Return an OREG node where it is located.
687 extern struct interpass
*storesave
;
688 struct interpass
*ip
;
692 s
= BITOOR(freetemp(szty(p
->n_type
)));
693 q
= mklnode(OREG
, s
, FPREG
, p
->n_type
);
694 r
= mklnode(OREG
, s
, FPREG
, p
->n_type
);
695 ip
= ipnode(mkbinode(ASSIGN
, q
, p
, p
->n_type
));
702 #define CDEBUG(x) if (c2debug) printf x
708 * Do a register-register move if necessary.
711 ckmove(NODE
*p
, NODE
*q
)
713 if (q
->n_op
!= REG
|| p
->n_reg
== -1)
714 return; /* no register */
715 if (DECRA(p
->n_reg
, 0) == DECRA(q
->n_reg
, 0))
716 return; /* no move necessary */
717 CDEBUG(("rmove: node %p, %s -> %s\n", p
, rnames
[DECRA(q
->n_reg
, 0)],
718 rnames
[DECRA(p
->n_reg
, 0)]));
719 rmove(DECRA(q
->n_reg
, 0), DECRA(p
->n_reg
, 0), p
->n_type
);
720 q
->n_reg
= q
->n_rval
= DECRA(p
->n_reg
, 0);
724 * Rewrite node to register after instruction emit.
727 rewrite(NODE
*p
, int dorewrite
, int cookie
)
739 if (o
== ASSIGN
|| o
== STASG
) {
740 /* special rewrite care */
741 int reg
= DECRA(p
->n_reg
, 0);
742 #define TL(x) (TBLIDX(x->n_su) || x->n_op == REG)
745 else if (TL(l
) && (DECRA(l
->n_reg
, 0) == reg
))
747 else if (TL(r
) && (DECRA(r
->n_reg
, 0) == reg
))
750 rmove(DECRA(l
->n_reg
, 0), reg
, p
->n_type
);
752 rmove(DECRA(r
->n_reg
, 0), reg
, p
->n_type
);
759 if (optype(o
) != LTYPE
)
761 if (optype(o
) == BITYPE
)
765 CDEBUG(("rewrite: %p, reg %s\n", p
,
766 p
->n_reg
== -1? "<none>" : rnames
[DECRA(p
->n_reg
, 0)]));
767 p
->n_rval
= DECRA(p
->n_reg
, 0);
771 #define XASM_TARGARG(x,y) 0
775 * printout extended assembler.
784 if (p
->n_left
->n_op
!= ICON
|| p
->n_left
->n_type
!= STRTY
) {
785 for (q
= p
->n_left
; q
->n_op
== CM
; q
= q
->n_left
)
787 nary
= tmpcalloc(sizeof(NODE
*)*(n
+1));
789 for (q
= p
->n_left
; q
->n_op
== CM
; q
= q
->n_left
) {
790 gencode(q
->n_right
->n_left
, INREGS
);
791 nary
[--o
] = q
->n_right
;
793 gencode(q
->n_left
, INREGS
);
804 else if (XASM_TARGARG(w
, nary
))
805 ; /* handled by target */
806 else if (w
[1] < '0' || w
[1] > (n
+ '0'))
807 uerror("bad xasm arg number %c", w
[1]);
809 if (w
[1] == (n
+ '0'))
810 q
= nary
[(int)w
[1]-'0' - 1]; /* XXX */
812 q
= nary
[(int)w
[1]-'0'];
813 adrput(stdout
, q
->n_left
);
816 } else if (*w
== '\\') { /* Always 3-digit octal */
817 int num
= *++w
- '0';
818 num
= (num
<< 3) + *++w
- '0';
819 num
= (num
<< 3) + *++w
- '0';
829 gencode(NODE
*p
, int cookie
)
831 struct optab
*q
= &table
[TBLIDX(p
->n_su
)];
833 int o
= optype(p
->n_op
);
835 int ismops
= (p
->n_op
== ASSIGN
&& (p
->n_flags
& 1));
841 if (TBLIDX(p
->n_su
) == 0) {
842 if (o
== BITYPE
&& (p
->n_su
& DORIGHT
))
844 if (optype(p
->n_op
) != LTYPE
)
846 if (o
== BITYPE
&& !(p
->n_su
& DORIGHT
))
851 CDEBUG(("gencode: node %p\n", p
));
853 if (p
->n_op
== REG
&& DECRA(p
->n_reg
, 0) == p
->n_rval
)
854 return; /* meaningless move to itself */
857 lastcall(p
); /* last chance before function args */
858 if (p
->n_op
== CALL
|| p
->n_op
== FORTCALL
|| p
->n_op
== STCALL
) {
859 /* Print out arguments first */
860 for (p1
= r
; p1
->n_op
== CM
; p1
= p1
->n_left
)
861 gencode(p1
->n_right
, FOREFF
);
863 o
= UTYPE
; /* avoid going down again */
866 if (o
== BITYPE
&& (p
->n_su
& DORIGHT
)) {
868 if (q
->rewrite
& RRIGHT
)
878 if (q
->rewrite
& RLEFT
)
881 if (o
== BITYPE
&& !(p
->n_su
& DORIGHT
)) {
883 if (q
->rewrite
& RRIGHT
)
889 /* reduce right tree to make expand() work */
890 if (optype(r
->n_op
) != LTYPE
) {
892 r
= tcopy(r
->n_right
);
901 if (q
->needs
& NSPECIAL
) {
902 int rr
= rspecial(q
, NRIGHT
);
903 int lr
= rspecial(q
, NLEFT
);
907 if (optype(p
->n_op
) != BITYPE
)
908 comperr("gencode: rspecial borked");
911 comperr("gencode: rop != REG");
913 rmove(r
->n_rval
, rr
, r
->n_type
);
914 r
->n_rval
= r
->n_reg
= rr
;
918 comperr("gencode: %p lop != REG", p
);
920 rmove(l
->n_rval
, lr
, l
->n_type
);
921 l
->n_rval
= l
->n_reg
= lr
;
923 if (rr
>= 0 && lr
>= 0 && (l
->n_reg
== rr
|| r
->n_reg
== lr
))
924 comperr("gencode: cross-reg-move");
927 if (p
->n_op
== ASSIGN
&&
928 p
->n_left
->n_op
== REG
&& p
->n_right
->n_op
== REG
&&
929 p
->n_left
->n_rval
== p
->n_right
->n_rval
&&
930 (p
->n_su
& RVCC
) == 0) { /* XXX should check if necessary */
931 /* do not emit anything */
932 CDEBUG(("gencode(%p) assign nothing\n", p
));
933 rewrite(p
, q
->rewrite
, cookie
);
937 CDEBUG(("emitting node %p\n", p
));
938 if (TBLIDX(p
->n_su
) == 0)
941 expand(p
, cookie
, q
->cstring
);
943 if (ismops
&& DECRA(p
->n_reg
, 0) != regno(l
) && cookie
!= FOREFF
) {
944 CDEBUG(("gencode(%p) rmove\n", p
));
945 rmove(regno(l
), DECRA(p
->n_reg
, 0), p
->n_type
);
948 if (callop(p
->n_op
) && cookie
!= FOREFF
&&
949 DECRA(p
->n_reg
, 0) != RETREG(p
->n_type
)) {
950 CDEBUG(("gencode(%p) retreg\n", p
));
951 rmove(RETREG(p
->n_type
), DECRA(p
->n_reg
, 0), p
->n_type
);
952 } else if (q
->needs
& NSPECIAL
) {
953 int rr
= rspecial(q
, NRES
);
955 if (rr
>= 0 && DECRA(p
->n_reg
, 0) != rr
) {
956 CDEBUG(("gencode(%p) nspec retreg\n", p
));
957 rmove(rr
, DECRA(p
->n_reg
, 0), p
->n_type
);
959 } else if ((q
->rewrite
& RESC1
) &&
960 (DECRA(p
->n_reg
, 1) != DECRA(p
->n_reg
, 0))) {
961 CDEBUG(("gencode(%p) RESC1 retreg\n", p
));
962 rmove(DECRA(p
->n_reg
, 1), DECRA(p
->n_reg
, 0), p
->n_type
);
965 /* XXX - kolla upp det h{r */
966 else if (p
->n_op
== ASSIGN
) {
967 /* may need move added if RLEFT/RRIGHT */
968 /* XXX should be handled in sucomp() */
969 if ((q
->rewrite
& RLEFT
) && (p
->n_left
->n_op
== REG
) &&
970 (p
->n_left
->n_rval
!= DECRA(p
->n_reg
, 0)) &&
972 rmove(p
->n_left
->n_rval
, DECRA(p
->n_reg
, 0), p
->n_type
);
973 } else if ((q
->rewrite
& RRIGHT
) && (p
->n_right
->n_op
== REG
) &&
974 (p
->n_right
->n_rval
!= DECRA(p
->n_reg
, 0)) &&
976 rmove(p
->n_right
->n_rval
, DECRA(p
->n_reg
, 0), p
->n_type
);
980 rewrite(p
, q
->rewrite
, cookie
);
983 int negrel
[] = { NE
, EQ
, GT
, GE
, LT
, LE
, UGT
, UGE
, ULT
, ULE
} ; /* negatives of relationals */
984 size_t negrelsize
= sizeof negrel
/ sizeof negrel
[0];
989 e2print(NODE
*p
, int down
, int *a
, int *b
)
992 extern int tablesize
;
998 fprintf(prfil
, "\t");
1001 if( down
-- ) fprintf(prfil
, " " );
1004 fprintf(prfil
, "%p) %s", p
, opst
[p
->n_op
] );
1005 switch( p
->n_op
) { /* special cases */
1008 fprintf(prfil
, " sz=%d, shift=%d",
1009 UPKFSZ(p
->n_rval
), UPKFOFF(p
->n_rval
));
1013 fprintf(prfil
, " %s", rnames
[p
->n_rval
] );
1017 fprintf(prfil
, " %d", regno(p
));
1022 fprintf(prfil
, " '%s'", p
->n_name
);
1028 fprintf(prfil
, " " );
1036 fprintf(prfil
, " size=%d", p
->n_stsize
);
1037 fprintf(prfil
, " align=%d", p
->n_stalign
);
1041 fprintf(prfil
, ", " );
1042 tprint(prfil
, p
->n_type
, p
->n_qual
);
1043 fprintf(prfil
, ", " );
1046 fprintf(prfil
, ", SU= %d(%cREG,%s,%s,%s,%s,%s,%s)\n",
1048 TCLASS(p
->n_su
)+'@',
1050 TBLIDX(p
->n_su
) >= 0 && TBLIDX(p
->n_su
) <= tablesize
?
1051 table
[TBLIDX(p
->n_su
)].cstring
: "",
1055 p
->n_su
& LREG
? "LREG" : "", p
->n_su
& RREG
? "RREG" : "",
1056 p
->n_su
& RVEFF
? "RVEFF" : "", p
->n_su
& RVCC
? "RVCC" : "",
1057 p
->n_su
& DORIGHT
? "DORIGHT" : "");
1063 * do this if there is no special hardware support for fields
1066 ffld(NODE
*p
, int down
, int *down1
, int *down2
)
1069 * look for fields that are not in an lvalue context,
1070 * and rewrite them...
1075 *down1
= asgop( p
->n_op
);
1078 if( !down
&& p
->n_op
== FLD
){ /* rewrite the node */
1080 if( !rewfld(p
) ) return;
1086 o
= UPKFOFF(v
); /* amount to shift */
1088 o
= szty(p
->n_type
)*SZINT
- s
- UPKFOFF(v
); /* amount to shift */
1090 /* make & mask part */
1092 if (ISUNSIGNED(ty
)) {
1094 p
->n_left
->n_type
= ty
;
1096 p
->n_right
= mklnode(ICON
, ((CONSZ
)1 << s
)-1, 0, ty
);
1098 /* now, if a shift is needed, do it */
1100 shp
= mkbinode(RS
, p
->n_left
,
1101 mklnode(ICON
, o
, 0, INT
), ty
);
1109 #define SZT(x) case x: mz = SZ ## x; break;
1111 SZT(CHAR
) SZT(SHORT
) SZT(INT
) SZT(LONG
)
1114 /* must sign-extend, assume RS will do */
1115 /* if not, arch must use rewfld() */
1116 p
->n_left
->n_type
= ty
;
1118 p
->n_right
= mklnode(ICON
, mz
-s
, 0, INT
);
1119 p
->n_left
= mkbinode(LS
, p
->n_left
,
1120 mklnode(ICON
, mz
-s
-o
, 0, INT
), ty
);
1127 * change left TEMPs into OREGs
1130 deltemp(NODE
*p
, void *arg
)
1135 if (p
->n_op
== TEMP
) {
1136 if (aor
[regno(p
)] == 0) {
1139 aor
[regno(p
)] = BITOOR(freetemp(szty(p
->n_type
)));
1141 l
= mklnode(REG
, 0, FPREG
, INCREF(p
->n_type
));
1142 r
= mklnode(ICON
, aor
[regno(p
)], 0, INT
);
1143 p
->n_left
= mkbinode(PLUS
, l
, r
, INCREF(p
->n_type
));
1145 } else if (p
->n_op
== ADDROF
&& p
->n_left
->n_op
== OREG
) {
1149 l
->n_type
= INCREF(l
->n_type
);
1150 p
->n_right
= mklnode(ICON
, l
->n_lval
, 0, INT
);
1151 } else if (p
->n_op
== ADDROF
&& p
->n_left
->n_op
== UMUL
) {
1153 *p
= *p
->n_left
->n_left
;
1160 * for pointer/integer arithmetic, set pointer at left node
1163 setleft(NODE
*p
, void *arg
)
1167 /* only additions for now */
1168 if (p
->n_op
!= PLUS
)
1170 if (ISPTR(p
->n_right
->n_type
) && !ISPTR(p
->n_left
->n_type
)) {
1172 p
->n_right
= p
->n_left
;
1177 /* It is OK to have these as externals */
1179 static CONSZ oregtemp
;
1180 static char *oregcp
;
1182 * look for situations where we can turn * into OREG
1183 * If sharp then do not allow temps.
1186 oregok(NODE
*p
, int sharp
)
1197 if ((q
->n_op
== REG
|| (q
->n_op
== TEMP
&& !sharp
)) &&
1198 q
->n_rval
== DECRA(q
->n_reg
, 0)) {
1200 if (q
->n_op
== REG
|| (q
->n_op
== TEMP
&& !sharp
)) {
1207 if (q
->n_op
!= PLUS
&& q
->n_op
!= MINUS
)
1214 /* look for doubly indexed expressions */
1215 /* XXX - fix checks */
1217 if( q
->n_op
== PLUS
) {
1219 if( (r
=base(ql
))>=0 && (i
=offset(qr
, tlen(p
)))>=0) {
1220 makeor2(p
, ql
, r
, i
);
1222 } else if((r
=base(qr
))>=0 && (i
=offset(ql
, tlen(p
)))>=0) {
1223 makeor2(p
, qr
, r
, i
);
1232 if( (q
->n_op
==PLUS
|| q
->n_op
==MINUS
) && qr
->n_op
== ICON
&&
1233 (ql
->n_op
==REG
|| (ql
->n_op
==TEMP
&& !sharp
)) &&
1234 szty(qr
->n_type
)==1 &&
1235 (ql
->n_rval
== DECRA(ql
->n_reg
, 0) ||
1237 ql
->n_rval
== FPREG
|| ql
->n_rval
== STKREG
)) {
1239 if ((q
->n_op
==PLUS
|| q
->n_op
==MINUS
) && qr
->n_op
== ICON
&&
1240 (ql
->n_op
==REG
|| (ql
->n_op
==TEMP
&& !sharp
))) {
1243 if( q
->n_op
== MINUS
) temp
= -temp
;
1247 if( *cp
&& ( q
->n_op
== MINUS
|| *ql
->n_name
) )
1249 if( !*cp
) cp
= ql
->n_name
;
1252 if( notoff( p
->n_type
, r
, temp
, cp
))
1265 NODE
*q
= p
->n_left
;
1269 p
->n_lval
= oregtemp
;
1275 * look for situations where we can turn * into OREG
1278 oreg2(NODE
*p
, void *arg
)
1280 if (p
->n_op
!= UMUL
)
1284 if (p
->n_op
== UMUL
)
1290 /* put p in canonical form */
1292 walkf(p
, setleft
, 0); /* ptrs at left node for arithmetic */
1293 walkf(p
, oreg2
, 0); /* look for and create OREG nodes */
1295 fwalk(p
, ffld
, 0); /* look for field operators */
1297 mycanon(p
); /* your own canonicalization routine(s) */
1302 comperr(char *str
, ...)
1304 extern char *ftitle
;
1309 "cannot recover from earlier errors: goodbye!\n");
1314 fprintf(stderr
, "%s, line %d: compiler error: ", ftitle
, thisline
);
1315 vfprintf(stderr
, str
, ap
);
1316 fprintf(stderr
, "\n");
1321 if (nodepole
&& nodepole
->n_op
!= FREE
)
1322 fwalk(nodepole
, e2print
, 0);
1328 * allocate k integers worth of temp space
1329 * we also make the convention that, if the number of words is
1330 * more than 1, it must be aligned for storing doubles...
1331 * Returns bits offset from base register.
1341 SETOFF(p2autooff
, ALDOUBLE
/ALCHAR
);
1344 p2autooff
+= k
*(SZINT
/SZCHAR
);
1345 if (p2autooff
> p2maxautooff
)
1346 p2maxautooff
= p2autooff
;
1350 p2autooff
+= k
*(SZINT
/SZCHAR
);
1352 SETOFF(p2autooff
, ALDOUBLE
/ALCHAR
);
1354 if (p2autooff
> p2maxautooff
)
1355 p2maxautooff
= p2autooff
;
1356 return( -p2autooff
);
1361 mklnode(int op
, CONSZ lval
, int rval
, TWORD type
)
1378 mkbinode(int op
, NODE
*left
, NODE
*right
, TWORD type
)
1395 mkunode(int op
, NODE
*left
, int rval
, TWORD type
)
1414 struct interpass
*ip
= tmpalloc(sizeof(struct interpass
));
1418 ip
->lineno
= thisline
;
1423 rspecial(struct optab
*q
, int what
)
1425 struct rspecial
*r
= nspecial(q
);
1434 #ifndef XASM_NUMCONV
1435 #define XASM_NUMCONV(x,y,z) 0
1439 * change numeric argument redirections to the correct node type after
1440 * cleaning up the other nodes.
1441 * be careful about input operands that may have different value than output.
1444 delnums(NODE
*p
, void *arg
)
1446 struct interpass
*ip
= arg
, *ip2
;
1447 NODE
*r
= ip
->ip_node
->n_left
;
1452 if (p
->n_name
[0] < '0' || p
->n_name
[0] > '9')
1453 return; /* not numeric */
1454 if ((q
= listarg(r
, p
->n_name
[0] - '0', &cnt
)) == NIL
)
1455 comperr("bad delnums");
1457 /* target may have opinions whether to do this conversion */
1458 if (XASM_NUMCONV(ip
, p
, q
))
1461 /* Delete number by adding move-to/from-temp. Later on */
1462 /* the temps may be rewritten to other LTYPEs */
1463 num
= p2env
.epp
->ip_tmpnum
++;
1466 t
= p
->n_left
->n_type
;
1467 r
= mklnode(TEMP
, 0, num
, t
);
1468 ip2
= ipnode(mkbinode(ASSIGN
, tcopy(r
), p
->n_left
, t
));
1469 DLIST_INSERT_BEFORE(ip
, ip2
, qelem
);
1473 t
= q
->n_left
->n_type
;
1474 r
= mklnode(TEMP
, 0, num
, t
);
1475 ip2
= ipnode(mkbinode(ASSIGN
, q
->n_left
, tcopy(r
), t
));
1476 DLIST_INSERT_AFTER(ip
, ip2
, qelem
);
1479 p
->n_name
= tmpstrdup(q
->n_name
);
1480 if (*p
->n_name
== '=')
1485 * Ensure that a node is correct for the destination.
1488 ltypify(NODE
*p
, void *arg
)
1490 struct interpass
*ip
= arg
;
1491 struct interpass
*ip2
;
1492 TWORD t
= p
->n_left
->n_type
;
1499 return; /* handled by target-specific code */
1501 cw
= xasmcode(p
->n_name
);
1502 switch (ww
= XASMVAL(cw
)) {
1505 /* just make register of it */
1506 p
->n_name
= tmpstrdup(p
->n_name
);
1507 c
= strchr(p
->n_name
, XASMVAL(cw
)); /* cannot fail */
1510 case 'g': /* general; any operand */
1511 if (ww
== 'g' && p
->n_left
->n_op
== ICON
) {
1512 /* should only be input */
1516 case 'r': /* general reg */
1517 /* set register class */
1518 p
->n_label
= gclass(p
->n_left
->n_type
);
1519 if (p
->n_left
->n_op
== REG
)
1522 r
= (cw
& XASMINOUT
? tcopy(q
) : q
);
1523 p
->n_left
= mklnode(TEMP
, 0, p2env
.epp
->ip_tmpnum
++, t
);
1524 if ((cw
& XASMASG
) == 0) {
1525 ip2
= ipnode(mkbinode(ASSIGN
, tcopy(p
->n_left
), r
, t
));
1526 DLIST_INSERT_BEFORE(ip
, ip2
, qelem
);
1528 if (cw
& (XASMASG
|XASMINOUT
)) {
1529 /* output parameter */
1530 ip2
= ipnode(mkbinode(ASSIGN
, q
, tcopy(p
->n_left
), t
));
1531 DLIST_INSERT_AFTER(ip
, ip2
, qelem
);
1535 case '0': case '1': case '2': case '3': case '4':
1536 case '5': case '6': case '7': case '8': case '9':
1539 case 'm': /* memory operand */
1540 /* store and reload value */
1542 if (optype(q
->n_op
) == LTYPE
) {
1543 if (q
->n_op
== TEMP
) {
1544 ooff
= BITOOR(freetemp(szty(t
)));
1545 cvtemps(ip
, q
->n_rval
, ooff
);
1546 } else if (q
->n_op
== REG
)
1547 comperr("xasm m and reg");
1548 } else if (q
->n_op
== UMUL
&&
1549 (q
->n_left
->n_op
!= TEMP
&& q
->n_left
->n_op
!= REG
)) {
1550 t
= q
->n_left
->n_type
;
1551 ooff
= p2env
.epp
->ip_tmpnum
++;
1552 ip2
= ipnode(mkbinode(ASSIGN
,
1553 mklnode(TEMP
, 0, ooff
, t
), q
->n_left
, t
));
1554 q
->n_left
= mklnode(TEMP
, 0, ooff
, t
);
1555 DLIST_INSERT_BEFORE(ip
, ip2
, qelem
);
1559 case 'i': /* immediate constant */
1560 case 'n': /* numeric constant */
1561 if (p
->n_left
->n_op
== ICON
)
1563 p
->n_name
= tmpstrdup(p
->n_name
);
1564 c
= strchr(p
->n_name
, XASMVAL(cw
)); /* cannot fail */
1566 c
[0] = c
[1], c
[1] = 0;
1569 uerror("constant required");
1573 uerror("unsupported xasm option string '%s'", p
->n_name
);
1577 /* Extended assembler hacks */
1579 fixxasm(struct p2env
*p2e
)
1581 struct interpass
*pole
= &p2e
->ipole
;
1582 struct interpass
*ip
;
1585 DLIST_FOREACH(ip
, pole
, qelem
) {
1586 if (ip
->type
!= IP_NODE
|| ip
->ip_node
->n_op
!= XASM
)
1588 thisline
= ip
->lineno
;
1589 p
= ip
->ip_node
->n_left
;
1591 if (p
->n_op
== ICON
&& p
->n_type
== STRTY
)
1594 /* replace numeric redirections with its underlying type */
1595 flist(p
, delnums
, ip
);
1598 * Ensure that the arg nodes can be directly addressable
1599 * We decide that everything shall be LTYPE here.
1601 flist(p
, ltypify
, ip
);
1606 * Extract codeword from xasm string */
1614 case '=': cw
|= XASMASG
; break;
1615 case '&': cw
|= XASMCONSTR
; break;
1616 case '+': cw
|= XASMINOUT
; break;
1619 if ((*s
>= 'a' && *s
<= 'z') ||
1620 (*s
>= 'A' && *s
<= 'Z') ||
1621 (*s
>= '0' && *s
<= '9')) {
1625 cw
|= (*s
<< ((nm
+ 1) * 8));
1629 uerror("bad xasm constraint %c", *s
);
1636 static int xasnum
, xoffnum
;
1639 xconv(NODE
*p
, void *arg
)
1641 if (p
->n_op
!= TEMP
|| p
->n_rval
!= xasnum
)
1645 p
->n_lval
= xoffnum
;
1649 * Convert nodes of type TEMP to op with lval off.
1652 cvtemps(struct interpass
*ipl
, int tnum
, int off
)
1654 struct interpass
*ip
;
1659 DLIST_FOREACH(ip
, ipl
, qelem
)
1660 if (ip
->type
== IP_NODE
)
1661 walkf(ip
->ip_node
, xconv
, 0);
1662 walkf(ipl
->ip_node
, xconv
, 0);