1 /* neatcc code generation */
7 static struct mem ds
; /* data segment */
8 static struct mem cs
; /* code segment */
9 static long bsslen
; /* bss segment size */
11 static long *loc_off
; /* offset of locals on the stack */
12 static long loc_n
, loc_sz
; /* number of locals */
13 static long loc_pos
; /* current stack position */
14 static int *loc_mem
; /* local memory was accessed */
15 static int *loc_ptr
; /* the address of this local is fetched */
16 static int *loc_dat
; /* the number of data accesses of this local */
18 static char (*ds_name
)[NAMELEN
];/* data section symbols */
19 static long *ds_off
; /* data section offsets */
20 static long ds_n
, ds_sz
; /* number of data section symbols */
22 static int func_argc
; /* number of arguments */
23 static int func_varg
; /* varargs */
24 static int func_regs
; /* used registers */
25 static int func_maxargs
; /* the maximum number of arguments on the stack */
26 static int func_leaf
; /* a leaf function */
27 static long *ic_luse
; /* the last use of values generated by instructions */
28 static long *ic_bbeg
; /* whether each instruction begins a basic block */
30 static long ra_vmap
[N_REGS
]; /* register to intermediate value assignments */
31 static long ra_lmap
[N_REGS
]; /* register to local assignments */
32 static long ra_lmapglob
[N_REGS
]; /* global register to local assignments */
33 static long *ra_gmask
; /* the mask of good registers for each value */
34 static long ra_live
[NTMPS
]; /* live values */
35 static int ra_vmax
; /* the number of values stored on the stack */
37 static long loc_add(long pos
)
39 if (loc_n
>= loc_sz
) {
40 loc_sz
= MAX(128, loc_sz
* 2);
41 loc_off
= mextend(loc_off
, loc_n
, loc_sz
, sizeof(loc_off
[0]));
47 long o_mklocal(long sz
)
49 loc_pos
+= ALIGN(sz
, ULNG
);
50 return loc_add(loc_pos
);
53 void o_rmlocal(long addr
, long sz
)
62 void o_bsnew(char *name
, long size
, int global
)
64 out_def(name
, OUT_BSS
| (global
? OUT_GLOB
: 0), bsslen
, size
);
65 bsslen
+= ALIGN(size
, OUT_ALIGNMENT
);
68 long o_dsnew(char *name
, long size
, int global
)
72 ds_sz
= MAX(128, ds_sz
* 2);
73 ds_name
= mextend(ds_name
, ds_n
, ds_sz
, sizeof(ds_name
[0]));
74 ds_off
= mextend(ds_off
, ds_n
, ds_sz
, sizeof(ds_off
[0]));
77 strcpy(ds_name
[idx
], name
);
78 ds_off
[idx
] = mem_len(&ds
);
79 out_def(name
, OUT_DS
| (global
? OUT_GLOB
: 0), mem_len(&ds
), size
);
80 mem_putz(&ds
, ALIGN(size
, OUT_ALIGNMENT
));
84 void o_dscpy(long addr
, void *buf
, long len
)
86 mem_cpy(&ds
, addr
, buf
, len
);
89 static int dat_off(char *name
)
92 for (i
= 0; i
< ds_n
; i
++)
93 if (!strcmp(name
, ds_name
[i
]))
98 void o_dsset(char *name
, long off
, long bt
)
100 long sym_off
= dat_off(name
) + off
;
101 long num
, roff
, rsym
;
102 if (!o_popnum(&num
)) {
103 mem_cpy(&ds
, sym_off
, &num
, T_SZ(bt
));
106 if (!o_popsym(&rsym
, &roff
)) {
107 out_rel(rsym
, OUT_DS
, sym_off
);
108 mem_cpy(&ds
, sym_off
, &roff
, T_SZ(bt
));
112 /* number of register arguments */
113 static int ic_regcnt(struct ic
*ic
)
117 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 2 : 3;
119 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 1 : 2;
121 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 1 : 2;
123 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 1 : 2;
131 return o
& (O_NUM
| O_SYM
| O_LOC
) ? 1 : 2;
134 if (o
& (O_LD
| O_ST
) && o
& (O_SYM
| O_LOC
))
136 if (o
& (O_LD
| O_ST
))
137 return o
& O_NUM
? 2 : 3;
141 static int ra_vreg(int val
)
144 for (i
= 0; i
< LEN(ra_vmap
); i
++)
145 if (ra_vmap
[i
] == val
)
150 static int ra_lreg(int loc
)
153 for (i
= 0; i
< LEN(ra_lmap
); i
++)
154 if (ra_lmap
[i
] == loc
)
159 /* mask of registers assigned to locals */
160 static long ra_lmask(void)
164 for (i
= 0; i
< LEN(ra_lmap
); i
++)
170 /* mask of registers assigned to values */
171 static long ra_vmask(void)
175 for (i
= 0; i
< LEN(ra_vmap
); i
++)
181 /* find a temporary register specified in the given mask */
182 static long ra_regscn(long mask
)
185 for (i
= 0; i
< N_TMPS
; i
++)
186 if ((1 << tmpregs
[i
]) & mask
)
191 /* find a register, with the given good, acceptable, and bad register masks */
192 static long ra_regget(long iv
, long gmask
, long amask
, long bmask
)
195 gmask
&= ~bmask
& amask
;
197 if (ra_vreg(iv
) >= 0 && (1 << ra_vreg(iv
)) & (gmask
| amask
))
201 if (ra_regscn(gmask
& ~vmask
& ~lmask
) >= 0)
202 return ra_regscn(gmask
& ~vmask
& ~lmask
);
203 if (ra_regscn(amask
& ~vmask
& ~lmask
) >= 0)
204 return ra_regscn(amask
& ~vmask
& ~lmask
);
205 if (ra_regscn(gmask
) >= 0)
206 return ra_regscn(gmask
);
207 if (ra_regscn(amask
) >= 0)
208 return ra_regscn(amask
);
209 die("neatcc: cannot allocate an acceptable register\n");
213 /* find a free and cheap register */
214 static long ra_regcheap(long mask
)
216 return ra_regscn(mask
& (func_regs
| (R_TMPS
& ~R_PERM
)) &
217 ~ra_lmask() & ~ra_vmask());
220 /* allocate registers for a 3-operand instruction */
221 static void ra_map(struct ic
*ic
, int *r0
, int *r1
, int *r2
, long *mt
)
225 int n
= ic_regcnt(ic
);
226 int oc
= O_C(ic
->op
);
232 /* optimizing loading locals: point to local's register */
233 if (oc
== (O_LD
| O_LOC
) && ra_lreg(ic
->arg1
) >= 0 &&
234 ra_vmap
[ra_lreg(ic
->arg1
)] < 0) {
235 *r0
= ra_lreg(ic
->arg1
);
236 func_regs
|= 1 << *r0
;
239 /* do not use argument registers to hold call destination */
241 for (i
= 0; i
< MIN(ic
->arg2
, N_ARGS
); i
++)
242 all
|= (1 << argregs
[i
]);
243 /* instructions on locals can be simplified */
247 if (oc
& (O_ST
| O_LD
))
248 oc
= (oc
& ~O_LOC
) & O_NUM
;
250 if (i_reg(ic
->op
, &m0
, &m1
, &m2
, mt
))
251 die("neatcc: instruction %08lx not supported\n", ic
->op
);
253 * the registers used in global register allocation should not
254 * be used in the last instruction of a basic block.
256 if (ic
->op
& (O_JZ
| O_JCC
))
257 for (i
= 0; i
< LEN(ra_lmap
); i
++)
258 if (ra_lmapglob
[i
] >= 0 && ra_lmap
[i
] != ra_lmapglob
[i
])
260 /* allocating registers for the operands */
262 *r2
= ra_regget(ic
->arg2
, m2
, m2
, all
);
266 *r1
= ra_regget(ic
->arg1
, m1
, m1
, all
);
270 int wop
= ic
->op
& O_OUT
;
271 if (wop
&& n
>= 3 && m0
& (1 << *r2
))
273 else if (wop
&& n
>= 2 && m0
& (1 << *r1
))
276 *r0
= ra_regget(ic
->arg0
, ra_gmask
[ic
->arg0
],
281 /* if r0 is overwritten and it is a local; use another register */
282 if (n
>= 1 && oc
& O_OUT
&& ra_lmap
[*r0
] >= 0) {
283 long m3
= (m0
? m0
: m1
) & ~(all
| (1 << *r0
));
284 long arg3
= m0
? ic
->arg0
: ic
->arg1
;
286 int r3
= ra_regget(arg3
, ra_gmask
[ic
->arg0
], m3
, 0);
287 if (n
>= 2 && *r0
== *r1
)
289 if (n
>= 3 && *r0
== *r2
)
296 func_regs
|= all
| *mt
;
299 static long iv_rank(long iv
)
302 for (i
= 0; i
< LEN(ra_live
); i
++)
303 if (ra_live
[i
] == iv
)
305 die("neatcc: the specified value is not live\n");
309 static long iv_addr(long rank
)
311 return loc_pos
+ rank
* ULNG
+ ULNG
;
314 static void loc_toreg(long loc
, long off
, int reg
, int bt
)
317 i_ins(O_MK(O_LD
| O_NUM
, bt
), reg
, REG_FP
, -loc_off
[loc
] + off
);
320 static void loc_tomem(long loc
, long off
, int reg
, int bt
)
323 i_ins(O_MK(O_ST
| O_NUM
, bt
), reg
, REG_FP
, -loc_off
[loc
] + off
);
326 static void loc_toadd(long loc
, long off
, int reg
)
329 i_ins(O_ADD
| O_NUM
, reg
, REG_FP
, -loc_off
[loc
] + off
);
332 static void val_toreg(long val
, int reg
)
334 i_ins(O_MK(O_LD
| O_NUM
, ULNG
), reg
, REG_FP
, -iv_addr(iv_rank(val
)));
337 static void val_tomem(long val
, int reg
)
339 long rank
= iv_rank(val
);
340 ra_vmax
= MAX(ra_vmax
, rank
+ 1);
341 i_ins(O_MK(O_ST
| O_NUM
, ULNG
), reg
, REG_FP
, -iv_addr(rank
));
344 /* move the value to the stack */
345 static void ra_spill(int reg
)
347 if (ra_vmap
[reg
] >= 0) {
348 val_tomem(ra_vmap
[reg
], reg
);
351 if (ra_lmap
[reg
] >= 0) {
352 if (ra_lmap
[reg
] == ra_lmapglob
[reg
])
353 loc_tomem(ra_lmap
[reg
], 0, reg
, ULNG
);
358 /* set the value to the given register */
359 static void ra_vsave(long iv
, int reg
)
363 for (i
= 0; i
< LEN(ra_live
); i
++)
366 if (i
== LEN(ra_live
))
367 die("neatcc: too many live values\n");
371 /* load the value into a register */
372 static void ra_vload(long iv
, int reg
)
374 if (ra_vmap
[reg
] == iv
)
376 if (ra_vmap
[reg
] >= 0 || ra_lmap
[reg
] >= 0)
378 if (ra_vreg(iv
) >= 0) {
379 i_ins(O_MK(O_MOV
, ULNG
), reg
, ra_vreg(iv
), 0);
380 ra_vmap
[ra_vreg(iv
)] = -1;
387 /* the value is no longer needed */
388 static void ra_vdrop(long iv
)
391 for (i
= 0; i
< LEN(ra_live
); i
++)
392 if (ra_live
[i
] == iv
)
394 if (ra_vreg(iv
) >= 0)
395 ra_vmap
[ra_vreg(iv
)] = -1;
398 /* move the given value to memory or a free register */
399 static void ra_vmove(long iv
, long mask
)
401 int src
= ra_vreg(iv
);
402 int dst
= ra_regcheap(mask
);
403 if (dst
>= 0 && ra_vmap
[dst
] < 0 && ra_lmap
[dst
] < 0) {
404 i_ins(O_MK(O_MOV
, ULNG
), dst
, src
, 0);
412 /* load the value of local loc into register reg */
413 static void ra_lload(long loc
, long off
, int reg
, int bt
)
415 if (ra_lreg(loc
) < 0 && !loc_ptr
[loc
] && loc_dat
[loc
] > 2) {
417 loc_toreg(loc
, off
, reg
, bt
);
419 if (ra_lreg(loc
) >= 0) {
420 if (ra_lreg(loc
) != reg
)
421 i_ins(O_MK(O_MOV
, bt
), reg
, ra_lreg(loc
), 0);
423 loc_toreg(loc
, off
, reg
, bt
);
427 /* register reg contains the value of local loc */
428 static void ra_lsave(long loc
, long off
, int reg
, int bt
)
430 int lreg
= ra_lreg(loc
);
431 if (lreg
>= 0 && ra_lmapglob
[lreg
] == ra_lmap
[lreg
]) {
432 if (ra_vmap
[lreg
] >= 0) /* values using the same register */
433 ra_vmove(ra_vmap
[lreg
],
434 ra_gmask
[ra_vmap
[lreg
]] & ~(1 << reg
));
435 i_ins(O_MK(O_MOV
, bt
), lreg
, reg
, 0);
439 loc_tomem(loc
, off
, reg
, bt
);
440 if (!loc_ptr
[loc
] && loc_dat
[loc
] > 2 && ra_lmap
[reg
] < 0)
445 /* end of a basic block */
446 static void ra_bbend(void)
449 /* save values to memory */
450 for (i
= 0; i
< LEN(ra_vmap
); i
++)
453 /* dropping local caches */
454 for (i
= 0; i
< LEN(ra_lmap
); i
++)
455 if (ra_lmap
[i
] != ra_lmapglob
[i
] && ra_lmap
[i
] >= 0)
457 /* load global register allocations from memory */
458 for (i
= 0; i
< LEN(ra_lmap
); i
++) {
459 if (ra_lmap
[i
] != ra_lmapglob
[i
]) {
460 ra_lmap
[i
] = ra_lmapglob
[i
];
461 loc_toreg(ra_lmap
[i
], 0, i
, ULNG
);
466 /* perform global register allocation */
467 static void ra_glob(struct ic
*ic
, int ic_n
)
473 mask
= func_leaf
? R_TMPS
: R_PERM
;
474 nregs
= MIN(N_TMPS
>> 1, 4);
475 srt
= malloc(loc_n
* sizeof(srt
[0]));
477 for (i
= 0; i
< loc_n
; i
++) {
478 for (j
= i
- 1; j
>= 0 && loc_dat
[i
] > loc_dat
[srt
[j
]]; j
--)
482 /* allocating registers */
483 for (i
= 0; i
< loc_n
&& nregs
> 0; i
++) {
487 if (func_leaf
&& l
< N_ARGS
&& l
< func_argc
&&
488 ra_lmapglob
[argregs
[l
]] < 0) {
489 ra_lmapglob
[argregs
[l
]] = l
;
495 for (j
= func_leaf
? 1 : 3; j
< N_TMPS
; j
++) {
497 if (ra_lmapglob
[r
] < 0 && (1 << r
) & mask
) {
507 /* return the values written to and read from in the given instruction */
508 static void ic_info(struct ic
*ic
, long **w
, long **r1
, long **r2
, long **r3
)
510 long n
= ic_regcnt(ic
);
511 long o
= ic
->op
& O_OUT
;
518 *r1
= n
>= 2 ? &ic
->arg1
: NULL
;
519 *r2
= n
>= 3 ? &ic
->arg2
: NULL
;
521 *r1
= n
>= 1 ? &ic
->arg0
: NULL
;
522 *r2
= n
>= 2 ? &ic
->arg1
: NULL
;
523 *r3
= n
>= 3 ? &ic
->arg2
: NULL
;
527 static void ra_init(struct ic
*ic
, int ic_n
)
532 ic_luse
= calloc(ic_n
, sizeof(ic_luse
[0]));
533 ic_bbeg
= calloc(ic_n
, sizeof(ic_bbeg
[0]));
534 ra_gmask
= calloc(ic_n
, sizeof(ra_gmask
[0]));
535 loc_mem
= calloc(loc_n
, sizeof(loc_mem
[0]));
537 for (i
= ic_n
- 1; i
>= 0; --i
) {
538 long *w
, *r1
, *r2
, *r3
;
539 ic_info(ic
+ i
, &w
, &r1
, &r2
, &r3
);
541 if (!w
|| ic
[i
].op
& O_CALL
)
545 if (r1
&& !ic_luse
[*r1
])
547 if (r2
&& !ic_luse
[*r2
])
549 if (r3
&& !ic_luse
[*r3
])
551 if (ic
[i
].op
& O_CALL
)
552 for (j
= 0; j
< ic
[i
].arg2
; j
++)
553 if (!ic_luse
[ic
[i
].args
[j
]])
554 ic_luse
[ic
[i
].args
[j
]] = i
;
557 for (i
= 0; i
< ic_n
; i
++) {
560 if (i
+ 1 < ic_n
&& ic
[i
].op
& (O_JXX
| O_RET
))
562 if (ic
[i
].op
& O_JXX
&& ic
[i
].arg2
< ic_n
)
563 ic_bbeg
[ic
[i
].arg2
] = 1;
566 for (i
= 0; i
< ic_n
; i
++) {
567 int n
= ic_regcnt(ic
+ i
);
571 i_reg(op
, &m0
, &m1
, &m2
, &mt
);
572 if (n
>= 1 && !(op
& O_OUT
))
573 ra_gmask
[ic
[i
].arg0
] = m0
;
575 ra_gmask
[ic
[i
].arg1
] = m1
;
577 ra_gmask
[ic
[i
].arg2
] = m2
;
579 for (j
= 0; j
< MIN(N_ARGS
, ic
[i
].arg2
); j
++)
580 ra_gmask
[ic
[i
].args
[j
]] = 1 << argregs
[j
];
582 /* loc_ptr and loc_dat */
583 loc_ptr
= calloc(loc_n
, sizeof(loc_ptr
[0]));
584 loc_dat
= calloc(loc_n
, sizeof(loc_dat
[0]));
585 loc_sz
= calloc(loc_n
, sizeof(loc_sz
[0]));
586 for (i
= 0; i
< ic_n
; i
++) {
587 long oc
= O_C(ic
[i
].op
);
590 if (oc
== (O_LD
| O_LOC
) || oc
== (O_ST
| O_LOC
)) {
591 int loc
= ic
[i
].arg1
;
592 int sz
= T_SZ(O_T(ic
[i
].op
));
595 if (ic
[i
].arg2
|| sz
< 2 || sz
!= loc_sz
[loc
])
600 if (oc
== (O_MOV
| O_LOC
))
601 loc_ptr
[ic
[i
].arg1
]++;
606 for (i
= 0; i
< ic_n
; i
++)
607 if (ic_luse
[i
] && ic
[i
].op
& O_CALL
)
610 for (i
= 0; i
< LEN(ra_vmap
); i
++)
613 for (i
= 0; i
< N_REGS
; i
++)
616 memcpy(ra_lmap
, ra_lmapglob
, sizeof(ra_lmap
));
617 for (i
= 0; i
< LEN(ra_lmapglob
); i
++)
618 if (ra_lmapglob
[i
] >= 0)
619 func_regs
|= (1 << i
);
621 for (i
= 0; i
< LEN(ra_live
); i
++)
627 static void ra_done(void)
637 static void ic_gencode(struct ic
*ic
, int ic_n
)
642 /* loading arguments in their allocated registers */
643 for (i
= 0; i
< LEN(ra_lmap
); i
++) {
644 int loc
= ra_lmap
[i
];
645 if (loc
>= 0 && loc
< func_argc
)
646 if (loc
>= N_ARGS
|| i
!= argregs
[loc
])
647 loc_toreg(loc
, 0, i
, ULNG
);
649 /* generating code */
650 for (i
= 0; i
< ic_n
; i
++) {
653 int n
= ic_regcnt(ic
+ i
);
657 ra_map(ic
+ i
, &r0
, &r1
, &r2
, &mt
);
659 int argc
= ic
[i
].arg2
;
660 int aregs
= MIN(N_ARGS
, argc
);
661 /* arguments passed via stack */
662 for (j
= argc
- 1; j
>= aregs
; --j
) {
663 int v
= ic
[i
].args
[j
];
664 int rx
= ra_vreg(v
) >= 0 ? ra_vreg(v
) : r0
;
666 i_ins(O_MK(O_ST
| O_NUM
, ULNG
), rx
, REG_SP
,
670 func_maxargs
= MAX(func_maxargs
, argc
- aregs
);
671 /* arguments passed via registers */
672 for (j
= aregs
- 1; j
>= 0; --j
)
673 ra_vload(ic
[i
].args
[j
], argregs
[j
]);
675 /* loading the operands */
676 if (n
>= 1 && !(oc
& O_OUT
))
677 ra_vload(ic
[i
].arg0
, r0
);
678 if (n
>= 2 && !(oc
& O_LOC
))
679 ra_vload(ic
[i
].arg1
, r1
);
681 ra_vload(ic
[i
].arg2
, r2
);
682 /* dropping values that are no longer used */
683 for (j
= 0; j
< LEN(ra_live
); j
++)
684 if (ra_live
[j
] >= 0 && ic_luse
[ra_live
[j
]] <= i
)
685 ra_vdrop(ra_live
[j
]);
686 /* saving values stored in registers that may change */
687 for (j
= 0; j
< N_REGS
; j
++)
690 /* overwriting a value that is needed later (unless loading a local to its register) */
691 if (n
>= 1 && oc
& O_OUT
)
692 if (oc
!= (O_LD
| O_LOC
) || ra_lmap
[r0
] != ic
[i
].arg1
||
695 /* before the last instruction of a basic block; for jumps */
696 if (i
+ 1 < ic_n
&& ic_bbeg
[i
+ 1] && oc
& O_JXX
)
698 /* performing the instruction */
700 i_ins(op
, r0
, r1
, oc
& O_NUM
? ic
[i
].arg2
: r2
);
702 i_ins(op
, r0
, r1
, r2
);
703 if (oc
== (O_LD
| O_NUM
))
704 i_ins(op
, r0
, r1
, ic
[i
].arg2
);
705 if (oc
== (O_LD
| O_LOC
))
706 ra_lload(ic
[i
].arg1
, ic
[i
].arg2
, r0
, O_T(op
));
707 if (oc
== (O_ST
| O_NUM
))
708 i_ins(op
, r0
, r1
, ic
[i
].arg2
);
709 if (oc
== (O_ST
| O_LOC
))
710 ra_lsave(ic
[i
].arg1
, ic
[i
].arg2
, r0
, O_T(op
));
714 i_ins(op
, r0
, r0
, 0);
715 if (oc
== (O_MOV
| O_NUM
))
716 i_ins(op
, r0
, ic
[i
].arg1
, 0);
717 if (oc
== (O_MOV
| O_LOC
))
718 loc_toadd(ic
[i
].arg1
, ic
[i
].arg2
, r0
);
719 if (oc
== (O_MOV
| O_SYM
))
720 i_ins(op
, r0
, ic
[i
].arg1
, ic
[i
].arg2
);
722 i_ins(op
, r0
, r1
, 0);
723 if (oc
== (O_CALL
| O_SYM
))
724 i_ins(op
, r0
, ic
[i
].arg1
, 0);
726 i_ins(op
, 0, 0, ic
[i
].arg2
);
728 i_ins(op
, r0
, 0, ic
[i
].arg2
);
730 i_ins(op
, r0
, oc
& O_NUM
? ic
[i
].arg1
: r1
, ic
[i
].arg2
);
732 i_ins(op
, r0
, r1
, r2
);
734 i_ins(op
, r0
, r1
, r2
);
735 /* saving back the output register */
737 ra_vsave(ic
[i
].arg0
, r0
);
738 /* after the last instruction of a basic block */
739 if (i
+ 1 < ic_n
&& ic_bbeg
[i
+ 1] && !(oc
& O_JXX
))
745 static void ic_reset(void)
756 void o_func_beg(char *name
, int argc
, int global
, int varg
)
763 for (i
= 0; i
< argc
; i
++)
764 loc_add(I_ARG0
+ -i
* ULNG
);
765 out_def(name
, (global
? OUT_GLOB
: 0) | OUT_CS
, mem_len(&cs
), 0);
768 void o_code(char *name
, char *c
, long c_len
)
770 out_def(name
, OUT_CS
, mem_len(&cs
), 0);
771 mem_put(&cs
, c
, c_len
);
774 void o_func_end(void)
779 long sargs_last
= -1;
782 long c_len
, *rsym
, *rflg
, *roff
, rcnt
;
783 int locs
= 0; /* accessing locals on the stack */
785 ic_get(&ic
, &ic_n
); /* the intermediate code */
786 ra_init(ic
, ic_n
); /* initialize register allocation */
787 ic_gencode(ic
, ic_n
); /* generating machine code */
788 /* deciding which arguments to save */
789 for (i
= 0; i
< func_argc
; i
++)
792 for (i
= 0; i
< N_ARGS
&& (func_varg
|| i
< sargs_last
); i
++)
793 sargs
|= 1 << argregs
[i
];
794 /* computing the amount of stack subtraction */
795 for (i
= 0; i
< loc_n
; i
++)
798 spsub
= (locs
|| ra_vmax
) ? loc_pos
+ ra_vmax
* ULNG
: 0;
799 for (i
= 0; i
< N_TMPS
; i
++)
800 if (((1 << tmpregs
[i
]) & func_regs
& R_PERM
) != 0)
803 spsub
+= func_maxargs
* ULNG
;
804 /* adding function prologue and epilogue */
805 i_wrap(func_argc
, sargs
, spsub
, spsub
|| locs
|| !func_leaf
,
806 func_regs
& R_PERM
, -sregs_pos
);
808 i_code(&c
, &c_len
, &rsym
, &rflg
, &roff
, &rcnt
);
809 for (i
= 0; i
< rcnt
; i
++) /* adding the relocations */
810 out_rel(rsym
[i
], rflg
[i
], roff
[i
] + mem_len(&cs
));
811 mem_put(&cs
, c
, c_len
); /* appending function code */
816 for (i
= 0; i
< ic_n
; i
++)
817 if (ic
[i
].op
& O_CALL
)
826 out_write(fd
, mem_buf(&cs
), mem_len(&cs
), mem_buf(&ds
), mem_len(&ds
));