1 /* neatcc intermediate code generation */
7 static struct ic
*ic
; /* intermediate code */
8 static long ic_n
, ic_sz
; /* number of instructions in ic[] */
9 static long iv
[NTMPS
]; /* operand stack */
10 static long iv_n
; /* number of values in iv[] */
11 static long *lab_loc
; /* label locations */
12 static long lab_n
, lab_sz
; /* number of labels in lab_loc[] */
13 static long lab_last
; /* the last label target */
15 static int io_num(void);
16 static int io_mul2(void);
17 static int io_cmp(void);
18 static int io_jmp(void);
19 static int io_addr(void);
20 static int io_loc(void);
21 static int io_imm(void);
22 static int io_call(void);
23 static void io_deadcode(void);
25 static struct ic
*ic_new(void)
28 ic_sz
= MAX(128, ic_sz
* 2);
29 ic
= mextend(ic
, ic_n
, ic_sz
, sizeof(*ic
));
34 static struct ic
*ic_put(long op
, long arg0
, long arg1
, long arg2
)
36 struct ic
*c
= ic_new();
44 static void ic_back(long pos
)
47 for (i
= pos
; i
< ic_n
; i
++)
48 if (ic
[i
].op
& O_CALL
)
53 static long iv_pop(void)
58 static long iv_get(int n
)
60 return iv
[iv_n
- n
- 1];
63 static long iv_new(void)
69 static void iv_put(long n
)
74 static void iv_drop(int n
)
76 iv_n
= MAX(0, iv_n
- n
);
79 static void iv_swap(int x
, int y
)
81 long v
= iv
[iv_n
- x
- 1];
82 iv
[iv_n
- x
- 1] = iv
[iv_n
- y
- 1];
86 static void iv_dup(void)
88 iv
[iv_n
] = iv
[iv_n
- 1];
94 ic_put(O_MOV
| O_NUM
, iv_new(), n
, 0);
99 ic_put(O_MOV
| O_LOC
, iv_new(), id
, 0);
102 void o_sym(char *sym
)
104 ic_put(O_MOV
| O_SYM
, iv_new(), out_sym(sym
), 0);
107 void o_tmpdrop(int n
)
109 iv_drop(n
>= 0 ? n
: iv_n
);
122 /* return one if the given value is constant */
123 static int ic_const(long iv
)
125 long oc
= O_C(ic
[iv
].op
);
126 return oc
& O_MOV
&& oc
& (O_NUM
| O_SYM
| O_LOC
);
129 /* return one if the given value is a simple load */
130 static int ic_load(long iv
)
132 long oc
= O_C(ic
[iv
].op
);
133 return oc
& O_LD
&& oc
& (O_NUM
| O_SYM
| O_LOC
);
140 if (ic_const(r2
) && !ic_const(r1
)) { /* load constants last */
141 ic_put(ic
[r2
].op
, iv_new(), ic
[r2
].arg1
, ic
[r2
].arg2
);
144 ic_put(op
, iv_new(), r2
, r1
);
145 io_num() && io_mul2() && io_addr() && io_imm();
151 ic_put(op
, iv_new(), r1
, 0);
156 void o_assign(long bt
)
158 ic_put(O_MK(O_ST
| O_NUM
, bt
), iv_get(0), iv_get(1), 0);
164 void o_deref(long bt
)
167 ic_put(O_MK(O_LD
| O_NUM
, bt
), iv_new(), r1
, 0);
173 if (T_SZ(bt
) != ULNG
) {
175 ic_put(O_MK(O_MOV
, bt
), iv_new(), r1
, 0);
185 ic_put(O_MCPY
, r0
, r1
, r2
);
193 ic_put(O_MSET
, r0
, r1
, r2
);
196 void o_call(int argc
, int ret
)
199 long *args
= malloc(argc
* sizeof(c
->args
[0]));
201 for (i
= argc
- 1; i
>= 0; --i
)
203 for (i
= argc
- 1; i
>= 0; --i
) {
205 if (ic_const(iv
) || ic_load(iv
)) { /* load constants last */
206 ic_put(ic
[iv
].op
, iv_new(), ic
[iv
].arg1
, ic
[iv
].arg2
);
211 c
= ic_put(O_CALL
, iv_new(), r1
, argc
);
221 ic_put(O_RET
, iv_pop(), 0, 0);
224 void o_label(long id
)
226 while (id
>= lab_sz
) {
227 lab_sz
= MAX(128, lab_sz
* 2);
228 lab_loc
= mextend(lab_loc
, lab_n
, lab_sz
, sizeof(*lab_loc
));
231 lab_loc
[lab_n
++] = -1;
238 ic_put(O_JMP
, 0, 0, id
);
243 ic_put(O_JZ
, iv_pop(), 0, id
);
247 int o_popnum(long *n
)
249 if (ic_num(ic
, iv_get(0), n
))
255 int o_popsym(long *sym
, long *off
)
257 if (ic_sym(ic
, iv_get(0), sym
, off
))
268 void o_back(long mark
)
273 void ic_get(struct ic
**c
, long *n
)
276 if (!ic_n
|| ~ic
[ic_n
- 1].op
& O_RET
|| lab_last
== ic_n
)
278 for (i
= 0; i
< ic_n
; i
++) /* filling branch targets */
279 if (ic
[i
].op
& O_JXX
)
280 ic
[i
].arg2
= lab_loc
[ic
[i
].arg2
];
281 io_deadcode(); /* removing dead code */
295 void ic_free(struct ic
*ic
)
301 /* intermediate code queries */
303 static long cb(long op
, long a
, long b
)
325 return O_T(op
) & T_MSIGN
? a
>> b
: (unsigned long) a
>> b
;
342 static long cu(int op
, long i
)
355 static long c_cast(long n
, unsigned bt
)
357 if (!(bt
& T_MSIGN
) && T_SZ(bt
) != ULNG
)
358 n
&= ((1l << (long) (T_SZ(bt
) * 8)) - 1);
359 if (bt
& T_MSIGN
&& T_SZ(bt
) != ULNG
&&
360 n
> (1l << (T_SZ(bt
) * 8 - 1)))
361 n
= -((1l << (T_SZ(bt
) * 8)) - n
);
365 int ic_num(struct ic
*ic
, long iv
, long *n
)
368 long oc
= O_C(ic
[iv
].op
);
369 long bt
= O_T(ic
[iv
].op
);
370 if (oc
& O_MOV
&& oc
& O_NUM
) {
375 if (ic_num(ic
, ic
[iv
].arg1
, &n1
))
377 if (ic_num(ic
, ic
[iv
].arg2
, &n2
))
379 *n
= cb(ic
[iv
].op
, n1
, n2
);
383 if (ic_num(ic
, ic
[iv
].arg1
, &n1
))
385 *n
= cu(ic
[iv
].op
, n1
);
388 if (oc
& O_MOV
&& !(oc
& (O_NUM
| O_LOC
| O_SYM
))) {
389 if (ic_num(ic
, ic
[iv
].arg1
, &n1
))
397 int ic_sym(struct ic
*ic
, long iv
, long *sym
, long *off
)
400 long oc
= O_C(ic
[iv
].op
);
401 if (oc
& O_MOV
&& oc
& O_SYM
) {
407 if ((ic_sym(ic
, ic
[iv
].arg1
, sym
, off
) ||
408 ic_num(ic
, ic
[iv
].arg2
, &n
)) &&
409 (ic_sym(ic
, ic
[iv
].arg2
, sym
, off
) ||
410 ic_num(ic
, ic
[iv
].arg1
, &n
)))
416 if (ic_sym(ic
, ic
[iv
].arg1
, sym
, off
) ||
417 ic_num(ic
, ic
[iv
].arg2
, &n
))
425 static int ic_off(struct ic
*ic
, long iv
, long *base_iv
, long *off
)
428 long oc
= O_C(ic
[iv
].op
);
429 if (oc
!= O_ADD
&& oc
!= O_SUB
) {
435 if ((ic_off(ic
, ic
[iv
].arg1
, base_iv
, off
) ||
436 ic_num(ic
, ic
[iv
].arg2
, &n
)) &&
437 (ic_off(ic
, ic
[iv
].arg2
, base_iv
, off
) ||
438 ic_num(ic
, ic
[iv
].arg1
, &n
)))
444 if (ic_off(ic
, ic
[iv
].arg1
, base_iv
, off
) ||
445 ic_num(ic
, ic
[iv
].arg2
, &n
))
453 /* number of register arguments */
454 int ic_regcnt(struct ic
*ic
)
458 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 2 : 3;
460 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 1 : 2;
462 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 1 : 2;
464 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 1 : 2;
472 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 1 : 2;
475 if (o
& (O_LD
| O_ST
) && o
& (O_SYM
| O_LOC
))
477 if (o
& (O_LD
| O_ST
))
478 return o
& O_NUM
? 2 : 3;
482 /* return the values written to and read from in the given instruction */
483 static void ic_info(struct ic
*ic
, long **w
, long **r1
, long **r2
, long **r3
)
485 long n
= ic_regcnt(ic
);
486 long o
= ic
->op
& O_OUT
;
493 *r1
= n
>= 2 ? &ic
->arg1
: NULL
;
494 *r2
= n
>= 3 ? &ic
->arg2
: NULL
;
496 *r1
= n
>= 1 ? &ic
->arg0
: NULL
;
497 *r2
= n
>= 2 ? &ic
->arg1
: NULL
;
498 *r3
= n
>= 3 ? &ic
->arg2
: NULL
;
503 * The returned array indicates the last instruction in
504 * which the value produced by each instruction is used.
506 long *ic_lastuse(struct ic
*ic
, long ic_n
)
508 long *luse
= calloc(ic_n
, sizeof(luse
[0]));
510 for (i
= ic_n
- 1; i
>= 0; --i
) {
511 long *w
, *r1
, *r2
, *r3
;
512 ic_info(ic
+ i
, &w
, &r1
, &r2
, &r3
);
514 if (!w
|| ic
[i
].op
& O_CALL
)
518 if (r1
&& !luse
[*r1
])
520 if (r2
&& !luse
[*r2
])
522 if (r3
&& !luse
[*r3
])
524 if (ic
[i
].op
& O_CALL
)
525 for (j
= 0; j
< ic
[i
].arg2
; j
++)
526 if (!luse
[ic
[i
].args
[j
]])
527 luse
[ic
[i
].args
[j
]] = i
;
532 /* intermediate code optimisations */
534 /* constant folding */
535 static int io_num(void)
538 if (!ic_num(ic
, iv_get(0), &n
)) {
546 static int log2a(unsigned long n
)
549 for (i
= 0; i
< LONGSZ
* 8; i
++)
552 if (i
== LONGSZ
* 8 || !(n
>> (i
+ 1)))
557 static long iv_num(long n
)
563 /* optimised multiplication operations for powers of two */
564 static int io_mul2(void)
569 long oc
= O_C(ic
[iv
].op
);
570 long bt
= O_T(ic
[iv
].op
);
573 if (oc
== O_MUL
&& !ic_num(ic
, ic
[iv
].arg1
, &n
)) {
574 long t
= ic
[iv
].arg1
;
575 ic
[iv
].arg1
= ic
[iv
].arg2
;
578 if (ic_num(ic
, ic
[iv
].arg2
, &n
))
594 ic_put(O_MK(O_SHL
, ULNG
), iv_new(), ic
[iv
].arg1
, r2
);
597 if (oc
== O_DIV
&& ~bt
& T_MSIGN
) {
604 ic_put(O_MK(O_SHR
, ULNG
), iv_new(), ic
[iv
].arg1
, r2
);
607 if (oc
== O_MOD
&& ~bt
& T_MSIGN
) {
613 r2
= iv_num(LONGSZ
* 8 - p
);
614 ic_put(O_MK(O_SHL
, ULNG
), iv_new(), ic
[iv
].arg1
, r2
);
616 r2
= iv_num(LONGSZ
* 8 - p
);
617 ic_put(O_MK(O_SHR
, ULNG
), iv_new(), r1
, r2
);
623 /* optimise comparison */
624 static int io_cmp(void)
627 long cmp
= ic
[iv
].arg1
;
628 if (O_C(ic
[iv
].op
) == O_LNOT
&& ic
[cmp
].op
& O_CMP
) {
631 iv_put(ic
[cmp
].arg0
);
637 /* optimise branch instructions after comparison */
638 static int io_jmp(void)
640 struct ic
*c
= &ic
[ic_n
- 1];
641 long oc
= O_C(c
->op
);
642 if (oc
& O_JZ
&& O_C(ic
[c
->arg0
].op
) == O_LNOT
) {
643 c
->arg0
= ic
[c
->arg0
].arg1
;
647 if (oc
& O_JZ
&& O_C(ic
[c
->arg0
].op
) & O_CMP
) {
648 long cop
= (ic
[c
->arg0
].op
& ~O_CMP
) | O_JCC
;
649 c
->op
= O_C(c
->op
) == O_JZ
? cop
^ 1 : cop
;
650 c
->arg1
= ic
[c
->arg0
].arg2
;
651 c
->arg0
= ic
[c
->arg0
].arg1
;
657 /* optimise accessing locals or symbols with an offset */
658 static int io_addr(void)
661 if (ic_off(ic
, iv_get(0), &iv
, &off
) || iv
== iv_get(0))
663 if (ic
[iv
].op
& O_MOV
&& ic
[iv
].op
& O_LOC
) {
665 ic_put(O_MOV
| O_LOC
, iv_new(), ic
[iv
].arg1
, ic
[iv
].arg2
+ off
);
668 if (ic
[iv
].op
& O_MOV
&& ic
[iv
].op
& O_SYM
) {
670 ic_put(O_MOV
| O_SYM
, iv_new(), ic
[iv
].arg1
, ic
[iv
].arg2
+ off
);
676 /* optimise loading and storing locals */
677 static int io_loc(void)
679 struct ic
*c
= &ic
[ic_n
- 1];
681 if (!(c
->op
& (O_LD
| O_ST
)) || !(c
->op
& O_NUM
))
683 if (ic_off(ic
, c
->arg1
, &iv
, &off
))
685 if (ic
[iv
].op
& O_MOV
&& ic
[iv
].op
& O_LOC
) {
686 c
->op
= (c
->op
& ~O_NUM
) | O_LOC
;
687 c
->arg1
= ic
[iv
].arg1
;
688 c
->arg2
+= ic
[iv
].arg2
+ off
;
696 static int imm_ok(long op
, long n
, int arg
)
699 if (i_reg(op
| O_NUM
, &m0
, &m1
, &m2
, &mt
))
701 return i_imm(arg
== 2 ? m2
: m1
, n
);
704 /* use instruction immediates */
705 static int io_imm(void)
707 struct ic
*c
= &ic
[ic_n
- 1];
708 long oc
= O_C(c
->op
);
710 if (oc
& (O_NUM
| O_LOC
| O_SYM
))
712 if (oc
== O_ADD
|| oc
== O_MUL
|| oc
== O_AND
|| oc
== O_OR
||
713 oc
== O_XOR
|| oc
== O_EQ
|| oc
== O_NE
) {
714 if (!ic_num(ic
, c
->arg1
, &n
)) {
720 if (oc
== O_LT
|| oc
== O_GE
|| oc
== O_LE
|| oc
== O_GT
) {
721 if (!ic_num(ic
, c
->arg1
, &n
)) {
728 if (oc
& O_JCC
&& !ic_num(ic
, c
->arg0
, &n
)) {
734 if (oc
& O_JCC
&& !ic_num(ic
, c
->arg1
, &n
) && imm_ok(c
->op
, n
, 1)) {
739 if (!(oc
& O_BOP
) || ic_num(ic
, c
->arg2
, &n
))
741 if ((oc
== O_ADD
|| oc
== O_SUB
|| oc
& O_SHL
) && n
== 0) {
746 if (imm_ok(c
->op
, n
, 2)) {
754 /* calling symbols */
755 static int io_call(void)
757 struct ic
*c
= &ic
[ic_n
- 1];
759 if (c
->op
& O_CALL
&& !ic_sym(ic
, c
->arg1
, &sym
, &off
) && !off
) {
767 /* remove dead code */
768 static void io_deadcode(void)
772 long src
= 0, dst
= 0;
774 /* liveness analysis */
775 live
= calloc(ic_n
, sizeof(live
[0]));
776 for (i
= ic_n
- 1; i
>= 0; i
--) {
777 long *w
, *r1
, *r2
, *r3
;
778 ic_info(ic
+ i
, &w
, &r1
, &r2
, &r3
);
779 if (!w
|| ic
[i
].op
& O_CALL
)
789 if (ic
[i
].op
& O_CALL
)
790 for (j
= 0; j
< ic
[i
].arg2
; j
++)
791 live
[ic
[i
].args
[j
]] = 1;
793 /* the new indices of intermediate instructions */
794 nidx
= calloc(ic_n
, sizeof(nidx
[0]));
796 while (src
< ic_n
&& !live
[src
]) {
803 memcpy(ic
+ dst
, ic
+ src
, sizeof(ic
[src
]));
809 /* adjusting arguments and branch targets */
810 for (i
= 0; i
< ic_n
; i
++) {
811 long *w
, *r1
, *r2
, *r3
;
812 ic_info(ic
+ i
, &w
, &r1
, &r2
, &r3
);
821 if (ic
[i
].op
& O_JXX
)
822 ic
[i
].arg2
= nidx
[ic
[i
].arg2
];
823 if (ic
[i
].op
& O_CALL
)
824 for (j
= 0; j
< ic
[i
].arg2
; j
++)
825 ic
[i
].args
[j
] = nidx
[ic
[i
].args
[j
]];