int: load assignment destination last if possible
[neatcc.git] / gen.c
blobf8fc04c71305179f8cd81086e9e1162ff2d976d3
1 /* neatcc code generation */
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include "ncc.h"
7 static struct mem ds; /* data segment */
8 static struct mem cs; /* code segment */
9 static long bsslen; /* bss segment size */
10 static struct ic *ic; /* current instruction stream */
11 static long ic_n; /* number of instructions in ic[] */
12 static long ic_i; /* current instruction */
13 static long *ic_luse; /* last instruction in which values are used */
15 static long *loc_off; /* offset of locals on the stack */
16 static long loc_n, loc_sz; /* number of locals */
17 static long loc_pos; /* current stack position */
18 static int *loc_mem; /* local was accessed on the stack */
20 static char (*ds_name)[NAMELEN];/* data section symbols */
21 static long *ds_off; /* data section offsets */
22 static long ds_n, ds_sz; /* number of data section symbols */
24 static int func_argc; /* number of arguments */
25 static int func_varg; /* varargs */
26 static int func_regs; /* used registers */
27 static int func_maxargs; /* the maximum number of arguments on the stack */
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_gmask; /* the mask of good registers for each value */
33 static long ra_live[NTMPS]; /* live values */
34 static int ra_vmax; /* the number of values stored on the stack */
36 static long loc_add(long pos)
38 if (loc_n >= loc_sz) {
39 loc_sz = MAX(128, loc_sz * 2);
40 loc_off = mextend(loc_off, loc_n, loc_sz, sizeof(loc_off[0]));
42 loc_off[loc_n] = pos;
43 return loc_n++;
46 long o_mklocal(long sz)
48 loc_pos += ALIGN(sz, ULNG);
49 return loc_add(loc_pos);
52 void o_rmlocal(long addr, long sz)
56 long o_arg2loc(int i)
58 return i;
61 void o_bsnew(char *name, long size, int global)
63 out_def(name, OUT_BSS | (global ? OUT_GLOB : 0), bsslen, size);
64 bsslen += ALIGN(size, OUT_ALIGNMENT);
67 long o_dsnew(char *name, long size, int global)
69 int idx;
70 if (ds_n >= ds_sz) {
71 ds_sz = MAX(128, ds_sz * 2);
72 ds_name = mextend(ds_name, ds_n, ds_sz, sizeof(ds_name[0]));
73 ds_off = mextend(ds_off, ds_n, ds_sz, sizeof(ds_off[0]));
75 idx = ds_n++;
76 strcpy(ds_name[idx], name);
77 ds_off[idx] = mem_len(&ds);
78 out_def(name, OUT_DS | (global ? OUT_GLOB : 0), mem_len(&ds), size);
79 mem_putz(&ds, ALIGN(size, OUT_ALIGNMENT));
80 return ds_off[idx];
83 void o_dscpy(long addr, void *buf, long len)
85 mem_cpy(&ds, addr, buf, len);
88 static int dat_off(char *name)
90 int i;
91 for (i = 0; i < ds_n; i++)
92 if (!strcmp(name, ds_name[i]))
93 return ds_off[i];
94 return 0;
97 void o_dsset(char *name, long off, long bt)
99 long sym_off = dat_off(name) + off;
100 long num, roff, rsym;
101 if (!o_popnum(&num)) {
102 mem_cpy(&ds, sym_off, &num, T_SZ(bt));
103 return;
105 if (!o_popsym(&rsym, &roff)) {
106 out_rel(rsym, OUT_DS, sym_off);
107 mem_cpy(&ds, sym_off, &roff, T_SZ(bt));
111 static int ra_vreg(int val)
113 int i;
114 for (i = 0; i < LEN(ra_vmap); i++)
115 if (ra_vmap[i] == val)
116 return i;
117 return -1;
120 static int ra_lreg(int loc)
122 int i;
123 for (i = 0; i < LEN(ra_lmap); i++)
124 if (ra_lmap[i] == loc)
125 return i;
126 return -1;
129 /* mask of registers assigned to locals */
130 static long ra_lmask(void)
132 long m = 0;
133 int i;
134 for (i = 0; i < LEN(ra_lmap); i++)
135 if (ra_lmap[i] >= 0)
136 m |= (1 << i);
137 return m;
140 /* mask of registers assigned to values */
141 static long ra_vmask(void)
143 long m = 0;
144 int i;
145 for (i = 0; i < LEN(ra_vmap); i++)
146 if (ra_vmap[i] >= 0)
147 m |= (1 << i);
148 return m;
151 /* find a temporary register specified in the given mask */
152 static long ra_regscn(long mask)
154 int i;
155 for (i = 0; i < N_TMPS; i++)
156 if ((1 << tmpregs[i]) & mask)
157 return tmpregs[i];
158 return -1;
161 /* find a register, with the given good, acceptable, and bad register masks */
162 static long ra_regget(long iv, long gmask, long amask, long bmask)
164 long lmask, vmask;
165 gmask &= ~bmask & amask;
166 amask &= ~bmask;
167 if (ra_vreg(iv) >= 0 && (1 << ra_vreg(iv)) & (gmask | amask))
168 return ra_vreg(iv);
169 vmask = ra_vmask();
170 lmask = ra_lmask();
171 if (ra_regscn(gmask & ~vmask & ~lmask) >= 0)
172 return ra_regscn(gmask & ~vmask & ~lmask);
173 if (ra_regscn(amask & ~vmask & ~lmask) >= 0)
174 return ra_regscn(amask & ~vmask & ~lmask);
175 if (ra_regscn(gmask) >= 0)
176 return ra_regscn(gmask);
177 if (ra_regscn(amask) >= 0)
178 return ra_regscn(amask);
179 die("neatcc: cannot allocate an acceptable register\n");
180 return 0;
183 /* find a free and cheap register */
184 static long ra_regcheap(long mask)
186 return ra_regscn(mask & (func_regs | (R_TMPS & ~R_PERM)) &
187 ~ra_lmask() & ~ra_vmask());
190 /* allocate registers for the current instruction */
191 static void ra_map(int *rd, int *r1, int *r2, int *r3, long *mt)
193 long md, m1, m2, m3;
194 struct ic *c = &ic[ic_i];
195 long all = 0;
196 int n = ic_regcnt(c);
197 int oc = O_C(c->op);
198 int i;
199 *rd = -1;
200 *r1 = -1;
201 *r2 = -1;
202 *r3 = -1;
203 *mt = 0;
204 /* optimizing loading locals: point to local's register */
205 if (oc == (O_LD | O_LOC) && ra_lreg(c->a1) >= 0 &&
206 ra_vmap[ra_lreg(c->a1)] < 0) {
207 *rd = ra_lreg(c->a1);
208 func_regs |= 1 << *rd;
209 return;
211 /* do not use argument registers to hold call destination */
212 if (oc & O_CALL)
213 for (i = 0; i < MIN(c->a3, N_ARGS); i++)
214 all |= (1 << argregs[i]);
215 /* instructions on locals can be simplified */
216 if (oc & O_LOC) {
217 if (oc & O_MOV)
218 oc = O_ADD | O_NUM;
219 if (oc & (O_ST | O_LD))
220 oc = (oc & ~O_LOC) & O_NUM;
222 if (i_reg(c->op, &md, &m1, &m2, &m3, mt))
223 die("neatcc: instruction %08lx not supported\n", c->op);
225 * the registers used in global register allocation should not
226 * be used in the last instruction of a basic block.
228 if (c->op & (O_JZ | O_JCC))
229 for (i = 0; i < LEN(ra_lmap); i++)
230 if (reg_rmap(ic_i, i) >= 0 && ra_lmap[i] != reg_rmap(ic_i, i))
231 all |= (1 << i);
232 /* allocating registers for the operands */
233 if (n >= 2) {
234 *r2 = ra_regget(c->a2, m2, m2, all);
235 all |= (1 << *r2);
237 if (n >= 1) {
238 *r1 = ra_regget(c->a1, m1, m1, all);
239 all |= (1 << *r1);
241 if (n >= 3) {
242 *r3 = ra_regget(c->a3, m3, m3, all);
243 all |= (1 << *r3);
245 if (c->op & O_OUT) {
246 if (n >= 1 && !md)
247 *rd = *r1;
248 else if (n >= 2 && md & (1 << *r2) && ic_luse[*r2] <= ic_i)
249 *rd = *r2;
250 else if (n >= 1 && md & (1 << *r1) && ic_luse[*r1] <= ic_i)
251 *rd = *r1;
252 else
253 *rd = ra_regget(ic_i, ra_gmask[ic_i], md, 0);
255 /* if r0 is overwritten and it is a local; use another register */
256 if (oc & O_OUT && ra_lmap[*rd] >= 0) {
257 long m4 = (md ? md : m1) & ~(all | (1 << *rd));
258 long a4 = md ? ic_i : c->a1;
259 if (m4) {
260 int r4 = ra_regget(a4, ra_gmask[ic_i], m4, 0);
261 if (n >= 1 && *rd == *r1)
262 *r1 = r4;
263 if (n >= 2 && *rd == *r2)
264 *r2 = r4;
265 *rd = r4;
268 if (oc & O_OUT)
269 all |= (1 << *rd);
270 func_regs |= all | *mt;
273 static long iv_rank(long iv)
275 int i;
276 for (i = 0; i < LEN(ra_live); i++)
277 if (ra_live[i] == iv)
278 return i;
279 die("neatcc: the specified value is not live\n");
280 return 0;
283 static long iv_addr(long rank)
285 return loc_pos + rank * ULNG + ULNG;
288 static void loc_toreg(long loc, long off, int reg, int bt)
290 loc_mem[loc]++;
291 i_ins(O_MK(O_LD | O_NUM, bt), reg, REG_FP, -loc_off[loc] + off, 0);
294 static void loc_tomem(long loc, long off, int reg, int bt)
296 loc_mem[loc]++;
297 i_ins(O_MK(O_ST | O_NUM, bt), 0, reg, REG_FP, -loc_off[loc] + off);
300 static void loc_toadd(long loc, long off, int reg)
302 loc_mem[loc]++;
303 i_ins(O_ADD | O_NUM, reg, REG_FP, -loc_off[loc] + off, 0);
306 /* return nonzero if the local is read at least once in this basic block */
307 static int loc_isread(long loc)
309 int i;
310 for (i = ic_i + 1; i < ic_n && !ic_bbeg[i]; i++)
311 if (ic[i].op & O_LOC)
312 return ic[i].op & O_LD;
313 return 0;
316 static void val_toreg(long val, int reg)
318 i_ins(O_MK(O_LD | O_NUM, ULNG), reg, REG_FP, -iv_addr(iv_rank(val)), 0);
321 static void val_tomem(long val, int reg)
323 long rank = iv_rank(val);
324 ra_vmax = MAX(ra_vmax, rank + 1);
325 i_ins(O_MK(O_ST | O_NUM, ULNG), 0, reg, REG_FP, -iv_addr(rank));
328 /* move the value to the stack */
329 static void ra_spill(int reg)
331 if (ra_vmap[reg] >= 0) {
332 val_tomem(ra_vmap[reg], reg);
333 ra_vmap[reg] = -1;
335 if (ra_lmap[reg] >= 0) {
336 if (ra_lmap[reg] == reg_rmap(ic_i, reg))
337 loc_tomem(ra_lmap[reg], 0, reg, ULNG);
338 ra_lmap[reg] = -1;
342 /* set the value to the given register */
343 static void ra_vsave(long iv, int reg)
345 int i;
346 ra_vmap[reg] = iv;
347 for (i = 0; i < LEN(ra_live); i++)
348 if (ra_live[i] < 0)
349 break;
350 if (i == LEN(ra_live))
351 die("neatcc: too many live values\n");
352 ra_live[i] = iv;
355 /* load the value into a register */
356 static void ra_vload(long iv, int reg)
358 if (ra_vmap[reg] == iv)
359 return;
360 if (ra_vmap[reg] >= 0 || ra_lmap[reg] >= 0)
361 ra_spill(reg);
362 if (ra_vreg(iv) >= 0) {
363 i_ins(O_MK(O_MOV, ULNG), reg, ra_vreg(iv), 0, 0);
364 ra_vmap[ra_vreg(iv)] = -1;
365 } else {
366 val_toreg(iv, reg);
368 ra_vmap[reg] = iv;
371 /* the value is no longer needed */
372 static void ra_vdrop(long iv)
374 int i;
375 for (i = 0; i < LEN(ra_live); i++)
376 if (ra_live[i] == iv)
377 ra_live[i] = -1;
378 if (ra_vreg(iv) >= 0)
379 ra_vmap[ra_vreg(iv)] = -1;
382 /* move the given value to memory or a free register */
383 static void ra_vmove(long iv, long mask)
385 int src = ra_vreg(iv);
386 int dst = ra_regcheap(mask);
387 if (dst >= 0 && ra_vmap[dst] < 0 && ra_lmap[dst] < 0) {
388 i_ins(O_MK(O_MOV, ULNG), dst, src, 0, 0);
389 ra_vmap[dst] = iv;
390 } else {
391 val_tomem(iv, src);
393 ra_vmap[src] = -1;
396 /* load the value of local loc into register reg */
397 static void ra_lload(long loc, long off, int reg, int bt)
399 int greg = reg_lmap(ic_i, loc);
400 if (greg >= 0) {
401 int lreg = ra_lreg(loc);
402 /* values using the same register */
403 if (ra_vmap[greg] >= 0)
404 ra_vmove(ra_vmap[greg],
405 ra_gmask[ra_vmap[greg]] & ~(1 << reg));
406 if (lreg >= 0) {
407 ra_lmap[lreg] = -1;
408 if (lreg != greg)
409 i_ins(O_MK(O_MOV, bt), greg, lreg, 0, 0);
410 } else {
411 loc_toreg(loc, off, greg, bt);
413 ra_lmap[greg] = loc;
415 if (ra_lreg(loc) < 0 && reg_safe(loc) && loc_isread(loc)) {
416 ra_lmap[reg] = loc;
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, 0);
422 } else {
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 int greg = reg_lmap(ic_i, loc);
432 if (greg >= 0) {
433 if (lreg >= 0 && lreg != greg)
434 ra_lmap[lreg] = -1;
435 if (ra_vmap[greg] >= 0) /* values using the same register */
436 ra_vmove(ra_vmap[greg],
437 ra_gmask[ra_vmap[greg]] & ~(1 << reg));
438 i_ins(O_MK(O_MOV, bt), greg, reg, 0, 0);
439 ra_lmap[greg] = loc;
440 } else {
441 if (lreg >= 0)
442 ra_lmap[lreg] = -1;
443 loc_tomem(loc, off, reg, bt);
444 if (ra_lmap[reg] < 0 && reg_safe(loc) && loc_isread(loc))
445 ra_lmap[reg] = loc;
449 /* end of a basic block */
450 static void ra_bbend(void)
452 int i;
453 /* save values to memory */
454 for (i = 0; i < LEN(ra_vmap); i++)
455 if (ra_vmap[i] >= 0)
456 ra_spill(i);
457 /* dropping local caches */
458 for (i = 0; i < LEN(ra_lmap); i++)
459 if (ra_lmap[i] != reg_rmap(ic_i, i) && ra_lmap[i] >= 0)
460 ra_spill(i);
461 /* load global register allocations from memory */
462 for (i = 0; i < LEN(ra_lmap); i++) {
463 if (ra_lmap[i] != reg_rmap(ic_i, i)) {
464 ra_lmap[i] = reg_rmap(ic_i, i);
465 loc_toreg(ra_lmap[i], 0, i, ULNG);
470 static void ra_init(struct ic *ic, long ic_n)
472 long md, m1, m2, m3, mt;
473 int i, j;
474 ic_bbeg = calloc(ic_n, sizeof(ic_bbeg[0]));
475 ra_gmask = calloc(ic_n, sizeof(ra_gmask[0]));
476 loc_mem = calloc(loc_n, sizeof(loc_mem[0]));
477 /* ic_bbeg */
478 for (i = 0; i < ic_n; i++) {
479 if (i + 1 < ic_n && ic[i].op & (O_JXX | O_RET))
480 ic_bbeg[i + 1] = 1;
481 if (ic[i].op & O_JXX && ic[i].a3 < ic_n)
482 ic_bbeg[ic[i].a3] = 1;
484 /* ra_gmask */
485 for (i = 0; i < ic_n; i++) {
486 int n = ic_regcnt(ic + i);
487 int op = ic[i].op;
488 i_reg(op, &md, &m1, &m2, &m3, &mt);
489 if (n >= 1)
490 ra_gmask[ic[i].a1] = m1;
491 if (n >= 2)
492 ra_gmask[ic[i].a2] = m2;
493 if (n >= 3)
494 ra_gmask[ic[i].a3] = m3;
495 if (op & O_CALL)
496 for (j = 0; j < MIN(N_ARGS, ic[i].a3); j++)
497 ra_gmask[ic[i].args[j]] = 1 << argregs[j];
499 /* ra_vmap */
500 for (i = 0; i < LEN(ra_vmap); i++)
501 ra_vmap[i] = -1;
502 /* ra_lmap */
503 for (i = 0; i < LEN(ra_lmap); i++)
504 ra_lmap[i] = reg_rmap(0, i);
505 func_regs |= reg_mask();
506 /* ra_live */
507 for (i = 0; i < LEN(ra_live); i++)
508 ra_live[i] = -1;
509 ra_vmax = 0;
510 func_maxargs = 0;
513 static void ra_done(void)
515 free(ic_bbeg);
516 free(ra_gmask);
517 free(loc_mem);
520 static void ic_gencode(struct ic *ic, long ic_n)
522 int rd, r1, r2, r3;
523 long mt;
524 int i, j;
525 /* loading arguments in their allocated registers */
526 for (i = 0; i < LEN(ra_lmap); i++) {
527 int loc = ra_lmap[i];
528 if (loc >= 0 && loc < func_argc)
529 if (loc >= N_ARGS || i != argregs[loc])
530 loc_toreg(loc, 0, i, ULNG);
532 /* generating code */
533 for (i = 0; i < ic_n; i++) {
534 long op = ic[i].op;
535 long oc = O_C(op);
536 int n = ic_regcnt(ic + i);
537 ic_i = i;
538 i_label(i);
539 ra_map(&rd, &r1, &r2, &r3, &mt);
540 if (oc & O_CALL) {
541 int argc = ic[i].a3;
542 int aregs = MIN(N_ARGS, argc);
543 /* arguments passed via stack */
544 for (j = argc - 1; j >= aregs; --j) {
545 int v = ic[i].args[j];
546 int rx = ra_vreg(v) >= 0 ? ra_vreg(v) : rd;
547 ra_vload(v, rx);
548 i_ins(O_MK(O_ST | O_NUM, ULNG), 0,
549 rx, REG_SP, (j - aregs) * ULNG);
550 ra_vdrop(v);
552 func_maxargs = MAX(func_maxargs, argc - aregs);
553 /* arguments passed via registers */
554 for (j = aregs - 1; j >= 0; --j)
555 ra_vload(ic[i].args[j], argregs[j]);
557 /* loading the operands */
558 if (n >= 1)
559 ra_vload(ic[i].a1, r1);
560 if (n >= 2)
561 ra_vload(ic[i].a2, r2);
562 if (n >= 3)
563 ra_vload(ic[i].a3, r3);
564 /* dropping values that are no longer used */
565 for (j = 0; j < LEN(ra_live); j++)
566 if (ra_live[j] >= 0 && ic_luse[ra_live[j]] <= i)
567 ra_vdrop(ra_live[j]);
568 /* saving values stored in registers that may change */
569 for (j = 0; j < N_REGS; j++)
570 if (mt & (1 << j))
571 ra_spill(j);
572 /* overwriting a value that is needed later (unless loading a local to its register) */
573 if (oc & O_OUT)
574 if (oc != (O_LD | O_LOC) || ra_lmap[rd] != ic[i].a1 ||
575 ra_vmap[rd] >= 0)
576 ra_spill(rd);
577 /* before the last instruction of a basic block; for jumps */
578 if (i + 1 < ic_n && ic_bbeg[i + 1] && oc & O_JXX)
579 ra_bbend();
580 /* performing the instruction */
581 if (oc & O_BOP)
582 i_ins(op, rd, r1, oc & O_NUM ? ic[i].a2 : r2, 0);
583 if (oc & O_UOP)
584 i_ins(op, rd, r1, r2, 0);
585 if (oc == (O_LD | O_NUM))
586 i_ins(op, rd, r1, ic[i].a2, 0);
587 if (oc == (O_LD | O_LOC))
588 ra_lload(ic[i].a1, ic[i].a2, rd, O_T(op));
589 if (oc == (O_ST | O_NUM))
590 i_ins(op, 0, r1, r2, ic[i].a3);
591 if (oc == (O_ST | O_LOC))
592 ra_lsave(ic[i].a2, ic[i].a3, r1, O_T(op));
593 if (oc == O_RET)
594 i_ins(op, 0, r1, 0, 0);
595 if (oc == O_MOV)
596 i_ins(op, rd, r1, 0, 0);
597 if (oc == (O_MOV | O_NUM))
598 i_ins(op, rd, ic[i].a1, 0, 0);
599 if (oc == (O_MOV | O_LOC))
600 loc_toadd(ic[i].a1, ic[i].a2, rd);
601 if (oc == (O_MOV | O_SYM))
602 i_ins(op, rd, ic[i].a1, ic[i].a2, 0);
603 if (oc == O_CALL)
604 i_ins(op, rd, r1, 0, 0);
605 if (oc == (O_CALL | O_SYM))
606 i_ins(op, rd, ic[i].a1, ic[i].a2, 0);
607 if (oc == O_JMP)
608 i_ins(op, 0, 0, 0, ic[i].a3);
609 if (oc & O_JZ)
610 i_ins(op, 0, r1, 0, ic[i].a3);
611 if (oc & O_JCC)
612 i_ins(op, 0, r1, oc & O_NUM ? ic[i].a2 : r2, ic[i].a3);
613 if (oc == O_MSET)
614 i_ins(op, 0, r1, r2, r3);
615 if (oc == O_MCPY)
616 i_ins(op, 0, r1, r2, r3);
617 /* saving back the output register */
618 if (oc & O_OUT && ic_luse[i] > i)
619 ra_vsave(ic_i, rd);
620 /* after the last instruction of a basic block */
621 if (i + 1 < ic_n && ic_bbeg[i + 1] && !(oc & O_JXX))
622 ra_bbend();
624 i_label(ic_n);
627 static void ic_reset(void)
629 o_tmpdrop(-1);
630 o_back(0);
631 free(loc_off);
632 loc_off = NULL;
633 loc_n = 0;
634 loc_sz = 0;
635 loc_pos = I_LOC0;
638 void o_func_beg(char *name, int argc, int global, int varg)
640 int i;
641 func_argc = argc;
642 func_varg = varg;
643 func_regs = 0;
644 ic_reset();
645 for (i = 0; i < argc; i++)
646 loc_add(I_ARG0 + -i * ULNG);
647 out_def(name, (global ? OUT_GLOB : 0) | OUT_CS, mem_len(&cs), 0);
650 void o_code(char *name, char *c, long c_len)
652 out_def(name, OUT_CS, mem_len(&cs), 0);
653 mem_put(&cs, c, c_len);
656 void o_func_end(void)
658 long spsub;
659 long sargs = 0;
660 long sargs_last = -1;
661 long sregs_pos;
662 char *c;
663 long c_len, *rsym, *rflg, *roff, rcnt;
664 int leaf = 1;
665 int locs = 0; /* accessing locals on the stack */
666 int i;
667 ic_get(&ic, &ic_n); /* the intermediate code */
668 reg_init(ic, ic_n); /* global register allocation */
669 ra_init(ic, ic_n); /* initialize register allocation */
670 ic_luse = ic_lastuse(ic, ic_n);
671 ic_gencode(ic, ic_n); /* generating machine code */
672 free(ic_luse);
673 /* deciding which arguments to save */
674 for (i = 0; i < func_argc; i++)
675 if (loc_mem[i])
676 sargs_last = i + 1;
677 for (i = 0; i < N_ARGS && (func_varg || i < sargs_last); i++)
678 sargs |= 1 << argregs[i];
679 /* computing the amount of stack subtraction */
680 for (i = 0; i < loc_n; i++)
681 if (loc_mem[i])
682 locs = 1;
683 spsub = (locs || ra_vmax) ? loc_pos + ra_vmax * ULNG : 0;
684 for (i = 0; i < N_TMPS; i++)
685 if (((1 << tmpregs[i]) & func_regs & R_PERM) != 0)
686 spsub += ULNG;
687 sregs_pos = spsub;
688 spsub += func_maxargs * ULNG;
689 /* leaf functions */
690 for (i = 0; i < ic_n; i++)
691 if (ic[i].op & O_CALL)
692 leaf = 0;
693 /* adding function prologue and epilogue */
694 i_wrap(func_argc, sargs, spsub, spsub || locs || !leaf,
695 func_regs & R_PERM, -sregs_pos);
696 ra_done();
697 i_code(&c, &c_len, &rsym, &rflg, &roff, &rcnt);
698 for (i = 0; i < rcnt; i++) /* adding the relocations */
699 out_rel(rsym[i], rflg[i], roff[i] + mem_len(&cs));
700 mem_put(&cs, c, c_len); /* appending function code */
701 free(c);
702 free(rsym);
703 free(rflg);
704 free(roff);
705 for (i = 0; i < ic_n; i++)
706 ic_free(&ic[i]);
707 free(ic);
708 reg_done();
709 ic_reset();
712 void o_write(int fd)
714 i_done();
715 out_write(fd, mem_buf(&cs), mem_len(&cs), mem_buf(&ds), mem_len(&ds));
716 free(loc_off);
717 free(ds_name);
718 free(ds_off);
719 mem_done(&cs);
720 mem_done(&ds);