RPA Toolkit
RJS prop access changes... continued.
[rpatk.git] / rvm / rvmcodegen.c
1 /*
2  *  Regular Pattern Analyzer (RPA)
3  *  Copyright (c) 2009-2010 Martin Stoilov
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  *  Martin Stoilov <martin@rpasearch.com>
19  */
20
21 #include "rlib/rmem.h"
22 #include "rvm/rvmcodegen.h"
23 #include "rvm/rvmcpu.h"
24
25
26 rvm_codegen_t *rvm_codegen_create()
27 {
28         rvm_codegen_t *cg;
29
30         cg = (rvm_codegen_t *)r_malloc(sizeof(*cg));
31         if (!cg)
32                 return (NULL);
33         r_memset(cg, 0, sizeof(*cg));
34         cg->code = r_array_create(sizeof(rvm_asmins_t));
35         cg->staticdata = r_array_create(sizeof(ruint8));
36         cg->dynamicdata = r_carray_create(sizeof(rvmreg_t));
37         cg->codemap = rvm_codemap_create();
38         cg->relocmap = rvm_relocmap_create();
39         cg->sourceidx = r_array_create(sizeof(unsigned long));
40         return cg;
41 }
42
43
44 void rvm_codegen_destroy(rvm_codegen_t *cg)
45 {
46         rvm_codemap_destroy(cg->codemap);
47         rvm_relocmap_destroy(cg->relocmap);
48         r_array_destroy(cg->staticdata);
49         r_array_destroy(cg->code);
50         r_array_destroy(cg->sourceidx);
51         r_carray_destroy(cg->dynamicdata);
52         r_free(cg);
53 }
54
55
56 void rvm_codegen_clear(rvm_codegen_t *cg)
57 {
58         r_array_setlength(cg->code, 0);
59         r_array_setlength(cg->staticdata, 0);
60         rvm_codemap_clear(cg->codemap);
61         rvm_relocmap_clear(cg->relocmap);
62 }
63
64
65 void rvm_codegen_setsource(rvm_codegen_t *cg, unsigned long srcidx)
66 {
67         cg->cursrcidx = srcidx;
68 }
69
70
71 long rvm_codegen_getsource(rvm_codegen_t *cg, unsigned long codeidx)
72 {
73         if (codeidx >= r_array_length(cg->sourceidx))
74                 return -1;
75         return r_array_index(cg->sourceidx, codeidx, long);
76 }
77
78
79 rvm_asmins_t *rvm_codegen_getcode(rvm_codegen_t *cg, unsigned int index)
80 {
81         return (rvm_asmins_t *)r_array_slot(cg->code, index);
82 }
83
84
85 unsigned long rvm_codegen_getcodesize(rvm_codegen_t *cg)
86 {
87         return r_array_length(cg->code);
88 }
89
90 void rvm_codegen_setcodesize(rvm_codegen_t *cg, unsigned int size)
91 {
92         r_array_setlength(cg->code, size);
93 }
94
95
96 unsigned long rvm_codegen_addins(rvm_codegen_t *cg, rvm_asmins_t ins)
97 {
98         unsigned long codeidx;
99
100         codeidx = r_array_add(cg->code, &ins);
101         r_array_replace(cg->sourceidx, codeidx, &cg->cursrcidx);
102         return codeidx;
103 }
104
105
106 long rvm_codegen_redefinelabel(rvm_codegen_t *cg, long index, unsigned long offset)
107 {
108         long codeidx = rvm_codemap_lookupadd_s(cg->codemap, ".code");
109         rvm_codelabel_t *label = rvm_codemap_label(cg->codemap, index);
110
111         if (!label)
112                 return -1;
113         rvm_codelabel_setoffset(label, codeidx, RVM_CODE2BYTE_OFFSET(offset));
114         return index;
115 }
116
117
118 long rvm_codegen_redefinelabel_default(rvm_codegen_t *cg, long index)
119 {
120         return rvm_codegen_redefinelabel(cg, index, rvm_codegen_getcodesize(cg));
121 }
122
123
124 long rvm_codegen_validlabel(rvm_codegen_t *cg, long index)
125 {
126         return rvm_codemap_validindex(cg->codemap, index);
127 }
128
129
130 long rvm_codegen_redefinepointer(rvm_codegen_t *cg, long index, rpointer data)
131 {
132         rvm_codelabel_t *label = rvm_codemap_label(cg->codemap, index);
133
134         if (!label)
135                 return -1;
136 //      return rvm_codemap_addpointer(cg->codemap, label->name->str, label->name->size, data);
137         rvm_codelabel_setpointer(label, data);
138         return index;
139 }
140
141
142 long rvm_codegen_addlabel(rvm_codegen_t *cg, const char* name, unsigned int namesize, unsigned long offset)
143 {
144         return rvm_codemap_addoffset(cg->codemap, name, namesize, rvm_codemap_lookupadd_s(cg->codemap, ".code"), RVM_CODE2BYTE_OFFSET(offset));
145 }
146
147
148 long rvm_codegen_addlabel_s(rvm_codegen_t *cg, const char* name, unsigned long offset)
149 {
150         return rvm_codegen_addlabel(cg, name, r_strlen(name), offset);
151 }
152
153
154 long rvm_codegen_addlabel_default(rvm_codegen_t *cg, const char* name, unsigned int namesize)
155 {
156         return rvm_codegen_addlabel(cg, name, namesize, rvm_codegen_getcodesize(cg));
157 }
158
159
160 long rvm_codegen_addlabel_default_s(rvm_codegen_t *cg, const char* name)
161 {
162         return rvm_codegen_addlabel_default(cg, name, r_strlen(name));
163 }
164
165
166 long rvm_codegen_invalid_addlabel(rvm_codegen_t *cg, const char* name, unsigned int namesize)
167 {
168         return rvm_codemap_invalid_add(cg->codemap, name, namesize);
169 }
170
171
172 long rvm_codegen_invalid_addlabel_s(rvm_codegen_t *cg, const char* name)
173 {
174         return rvm_codegen_invalid_addlabel(cg, name, r_strlen(name));
175 }
176
177
178 unsigned long rvm_codegen_addlabelins(rvm_codegen_t *cg, const char* name, unsigned int namesize, rvm_asmins_t ins)
179 {
180         rvm_codemap_addoffset(cg->codemap, name, namesize, rvm_codemap_lookupadd_s(cg->codemap, ".code"), RVM_CODE2BYTE_OFFSET(rvm_codegen_getcodesize(cg)));
181         return rvm_codegen_addins(cg, ins);
182 }
183
184
185 unsigned long rvm_codegen_addlabelins_s(rvm_codegen_t *cg, const char* name, rvm_asmins_t ins)
186 {
187         return rvm_codegen_addlabelins(cg, name, r_strlen(name), ins);
188 }
189
190
191 unsigned long rvm_codegen_index_addrelocins(rvm_codegen_t *cg, rvm_reloctype_t type, unsigned long index, rvm_asmins_t ins)
192 {
193         rvm_relocmap_add(cg->relocmap, RVM_RELOC_CODE, type, rvm_codegen_getcodesize(cg), index);
194         return rvm_codegen_addins(cg, ins);
195 }
196
197
198 unsigned long rvm_codegen_addrelocins(rvm_codegen_t *cg, rvm_reloctype_t type, const char* name, unsigned int namesize, rvm_asmins_t ins)
199 {
200         return rvm_codegen_index_addrelocins(cg, type, rvm_codemap_lookupadd(cg->codemap, name, namesize), ins);
201 }
202
203
204 unsigned long rvm_codegen_addrelocins_s(rvm_codegen_t *cg, rvm_reloctype_t type, const char* name, rvm_asmins_t ins)
205 {
206         return rvm_codegen_addrelocins(cg, type, name, r_strlen(name), ins);
207 }
208
209
210 int rvm_codegen_relocate(rvm_codegen_t *cg, rvm_codelabel_t **err)
211 {
212         rvm_codemap_addpointer_s(cg->codemap, ".code", r_array_slot(cg->code, 0));
213         rvm_codemap_addpointer_s(cg->codemap, ".data", r_array_slot(cg->staticdata, 0));
214         return rvm_relocmap_relocate(cg->relocmap, cg->codemap, (rvm_asmins_t *)r_array_slot(cg->code, 0), err);
215 }
216
217
218 unsigned long rvm_codegen_insertins(rvm_codegen_t *cg, unsigned int index, rvm_asmins_t ins)
219 {
220         return r_array_insert(cg->code, index, &ins);
221 }
222
223
224 unsigned long rvm_codegen_replaceins(rvm_codegen_t *cg, unsigned int index, rvm_asmins_t ins)
225 {
226         return r_array_replace(cg->code, index, &ins);
227
228 }
229
230
231 unsigned int rvm_codegen_funcstart(rvm_codegen_t *cg, const char* name, unsigned int namesize, unsigned int args)
232 {
233         unsigned int start;
234         rvm_codegen_addins(cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
235         start = rvm_codegen_addlabelins(cg, name, namesize, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(FP)|BIT(SP)|BIT(LR)));
236         rvm_codegen_addins(cg, rvm_asm(RVM_MOV, FP, SP, XX, 0));
237         rvm_codegen_addins(cg, rvm_asm(RVM_ADD, SP, SP, DA, args));
238 //      rvm_codemap_addoffset(cg->codemap, name, namesize, rvm_codemap_lookupadd_s(cg->codemap, ".code"), start);
239         return start;
240 }
241
242
243 unsigned int rvm_codegen_funcstart_s(rvm_codegen_t *cg, const char* name, unsigned int args)
244 {
245         return rvm_codegen_funcstart(cg, name, r_strlen(name), args);
246 }
247
248
249 unsigned int rvm_codegen_vargs_funcstart(rvm_codegen_t *cg, const char* name, unsigned int namesize)
250 {
251         unsigned int start;
252         rvm_codegen_addins(cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
253         start = rvm_codegen_addlabelins(cg, name, namesize, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(FP)|BIT(SP)|BIT(LR)));
254         rvm_codegen_addins(cg, rvm_asm(RVM_MOV, FP, SP, XX, 0));
255         rvm_codegen_addins(cg, rvm_asm(RVM_ADD, SP, SP, R0, 0));
256 //      rvm_codemap_addoffset(cg->codemap, name, namesize, rvm_codemap_lookupadd_s(cg->codemap, ".code"), start);
257         return start;
258 }
259
260
261 unsigned int rvm_codegen_vargs_funcstart_s(rvm_codegen_t *cg, const char* name)
262 {
263         return rvm_codegen_vargs_funcstart(cg, name, r_strlen(name));
264 }
265
266
267 void rvm_codegen_funcend(rvm_codegen_t *cg)
268 {
269         rvm_codegen_addins(cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
270         rvm_codegen_addins(cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(FP)|BIT(SP)|BIT(LR)));
271         rvm_codegen_addins(cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
272 }
273
274 long rvm_codegen_adddata(rvm_codegen_t *cg, const char *name, unsigned int namesize, rconstpointer data, unsigned long size)
275 {
276         rpointer buffer;
277         unsigned long cursize = R_SIZE_ALIGN(r_array_length(cg->staticdata), sizeof(ruword));
278
279         r_array_setlength(cg->staticdata, cursize + size + sizeof(ruword) + 1);
280         buffer = r_array_slot(cg->staticdata, cursize);
281         r_memset(buffer, 0, size + sizeof(ruword));
282         r_memmove(buffer, data, size);
283         return rvm_codemap_addoffset(cg->codemap, name, namesize, rvm_codemap_lookupadd_s(cg->codemap, ".data"), cursize);
284 }
285
286
287 long rvm_codegen_adddata_s(rvm_codegen_t *cg, const char *name, rconstpointer data, unsigned long size)
288 {
289         return rvm_codegen_adddata(cg, name, r_strlen(name), data, size);
290 }
291
292
293 long rvm_codegen_addstring(rvm_codegen_t *cg, const char *name, unsigned int namesize, const char* data)
294 {
295         return rvm_codegen_adddata(cg, name, namesize, data, r_strlen(data) + 1);
296 }
297
298
299 long rvm_codegen_addstring_s(rvm_codegen_t *cg, const char *name, const char* data)
300 {
301         return rvm_codegen_addstring(cg, name, r_strlen(name), data);
302 }
303
304
305 long rvm_codegen_add_numlabel_s(rvm_codegen_t *cg, const char *alphaname, long numname)
306 {
307         char label[128];
308
309         r_memset(label, 0, sizeof(label));
310         r_snprintf(label, sizeof(label) - 1, "L%07ld__%s:", numname, alphaname);
311         return rvm_codegen_addlabel_default_s(cg, label);
312 }
313
314
315 long rvm_codegen_invalid_add_numlabel_s(rvm_codegen_t *cg, const char *alphaname, long numname)
316 {
317         char label[128];
318
319         r_memset(label, 0, sizeof(label));
320         r_snprintf(label, sizeof(label) - 1, "L%07ld__%s:", numname, alphaname);
321         return rvm_codegen_invalid_addlabel_s(cg, label);
322 }
323