RPA Toolkit
implemented conditional expressions
[rpatk.git] / tests / rpagen-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 "rvmcpu.h"
11 #include "rpadbex.h"
12 #include "rpaerror.h"
13 #include "rvmcodegen.h"
14 #include "rvmcodemap.h"
15 #include "rvmscope.h"
16 #include "rvmoperator.h"
17
18 #define DEBUGPRINT 1
19 static int debuginfo = 0;
20 static int parseinfo = 0;
21 static int verboseinfo = 0;
22 static int compileonly = 0;
23
24 typedef struct rvm_vardeclaration_s {
25         const rchar *varname;
26         ruint varnamesiz;
27         const rchar *val;
28         ruint valsiz;
29 } rvm_vardeclaration_t;
30
31
32 typedef struct rvm_fundecl_s {
33         const rchar *funname;
34         rword funnamesiz;
35         rword params;
36         rword codestart;
37         rword codesize;
38 } rvm_fundecl_t;
39
40
41 typedef struct rvm_funcall_s {
42         const rchar *funname;
43         rword funnamesiz;
44         rword params;
45 } rvm_funcall_t;
46
47
48 typedef struct rvm_codespan_s {
49         rword codestart;
50         rword codesize;
51         rword l1;
52         rword l2;
53 } rvm_codespan_t;
54
55
56 typedef struct rvm_costat_s rvm_costat_t;
57
58 struct rvm_costat_s {
59         ruint binaryop;
60         ruint level;
61         ruint dirty;
62         ruint funcalls;
63         rvm_costat_t *root;
64 };
65
66 typedef struct rvm_compiler_s {
67         rpa_dbex_handle dbex;
68         rvm_codegen_t *cg;
69         rvm_scope_t *scope;
70         rarray_t *fp;
71         rarray_t *funcall;
72         rarray_t *fundecl;
73         rarray_t *opcodes;
74         rarray_t *codespan;
75         rarray_t *varmap;
76         rarray_t *stat;
77         rvmcpu_t *cpu;
78         rboolean optimized;
79 } rvm_compiler_t;
80
81
82
83 #define RVM_SAVEDREGS_FIRST 4
84 #define RVM_SAVEDREGS_MAX (RLST - (RLST - FP) - RVM_SAVEDREGS_FIRST - 1)
85
86
87 void rpagen_load_rules(rpa_dbex_handle dbex, rvm_compiler_t *co);
88
89 rvm_costat_t *rvm_costat_current(rvm_compiler_t *co)
90 {
91         return (rvm_costat_t *)r_array_lastslot(co->stat);
92 }
93
94
95 ruint rvm_costat_getdebth(rvm_compiler_t *co)
96 {
97         return r_array_length(co->stat);
98 }
99
100 ruint rvm_costat_getlevel(rvm_compiler_t *co)
101 {
102         if (!rvm_costat_current(co))
103                 return 0;
104         return rvm_costat_current(co)->level;
105 }
106
107
108 void rvm_costat_inclevel(rvm_compiler_t *co)
109 {
110         rvm_costat_current(co)->level += 1;
111         if (rvm_costat_current(co)->level > rvm_costat_current(co)->root->dirty)
112                 rvm_costat_current(co)->root->dirty = rvm_costat_current(co)->level;
113 }
114
115 void rvm_costat_declevel(rvm_compiler_t *co)
116 {
117         rvm_costat_current(co)->level -= 1;
118 }
119
120
121 ruint rvm_costat_getbinaryop(rvm_compiler_t *co)
122 {
123         if (!rvm_costat_current(co))
124                 return 0;
125         return rvm_costat_current(co)->binaryop;
126 }
127
128
129 void rvm_costat_incbinaryop(rvm_compiler_t *co)
130 {
131         rvm_costat_current(co)->binaryop += 1;
132 }
133
134
135 void rvm_costat_decbinaryop(rvm_compiler_t *co)
136 {
137         rvm_costat_current(co)->binaryop -= 1;
138 }
139
140 /*
141 ruint rvm_costat_getfuncalls(rvm_compiler_t *co)
142 {
143         if (!rvm_costat_current(co))
144                 return 0;
145         return rvm_costat_current(co)->root->funcalls;
146 }
147
148
149 void rvm_costat_incfuncalls(rvm_compiler_t *co)
150 {
151         rvm_costat_current(co)->root->funcalls += 1;
152 }
153
154
155 void rvm_costat_decfuncalls(rvm_compiler_t *co)
156 {
157         rvm_costat_current(co)->root->funcalls -= 1;
158 }
159 */
160
161 ruint rvm_costat_getdirty(rvm_compiler_t *co)
162 {
163         if (!rvm_costat_current(co))
164                 return 0;
165         return rvm_costat_current(co)->root->dirty;
166 }
167
168
169 void rvm_costat_push(rvm_compiler_t *co)
170 {
171         rvm_costat_t stat = *rvm_costat_current(co);
172         stat.binaryop = 0;
173         r_array_add(co->stat, &stat);
174 }
175
176
177 void rvm_costat_pushroot(rvm_compiler_t *co)
178 {
179         rvm_costat_t stat;
180         r_memset(&stat, 0, sizeof(stat));
181         r_array_add(co->stat, &stat);
182         rvm_costat_current(co)->root = rvm_costat_current(co);
183 }
184
185 void rvm_costat_pop(rvm_compiler_t *co)
186 {
187         r_array_removelast(co->stat);
188 }
189
190
191
192 rvm_compiler_t *rvm_compiler_create(rpa_dbex_handle dbex)
193 {
194         rvm_compiler_t *co;
195
196         co = r_malloc(sizeof(*co));
197         r_memset(co, 0, sizeof(*co));
198         co->cg = rvm_codegen_create();
199         co->scope = rvm_scope_create();
200         co->opcodes = r_array_create(sizeof(ruint));
201         co->fp = r_array_create(sizeof(rword));
202         co->funcall = r_array_create(sizeof(rvm_funcall_t));
203         co->stat = r_array_create(sizeof(rvm_costat_t));
204         co->fundecl = r_array_create(sizeof(rvm_fundecl_t));
205         co->codespan = r_array_create(sizeof(rvm_codespan_t));
206         co->varmap = r_array_create(sizeof(rvm_varmap_t*));
207         r_array_push(co->fp, 0, rword);
208         co->dbex = dbex;
209         return co;
210 }
211
212
213 void rvm_compiler_destroy(rvm_compiler_t *co)
214 {
215         if (co) {
216                 rvm_codegen_destroy(co->cg);
217                 rvm_scope_destroy(co->scope);
218                 r_object_destroy((robject_t*) co->opcodes);
219                 r_object_destroy((robject_t*) co->stat);
220                 r_object_destroy((robject_t*) co->fp);
221                 r_object_destroy((robject_t*) co->funcall);
222                 r_object_destroy((robject_t*) co->fundecl);
223                 r_object_destroy((robject_t*) co->codespan);
224                 r_object_destroy((robject_t*) co->varmap);
225                 r_free(co);
226         }
227 }
228
229
230 static void test_swi_none(rvmcpu_t *cpu, rvm_asmins_t *ins)
231 {
232 }
233
234
235 static void rvm_swi_negative(rvmcpu_t *cpu, rvm_asmins_t *ins)
236 {
237         rvmreg_t *res = RVM_CPUREG_PTR(cpu, ins->op1);
238         rvmreg_t *arg = RVM_CPUREG_PTR(cpu, ins->op2);
239         rvmreg_t zero;
240
241         RVM_REG_CLEAR(&zero);
242         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_SUB, cpu, res, &zero, arg);
243 }
244
245
246 static void rvm_swi_eadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
247 {
248         rvmreg_t *res = RVM_CPUREG_PTR(cpu, R0);
249         rvmreg_t *arg1 = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 1);
250         rvmreg_t *arg2 = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 2);
251
252         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_ADD, cpu, res, arg1, arg2);
253 }
254
255
256 static rvm_switable_t switable[] = {
257                 {"none", test_swi_none},
258                 {"RVM_SWI_NEG", rvm_swi_negative},
259                 {"rvm_swi_eadd", rvm_swi_eadd},
260                 {NULL, NULL},
261 };
262
263
264 static void rvm_js_print(rvmcpu_t *cpu, rvm_asmins_t *ins)
265 {
266         rvmreg_t *r = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 1);
267
268         if (rvm_reg_gettype(r) == RVM_DTYPE_UNSIGNED)
269                 r_printf("%lu\n", RVM_REG_GETU(r));
270         else if (rvm_reg_gettype(r) == RVM_DTYPE_BOOLEAN)
271                 r_printf("%s\n", RVM_REG_GETU(r) ? "true" : "false");
272         else if (rvm_reg_gettype(r) == RVM_DTYPE_POINTER)
273                 r_printf("%p\n", RVM_REG_GETP(r));
274         else if (rvm_reg_gettype(r) == RVM_DTYPE_LONG)
275                 r_printf("%ld\n", RVM_REG_GETL(r));
276         else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
277                 r_printf("%f\n", RVM_REG_GETD(r));
278         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
279                 r_printf("%s\n", ((rstring_t*) RVM_REG_GETP(r))->s.str);
280         else if (rvm_reg_gettype(r) == RVM_DTYPE_ARRAY)
281                 r_printf("(array) %p\n",RVM_REG_GETP(r));
282         else if (rvm_reg_gettype(r) == RVM_DTYPE_SWIID)
283                 r_printf("(function) %p\n",RVM_REG_GETP(r));
284         else
285                 r_printf("%p\n", RVM_REG_GETP(r));
286 }
287
288 static rvm_switable_t switable_js[] = {
289                 {"print", rvm_js_print},
290                 {NULL, NULL},
291 };
292
293 inline int codegen_print_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
294 {
295         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
296
297         if (parseinfo) {
298                 if (reason & RPA_REASON_START)
299                         fprintf(stdout, "START ");
300                 if (reason & RPA_REASON_MATCHED)
301                         fprintf(stdout, "MATCHED ");
302                 if (reason & RPA_REASON_END)
303                         fprintf(stdout, "END ");
304                 fprintf(stdout, "%s: ", name);
305                 if (!(reason & RPA_REASON_START))
306                                 fwrite(input, sizeof(char), size, stdout);
307                 fprintf(stdout, " (debth: %d, level: %d, binaryop: %d, dirty: %d)", rvm_costat_getdebth(co), rvm_costat_getlevel(co), rvm_costat_getbinaryop(co), rvm_costat_getdirty(co));
308                 fprintf(stdout, "\n");
309                 fflush(stdout);
310         }
311
312         return size;
313 }
314
315
316 void codegen_dump_code(rvm_asmins_t *code, rulong size)
317 {
318         if (parseinfo)
319                 rvm_asm_dump(code, size);
320 }
321
322
323 int codegen_opcode_unary_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
324 {
325         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
326
327         if (r_stringncmp("-", input, size))
328                 r_array_push(co->opcodes, RVM_OPSWI(rvm_cpu_getswi_s(co->cpu, "RVM_SWI_NEG")), ruint);
329         else if (r_stringncmp("+", input, size))
330                 r_array_push(co->opcodes, RVM_NOP, ruint);
331         else if (r_stringncmp("delete", input, size))
332                 r_array_push(co->opcodes, RVM_NOP, ruint);
333         else if (r_stringncmp("void", input, size))
334                 r_array_push(co->opcodes, RVM_NOP, ruint);
335         else if (r_stringncmp("typeof", input, size))
336                 r_array_push(co->opcodes, RVM_NOP, ruint);
337
338         else
339                 r_array_push(co->opcodes, RVM_ABORT, ruint);
340
341         codegen_print_callback(name, userdata, input, size, reason, start, end);
342         return size;
343 }
344
345
346 int codegen_opcode_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
347 {
348         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
349
350         if (r_stringncmp("++", input,  size))
351                 r_array_push(co->opcodes, RVM_EADD, ruint);
352         else if (r_stringncmp("+", input,  size))
353                 r_array_push(co->opcodes, RVM_EADD, ruint);
354         else if (r_stringncmp("+=", input,  size))
355                 r_array_push(co->opcodes, RVM_EADD, ruint);
356         else if (r_stringncmp("--", input,  size))
357                 r_array_push(co->opcodes, RVM_ESUB, ruint);
358         else if (r_stringncmp("-", input,  size))
359                 r_array_push(co->opcodes, RVM_ESUB, ruint);
360         else if (r_stringncmp("-=", input,  size))
361                 r_array_push(co->opcodes, RVM_ESUB, ruint);
362         else if (r_stringncmp("*", input,  size))
363                 r_array_push(co->opcodes, RVM_EMUL, ruint);
364         else if (r_stringncmp("*=", input,  size))
365                 r_array_push(co->opcodes, RVM_EMUL, ruint);
366         else if (r_stringncmp("/", input,  size))
367                 r_array_push(co->opcodes, RVM_EDIV, ruint);
368         else if (r_stringncmp("/=", input,  size))
369                 r_array_push(co->opcodes, RVM_EDIV, ruint);
370         else if (r_stringncmp("%", input,  size))
371                 r_array_push(co->opcodes, RVM_EMOD, ruint);
372         else if (r_stringncmp("%=", input,  size))
373                 r_array_push(co->opcodes, RVM_EMOD, ruint);
374         else if (r_stringncmp("&&", input,  size))
375                 r_array_push(co->opcodes, RVM_ELAND, ruint);
376         else if (r_stringncmp("||", input,  size))
377                 r_array_push(co->opcodes, RVM_ELOR, ruint);
378         else if (r_stringncmp("&", input,  size))
379                 r_array_push(co->opcodes, RVM_EAND, ruint);
380         else if (r_stringncmp("&=", input,  size))
381                 r_array_push(co->opcodes, RVM_EAND, ruint);
382         else if (r_stringncmp("|", input,  size))
383                 r_array_push(co->opcodes, RVM_EORR, ruint);
384         else if (r_stringncmp("|=", input,  size))
385                 r_array_push(co->opcodes, RVM_EORR, ruint);
386         else if (r_stringncmp("^", input,  size))
387                 r_array_push(co->opcodes, RVM_EXOR, ruint);
388         else if (r_stringncmp("^=", input,  size))
389                 r_array_push(co->opcodes, RVM_EXOR, ruint);
390         else if (r_stringncmp(">>", input,  size))
391                 r_array_push(co->opcodes, RVM_ELSR, ruint);
392         else if (r_stringncmp(">>=", input,  size))
393                 r_array_push(co->opcodes, RVM_ELSR, ruint);
394         else if (r_stringncmp("<<", input,  size))
395                 r_array_push(co->opcodes, RVM_ELSL, ruint);
396         else if (r_stringncmp("<<=", input,  size))
397                 r_array_push(co->opcodes, RVM_ELSL, ruint);
398         else if (r_stringncmp(">>>", input,  size))
399                 r_array_push(co->opcodes, RVM_ELSRU, ruint);
400         else if (r_stringncmp(">>>=", input,  size))
401                 r_array_push(co->opcodes, RVM_ELSRU, ruint);
402         else if (r_stringncmp("<=", input,  size))
403                 r_array_push(co->opcodes, RVM_ELESSEQ, ruint);
404         else if (r_stringncmp(">=", input,  size))
405                 r_array_push(co->opcodes, RVM_EGREATEQ, ruint);
406         else if (r_stringncmp("<", input,  size))
407                 r_array_push(co->opcodes, RVM_ELESS, ruint);
408         else if (r_stringncmp(">", input,  size))
409                 r_array_push(co->opcodes, RVM_EGREAT, ruint);
410         else if (r_stringncmp("===", input,  size))
411                 r_array_push(co->opcodes, RVM_EEQ, ruint);
412         else if (r_stringncmp("==", input,  size))
413                 r_array_push(co->opcodes, RVM_EEQ, ruint);
414         else if (r_stringncmp("!==", input,  size))
415                 r_array_push(co->opcodes, RVM_ENOTEQ, ruint);
416         else if (r_stringncmp("!=", input,  size))
417                 r_array_push(co->opcodes, RVM_ENOTEQ, ruint);
418         else if (r_stringncmp("!", input,  size))
419                 r_array_push(co->opcodes, RVM_ELNOT, ruint);
420         else if (r_stringncmp("~", input,  size))
421                 r_array_push(co->opcodes, RVM_ENOT, ruint);
422         else if (r_stringncmp("=", input,  size))
423                 r_array_push(co->opcodes, RVM_NOP, ruint);
424         else
425                 r_array_push(co->opcodes, RVM_ABORT, ruint);
426
427         codegen_print_callback(name, userdata, input, size, reason, start, end);
428         return size;
429 }
430
431
432 int codegen_binary_asmop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
433 {
434         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
435         rulong off = rvm_codegen_getcodesize(co->cg);
436
437         if (reason & RPA_REASON_START) {
438                 rvm_costat_inclevel(co);
439                 rvm_costat_incbinaryop(co);
440         } else if (reason & RPA_REASON_MATCHED) {
441                 ruint op1;
442                 ruint opcode = r_array_pop(co->opcodes, ruint);
443
444                 if (rvm_costat_getlevel(co) < RVM_SAVEDREGS_MAX) {
445                         op1 = rvm_costat_getlevel(co) + RVM_SAVEDREGS_FIRST - 1;
446                 } else {
447                         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
448                         op1 = R1;
449                 }
450                 rvm_codegen_addins(co->cg, rvm_asm(opcode, R0, op1, R0, 0));
451                 rvm_costat_declevel(co);
452                 rvm_costat_decbinaryop(co);
453         } else if (reason & RPA_REASON_END) {
454                 rvm_costat_declevel(co);
455                 rvm_costat_decbinaryop(co);
456         }
457
458         codegen_print_callback(name, userdata, input, size, reason, start, end);
459         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
460
461         return size;
462 }
463
464
465 int codegen_valop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
466 {
467         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
468         rulong off = rvm_codegen_getcodesize(co->cg);
469         rvm_asmins_t *last = rvm_codegen_getcode(co->cg, off - 1);
470
471         if ((reason & RPA_REASON_START) && rvm_costat_getbinaryop(co)) {
472                 if (rvm_costat_getlevel(co) < RVM_SAVEDREGS_MAX) {
473                         if (co->optimized && last->op1 == R0 && (last->opcode == RVM_MOV || last->opcode == RVM_LDRR ||
474                                         last->opcode == RVM_LDS || (last->opcode >= RVM_EADD && last->opcode <= RVM_ELESSEQ))) {
475                                 last->op1 = rvm_costat_getlevel(co) + RVM_SAVEDREGS_FIRST - 1;
476                                 off -= 1;
477                         } else {
478                                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, rvm_costat_getlevel(co) + RVM_SAVEDREGS_FIRST - 1, R0, XX, 0));
479                         }
480                 } else {
481                         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
482                 }
483         }
484
485
486         if (reason & RPA_REASON_MATCHED) {
487
488         }
489
490         codegen_print_callback(name, userdata, input, size, reason, start, end);
491         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
492
493         return size;
494 }
495
496
497 int codegen_conditionalexp_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
498 {
499         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
500         rulong off = rvm_codegen_getcodesize(co->cg);
501
502         codegen_print_callback(name, userdata, input, size, reason, start, end);
503         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
504
505         return size;
506 }
507
508
509 int codegen_unary_asmop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
510 {
511         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
512         rulong off = rvm_codegen_getcodesize(co->cg);
513         ruint op1 = rvm_costat_getlevel(co) ? RVM_SAVEDREGS_FIRST - 1 + rvm_costat_getlevel(co) : R0;
514
515         if (reason & RPA_REASON_START) {
516         }
517
518         if (reason & RPA_REASON_MATCHED) {
519                 ruint opcode = r_array_pop(co->opcodes, ruint);
520                 rvm_codegen_addins(co->cg, rvm_asm(opcode, op1, op1, XX, 0));
521         }
522
523         if (reason & RPA_REASON_END) {
524         }
525
526         codegen_print_callback(name, userdata, input, size, reason, start, end);
527         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
528         return size;
529 }
530
531
532 int codegen_costate_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
533 {
534         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
535         rulong off = rvm_codegen_getcodesize(co->cg);
536
537         if (reason & RPA_REASON_START) {
538                 rvm_costat_push(co);
539         }
540
541         if (reason & RPA_REASON_END) {
542                 rvm_costat_pop(co);
543         }
544
545         codegen_print_callback(name, userdata, input, size, reason, start, end);
546         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
547         return size;
548 }
549
550
551 int codegen_push_r0_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
552 {
553         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
554         rulong off = rvm_codegen_getcodesize(co->cg);
555
556         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
557
558         codegen_print_callback(name, userdata, input, size, reason, start, end);
559         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
560
561         return size;
562 }
563
564
565 int codegen_integer_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
566 {
567         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
568         rulong off = rvm_codegen_getcodesize(co->cg);
569
570         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R0, DA, XX, r_strtol(input, NULL, 10)));
571
572         codegen_print_callback(name, userdata, input, size, reason, start, end);
573         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
574
575         return size;
576 }
577
578
579 int codegen_printop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
580 {
581         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
582         rulong off = rvm_codegen_getcodesize(co->cg);
583
584         rvm_codegen_addins(co->cg, rvm_asmd(RVM_PRN, R0, DA, XX, 0));
585
586         codegen_print_callback(name, userdata, input, size, reason, start, end);
587         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
588
589         return size;
590 }
591
592
593 int codegen_double_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
594 {
595         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
596         rulong off = rvm_codegen_getcodesize(co->cg);
597
598         rvm_codegen_addins(co->cg, rvm_asmd(RVM_MOV, R0, DA, XX, r_strtod(input, NULL)));
599
600         codegen_print_callback(name, userdata, input, size, reason, start, end);
601         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
602
603         return size;
604 }
605
606
607 int codegen_string_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
608 {
609         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
610         rulong off = rvm_codegen_getcodesize(co->cg);
611
612         rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R1, DA, XX, (void*)input));
613         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R2, DA, XX, size));
614         rvm_codegen_addins(co->cg, rvm_asm(RVM_ALLOCSTR, R0, R1, R2, 0));
615
616         codegen_print_callback(name, userdata, input, size, reason, start, end);
617         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
618
619         return size;
620 }
621
622
623 int codegen_program_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
624 {
625         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
626         ruint off;
627
628         if (reason & RPA_REASON_START) {
629                 off = rvm_codegen_getcodesize(co->cg);
630                 rvm_costat_pushroot(co);
631                 rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
632                 rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
633         } else {
634                 rvm_codegen_replaceins(co->cg, 0, rvm_asm(RVM_MOV, FP, SP, XX, 0));
635                 rvm_codegen_replaceins(co->cg, 1, rvm_asm(RVM_ADD, SP, SP, DA, r_array_pop(co->fp, rword)));
636                 off = rvm_codegen_getcodesize(co->cg);
637                 if (debuginfo)
638                         rvm_codegen_addins(co->cg, rvm_asm(RVM_PRN, R0, XX, XX, 0));
639                 rvm_codegen_addins(co->cg, rvm_asm(RVM_EXT, XX, XX, XX, 0));
640         }
641
642
643         codegen_print_callback(name, userdata, input, size, reason, start, end);
644         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
645
646         if (reason & RPA_REASON_END) {
647                 rvm_costat_pop(co);
648         }
649         return size;
650 }
651
652
653 int codegen_opinit_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
654 {
655         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
656         rulong off = rvm_codegen_getcodesize(co->cg);
657
658         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
659         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
660
661         codegen_print_callback(name, userdata, input, size, reason, start, end);
662         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
663
664         return size;
665 }
666
667
668 int codegen_opassign_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
669 {
670         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
671         rulong off = rvm_codegen_getcodesize(co->cg);
672         ruint opcode = r_array_pop(co->opcodes, ruint);
673
674         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
675         if (opcode != RVM_NOP) {
676                 rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R2, R1, XX, 0));
677                 rvm_codegen_addins(co->cg, rvm_asm(opcode, R0, R2, R0, 0));
678         }
679         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
680
681         codegen_print_callback(name, userdata, input, size, reason, start, end);
682         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
683
684         return size;
685 }
686
687
688 int codegen_oppostfix_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
689 {
690         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
691         rulong off = rvm_codegen_getcodesize(co->cg);
692         ruint opcode = r_array_pop(co->opcodes, ruint);
693
694         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));
695         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R1, XX, 0));
696         rvm_codegen_addins(co->cg, rvm_asm(opcode, R2, R0, DA, 1));
697         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R2, R1, XX, 0));
698
699
700         codegen_print_callback(name, userdata, input, size, reason, start, end);
701         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
702
703         return size;
704 }
705
706
707 int codegen_opprefix_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
708 {
709         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
710         rulong off = rvm_codegen_getcodesize(co->cg);
711         ruint opcode = r_array_pop(co->opcodes, ruint);
712
713         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));
714         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R1, XX, 0));
715         rvm_codegen_addins(co->cg, rvm_asm(opcode, R0, R0, DA, 1));
716         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
717
718         codegen_print_callback(name, userdata, input, size, reason, start, end);
719         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
720
721         return size;
722 }
723
724
725 int codegen_ptr_deref_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
726 {
727         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
728         rulong off = rvm_codegen_getcodesize(co->cg);
729
730         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Address
731         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R1, XX, 0));   // Load the value from offset
732         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));   // Push it on the stack
733
734         codegen_print_callback(name, userdata, input, size, reason, start, end);
735         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
736
737         return size;
738 }
739
740
741 int codegen_arrayelementvalue_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
742 {
743         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
744         rulong off = rvm_codegen_getcodesize(co->cg);
745
746         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Array
747         rvm_codegen_addins(co->cg, rvm_asm(RVM_ELDA, R0, R1, R0, 0));   // Load the value from array offset
748
749         codegen_print_callback(name, userdata, input, size, reason, start, end);
750         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
751
752         return size;
753 }
754
755
756 int codegen_memberexpressionbase_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
757 {
758         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
759         rulong off = rvm_codegen_getcodesize(co->cg);
760
761         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R0, XX, 0));   // Array Address
762         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));   // Array -> On Stack
763
764         codegen_print_callback(name, userdata, input, size, reason, start, end);
765         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
766
767         return size;
768 }
769
770
771 int codegen_arrayelementaddress_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
772 {
773         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
774         rulong off = rvm_codegen_getcodesize(co->cg);
775
776         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Supposedly Array Address
777         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRA, R0, R1, R0, 0));  // Get the address of the element at offset R0
778
779         codegen_print_callback(name, userdata, input, size, reason, start, end);
780         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
781
782         return size;
783 }
784
785
786 int codegen_offset_to_ptr_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
787 {
788         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
789         rulong off = rvm_codegen_getcodesize(co->cg);
790
791         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R2, XX, XX, 0));    // Offset
792         rvm_codegen_addins(co->cg, rvm_asm(RVM_CAST, R2, R2, DA, RVM_DTYPE_UNSIGNED));  // cast to unsigned
793         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Array
794         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRA, R0, R1, R2, 0));  // Pointer to element at offset
795         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));   // Push it on the stack
796
797         codegen_print_callback(name, userdata, input, size, reason, start, end);
798         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
799
800         return size;
801 }
802
803
804 int codegen_swiidexist_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
805 {
806         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
807         rint swi = rvm_cpu_getswi(co->cpu, input, size);
808
809         if (swi < 0)
810                 return 0;
811
812
813         return size;
814 }
815
816
817 int codegen_swiid_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
818 {
819         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
820         rulong off = rvm_codegen_getcodesize(co->cg);
821         rint swi = rvm_cpu_getswi(co->cpu, input, size);
822
823         if (swi < 0)
824                 return 0;
825
826         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, swi));
827         rvm_codegen_addins(co->cg, rvm_asm(RVM_SETTYPE, R0, DA, XX, RVM_DTYPE_SWIID));
828
829         codegen_print_callback(name, userdata, input, size, reason, start, end);
830         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
831
832         return size;
833 }
834
835
836 int codegen_opidentifier_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
837 {
838         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
839         rulong off = rvm_codegen_getcodesize(co->cg);
840         rvm_varmap_t *v = rvm_scope_lookup(co->scope, input, size);
841
842         if (v) {
843                 if (v->datatype == VARMAP_DATATYPE_OFFSET) {
844                         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRS, R0, FP, DA, v->data.offset));
845                 } else {
846                         rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R0, DA, XX, v->data.ptr));
847                 }
848                 codegen_print_callback(name, userdata, input, size, reason, start, end);
849                 codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
850
851                 return size;
852         }
853
854         fprintf(stdout, "ERROR: undefined variable: ");
855         fwrite(input, sizeof(char), size, stdout);
856         fprintf(stdout, "\n");
857         rpa_dbex_abort(co->dbex);
858         return 0;
859 }
860
861
862 int codegen_validentifierop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
863 {
864         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
865         rulong off = rvm_codegen_getcodesize(co->cg);
866         rvm_varmap_t *v = rvm_scope_lookup(co->scope, input, size);
867
868         if (v) {
869                 if (v->datatype == VARMAP_DATATYPE_OFFSET) {
870                         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDS, R0, FP, DA, v->data.offset));
871                 } else {
872                         rvm_codegen_addins(co->cg, rvm_asmp(RVM_LDRR, R0, DA, XX, v->data.ptr));
873                 }
874                 codegen_print_callback(name, userdata, input, size, reason, start, end);
875                 codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
876
877                 return size;
878         }
879
880         fprintf(stdout, "ERROR: undefined variable: ");
881         fwrite(input, sizeof(char), size, stdout);
882         fprintf(stdout, "\n");
883         rpa_dbex_abort(co->dbex);
884         return 0;
885 }
886
887
888 int codegen_varalloc_to_ptr_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
889 {
890         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
891         rulong off = rvm_codegen_getcodesize(co->cg);
892         rvm_varmap_t *v = rvm_scope_tiplookup(co->scope, input, size);
893         if (v) {
894                 fprintf(stdout, "ERROR: variable already defined: ");
895                 fwrite(input, sizeof(char), size, stdout);
896                 fprintf(stdout, "\n");
897                 rpa_dbex_abort(co->dbex);
898                 return 0;
899         }
900
901         if (rvm_scope_count(co->scope)) {
902                 r_array_inclast(co->fp, rword);
903                 rvm_scope_addoffset(co->scope, input, size, r_array_last(co->fp, rword));
904         } else {
905                 rvm_scope_addpointer(co->scope, input, size, r_carray_slot_expand(co->cpu->data, r_carray_length(co->cpu->data)));
906                 r_carray_inclength(co->cpu->data);
907         }
908         v = rvm_scope_tiplookup(co->scope, input, size);
909
910         if (v->datatype == VARMAP_DATATYPE_OFFSET) {
911                 rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRS, R0, FP, DA, v->data.offset));
912         } else {
913                 rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R0, DA, XX, v->data.ptr));
914         }
915         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
916
917         codegen_print_callback(name, userdata, input, size, reason, start, end);
918         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
919
920         return size;
921 }
922
923
924 int codegen_varalloc_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
925 {
926         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
927         rulong off = rvm_codegen_getcodesize(co->cg);
928         rvm_varmap_t *v = rvm_scope_tiplookup(co->scope, input, size);
929         if (v) {
930                 fprintf(stdout, "ERROR: variable already defined: ");
931                 fwrite(input, sizeof(char), size, stdout);
932                 fprintf(stdout, "\n");
933                 rpa_dbex_abort(co->dbex);
934                 return 0;
935         }
936
937         if (rvm_scope_count(co->scope)) {
938                 r_array_inclast(co->fp, rword);
939                 rvm_scope_addoffset(co->scope, input, size, r_array_last(co->fp, rword));
940         } else {
941                 rvm_scope_addpointer(co->scope, input, size, r_carray_slot_expand(co->cpu->data, r_carray_length(co->cpu->data)));
942                 r_carray_inclength(co->cpu->data);
943         }
944
945         codegen_print_callback(name, userdata, input, size, reason, start, end);
946         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
947
948         return size;
949 }
950
951
952 int codegen_newarraysize_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
953 {
954         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
955         rulong off = rvm_codegen_getcodesize(co->cg);
956
957         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));
958         rvm_codegen_addins(co->cg, rvm_asm(RVM_ALLOCARR, R0, R1, XX, 0));
959
960         codegen_print_callback(name, userdata, input, size, reason, start, end);
961         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
962
963         return size;
964 }
965
966
967 int codegen_newarraynosize_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
968 {
969         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
970         rulong off = rvm_codegen_getcodesize(co->cg);
971
972         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, DA, XX, 0));
973         rvm_codegen_addins(co->cg, rvm_asm(RVM_ALLOCARR, R0, R1, XX, 0));
974 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
975
976         codegen_print_callback(name, userdata, input, size, reason, start, end);
977         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
978
979         return size;
980 }
981
982
983 int codegen_scopepush_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
984 {
985         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
986         rulong off = rvm_codegen_getcodesize(co->cg);
987
988         rvm_scope_push(co->scope);
989         codegen_print_callback(name, userdata, input, size, reason, start, end);
990         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
991
992         return size;
993 }
994
995
996 int codegen_scopepop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
997 {
998         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
999         rulong off = rvm_codegen_getcodesize(co->cg);
1000
1001         rvm_scope_pop(co->scope);
1002         codegen_print_callback(name, userdata, input, size, reason, start, end);
1003         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1004
1005         return size;
1006 }
1007
1008
1009 int codegen_compile_error_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1010 {
1011         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1012         fprintf(stdout, "COMPILE ERROR pos: %ld\n", (long) (input - start));
1013         rpa_dbex_abort(co->dbex);
1014         return 0;
1015 }
1016
1017
1018 int codegen_funcallparameter_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1019 {
1020         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1021         rulong off = rvm_codegen_getcodesize(co->cg);
1022         rvm_funcall_t *funcall = (rvm_funcall_t *)r_array_slot(co->funcall, r_array_length(co->funcall) - 1);
1023
1024         funcall->params += 1;
1025         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
1026         codegen_print_callback(name, userdata, input, size, reason, start, end);
1027         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1028
1029         return size;
1030 }
1031
1032
1033 int codegen_funcallname_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1034 {
1035         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1036         rulong off = rvm_codegen_getcodesize(co->cg);
1037         rvm_funcall_t funcall = {input, size, 0};
1038
1039         r_array_add(co->funcall, &funcall);
1040
1041
1042         /*
1043          * R0 holds the label of the called function, we save on the stack
1044          * and FP will point there. After the call we save the LR at that spot
1045          * as we don't need the RO anymore.
1046          */
1047 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_TYPE, R1, R0, XX, 0));
1048 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R1, DA, XX, RVM_DTYPE_POINTER));
1049 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_BNEQ, DA, XX, XX, 2));
1050 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R0, XX, 0));
1051
1052         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(FP)|BIT(SP)));
1053         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
1054
1055         codegen_print_callback(name, userdata, input, size, reason, start, end);
1056         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1057
1058         return size;
1059 }
1060
1061
1062 int codegen_funcallexpression_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1063 {
1064         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1065         rulong off = rvm_codegen_getcodesize(co->cg);
1066         rvm_funcall_t *funcall = r_array_empty(co->funcall) ? NULL : (rvm_funcall_t *) r_array_slot(co->funcall, r_array_length(co->funcall) - 1);
1067
1068         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, FP, SP, DA, funcall->params));
1069         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDS, R1, FP, XX, 0));
1070         rvm_codegen_addins(co->cg, rvm_asm(RVM_STS, LR, FP, XX, 0));
1071         rvm_codegen_addins(co->cg, rvm_asm(RVM_CALL, R1, DA, XX, -rvm_codegen_getcodesize(co->cg)));
1072         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
1073         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(FP,LR)));
1074
1075         r_array_removelast(co->funcall);
1076         codegen_print_callback(name, userdata, input, size, reason, start, end);
1077         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1078
1079         return size;
1080 }
1081
1082
1083 int codegen_fundeclparameter_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1084 {
1085         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1086         rulong off = rvm_codegen_getcodesize(co->cg);
1087         rvm_fundecl_t *fundecl = (rvm_fundecl_t *)r_array_lastslot(co->fundecl);
1088         rvm_varmap_t *v = rvm_scope_tiplookup(co->scope, input, size);
1089         if (v) {
1090                 fprintf(stdout, "ERROR: variable already defined: ");
1091                 fwrite(input, sizeof(char), size, stdout);
1092                 fprintf(stdout, "\n");
1093                 rpa_dbex_abort(co->dbex);
1094                 return 0;
1095         }
1096
1097         fundecl->params += 1;
1098         r_array_inclast(co->fp, rword);
1099         rvm_scope_addoffset(co->scope, input, size, r_array_last(co->fp, rword));
1100         codegen_print_callback(name, userdata, input, size, reason, start, end);
1101         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1102
1103         return size;
1104 }
1105
1106
1107 int codegen_fundeclname_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1108 {
1109         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1110         rulong off = rvm_codegen_getcodesize(co->cg);
1111         rvm_fundecl_t fundecl = {input, size, 0, off};
1112         rint ret;
1113
1114         ret = codegen_varalloc_callback(name, userdata, input, size, reason, start, end);
1115         if (ret == 0)
1116                 return ret;
1117
1118         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, 0));    /* Will be re-written later */
1119         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, DA, R0, XX, 0));   /* Will be re-written later */
1120         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));              /* Will be re-written later */
1121         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, SP, FP, DA, 0));    /* Will be re-written later */
1122         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0xffffffff));
1123 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0xffffffff));
1124
1125         r_array_push(co->fp, 0, rword);
1126         r_array_add(co->fundecl, &fundecl);
1127         rvm_scope_push(co->scope);
1128         rvm_costat_pushroot(co);
1129
1130         codegen_print_callback(name, userdata, input, size, reason, start, end);
1131         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1132         return size;
1133 }
1134
1135
1136
1137 int codegen_fundeclsignature_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1138 {
1139         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1140         rulong off = rvm_codegen_getcodesize(co->cg);
1141
1142 //      rvm_codemap_add(cg->codemap, fundecl->funname, fundecl->funnamesiz, rvm_codegen_getcodesize(co->cg));
1143
1144         codegen_print_callback(name, userdata, input, size, reason, start, end);
1145         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1146
1147         return size;
1148 }
1149
1150
1151 int codegen_fundecl_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1152 {
1153         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1154         rulong off = rvm_codegen_getcodesize(co->cg);
1155         rvm_fundecl_t *fundecl = (rvm_fundecl_t *)r_array_lastslot(co->fundecl);
1156         rvm_varmap_t *fname;
1157         rword fp = r_array_pop(co->fp, rword);
1158         rvm_scope_pop(co->scope);
1159         fname = rvm_scope_tiplookup(co->scope, fundecl->funname, fundecl->funnamesiz);
1160
1161         /*
1162          * Function end, we first define the function end
1163          */
1164         if (rvm_costat_getdirty(co))
1165                 rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(RVM_SAVEDREGS_FIRST, RVM_SAVEDREGS_FIRST+ rvm_costat_getdirty(co) - 1)));
1166         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
1167
1168         /*
1169          * the number of arguments passed is = SP - FP
1170          */
1171         fundecl->codesize = rvm_codegen_getcodesize(co->cg) - fundecl->codestart;
1172         if (fname->datatype == VARMAP_DATATYPE_OFFSET) {
1173                 rvm_codegen_replaceins(co->cg, fundecl->codestart + 0, rvm_asm(RVM_ADDRS, R0, FP, DA, fname->data.offset));
1174         } else {
1175                 rvm_codegen_replaceins(co->cg, fundecl->codestart + 0, rvm_asmp(RVM_MOV, R0, DA, XX, fname->data.ptr));
1176         }
1177         rvm_codegen_replaceins(co->cg, fundecl->codestart + 1, rvm_asm(RVM_STRR, DA, R0, XX, fundecl->codestart + 3));
1178         rvm_codegen_replaceins(co->cg, fundecl->codestart + 2, rvm_asm(RVM_B, DA, XX, XX, fundecl->codesize - 2));
1179         rvm_codegen_replaceins(co->cg, fundecl->codestart + 3, rvm_asm(RVM_ADD, SP, FP, DA, fp));
1180         if (rvm_costat_getdirty(co))
1181                 rvm_codegen_replaceins(co->cg, fundecl->codestart + 4, rvm_asm(RVM_PUSHM, DA, XX, XX, BITS(RVM_SAVEDREGS_FIRST, RVM_SAVEDREGS_FIRST + rvm_costat_getdirty(co) - 1)));
1182
1183         fundecl->codesize = rvm_codegen_getcodesize(co->cg) - fundecl->codestart;
1184         fundecl->params = r_array_last(co->fp, rword);
1185
1186         r_array_removelast(co->fundecl);
1187         rvm_costat_pop(co);
1188         codegen_print_callback(name, userdata, input, size, reason, start, end);
1189         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1190
1191         return size;
1192 }
1193
1194
1195 int codegen_opreturn_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1196 {
1197         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1198         rulong off = rvm_codegen_getcodesize(co->cg);
1199
1200         if (rvm_costat_getdirty(co))
1201                 rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(RVM_SAVEDREGS_FIRST, RVM_SAVEDREGS_FIRST + rvm_costat_getdirty(co) - 1)));
1202         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
1203
1204         codegen_print_callback(name, userdata, input, size, reason, start, end);
1205         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1206
1207         return size;
1208 }
1209
1210
1211 int codegen_ifconditionop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1212 {
1213         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1214         rulong off = rvm_codegen_getcodesize(co->cg);
1215         rvm_codespan_t cs = {0, 0, 0, 0};
1216
1217         cs.codestart = rvm_codegen_getcodesize(co->cg);
1218         r_array_add(co->codespan, &cs);
1219
1220         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1221         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, -1));   //This has to be redefined when we know the size of the code block
1222
1223         codegen_print_callback(name, userdata, input, size, reason, start, end);
1224         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1225
1226         return size;
1227 }
1228
1229
1230 int codegen_ifop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1231 {
1232         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1233         rulong off = rvm_codegen_getcodesize(co->cg);
1234         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1235
1236         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1237         rvm_codegen_replaceins(co->cg, cs.codestart + 1, rvm_asm(RVM_BEQ, DA, XX, XX, cs.codesize - 1));        //This has to be redefined when we know the size of the code block
1238
1239         codegen_print_callback(name, userdata, input, size, reason, start, end);
1240         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1241
1242         return size;
1243 }
1244
1245
1246 int codegen_elseop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1247 {
1248         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1249         rulong off = rvm_codegen_getcodesize(co->cg);
1250         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1251
1252         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, - 1));            // Branch to the end of the else block, has to be redefined
1253         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1254         rvm_codegen_replaceins(co->cg, cs.codestart + 1, rvm_asm(RVM_BEQ, DA, XX, XX, cs.codesize - 1));        // Branch to the begining of the else block
1255
1256         /* Reuse the cs to define the *else* codespan */
1257         cs.codestart = rvm_codegen_getcodesize(co->cg);
1258         cs.codesize = 0;
1259         r_array_add(co->codespan, &cs);
1260
1261         codegen_print_callback(name, userdata, input, size, reason, start, end);
1262         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1263
1264         return size;
1265 }
1266
1267
1268 int codegen_ifelseop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1269 {
1270         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1271         rulong off = rvm_codegen_getcodesize(co->cg);
1272         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1273
1274         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1275         rvm_codegen_replaceins(co->cg, cs.codestart - 1, rvm_asm(RVM_B, DA, XX, XX, cs.codesize));      //Branch to the end of the else block, now we know the size
1276
1277         codegen_print_callback(name, userdata, input, size, reason, start, end);
1278         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1279
1280         return size;
1281 }
1282
1283
1284 int codegen_dokeyword_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1285 {
1286         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1287         rulong off = rvm_codegen_getcodesize(co->cg);
1288         rvm_codespan_t cs = {0, 0, 0, 0};
1289
1290         cs.codestart = rvm_codegen_getcodesize(co->cg);
1291         r_array_add(co->codespan, &cs);
1292
1293         codegen_print_callback(name, userdata, input, size, reason, start, end);
1294         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1295         return size;
1296 }
1297
1298
1299 int codegen_iterationdo_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1300 {
1301         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1302         rulong off = rvm_codegen_getcodesize(co->cg);
1303         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1304         rvm_asmins_t *last = rvm_codegen_getcode(co->cg, off - 1);
1305
1306         if (last->op1 == R0 && last->opcode >= RVM_EADD && last->opcode <= RVM_ELESSEQ) {
1307                 /*
1308                  * Nothing to do, the status register will be updated.
1309                  */
1310         } else {
1311                 rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1312         }
1313
1314         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1315         rvm_codegen_addins(co->cg, rvm_asm(RVM_BNEQ, DA, XX, XX, -cs.codesize));
1316         rvm_codemap_poploopblock(co->cg->codemap);
1317
1318         codegen_print_callback(name, userdata, input, size, reason, start, end);
1319         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1320         return size;
1321 }
1322
1323
1324 int codegen_whileconditionop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1325 {
1326         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1327         rulong off = rvm_codegen_getcodesize(co->cg);
1328         rvm_codespan_t *cs = (rvm_codespan_t*)r_array_lastslot(co->codespan);
1329
1330         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1331         cs->l1 = rvm_codegen_getcodesize(co->cg);
1332         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, -1));   //This has to be redefined when we know the size of the code block
1333
1334         codegen_print_callback(name, userdata, input, size, reason, start, end);
1335         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1336
1337         return size;
1338 }
1339
1340
1341 int codegen_iterationwhileop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1342 {
1343         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1344         rulong off = rvm_codegen_getcodesize(co->cg);
1345
1346         if (reason & RPA_REASON_START) {
1347                 rvm_codespan_t cs = {0, 0, 0, 0};
1348
1349                 cs.codestart = rvm_codegen_getcodesize(co->cg);
1350                 r_array_add(co->codespan, &cs);
1351         } else if (reason & RPA_REASON_MATCHED) {
1352                 rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1353
1354                 cs.codesize = rvm_codegen_getcodesize(co->cg) + 1 - cs.codestart;
1355                 rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, -(cs.codesize - 1)));
1356 //              rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, DA, XX, XX, 0xaaaaa));
1357
1358                 rvm_codegen_replaceins(co->cg, cs.l1, rvm_asm(RVM_BEQ, DA, XX, XX, cs.codesize - (cs.l1 - cs.codestart)));      // Re-writing the instruction
1359         } else if (reason & RPA_REASON_END) {
1360                 rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1361                 cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1362         }
1363
1364         codegen_print_callback(name, userdata, input, size, reason, start, end);
1365         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1366
1367         return size;
1368 }
1369
1370
1371 int codegen_questionmarkop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1372 {
1373         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1374         rulong off = rvm_codegen_getcodesize(co->cg);
1375         rvm_codespan_t cs = {0, 0, 0, 0};
1376
1377         cs.codestart = rvm_codegen_getcodesize(co->cg);
1378         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1379         cs.l1 = rvm_codegen_getcodesize(co->cg);
1380         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 0)); // This will be re-written
1381         r_array_add(co->codespan, &cs);
1382
1383         codegen_print_callback(name, userdata, input, size, reason, start, end);
1384         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1385
1386         return size;
1387 }
1388
1389
1390 int codegen_iftrueop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1391 {
1392         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1393         rulong off = rvm_codegen_getcodesize(co->cg);
1394         rvm_codespan_t *cs = (rvm_codespan_t*) r_array_lastslot(co->codespan);
1395
1396         cs->l2 = rvm_codegen_getcodesize(co->cg);
1397         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0)); // This will be re-written
1398         rvm_codegen_replaceins(co->cg, cs->l1, rvm_asm(RVM_BEQ, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - cs->l1)); // Re-writing the instruction
1399
1400         codegen_print_callback(name, userdata, input, size, reason, start, end);
1401         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1402
1403         return size;
1404 }
1405
1406
1407 int codegen_iffalseop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1408 {
1409         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1410         rulong off = rvm_codegen_getcodesize(co->cg);
1411         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1412
1413         rvm_codegen_replaceins(co->cg, cs.l2, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - cs.l2));     // Re-writing the instruction
1414
1415         codegen_print_callback(name, userdata, input, size, reason, start, end);
1416         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1417
1418         return size;
1419 }
1420
1421
1422 void codegen_unmap_file(rstr_t *buf)
1423 {
1424         if (buf) {
1425                 munmap(buf->str, buf->size);
1426                 r_free(buf);
1427         }
1428 }
1429
1430
1431 rstr_t *codegen_map_file(const char *filename)
1432 {
1433         struct stat st;
1434         rstr_t *str;
1435         char *buffer;
1436
1437
1438         int fd = open(filename, O_RDONLY);
1439         if (fd < 0) {
1440                 return (void*)0;
1441         }
1442         if (fstat(fd, &st) < 0) {
1443                 close(fd);
1444                 return (void*)0;
1445         }
1446         buffer = (char*)mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
1447         if (buffer == (void*)-1) {
1448                 close(fd);
1449                 return (void*)0;
1450         }
1451         str = (rstr_t *)r_malloc(sizeof(*str));
1452         if (!str)
1453                 goto error;
1454         r_memset(str, 0, sizeof(*str));
1455         str->str = buffer;
1456         str->size = st.st_size;
1457         close(fd);
1458         return str;
1459
1460 error:
1461         munmap(buffer, st.st_size);
1462         close(fd);
1463         return str;
1464 }
1465
1466
1467 int main(int argc, char *argv[])
1468 {
1469         int res, i;
1470         rvmcpu_t *cpu;
1471         ruint ntable;
1472         rpa_dbex_handle dbex = rpa_dbex_create();
1473         rvm_compiler_t *co = rvm_compiler_create(dbex);
1474
1475         cpu = rvm_cpu_create();
1476         ntable = rvm_cpu_addswitable(cpu, switable);
1477         rvm_cpu_addswitable(cpu, switable_js);
1478         co->cpu = cpu;
1479
1480         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
1481         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
1482         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
1483         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
1484
1485         for (i = 1; i < argc; i++) {
1486                 if (r_strcmp(argv[i], "-L") == 0) {
1487                 } else if (r_strcmp(argv[i], "-d") == 0) {
1488                         debuginfo = 1;
1489                 } else if (r_strcmp(argv[i], "-p") == 0) {
1490                         parseinfo = 1;
1491                 } else if (r_strcmp(argv[i], "-P") == 0) {
1492                         parseinfo = 1;
1493                         verboseinfo = 1;
1494                 } else if (r_strcmp(argv[i], "-c") == 0) {
1495                         compileonly = 1;
1496                 } else if (r_strcmp(argv[i], "-o") == 0) {
1497                         co->optimized = 1;
1498                 } else if (r_strcmp(argv[i], "-m") == 0) {
1499
1500                 }
1501         }
1502
1503         rpagen_load_rules(dbex, co);
1504
1505         for (i = 1; i < argc; i++) {
1506                 if (r_strcmp(argv[i], "-e") == 0) {
1507                         if (++i < argc) {
1508                                 rstr_t script = { argv[i], r_strlen(argv[i]) };
1509                                 res = rpa_dbex_parse(dbex, rpa_dbex_default_pattern(dbex), script.str, script.str, script.str + script.size);
1510                                 if (res <= 0)
1511                                         rvm_codegen_clear(co->cg);
1512                         }
1513                         goto exec;
1514                 }
1515         }
1516
1517         for (i = 1; i < argc; i++) {
1518                 if (r_strcmp(argv[i], "-f") == 0) {
1519                         rstr_t *script = NULL;
1520                         if (++i < argc) {
1521                                 script = codegen_map_file(argv[i]);
1522                                 if (script) {
1523                                         res = rpa_dbex_parse(dbex, rpa_dbex_default_pattern(dbex), script->str, script->str, script->str + script->size);
1524                                         codegen_unmap_file(script);
1525                                 }
1526
1527                         }
1528                         goto exec;
1529                 }
1530         }
1531
1532
1533 exec:
1534         rvm_relocate(rvm_codegen_getcode(co->cg, 0), rvm_codegen_getcodesize(co->cg));
1535
1536         if (debuginfo) {
1537                 fprintf(stdout, "\nGenerated Code:\n");
1538                 rvm_asm_dump(rvm_codegen_getcode(co->cg, 0), rvm_codegen_getcodesize(co->cg));
1539                 if (rvm_codegen_getcodesize(co->cg)) {
1540                         if (!compileonly) {
1541                                 fprintf(stdout, "\nExecution:\n");
1542                                 rvm_cpu_exec_debug(cpu, rvm_codegen_getcode(co->cg, 0), 0);
1543                         }
1544                 }
1545         } else {
1546                 if (!compileonly)
1547                         rvm_cpu_exec(cpu, rvm_codegen_getcode(co->cg, 0), 0);
1548         }
1549
1550
1551         rpa_dbex_destroy(dbex);
1552         rvm_cpu_destroy(cpu);
1553         rvm_compiler_destroy(co);
1554
1555         if (debuginfo) {
1556                 r_printf("Max alloc mem: %ld\n", r_debug_get_maxmem());
1557                 r_printf("Leaked mem: %ld\n", r_debug_get_allocmem());
1558         }
1559         return 0;
1560 }
1561
1562
1563 #define EOL "\n"
1564
1565
1566 extern char _binary_____________tests_ecma262_rpa_start[];
1567 extern char _binary_____________tests_ecma262_rpa_end[];
1568 extern unsigned long *_binary_____________tests_ecma262_rpa_size;
1569
1570 void rpagen_load_rules(rpa_dbex_handle dbex, rvm_compiler_t *co)
1571 {
1572         int ret, line;
1573         int inputsize = _binary_____________tests_ecma262_rpa_end - _binary_____________tests_ecma262_rpa_start;
1574         const char *buffer = _binary_____________tests_ecma262_rpa_start;
1575         const char *pattern = buffer;
1576
1577         rpa_dbex_open(dbex);
1578
1579         rpa_dbex_add_callback_exact(dbex, "BitwiseANDOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1580         rpa_dbex_add_callback_exact(dbex, "BitwiseXOROp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1581         rpa_dbex_add_callback_exact(dbex, "BitwiseOROp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1582         rpa_dbex_add_callback_exact(dbex, "AdditiveExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1583
1584         rpa_dbex_add_callback_exact(dbex, "MultiplicativeExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1585         rpa_dbex_add_callback_exact(dbex, "ShiftExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1586         rpa_dbex_add_callback_exact(dbex, "EqualityExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1587         rpa_dbex_add_callback_exact(dbex, "RelationalExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1588         rpa_dbex_add_callback_exact(dbex, "LogicalOROp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1589         rpa_dbex_add_callback_exact(dbex, "LogicalANDOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1590
1591         rpa_dbex_add_callback_exact(dbex, "AssignmentOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1592         rpa_dbex_add_callback_exact(dbex, "EqualityOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1593         rpa_dbex_add_callback_exact(dbex, "RelationalOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1594         rpa_dbex_add_callback_exact(dbex, "AdditiveOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1595         rpa_dbex_add_callback_exact(dbex, "MultiplicativeOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1596         rpa_dbex_add_callback_exact(dbex, "ShiftOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1597         rpa_dbex_add_callback_exact(dbex, "BitwiseANDOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1598         rpa_dbex_add_callback_exact(dbex, "BitwiseXOROperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1599         rpa_dbex_add_callback_exact(dbex, "BitwiseOROperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1600         rpa_dbex_add_callback_exact(dbex, "LogicalANDOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1601         rpa_dbex_add_callback_exact(dbex, "LogicalOROperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1602         rpa_dbex_add_callback_exact(dbex, "LogicalNotOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1603         rpa_dbex_add_callback_exact(dbex, "BitwiseNotOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1604         rpa_dbex_add_callback_exact(dbex, "UnaryOperatorOpcode", RPA_REASON_MATCHED, codegen_opcode_unary_callback, co);
1605         rpa_dbex_add_callback_exact(dbex, "PrintOp", RPA_REASON_MATCHED, codegen_printop_callback, co);
1606
1607
1608         rpa_dbex_add_callback_exact(dbex, "PostfixOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1609         rpa_dbex_add_callback_exact(dbex, "PostfixExpressionOp", RPA_REASON_MATCHED, codegen_oppostfix_callback, co);
1610         rpa_dbex_add_callback_exact(dbex, "PrefixExpressionOp", RPA_REASON_MATCHED, codegen_opprefix_callback, co);
1611
1612
1613         rpa_dbex_add_callback_exact(dbex, "UnaryExpressionOp", RPA_REASON_ALL, codegen_unary_asmop_callback, co);
1614         rpa_dbex_add_callback_exact(dbex, "LogicalNotExpressionOp", RPA_REASON_ALL, codegen_unary_asmop_callback, co);
1615         rpa_dbex_add_callback_exact(dbex, "BitwiseNotExpressionOp", RPA_REASON_ALL, codegen_unary_asmop_callback, co);
1616
1617         rpa_dbex_add_callback_exact(dbex, "DecimalIntegerLiteral", RPA_REASON_MATCHED, codegen_integer_callback, co);
1618         rpa_dbex_add_callback_exact(dbex, "DecimalNonIntegerLiteral", RPA_REASON_MATCHED, codegen_double_callback, co);
1619         rpa_dbex_add_callback_exact(dbex, "BlockBegin", RPA_REASON_MATCHED, codegen_scopepush_callback, co);
1620         rpa_dbex_add_callback_exact(dbex, "BlockEnd", RPA_REASON_MATCHED, codegen_scopepop_callback, co);
1621
1622         rpa_dbex_add_callback_exact(dbex, "DoKeyword", RPA_REASON_MATCHED, codegen_dokeyword_callback, co);
1623         rpa_dbex_add_callback_exact(dbex, "IterationDo", RPA_REASON_MATCHED, codegen_iterationdo_callback, co);
1624
1625         rpa_dbex_add_callback_exact(dbex, "sqstring", RPA_REASON_MATCHED, codegen_string_callback, co);
1626         rpa_dbex_add_callback_exact(dbex, "dqstring", RPA_REASON_MATCHED, codegen_string_callback, co);
1627         rpa_dbex_add_callback_exact(dbex, "DoubleStringCharacters", RPA_REASON_MATCHED, codegen_string_callback, co);
1628         rpa_dbex_add_callback_exact(dbex, "SingleStringCharacters", RPA_REASON_MATCHED, codegen_string_callback, co);
1629         rpa_dbex_add_callback_exact(dbex, "Program", RPA_REASON_START|RPA_REASON_MATCHED, codegen_program_callback, co);
1630         rpa_dbex_add_callback_exact(dbex, "Initialiser", RPA_REASON_MATCHED, codegen_opinit_callback, co);
1631         rpa_dbex_add_callback_exact(dbex, "AssignmentExpressionOp", RPA_REASON_MATCHED, codegen_opassign_callback, co);
1632
1633         rpa_dbex_add_callback_exact(dbex, "VariableAllocate", RPA_REASON_MATCHED, codegen_varalloc_callback, co);
1634         rpa_dbex_add_callback_exact(dbex, "VariableAllocateAndInit", RPA_REASON_MATCHED, codegen_varalloc_to_ptr_callback, co);
1635
1636         rpa_dbex_add_callback_exact(dbex, "ReturnOp", RPA_REASON_MATCHED, codegen_opreturn_callback, co);
1637
1638         rpa_dbex_add_callback_exact(dbex, "SwiId", RPA_REASON_MATCHED, codegen_swiid_callback, co);
1639         rpa_dbex_add_callback_exact(dbex, "SwiIdExist", RPA_REASON_MATCHED, codegen_swiidexist_callback, co);
1640
1641         rpa_dbex_add_callback_exact(dbex, "IdentifierOp", RPA_REASON_MATCHED, codegen_opidentifier_callback, co);
1642         rpa_dbex_add_callback_exact(dbex, "ValIdentifierOp", RPA_REASON_MATCHED, codegen_validentifierop_callback, co);
1643         rpa_dbex_add_callback_exact(dbex, "PostfixExpressionValOp", RPA_REASON_ALL, codegen_valop_callback, co);
1644
1645         rpa_dbex_add_callback_exact(dbex, "LeftHandSideExpressionPush", RPA_REASON_MATCHED, codegen_push_r0_callback, co);
1646         rpa_dbex_add_callback_exact(dbex, "LiteralPushOp", RPA_REASON_MATCHED, codegen_push_r0_callback, co);
1647
1648         rpa_dbex_add_callback_exact(dbex, "MemberExpressionIndexBaseOp", RPA_REASON_MATCHED, codegen_memberexpressionbase_callback, co);
1649         rpa_dbex_add_callback_exact(dbex, "MemberExpressionIndexOp", RPA_REASON_MATCHED, codegen_arrayelementaddress_callback, co);
1650
1651         rpa_dbex_add_callback_exact(dbex, "ValMemberExpressionIndexBaseOp", RPA_REASON_MATCHED, codegen_push_r0_callback, co);
1652         rpa_dbex_add_callback_exact(dbex, "ValMemberExpressionIndexOp", RPA_REASON_MATCHED, codegen_arrayelementvalue_callback, co);
1653
1654         rpa_dbex_add_callback_exact(dbex, "CallExpressionIndexBaseOp", RPA_REASON_MATCHED, codegen_memberexpressionbase_callback, co);
1655         rpa_dbex_add_callback_exact(dbex, "CallExpressionIndexOp", RPA_REASON_MATCHED, codegen_arrayelementaddress_callback, co);
1656
1657
1658         rpa_dbex_add_callback_exact(dbex, "ValCallExpressionIndexBaseOp", RPA_REASON_MATCHED, codegen_push_r0_callback, co);
1659         rpa_dbex_add_callback_exact(dbex, "ValCallExpressionIndexOp", RPA_REASON_MATCHED, codegen_arrayelementvalue_callback, co);
1660
1661         rpa_dbex_add_callback_exact(dbex, "ConditionalExpression", RPA_REASON_MATCHED, codegen_conditionalexp_callback, co);
1662
1663         rpa_dbex_add_callback_exact(dbex, "NewArraySize", RPA_REASON_MATCHED, codegen_newarraysize_callback, co);
1664         rpa_dbex_add_callback_exact(dbex, "NewArrayNoSize", RPA_REASON_MATCHED, codegen_newarraynosize_callback, co);
1665         rpa_dbex_add_callback_exact(dbex, "compile_error", RPA_REASON_MATCHED, codegen_compile_error_callback, co);
1666
1667         rpa_dbex_add_callback_exact(dbex, "ArgumentsOp", RPA_REASON_ALL, codegen_costate_callback, co);
1668         rpa_dbex_add_callback_exact(dbex, "BracketExpressionOp", RPA_REASON_ALL, codegen_costate_callback, co);
1669
1670         rpa_dbex_add_callback_exact(dbex, "FunctionName", RPA_REASON_MATCHED, codegen_fundeclname_callback, co);
1671         rpa_dbex_add_callback_exact(dbex, "FunctionDefinition", RPA_REASON_MATCHED, codegen_fundeclsignature_callback, co);
1672         rpa_dbex_add_callback_exact(dbex, "FunctionDeclaration", RPA_REASON_MATCHED, codegen_fundecl_callback, co);
1673         rpa_dbex_add_callback_exact(dbex, "FunctionParameter", RPA_REASON_MATCHED, codegen_fundeclparameter_callback, co);
1674         rpa_dbex_add_callback_exact(dbex, "FunctionCallParameter", RPA_REASON_MATCHED, codegen_funcallparameter_callback, co);
1675         rpa_dbex_add_callback_exact(dbex, "FunctionCallName", RPA_REASON_MATCHED, codegen_funcallname_callback, co);
1676         rpa_dbex_add_callback_exact(dbex, "CallExpressionOp", RPA_REASON_MATCHED, codegen_funcallexpression_callback, co);
1677
1678         rpa_dbex_add_callback_exact(dbex, "ValFunctionCallName", RPA_REASON_MATCHED, codegen_funcallname_callback, co);
1679         rpa_dbex_add_callback_exact(dbex, "ValCallExpressionOp", RPA_REASON_MATCHED, codegen_funcallexpression_callback, co);
1680
1681
1682         rpa_dbex_add_callback_exact(dbex, "IfConditionOp", RPA_REASON_MATCHED, codegen_ifconditionop_callback, co);
1683         rpa_dbex_add_callback_exact(dbex, "IfOp", RPA_REASON_MATCHED, codegen_ifop_callback, co);
1684         rpa_dbex_add_callback_exact(dbex, "ElseOp", RPA_REASON_MATCHED, codegen_elseop_callback, co);
1685         rpa_dbex_add_callback_exact(dbex, "IfElseOp", RPA_REASON_MATCHED, codegen_ifelseop_callback, co);
1686
1687         rpa_dbex_add_callback_exact(dbex, "WhileConditionOp", RPA_REASON_MATCHED, codegen_whileconditionop_callback, co);
1688         rpa_dbex_add_callback_exact(dbex, "IterationWhileOp", RPA_REASON_ALL, codegen_iterationwhileop_callback, co);
1689         rpa_dbex_add_callback_exact(dbex, "QuestionMarkOp", RPA_REASON_MATCHED, codegen_questionmarkop_callback, co);
1690         rpa_dbex_add_callback_exact(dbex, "AssignmentExpressionIfTrueOp", RPA_REASON_MATCHED, codegen_iftrueop_callback, co);
1691         rpa_dbex_add_callback_exact(dbex, "AssignmentExpressionIfFalseOp", RPA_REASON_MATCHED, codegen_iffalseop_callback, co);
1692
1693
1694
1695         if (verboseinfo)
1696                 rpa_dbex_add_callback(dbex, ".*", RPA_REASON_MATCHED, codegen_print_callback, co);
1697
1698         while ((ret = rpa_dbex_load(dbex, pattern, inputsize)) > 0) {
1699                 inputsize -= ret;
1700                 pattern += ret;
1701         }
1702         if (ret < 0) {
1703                 for (line = 1; pattern >= buffer; --pattern) {
1704                         if (*pattern == '\n')
1705                                 line += 1;
1706                 }
1707                 fprintf(stdout, "Line: %d, RPA LOAD ERROR: %s\n", line, (rpa_dbex_get_error(dbex) == RPA_E_SYNTAX_ERROR) ? "Syntax Error." : "Pattern Loading failed.");
1708                 goto error;
1709         }
1710
1711 error:
1712         rpa_dbex_close(dbex);
1713 }