ncc: use label identifiers more carefully
[neatcc.git] / reg.c
blob95e19cbec50bfdaa2c47c576ab40984ce154ac07
1 #include <stdio.h>
2 #include <string.h>
3 #include "gen.h"
4 #include "ncc.h"
5 #include "reg.h"
7 static int l_sz[NLOCALS]; /* size of locals */
8 static int l_nr[NLOCALS]; /* # of reads */
9 static int l_nw[NLOCALS]; /* # of writes */
10 static int l_na[NLOCALS]; /* # of address accesses */
11 static int l_reg[NLOCALS]; /* register mapped to locals */
12 static int l_n; /* # of locals */
14 static int f_argc; /* number of arguments */
15 static int f_varg; /* function has variable argument list */
16 static int f_lregs; /* mask of R_TMPS allocated to locals */
17 static int f_sargs; /* mask of R_ARGS to be saved */
19 void r_func(int nargs, int varg)
21 int i;
22 f_varg = varg;
23 f_argc = nargs;
24 f_lregs = 0;
25 l_n = 0;
26 for (i = 0; i < f_argc; i++)
27 r_mk(LONGSZ);
28 f_sargs = f_varg ? R_ARGS : 0;
29 for (i = 0; i < f_argc && i < N_ARGS; i++)
30 f_sargs |= 1 << argregs[i];
33 void r_mk(int sz)
35 if (!f_lregs) {
36 l_sz[l_n] = sz;
37 l_nr[l_n] = 0;
38 l_nw[l_n] = 0;
39 l_na[l_n] = 0;
40 l_reg[l_n] = -1;
41 l_n++;
45 void r_rm(int id)
49 void r_read(int id)
51 l_nr[id]++;
54 void r_write(int id)
56 l_nw[id]++;
59 void r_addr(int id)
61 l_na[id]++;
64 void r_label(int l)
68 void r_jmp(int l)
72 int r_regmap(int id)
74 return l_reg[id];
77 int r_lregs(void)
79 return f_lregs;
82 int r_sargs(void)
84 return f_sargs;
87 /* sort locals for register allocation based on the number of accesses */
88 static int *sortedlocals(void)
90 static int ord[NLOCALS];
91 int i, j;
92 for (i = 0; i < l_n; i++) {
93 for (j = i - 1; j >= 0; j--) {
94 if (l_nr[i] + l_nw[i] <= l_nw[ord[j]] + l_nr[ord[j]])
95 break;
96 ord[j + 1] = ord[j];
98 ord[j + 1] = i;
100 return ord;
103 int r_alloc(int leaf, int used)
105 int nlocregs = 0;
106 int *ord = sortedlocals();
107 int idx = 0;
108 int i;
109 f_lregs = 0;
110 f_sargs = f_varg ? R_ARGS : 0;
111 /* except unused arguments, save all arguments on the stack */
112 for (i = 0; i < f_argc && i < N_ARGS; i++)
113 if (f_varg || l_nr[i] + l_nw[i] + l_na[i])
114 f_sargs |= 1 << argregs[i];
115 /* letting arguments stay in their registers for leaf functions */
116 if (!f_varg && leaf) {
117 for (i = 0; i < f_argc && i < N_ARGS; i++) {
118 if (l_sz[i] > LONGSZ || (1 << argregs[i]) & used)
119 continue;
120 if (l_nr[i] + l_nw[i] && !l_na[i]) {
121 l_reg[i] = argregs[i];
122 f_sargs &= ~(1 << argregs[i]);
123 f_lregs |= (1 << argregs[i]);
124 nlocregs++;
128 /* try finding a register for each local */
129 for (i = 0; i < l_n; i++) {
130 int l = ord[i];
131 int nmask = (leaf ? 0 : ~R_SAVED) | used | f_lregs;
132 if (l_reg[l] >= 0 || (f_varg && l < f_argc))
133 continue;
134 /* find a free register */
135 while (idx < N_TMPS && ((1 << tmpregs[idx]) & nmask))
136 idx++;
137 if (idx >= N_TMPS)
138 break;
139 if (l_sz[l] > LONGSZ || l_na[l])
140 continue;
141 if (l_nr[l] + l_nw[l] > (leaf ? 0 : 1)) {
142 l_reg[l] = tmpregs[idx];
143 f_lregs |= 1 << tmpregs[idx];
144 if (l < N_ARGS && l < f_argc)
145 f_sargs &= ~(1 << argregs[l]);
146 nlocregs++;
147 idx++;
150 return nlocregs;