RPA Toolkit
Moving away from RPA_BXL... 3
[rpatk.git] / tests / rpavm-test.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <sys/types.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 #include <sys/mman.h>
9 #include "rmem.h"
10 #include "rpacompiler.h"
11 #include "rpastat.h"
12
13
14 static int debuginfo = 0;
15 static int parseinfo = 0;
16 static int compileonly = 0;
17
18
19
20 void codegen_rpa_match_aorb(rpa_compiler_t *co)
21 {
22         rulong ruleidx;
23         const rchar *rule = "rpa_match_aorb";
24         const rchar *ruleend = "rpa_match_aorb_end";
25
26         ruleidx = rvm_codegen_addstring_s(co->cg, NULL, rule);
27         rvm_codegen_addlabel_s(co->cg, rule);
28
29         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
30         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
31
32         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'a'));
33         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
34
35         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_MOP, DA, XX, XX, 'b'));
36         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
37
38         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
39         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
40         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
41         rvm_codegen_addlabel_s(co->cg, ruleend);
42         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_WHT)|BIT(LR)));
43         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
44         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITEND, DA, R1, R0, 0));
45         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
46 }
47
48
49 void codegen_rpa_match_xyz(rpa_compiler_t *co)
50 {
51         rulong ruleidx;
52         const rchar *rule = "rpa_match_xyz";
53         const rchar *ruleend = "rpa_match_xyz_end";
54
55         ruleidx = rvm_codegen_addstring_s(co->cg, NULL, rule);
56         rvm_codegen_addlabel_s(co->cg, rule);
57
58         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
59         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
60
61         rpa_compiler_reference_mop_s(co, "rpa_match_squared");
62         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
63
64         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'x'));
65         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
66
67         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_MOP, DA, XX, XX, 'y'));
68         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
69
70         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'z'));
71         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
72
73         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_WHT)|BIT(LR)));
74         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
75         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITEND, DA, R1, R0, 0));
76         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
77         rvm_codegen_addlabel_s(co->cg, ruleend);
78         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
79         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
80         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
81 }
82
83
84 void codegen_rpa_match_abc(rpa_compiler_t *co)
85 {
86         rulong ruleidx;
87         const rchar *rule = "rpa_match_abc";
88         const rchar *ruleend = "rpa_match_abc_end";
89
90         ruleidx = rvm_codegen_addstring_s(co->cg, NULL, rule);
91         rvm_codegen_addlabel_s(co->cg, rule);
92
93         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
94         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
95
96         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'a'));
97         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
98
99         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_MOP, DA, XX, XX, 'b'));
100         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
101
102         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'c'));
103         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
104
105
106         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_WHT)|BIT(LR)));
107         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
108         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITEND, DA, R1, R0, 0));
109         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
110         rvm_codegen_addlabel_s(co->cg, ruleend);
111         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
112         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
113         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
114 }
115
116
117 void codegen_rpa_match_xyzorabc(rpa_compiler_t *co)
118 {
119         rulong ruleidx;
120         const rchar *rule = "rpa_match_xyzorabc";
121         const rchar *ruleend = "rpa_match_xyzorabc_end";
122
123         ruleidx = rvm_codegen_addstring_s(co->cg, NULL, rule);
124         rvm_codegen_addlabel_s(co->cg, rule);
125         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
126         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
127
128
129         rpa_compiler_reference_mop_s(co, "rpa_match_xyz");
130         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
131
132         rpa_compiler_reference_mop_s(co, "rpa_match_abc");
133         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
134
135         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
136         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
137         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
138         rvm_codegen_addlabel_s(co->cg, ruleend);
139         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_WHT)|BIT(LR)));
140         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
141         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITEND, DA, R1, R0, 0));
142         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
143 }
144
145
146
147 void codegen_rpa_match_squared(rpa_compiler_t *co)
148 {
149         rulong ruleidx;
150         const rchar *rule = "rpa_match_squared";
151         const rchar *ruleend = "rpa_match_squared_end";
152
153         ruleidx = rvm_codegen_addstring_s(co->cg, NULL, rule);
154         rvm_codegen_addlabel_s(co->cg, rule);
155         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
156         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
157
158         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, '['));
159         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
160
161         rpa_compiler_reference_mop_s(co, "rpa_match_xyzorabc");
162         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
163
164         rpa_compiler_reference_mop_s(co, "rpa_match_aorb");
165         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
166
167         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, ']'));
168         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
169
170         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHSPCHR_MOP, DA, XX, XX, 'n'));
171         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
172
173         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_WHT)|BIT(LR)));
174         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
175         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITEND, DA, R1, R0, 0));
176         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
177         rvm_codegen_addlabel_s(co->cg, ruleend);
178         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
179         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
180         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
181 }
182
183
184
185
186
187
188 void codegen_unmap_file(rstr_t *buf)
189 {
190         if (buf) {
191                 munmap(buf->str, buf->size);
192                 r_free(buf);
193         }
194 }
195
196
197 rstr_t *codegen_map_file(const char *filename)
198 {
199         struct stat st;
200         rstr_t *str;
201         char *buffer;
202
203
204         int fd = open(filename, O_RDONLY);
205         if (fd < 0) {
206                 return (void*)0;
207         }
208         if (fstat(fd, &st) < 0) {
209                 close(fd);
210                 return (void*)0;
211         }
212         buffer = (char*)mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
213         if (buffer == (void*)-1) {
214                 close(fd);
215                 return (void*)0;
216         }
217         str = (rstr_t *)r_malloc(sizeof(*str));
218         if (!str)
219                 goto error;
220         r_memset(str, 0, sizeof(*str));
221         str->str = buffer;
222         str->size = st.st_size;
223         close(fd);
224         return str;
225
226 error:
227         munmap(buffer, st.st_size);
228         close(fd);
229         return str;
230 }
231
232
233 int main(int argc, char *argv[])
234 {
235         rstr_t *script = NULL, *unmapscript = NULL;
236         rvm_codelabel_t *err;
237         rpa_compiler_t *co;
238         rpastat_t *stat;
239         ruint mainoff;
240         rint i;
241
242         co = rpa_compiler_create();
243         stat = rpa_stat_create(NULL, 4096);
244
245         for (i = 1; i < argc; i++) {
246                 if (r_strcmp(argv[i], "-L") == 0) {
247                 } else if (r_strcmp(argv[i], "-d") == 0) {
248                         debuginfo = 1;
249                 } else if (r_strcmp(argv[i], "-c") == 0) {
250                         compileonly = 1;
251                 } else if (r_strcmp(argv[i], "-p") == 0) {
252                         parseinfo = 1;
253                 }
254         }
255
256         for (i = 1; i < argc; i++) {
257                 if (r_strcmp(argv[i], "-e") == 0) {
258                         if (++i < argc) {
259                                 rstr_t bnfexpr = { argv[i], r_strlen(argv[i]) };
260                                 rpa_stat_init(stat, bnfexpr.str, bnfexpr.str, bnfexpr.str + bnfexpr.size);
261                         }
262                 }
263         }
264
265         for (i = 1; i < argc; i++) {
266                 if (r_strcmp(argv[i], "-f") == 0) {
267                         if (++i < argc) {
268                                 script = codegen_map_file(argv[i]);
269                                 if (script) {
270                                         rpa_stat_init(stat, script->str, script->str, script->str + script->size);
271                                         unmapscript = script;
272                                 }
273                         }
274                         goto exec;
275                 }
276         }
277
278
279 exec:
280
281         mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
282         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));
283         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, FP, DA, XX, 0));
284         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, SP, DA, XX, 0));
285
286         rvm_codegen_addins(co->cg, rvm_asm(RPA_SHIFT, XX, XX, XX, 0));
287         rpa_compiler_reference_mul_s(co, "rpa_match_squared");
288         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0xabc));
289         rvm_codegen_addins(co->cg, rvm_asm(RVM_EXT, XX, XX, XX, 0));
290
291         codegen_rpa_match_abc(co);
292         codegen_rpa_match_xyz(co);
293         codegen_rpa_match_xyzorabc(co);
294         codegen_rpa_match_aorb(co);
295         codegen_rpa_match_squared(co);
296
297         if (rvm_codegen_relocate(co->cg, &err) < 0) {
298                 r_printf("Unresolved symbol: %s\n", err->name->str);
299                 goto end;
300         }
301
302         if (debuginfo) {
303                 fprintf(stdout, "\nGenerated Code:\n");
304                 rvm_asm_dump(rvm_codegen_getcode(co->cg, 0), rvm_codegen_getcodesize(co->cg));
305                 if (rvm_codegen_getcodesize(co->cg)) {
306                         if (!compileonly) {
307                                 fprintf(stdout, "\nExecution:\n");
308                                 rvm_cpu_exec_debug(stat->cpu, rvm_codegen_getcode(co->cg, 0), mainoff);
309                         }
310                 }
311         } else {
312                 if (!compileonly)
313                         rvm_cpu_exec(stat->cpu, rvm_codegen_getcode(co->cg, 0), mainoff);
314         }
315
316         r_printf("Matched: %d\n", RVM_CPUREG_GETU(stat->cpu, R0));
317 end:
318
319         for (i = 0; 0 && i < r_array_length(stat->records); i++) {
320                 rparecord_t *rec = (rparecord_t *)r_array_slot(stat->records, i);
321                 if (rec->type & RPA_RECORD_MATCH) {
322                         r_printf("%d: rule: %s(%d, %d)\n", i, rec->rule, (rint)rec->top, (rint)rec->size);
323                 }
324         }
325
326         rpa_stat_destroy(stat);
327         rpa_compiler_destroy(co);
328         if (unmapscript)
329                 codegen_unmap_file(unmapscript);
330
331
332         if (1||debuginfo) {
333                 r_printf("Max alloc mem: %ld\n", r_debug_get_maxmem());
334                 r_printf("Leaked mem: %ld\n", r_debug_get_allocmem());
335         }
336         return 0;
337 }