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);
24 static struct ic
*ic_new(void)
27 ic_sz
= MAX(128, ic_sz
* 2);
28 ic
= mextend(ic
, ic_n
, ic_sz
, sizeof(*ic
));
33 static struct ic
*ic_put(long op
, long arg0
, long arg1
, long arg2
)
35 struct ic
*c
= ic_new();
43 static void ic_back(long pos
)
46 for (i
= pos
; i
< ic_n
; i
++)
47 if (ic
[i
].op
& O_CALL
)
52 static long iv_pop(void)
57 static long iv_get(int n
)
59 return iv
[iv_n
- n
- 1];
62 static long iv_new(void)
68 static void iv_put(long n
)
73 static void iv_drop(int n
)
75 iv_n
= MAX(0, iv_n
- n
);
78 static void iv_swap(int x
, int y
)
80 long v
= iv
[iv_n
- x
- 1];
81 iv
[iv_n
- x
- 1] = iv
[iv_n
- y
- 1];
85 static void iv_dup(void)
87 iv
[iv_n
] = iv
[iv_n
- 1];
93 ic_put(O_MOV
| O_NUM
, iv_new(), n
, 0);
98 ic_put(O_MOV
| O_LOC
, iv_new(), id
, 0);
101 void o_sym(char *sym
)
103 ic_put(O_MOV
| O_SYM
, iv_new(), out_sym(sym
), 0);
106 void o_tmpdrop(int n
)
108 iv_drop(n
>= 0 ? n
: iv_n
);
125 ic_put(op
, iv_new(), r2
, r1
);
126 io_num() && io_mul2() && io_imm() && io_addr();
132 ic_put(op
, iv_new(), r1
, 0);
137 void o_assign(long bt
)
139 ic_put(O_MK(O_ST
| O_NUM
, bt
), iv_get(0), iv_get(1), 0);
145 void o_deref(long bt
)
148 ic_put(O_MK(O_LD
| O_NUM
, bt
), iv_new(), r1
, 0);
154 if (T_SZ(bt
) != ULNG
) {
156 ic_put(O_MK(O_MOV
, bt
), iv_new(), r1
, 0);
166 ic_put(O_MCPY
, r0
, r1
, r2
);
174 ic_put(O_MSET
, r0
, r1
, r2
);
177 void o_call(int argc
, int ret
)
180 long *args
= malloc(argc
* sizeof(c
->args
[0]));
182 for (i
= argc
- 1; i
>= 0; --i
)
185 c
= ic_put(O_CALL
, iv_new(), r1
, argc
);
195 ic_put(O_RET
, iv_pop(), 0, 0);
198 void o_label(long id
)
200 while (id
>= lab_sz
) {
201 lab_sz
= MAX(128, lab_sz
* 2);
202 lab_loc
= mextend(lab_loc
, lab_n
, lab_sz
, sizeof(*lab_loc
));
205 lab_loc
[lab_n
++] = -1;
212 ic_put(O_JMP
, 0, 0, id
);
217 ic_put(O_JZ
, iv_pop(), 0, id
);
221 int o_popnum(long *n
)
223 if (ic_num(ic
, iv_get(0), n
))
229 int o_popsym(long *sym
, long *off
)
231 if (ic_sym(ic
, iv_get(0), sym
, off
))
242 void o_back(long mark
)
247 void ic_get(struct ic
**c
, long *n
)
250 if (!ic_n
|| ~ic
[ic_n
- 1].op
& O_RET
|| lab_last
== ic_n
)
252 /* filling jump destinations */
253 for (i
= 0; i
< ic_n
; i
++)
254 if (ic
[i
].op
& O_JXX
)
255 ic
[i
].arg2
= lab_loc
[ic
[i
].arg2
];
269 /* intermediate code queries */
271 static long cb(long op
, long a
, long b
)
293 return O_T(op
) & T_MSIGN
? a
>> b
: (unsigned long) a
>> b
;
310 static long cu(int op
, long i
)
323 static long c_cast(long n
, unsigned bt
)
325 if (!(bt
& T_MSIGN
) && T_SZ(bt
) != ULNG
)
326 n
&= ((1l << (long) (T_SZ(bt
) * 8)) - 1);
327 if (bt
& T_MSIGN
&& T_SZ(bt
) != ULNG
&&
328 n
> (1l << (T_SZ(bt
) * 8 - 1)))
329 n
= -((1l << (T_SZ(bt
) * 8)) - n
);
333 int ic_num(struct ic
*ic
, long iv
, long *n
)
336 long oc
= O_C(ic
[iv
].op
);
337 long bt
= O_T(ic
[iv
].op
);
338 if (oc
& O_MOV
&& oc
& O_NUM
) {
343 if (ic_num(ic
, ic
[iv
].arg1
, &n1
))
345 if (ic_num(ic
, ic
[iv
].arg2
, &n2
))
347 *n
= cb(ic
[iv
].op
, n1
, n2
);
351 if (ic_num(ic
, ic
[iv
].arg1
, &n1
))
353 *n
= cu(ic
[iv
].op
, n1
);
356 if (oc
& O_MOV
&& !(oc
& (O_NUM
| O_LOC
| O_SYM
))) {
357 if (ic_num(ic
, ic
[iv
].arg1
, &n1
))
365 int ic_sym(struct ic
*ic
, long iv
, long *sym
, long *off
)
368 long oc
= O_C(ic
[iv
].op
);
369 if (oc
& O_MOV
&& oc
& O_SYM
) {
375 if ((ic_sym(ic
, ic
[iv
].arg1
, sym
, off
) ||
376 ic_num(ic
, ic
[iv
].arg2
, &n
)) &&
377 (ic_sym(ic
, ic
[iv
].arg2
, sym
, off
) ||
378 ic_num(ic
, ic
[iv
].arg1
, &n
)))
384 if (ic_sym(ic
, ic
[iv
].arg1
, sym
, off
) ||
385 ic_num(ic
, ic
[iv
].arg2
, &n
))
393 static int ic_off(struct ic
*ic
, long iv
, long *base_iv
, long *off
)
396 long oc
= O_C(ic
[iv
].op
);
397 if (oc
!= O_ADD
&& oc
!= O_SUB
) {
403 if ((ic_off(ic
, ic
[iv
].arg1
, base_iv
, off
) ||
404 ic_num(ic
, ic
[iv
].arg2
, &n
)) &&
405 (ic_off(ic
, ic
[iv
].arg2
, base_iv
, off
) ||
406 ic_num(ic
, ic
[iv
].arg1
, &n
)))
412 if (ic_off(ic
, ic
[iv
].arg1
, base_iv
, off
) ||
413 ic_num(ic
, ic
[iv
].arg2
, &n
))
421 /* intermediate code optimisations */
423 /* constant folding */
424 static int io_num(void)
427 if (!ic_num(ic
, iv_get(0), &n
)) {
435 static int log2a(unsigned long n
)
438 for (i
= 0; i
< LONGSZ
* 8; i
++)
441 if (i
== LONGSZ
* 8 || !(n
>> (i
+ 1)))
446 static long iv_num(long n
)
452 /* optimised multiplication operations for powers of two */
453 static int io_mul2(void)
458 long oc
= O_C(ic
[iv
].op
);
459 long bt
= O_T(ic
[iv
].op
);
462 if (oc
== O_MUL
&& !ic_num(ic
, ic
[iv
].arg1
, &n
)) {
463 long t
= ic
[iv
].arg1
;
464 ic
[iv
].arg1
= ic
[iv
].arg2
;
467 if (ic_num(ic
, ic
[iv
].arg2
, &n
))
483 ic_put(O_MK(O_SHL
, ULNG
), iv_new(), ic
[iv
].arg1
, r2
);
486 if (oc
== O_DIV
&& ~bt
& T_MSIGN
) {
493 ic_put(O_MK(O_SHR
, ULNG
), iv_new(), ic
[iv
].arg1
, r2
);
496 if (oc
== O_MOD
&& ~bt
& T_MSIGN
) {
502 r2
= iv_num(LONGSZ
* 8 - p
);
503 ic_put(O_MK(O_SHL
, ULNG
), iv_new(), ic
[iv
].arg1
, r2
);
505 r2
= iv_num(LONGSZ
* 8 - p
);
506 ic_put(O_MK(O_SHR
, ULNG
), iv_new(), r1
, r2
);
512 /* optimise comparison */
513 static int io_cmp(void)
516 long cmp
= ic
[iv
].arg1
;
517 if (O_C(ic
[iv
].op
) == O_LNOT
&& ic
[cmp
].op
& O_CMP
) {
520 iv_put(ic
[cmp
].arg0
);
526 /* optimise branch instructions after comparison */
527 static int io_jmp(void)
529 struct ic
*c
= &ic
[ic_n
- 1];
530 long oc
= O_C(c
->op
);
531 if (oc
& O_JZ
&& O_C(ic
[c
->arg0
].op
) == O_LNOT
) {
532 c
->arg0
= ic
[c
->arg0
].arg1
;
536 if (oc
& O_JZ
&& O_C(ic
[c
->arg0
].op
) & O_CMP
) {
537 long cop
= (ic
[c
->arg0
].op
& ~O_CMP
) | O_JCC
;
538 c
->op
= O_C(c
->op
) == O_JZ
? cop
^ 1 : cop
;
539 c
->arg1
= ic
[c
->arg0
].arg2
;
540 c
->arg0
= ic
[c
->arg0
].arg1
;
546 /* optimise accessing locals or symbols with an offset */
547 static int io_addr(void)
550 if (ic_off(ic
, ic_n
- 1, &iv
, &off
) || iv
!= ic_n
- 1)
552 if (ic
[iv
].op
& O_MOV
&& ic
[iv
].op
& O_LOC
) {
554 ic_put(O_MOV
| O_LOC
, iv_new(), ic
[iv
].arg1
, ic
[iv
].arg2
+ off
);
557 if (ic
[iv
].op
& O_MOV
&& ic
[iv
].op
& O_SYM
) {
559 ic_put(O_MOV
| O_SYM
, iv_new(), ic
[iv
].arg1
, ic
[iv
].arg2
+ off
);
565 /* optimise loading and storing locals */
566 static int io_loc(void)
568 struct ic
*c
= &ic
[ic_n
- 1];
570 if (!(c
->op
& (O_LD
| O_ST
)) || !(c
->op
& O_NUM
))
572 if (ic_off(ic
, c
->arg1
, &iv
, &off
))
574 if (ic
[iv
].op
& O_MOV
&& ic
[iv
].op
& O_LOC
) {
575 c
->op
= (c
->op
& ~O_NUM
) | O_LOC
;
576 c
->arg1
= ic
[iv
].arg1
;
577 c
->arg2
+= ic
[iv
].arg2
+ off
;
585 static int imm_ok(long op
, long n
, int arg
)
588 if (i_reg(op
| O_NUM
, &m0
, &m1
, &m2
, &mt
))
590 return i_imm(arg
== 2 ? m2
: m1
, n
);
593 /* use instruction immediates */
594 static int io_imm(void)
596 struct ic
*c
= &ic
[ic_n
- 1];
597 long oc
= O_C(c
->op
);
599 if (oc
& (O_NUM
| O_LOC
| O_SYM
))
601 if (oc
== O_ADD
|| oc
== O_MUL
|| oc
== O_AND
|| oc
== O_OR
||
602 oc
== O_XOR
|| oc
== O_EQ
|| oc
== O_NE
) {
603 if (!ic_num(ic
, c
->arg1
, &n
)) {
609 if (oc
== O_LT
|| oc
== O_GE
|| oc
== O_LE
|| oc
== O_GT
) {
610 if (!ic_num(ic
, c
->arg1
, &n
)) {
617 if (oc
& O_JCC
&& !ic_num(ic
, c
->arg0
, &n
)) {
623 if (oc
& O_JCC
&& !ic_num(ic
, c
->arg1
, &n
) && imm_ok(c
->op
, n
, 1)) {
628 if (!(oc
& O_BOP
) || ic_num(ic
, c
->arg2
, &n
))
630 if ((oc
== O_ADD
|| oc
== O_SUB
|| oc
& O_SHL
) && n
== 0) {
635 if (imm_ok(c
->op
, n
, 2)) {
643 /* calling symbols */
644 static int io_call(void)
647 struct ic
*c
= &ic
[iv
];
649 if (c
->op
& O_CALL
&& !ic_sym(ic
, c
->arg1
, &sym
, &off
) && !off
) {