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 void iv_put(long n
);
27 static struct ic
*ic_put(long op
, long arg1
, long arg2
, long arg3
)
31 ic_sz
= MAX(128, ic_sz
* 2);
32 ic
= mextend(ic
, ic_n
, ic_sz
, sizeof(*ic
));
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 void iv_put(long n
)
68 static void iv_drop(int n
)
70 iv_n
= MAX(0, iv_n
- n
);
73 static void iv_swap(int x
, int y
)
75 long v
= iv
[iv_n
- x
- 1];
76 iv
[iv_n
- x
- 1] = iv
[iv_n
- y
- 1];
80 static void iv_dup(void)
82 iv
[iv_n
] = iv
[iv_n
- 1];
88 ic_put(O_MOV
| O_NUM
, n
, 0, 0);
93 ic_put(O_MOV
| O_LOC
, id
, 0, 0);
98 ic_put(O_MOV
| O_SYM
, out_sym(sym
), 0, 0);
101 void o_tmpdrop(int n
)
103 iv_drop(n
>= 0 ? n
: iv_n
);
116 /* return one if the given value is constant */
117 static int ic_const(long iv
)
119 long oc
= O_C(ic
[iv
].op
);
120 return oc
& O_MOV
&& oc
& (O_NUM
| O_SYM
| O_LOC
);
123 /* return one if the given value is a simple load */
124 static int ic_load(long iv
)
126 long oc
= O_C(ic
[iv
].op
);
128 if (oc
& O_LD
&& oc
& (O_NUM
| O_SYM
| O_LOC
)) {
129 for (i
= iv
+ 1; i
< ic_n
; i
++)
141 /* load constants as late as possible */
142 if (opt(1) && ic_const(r2
) && !ic_const(r1
)) {
143 ic_put(ic
[r2
].op
, ic
[r2
].a1
, ic
[r2
].a2
, ic
[r2
].a3
);
146 ic_put(op
, r2
, r1
, 0);
158 ic_put(op
, r1
, 0, 0);
165 void o_assign(long bt
)
169 /* load constants as late as possible */
170 if (opt(1) && (ic_const(lv
) || ic_load(lv
))) {
171 ic_put(ic
[lv
].op
, ic
[lv
].a1
, ic
[lv
].a2
, ic
[lv
].a3
);
174 ic_put(O_MK(O_ST
| O_NUM
, bt
), rv
, lv
, 0);
180 void o_deref(long bt
)
183 ic_put(O_MK(O_LD
| O_NUM
, bt
), r1
, 0, 0);
190 if (T_SZ(bt
) != ULNG
) {
192 ic_put(O_MK(O_MOV
, bt
), r1
, 0, 0);
203 ic_put(O_MCPY
, r0
, r1
, r2
);
211 ic_put(O_MSET
, r0
, r1
, r2
);
214 void o_call(int argc
, int ret
)
217 long *args
= malloc(argc
* sizeof(c
->args
[0]));
219 for (i
= argc
- 1; i
>= 0; --i
)
221 for (i
= argc
- 1; i
>= 0; --i
) {
223 /* load constants as late as possible */
224 if (opt(1) && (ic_const(iv
) || ic_load(iv
))) {
225 ic_put(ic
[iv
].op
, ic
[iv
].a1
, ic
[iv
].a2
, ic
[iv
].a3
);
230 c
= ic_put(O_CALL
, r1
, 0, argc
);
241 ic_put(O_RET
, iv_pop(), 0, 0);
244 void o_label(long id
)
246 while (id
>= lab_sz
) {
247 lab_sz
= MAX(128, lab_sz
* 2);
248 lab_loc
= mextend(lab_loc
, lab_n
, lab_sz
, sizeof(*lab_loc
));
251 lab_loc
[lab_n
++] = -1;
258 ic_put(O_JMP
, 0, 0, id
);
263 ic_put(O_JZ
, iv_pop(), 0, id
);
268 int o_popnum(long *n
)
270 if (ic_num(ic
, iv_get(0), n
))
276 int o_popsym(long *sym
, long *off
)
278 if (ic_sym(ic
, iv_get(0), sym
, off
))
289 void o_back(long mark
)
294 void ic_get(struct ic
**c
, long *n
)
297 if (!ic_n
|| ~ic
[ic_n
- 1].op
& O_RET
|| lab_last
== ic_n
)
299 for (i
= 0; i
< ic_n
; i
++) /* filling branch targets */
300 if (ic
[i
].op
& O_JXX
)
301 ic
[i
].a3
= lab_loc
[ic
[i
].a3
];
302 io_deadcode(); /* removing dead code */
316 void ic_free(struct ic
*ic
)
322 /* intermediate code queries */
324 static long cb(long op
, long *r
, long a
, long b
)
359 *r
= O_T(op
) & T_MSIGN
? a
>> b
: (unsigned long) a
>> b
;
383 static long cu(int op
, long i
)
396 static long c_cast(long n
, unsigned bt
)
398 if (!(bt
& T_MSIGN
) && T_SZ(bt
) != ULNG
)
399 n
&= ((1l << (long) (T_SZ(bt
) * 8)) - 1);
400 if (bt
& T_MSIGN
&& T_SZ(bt
) != ULNG
&&
401 n
> (1l << (T_SZ(bt
) * 8 - 1)))
402 n
= -((1l << (T_SZ(bt
) * 8)) - n
);
406 int ic_num(struct ic
*ic
, long iv
, long *n
)
409 long oc
= O_C(ic
[iv
].op
);
410 long bt
= O_T(ic
[iv
].op
);
411 if (oc
& O_MOV
&& oc
& O_NUM
) {
416 if (ic_num(ic
, ic
[iv
].a1
, &n1
))
418 if (ic_num(ic
, ic
[iv
].a2
, &n2
))
420 return cb(ic
[iv
].op
, n
, n1
, n2
);
423 if (ic_num(ic
, ic
[iv
].a1
, &n1
))
425 *n
= cu(ic
[iv
].op
, n1
);
428 if (oc
& O_MOV
&& !(oc
& (O_NUM
| O_LOC
| O_SYM
))) {
429 if (ic_num(ic
, ic
[iv
].a1
, &n1
))
437 int ic_sym(struct ic
*ic
, long iv
, long *sym
, long *off
)
440 long oc
= O_C(ic
[iv
].op
);
441 if (oc
& O_MOV
&& oc
& O_SYM
) {
447 if ((ic_sym(ic
, ic
[iv
].a1
, sym
, off
) ||
448 ic_num(ic
, ic
[iv
].a2
, &n
)) &&
449 (ic_sym(ic
, ic
[iv
].a2
, sym
, off
) ||
450 ic_num(ic
, ic
[iv
].a1
, &n
)))
456 if (ic_sym(ic
, ic
[iv
].a1
, sym
, off
) ||
457 ic_num(ic
, ic
[iv
].a2
, &n
))
465 static int ic_off(struct ic
*ic
, long iv
, long *base_iv
, long *off
)
468 long oc
= O_C(ic
[iv
].op
);
469 if (oc
== (O_ADD
| O_NUM
)) {
470 *base_iv
= ic
[iv
].a1
;
474 if (oc
== (O_SUB
| O_NUM
)) {
475 *base_iv
= ic
[iv
].a1
;
480 if ((ic_off(ic
, ic
[iv
].a1
, base_iv
, off
) ||
481 ic_num(ic
, ic
[iv
].a2
, &n
)) &&
482 (ic_off(ic
, ic
[iv
].a2
, base_iv
, off
) ||
483 ic_num(ic
, ic
[iv
].a1
, &n
)))
489 if (ic_off(ic
, ic
[iv
].a1
, base_iv
, off
) ||
490 ic_num(ic
, ic
[iv
].a2
, &n
))
500 /* number of register arguments */
501 int ic_regcnt(struct ic
*ic
)
505 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 1 : 2;
507 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 0 : 1;
509 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 0 : 1;
511 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 0 : 1;
519 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 1 : 2;
523 return ((o
& O_NUM
) != 0);
525 return 1 + ((o
& O_NUM
) != 0);
530 * The returned array indicates the last instruction in
531 * which the value produced by each instruction is used.
533 long *ic_lastuse(struct ic
*ic
, long ic_n
)
535 long *luse
= calloc(ic_n
, sizeof(luse
[0]));
537 for (i
= ic_n
- 1; i
>= 0; --i
) {
538 int n
= ic_regcnt(ic
+ i
);
540 if (!(ic
[i
].op
& O_OUT
) || ic
[i
].op
& O_CALL
)
544 if (n
>= 1 && !luse
[ic
[i
].a1
])
546 if (n
>= 2 && !luse
[ic
[i
].a2
])
548 if (n
>= 3 && !luse
[ic
[i
].a3
])
550 if (ic
[i
].op
& O_CALL
)
551 for (j
= 0; j
< ic
[i
].a3
; j
++)
552 if (!luse
[ic
[i
].args
[j
]])
553 luse
[ic
[i
].args
[j
]] = i
;
558 /* intermediate code optimisations */
560 /* constant folding */
561 static int io_num(void)
564 if (!ic_num(ic
, iv_get(0), &n
)) {
572 static int log2a(unsigned long n
)
575 for (i
= 0; i
< LONGSZ
* 8; i
++)
578 if (i
== LONGSZ
* 8 || !(n
>> (i
+ 1)))
583 static long iv_num(long n
)
589 /* optimised multiplication operations for powers of two */
590 static int io_mul2(void)
595 long oc
= O_C(ic
[iv
].op
);
596 long bt
= O_T(ic
[iv
].op
);
599 if (oc
== O_MUL
&& !ic_num(ic
, ic
[iv
].a1
, &n
)) {
601 ic
[iv
].a1
= ic
[iv
].a2
;
604 if (ic_num(ic
, ic
[iv
].a2
, &n
))
620 ic_put(O_MK(O_SHL
, ULNG
), ic
[iv
].a1
, r2
, 0);
623 if (oc
== O_DIV
&& ~bt
& T_MSIGN
) {
630 ic_put(O_MK(O_SHR
, ULNG
), ic
[iv
].a1
, r2
, 0);
633 if (oc
== O_MOD
&& ~bt
& T_MSIGN
) {
639 r2
= iv_num(LONGSZ
* 8 - p
);
640 ic_put(O_MK(O_SHL
, ULNG
), ic
[iv
].a1
, r2
, 0);
642 r2
= iv_num(LONGSZ
* 8 - p
);
643 ic_put(O_MK(O_SHR
, ULNG
), r1
, r2
, 0);
649 /* optimise comparison */
650 static int io_cmp(void)
653 long cmp
= ic
[iv
].a1
;
654 if (O_C(ic
[iv
].op
) == O_LNOT
&& ic
[cmp
].op
& O_CMP
) {
663 /* optimise branch instructions after comparison */
664 static int io_jmp(void)
666 struct ic
*c
= &ic
[ic_n
- 1];
667 long oc
= O_C(c
->op
);
668 if (oc
& O_JZ
&& O_C(ic
[c
->a1
].op
) == O_LNOT
) {
669 c
->a1
= ic
[c
->a1
].a1
;
673 if (oc
& O_JZ
&& O_C(ic
[c
->a1
].op
) & O_CMP
) {
674 long cop
= (ic
[c
->a1
].op
& ~O_CMP
) | O_JCC
;
675 c
->op
= O_C(c
->op
) == O_JZ
? cop
^ 1 : cop
;
676 c
->a2
= ic
[c
->a1
].a2
;
677 c
->a1
= ic
[c
->a1
].a1
;
683 /* optimise accessing locals or symbols with an offset */
684 static int io_addr(void)
687 if (ic_off(ic
, iv_get(0), &iv
, &off
) || iv
== iv_get(0))
689 if (ic
[iv
].op
& O_MOV
&& ic
[iv
].op
& O_LOC
) {
691 ic_put(O_MOV
| O_LOC
, ic
[iv
].a1
, ic
[iv
].a2
+ off
, 0);
694 if (ic
[iv
].op
& O_MOV
&& ic
[iv
].op
& O_SYM
) {
696 ic_put(O_MOV
| O_SYM
, ic
[iv
].a1
, ic
[iv
].a2
+ off
, 0);
702 static int imm_ok(long op
, long n
, int arg
)
705 if (i_reg(op
| O_NUM
, m
+ 0, m
+ 1, m
+ 2, m
+ 3, m
+ 4))
707 return i_imm(m
[arg
], n
);
710 /* optimise loading and storing locals */
711 static int io_loc(void)
713 struct ic
*c
= &ic
[ic_n
- 1];
715 if (c
->op
& O_LD
&& c
->op
& O_NUM
) {
716 if (ic_off(ic
, c
->a1
, &iv
, &off
))
718 if (ic
[iv
].op
& O_MOV
&& ic
[iv
].op
& O_LOC
) {
719 c
->op
= (c
->op
& ~O_NUM
) | O_LOC
;
721 c
->a2
+= ic
[iv
].a2
+ off
;
724 if (imm_ok(c
->op
, off
, 2)) {
730 if (c
->op
& O_ST
&& c
->op
& O_NUM
) {
731 if (ic_off(ic
, c
->a2
, &iv
, &off
))
733 if (ic
[iv
].op
& O_MOV
&& ic
[iv
].op
& O_LOC
) {
734 c
->op
= (c
->op
& ~O_NUM
) | O_LOC
;
736 c
->a3
+= ic
[iv
].a2
+ off
;
739 if (imm_ok(c
->op
, off
, 3)) {
748 /* reverse the order of comparison operands (e.g., <= to >=) */
749 static int flip_cond(int op
) {
750 /* lt -> gt, ge -> le, eq -> eq, ne -> ne, le -> ge, gt -> lt */
751 static int cond
[] = {5, 4, 2, 3, 1, 0};
752 return (op
& ~0x0f) | cond
[op
& 0x0f];
755 /* use instruction immediates */
756 static int io_imm(void)
758 struct ic
*c
= &ic
[ic_n
- 1];
759 long oc
= O_C(c
->op
);
761 if (oc
& (O_NUM
| O_LOC
| O_SYM
))
763 if (oc
== O_ADD
|| oc
== O_MUL
|| oc
== O_AND
|| oc
== O_OR
||
764 oc
== O_XOR
|| oc
== O_EQ
|| oc
== O_NE
) {
765 if (!ic_num(ic
, c
->a1
, &n
)) {
771 if (oc
== O_LT
|| oc
== O_GE
|| oc
== O_LE
|| oc
== O_GT
) {
772 if (!ic_num(ic
, c
->a1
, &n
)) {
776 c
->op
= flip_cond(c
->op
);
779 if (oc
& O_JCC
&& !ic_num(ic
, c
->a1
, &n
)) {
783 c
->op
= flip_cond(c
->op
);
785 if (oc
& O_JCC
&& !ic_num(ic
, c
->a2
, &n
) && imm_ok(c
->op
, n
, 2)) {
790 if (!(oc
& O_BOP
) || ic_num(ic
, c
->a2
, &n
))
792 if ((oc
== O_ADD
|| oc
== O_SUB
|| oc
& O_SHL
) && n
== 0) {
797 if (imm_ok(c
->op
, n
, 2)) {
805 /* calling symbols */
806 static int io_call(void)
808 struct ic
*c
= &ic
[ic_n
- 1];
810 if (c
->op
& O_CALL
&& !ic_sym(ic
, c
->a1
, &sym
, &off
) && !off
) {
818 /* remove dead code */
819 static void io_deadcode(void)
823 long src
= 0, dst
= 0;
825 /* liveness analysis */
826 live
= calloc(ic_n
, sizeof(live
[0]));
827 for (i
= ic_n
- 1; i
>= 0; i
--) {
828 int n
= ic_regcnt(ic
+ i
);
829 if (!(ic
[i
].op
& O_OUT
) || ic
[i
].op
& O_CALL
)
839 if (ic
[i
].op
& O_CALL
)
840 for (j
= 0; j
< ic
[i
].a3
; j
++)
841 live
[ic
[i
].args
[j
]] = 1;
843 /* the new indices of intermediate instructions */
844 nidx
= calloc(ic_n
, sizeof(nidx
[0]));
846 while (src
< ic_n
&& !live
[src
]) {
853 memcpy(ic
+ dst
, ic
+ src
, sizeof(ic
[src
]));
859 /* adjusting arguments and branch targets */
860 for (i
= 0; i
< ic_n
; i
++) {
861 int n
= ic_regcnt(ic
+ i
);
863 ic
[i
].a1
= nidx
[ic
[i
].a1
];
865 ic
[i
].a2
= nidx
[ic
[i
].a2
];
867 ic
[i
].a3
= nidx
[ic
[i
].a3
];
868 if (ic
[i
].op
& O_JXX
)
869 ic
[i
].a3
= nidx
[ic
[i
].a3
];
870 if (ic
[i
].op
& O_CALL
)
871 for (j
= 0; j
< ic
[i
].a3
; j
++)
872 ic
[i
].args
[j
] = nidx
[ic
[i
].args
[j
]];