RPA Toolkit
2172a3f97b808222e5cdc87adf454406bd645bf8
[rpatk.git] / rpa2 / rpacompiler.c
1 #include "rmem.h"
2 #include "rpacompiler.h"
3 #include "rstring.h"
4
5
6 static rlong rpa_codegen_add_numlabel_s(rvm_codegen_t *cg, const rchar *alphaname, rlong numname)
7 {
8         rchar label[128];
9
10         r_memset(label, 0, sizeof(label));
11         r_snprintf(label, sizeof(label) - 1, "L%07ld__%s:", numname, alphaname);
12         return rvm_codegen_addlabel_s(cg, label);
13 }
14
15
16 static rlong rpa_codegen_invalid_add_numlabel_s(rvm_codegen_t *cg, const rchar *alphaname, rlong numname)
17 {
18         rchar label[128];
19
20         r_memset(label, 0, sizeof(label));
21         r_snprintf(label, sizeof(label) - 1, "L%07ld__%s:", numname, alphaname);
22         return rvm_codegen_invalid_addlabel_s(cg, label);
23 }
24
25
26 void rpa_compiler_index_reference_nan(rpa_compiler_t *co, rulong index)
27 {
28         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, index, rvm_asm(RVM_BL, DA, XX, XX, 0));
29 }
30
31
32 void rpa_compiler_reference_nan(rpa_compiler_t *co, const rchar *name, rsize_t namesize)
33 {
34         rpa_compiler_index_reference_nan(co, rvm_codemap_lookup(co->cg->codemap, name, namesize));
35 }
36
37
38 void rpa_compiler_reference_nan_s(rpa_compiler_t *co, const rchar *name)
39 {
40         rpa_compiler_reference_nan(co, name, r_strlen(name));
41 }
42
43
44 void rpa_compiler_index_reference_opt(rpa_compiler_t *co, rulong index)
45 {
46         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, index, rvm_asm(RVM_BL, DA, XX, XX, 0));
47         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOVS, R0, R0, XX, 0));
48         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 2));
49         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, 0));
50 }
51
52
53 void rpa_compiler_reference_opt(rpa_compiler_t *co, const rchar *name, rsize_t namesize)
54 {
55         rpa_compiler_index_reference_opt(co, rvm_codemap_lookup(co->cg->codemap, name, namesize));
56 }
57
58
59 void rpa_compiler_reference_opt_s(rpa_compiler_t *co, const rchar *name)
60 {
61         rpa_compiler_reference_opt(co, name, r_strlen(name));
62 }
63
64
65 void rpa_compiler_index_reference_mul(rpa_compiler_t *co, rulong index)
66 {
67         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
68         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, index, rvm_asm(RVM_BL, DA, XX, XX, 0));
69         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOVS, R0, R0, XX, 0));
70         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, -2));
71         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
72         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R0, 0));
73         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 2));
74         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
75 }
76
77
78 void rpa_compiler_reference_mul(rpa_compiler_t *co, const rchar *name, rsize_t namesize)
79 {
80         rpa_compiler_index_reference_mul(co, rvm_codemap_lookup(co->cg->codemap, name, namesize));
81
82 }
83
84
85 void rpa_compiler_reference_mul_s(rpa_compiler_t *co, const rchar *name)
86 {
87         rpa_compiler_reference_mul(co, name, r_strlen(name));
88 }
89
90
91 void rpa_compiler_index_reference_mop(rpa_compiler_t *co, rulong index)
92 {
93         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
94         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, index, rvm_asm(RVM_BL, DA, XX, XX, 0));
95         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOVS, R0, R0, XX, 0));
96         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, -2));
97         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
98         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R0, 0));
99         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 2));
100         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, 0));
101 }
102
103
104 void rpa_compiler_reference_mop(rpa_compiler_t *co, const rchar *name, rsize_t namesize)
105 {
106         rpa_compiler_index_reference_mop(co, rvm_codemap_lookup(co->cg->codemap, name, namesize));
107 }
108
109
110 void rpa_compiler_reference_mop_s(rpa_compiler_t *co, const rchar *name)
111 {
112         rpa_compiler_reference_mop(co, name, r_strlen(name));
113 }
114
115
116 void rpa_compiler_index_reference(rpa_compiler_t *co, rulong index, ruint qflag)
117 {
118         if (qflag == RPA_MATCH_OPTIONAL) {
119                 rpa_compiler_index_reference_opt(co, index);
120         } else if (qflag == RPA_MATCH_MULTIPLE) {
121                 rpa_compiler_index_reference_mul(co, index);
122         } else if (qflag == RPA_MATCH_MULTIOPT) {
123                 rpa_compiler_index_reference_mop(co, index);
124         } else {
125                 rpa_compiler_index_reference_nan(co, index);
126         }
127 }
128
129
130 void rpa_compiler_reference(rpa_compiler_t *co, const rchar *name, rsize_t namesize, ruint qflag)
131 {
132         rpa_compiler_index_reference(co, rvm_codemap_lookup(co->cg->codemap, name, namesize), qflag);
133 }
134
135
136 void rpa_compiler_reference_s(rpa_compiler_t *co, const rchar *name, ruint qflag)
137 {
138         rpa_compiler_reference(co, name, r_strlen(name), qflag);
139 }
140
141
142 rpa_compiler_t *rpa_compiler_create()
143 {
144         rpa_compiler_t *co;
145
146         co = (rpa_compiler_t *)r_malloc(sizeof(*co));
147         r_memset(co, 0, sizeof(*co));
148         co->cg = rvm_codegen_create();
149         co->scope = rvm_scope_create();
150         co->expressions = r_array_create(sizeof(rpa_ruledef_t));
151         co->ruleprefs = r_harray_create(sizeof(rpa_rulepref_t));
152         return co;
153 }
154
155
156 void rpa_compiler_destroy(rpa_compiler_t *co)
157 {
158         if (co) {
159                 rvm_codegen_destroy(co->cg);
160                 rvm_scope_destroy(co->scope);
161                 r_object_destroy((robject_t*)co->ruleprefs);
162                 r_object_destroy((robject_t*)co->expressions);
163                 r_free(co);
164         }
165 }
166
167
168 rpa_rulepref_t *rpa_compiler_rulepref_lookup(rpa_compiler_t *co, const rchar *name, ruint namesize)
169 {
170         rlong index = r_harray_lookup(co->ruleprefs, name, namesize);
171         if (index < 0)
172                 return NULL;
173         return (rpa_rulepref_t *)r_harray_slot(co->ruleprefs, index);
174 }
175
176
177 rpa_rulepref_t *rpa_compiler_rulepref_lookup_s(rpa_compiler_t *co, const rchar *name)
178 {
179         return rpa_compiler_rulepref_lookup(co, name, r_strlen(name));
180 }
181
182
183 rpa_rulepref_t *rpa_compiler_rulepref(rpa_compiler_t *co, const rchar *name, ruint namesize)
184 {
185         rlong index = r_harray_lookup(co->ruleprefs, name, namesize);
186         if (index < 0)
187                 index = r_harray_add(co->ruleprefs, name, namesize, NULL);
188         return (rpa_rulepref_t *)r_harray_slot(co->ruleprefs, index);
189 }
190
191
192 rpa_rulepref_t *rpa_compiler_rulepref_s(rpa_compiler_t *co, const rchar *name)
193 {
194         return rpa_compiler_rulepref(co, name, r_strlen(name));
195 }
196
197
198 void rpa_compiler_rulepref_set_ruleuid(rpa_compiler_t *co, const rchar *name, ruint namesize, rlong ruleuid)
199 {
200         rpa_rulepref_t *rulepref = rpa_compiler_rulepref(co, name, namesize);
201
202         R_ASSERT(rulepref);
203         rulepref->ruleuid = ruleuid;
204 }
205
206
207 void rpa_compiler_rulepref_set_ruleuid_s(rpa_compiler_t *co, const rchar *name, rlong ruleuid)
208 {
209         rpa_compiler_rulepref_set_ruleuid(co, name, r_strlen(name), ruleuid);
210 }
211
212
213 void rpa_compiler_rulepref_set_flag(rpa_compiler_t *co, const rchar *name, ruint namesize, rulong flag)
214 {
215         rpa_rulepref_t *rulepref = rpa_compiler_rulepref(co, name, namesize);
216
217         R_ASSERT(rulepref);
218         rulepref->flags |= flag;
219 }
220
221
222 void rpa_compiler_rulepref_set_flag_s(rpa_compiler_t *co, const rchar *name, rulong flag)
223 {
224         rpa_compiler_rulepref_set_flag(co, name, r_strlen(name), flag);
225 }
226
227
228 void rpa_compiler_rulepref_clear_flag(rpa_compiler_t *co, const rchar *name, ruint namesize, rulong flag)
229 {
230         rpa_rulepref_t *rulepref = rpa_compiler_rulepref(co, name, namesize);
231
232         R_ASSERT(rulepref);
233         rulepref->flags &= ~flag;
234 }
235
236
237 void rpa_compiler_rulepref_clear_flag_s(rpa_compiler_t *co, const rchar *name, rulong flag)
238 {
239         rpa_compiler_rulepref_clear_flag(co, name, r_strlen(name), flag);
240 }
241
242
243 void rpa_compiler_rulepref_set_ruleuid_flags(rpa_compiler_t *co, const rchar *name, ruint namesize, rlong ruleuid, rulong flags)
244 {
245         rpa_rulepref_t *rulepref = rpa_compiler_rulepref(co, name, namesize);
246
247         R_ASSERT(rulepref);
248         rulepref->ruleuid = ruleuid;
249         rulepref->flags = flags;
250 }
251
252
253 void rpa_compiler_rulepref_set_ruleuid_flags_s(rpa_compiler_t *co, const rchar *name, rlong ruleuid, rulong flags)
254 {
255         rpa_compiler_rulepref_set_ruleuid_flags(co, name, r_strlen(name), ruleuid, flags);
256 }
257
258
259 #define RPA_RULEBLOB_SIZE (RPA_RULENAME_MAXSIZE + sizeof(rpa_ruledata_t) + 2*sizeof(rulong))
260
261 rlong rpa_compiler_addblob(rpa_compiler_t *co, rlong ruleid, rlong ruleuid, rulong flags, const rchar *name, rulong namesize)
262 {
263         rchar blob[RPA_RULEBLOB_SIZE];
264         rchar *ptr;
265         rpa_ruledata_t *pblob = (rpa_ruledata_t *)blob;
266
267         if (namesize >= RPA_RULENAME_MAXSIZE)
268                 return -1;
269         r_memset(pblob, 0, RPA_RULEBLOB_SIZE);
270         ptr = blob + sizeof(rpa_ruledata_t);
271         pblob->name = ptr - blob;
272         pblob->ruleid = ruleid;
273         pblob->ruleuid = ruleuid;
274         pblob->flags = flags;
275         pblob->namesize = namesize;
276         r_strncpy(ptr, name, namesize);
277         ptr += namesize;
278         pblob->size = ptr - blob + 1;
279         return rvm_codegen_adddata_s(co->cg, NULL, pblob, pblob->size);
280 }
281
282
283 rlong rpa_compiler_addblob_s(rpa_compiler_t *co, rlong ruleid, rlong ruleuid, rulong flags, const rchar *name)
284 {
285         return 0;
286 }
287
288
289 rint rpa_compiler_loop_begin(rpa_compiler_t *co, const rchar *name, ruint namesize)
290 {
291         rpa_ruledef_t exp;
292         rlong ruleuid = RPA_RECORD_INVALID_UID;
293         rulong flags = 0;
294         rpa_rulepref_t *rulepref = rpa_compiler_rulepref_lookup(co, name, namesize);
295
296         if (rulepref) {
297                 flags = rulepref->flags;
298                 ruleuid = rulepref->ruleuid;
299         }
300
301         r_memset(&exp, 0, sizeof(exp));
302         exp.start = rvm_codegen_getcodesize(co->cg);
303         exp.startidx = rvm_codegen_addlabel(co->cg, name, namesize);
304         exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
305         exp.successidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__success", exp.start);
306         exp.failidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__fail", exp.start);
307         exp.againidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__again", exp.start);
308         exp.dataidx = rpa_compiler_addblob(co, exp.start, ruleuid, flags, name, namesize);
309
310         rvm_codegen_addins(co->cg, rvm_asm(RVM_CLR, R3, XX, XX, 0));
311         rvm_codegen_addins(co->cg, rvm_asm(RVM_CLR, R0, XX, XX, 0));
312         exp.loopidx = rpa_codegen_add_numlabel_s(co->cg, "__loop", exp.start);
313         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_REC)|BIT(R_LOO)|BIT(R_TOP)|BIT(LR)));
314         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
315         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_LOO, R3, XX, 0));
316         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
317
318         r_array_add(co->expressions, &exp);
319         return 0;
320 }
321
322
323 rint rpa_compiler_loop_begin_s(rpa_compiler_t *co, const rchar *name)
324 {
325         return rpa_compiler_loop_begin(co, name, r_strlen(name));
326 }
327
328
329 rint rpa_compiler_loop_end(rpa_compiler_t *co)
330 {
331         rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
332
333         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R3, R_LOO, XX, 0));         // Save LOO to R3 before restoring the old one
334         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));            // Pop the accumulated ret, although ignored here
335         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_LOO)|BIT(R_OTP)|BIT(LR)));
336         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R_OTP, 0));
337         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.failidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));  // ------------- R_TOP is the same
338         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITEND, DA, R_OTP, R0, 0));     //          |
339         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R3, R0, XX, 0));                                                                                            //          |
340         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_TOP, R_OTP, XX, 0));                                                                                      //          |
341         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.loopidx, rvm_asm(RVM_B, DA, XX, XX, 0));            //          |
342         rvm_codegen_redefinelabel(co->cg, exp.failidx);                                                                                 //          |
343         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_REC, R1, XX, 0));                 //        <-------------------------------------
344         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
345         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
346
347         /*
348          *  END FAILED:
349          */
350         rvm_codegen_redefinelabel(co->cg, exp.endidx);
351         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R3, R_LOO, XX, 0));         // Save LOO to R3 before restoring the old one
352         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));            // Pop the accumulated ret, use it to save the status for return
353         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_REC)|BIT(R_LOO)|BIT(R_TOP)|BIT(LR)));
354         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
355         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 3));
356         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
357         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
358         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, R_TOP, R_TOP, R3, 0));
359         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
360         return 0;
361 }
362
363
364 rint rpa_compiler_rule_begin(rpa_compiler_t *co, const rchar *name, ruint namesize)
365 {
366         rpa_ruledef_t exp;
367         rlong ruleuid = RPA_RECORD_INVALID_UID;
368         rulong flags = 0;
369         rpa_rulepref_t *rulepref = rpa_compiler_rulepref_lookup(co, name, namesize);
370
371         if (rulepref) {
372                 flags = rulepref->flags;
373                 ruleuid = rulepref->ruleuid;
374         }
375
376         r_memset(&exp, 0, sizeof(exp));
377         exp.start = rvm_codegen_getcodesize(co->cg);
378         exp.startidx = rvm_codegen_addlabel(co->cg, name, namesize);
379         exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
380         exp.dataidx = rpa_compiler_addblob(co, exp.start, ruleuid, flags, name, namesize);
381
382         rvm_codegen_addins(co->cg, rvm_asm(RPA_CHECKCACHE, DA, R_TOP, XX, exp.start));
383         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXNEQ, LR, XX, XX, 0));
384         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
385         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
386         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
387         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
388
389         r_array_add(co->expressions, &exp);
390         return 0;
391 }
392
393
394 rint rpa_compiler_rule_begin_s(rpa_compiler_t *co, const rchar *name)
395 {
396         return rpa_compiler_rule_begin(co, name, r_strlen(name));
397 }
398
399
400 rint rpa_compiler_rule_end(rpa_compiler_t *co)
401 {
402         rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
403
404         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
405         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_OTP, XX, XX, 0));
406         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
407         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R_OTP, 0));
408         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 4));
409         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITEND, DA, R_OTP, R0, 0));
410         rvm_codegen_addins(co->cg, rvm_asml(RPA_SETCACHE, DA, R1, R_REC, exp.start));
411         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
412         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_REC, R1, XX, 0));
413         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
414         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
415         rvm_codegen_redefinelabel(co->cg, exp.endidx);
416         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
417         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
418         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
419         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_OTP, R_TOP, XX, 0));
420         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
421         rvm_codegen_addins(co->cg, rvm_asml(RPA_SETCACHE, DA, R_REC, R_REC, exp.start));
422         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
423         return 0;
424 }
425
426
427 rint rpa_compiler_inlinerule_begin(rpa_compiler_t *co, const rchar *name, ruint namesize, ruint flags)
428 {
429         rpa_ruledef_t exp;
430         rlong ruleuid = RPA_RECORD_INVALID_UID;
431         rulong ruleflags = 0;
432         rpa_rulepref_t *rulepref = rpa_compiler_rulepref_lookup(co, name, namesize);
433
434         if (rulepref) {
435                 ruleflags = rulepref->flags;
436                 ruleuid = rulepref->ruleuid;
437         }
438
439         r_memset(&exp, 0, sizeof(exp));
440         exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
441         exp.start = rvm_codegen_getcodesize(co->cg);
442         exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__inlined", exp.start);
443         exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
444         exp.dataidx = rpa_compiler_addblob(co, exp.start, ruleuid, ruleflags, name, namesize);
445
446         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
447         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
448         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
449         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
450         r_array_add(co->expressions, &exp);
451         return 0;
452 }
453
454
455 rint rpa_compiler_inlinerule_begin_s(rpa_compiler_t *co, const rchar *name, ruint flags)
456 {
457         return rpa_compiler_inlinerule_begin(co, name, r_strlen(name), flags);
458 }
459
460
461 rint rpa_compiler_inlinerule_end(rpa_compiler_t *co)
462 {
463         rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
464
465         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
466         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_OTP, XX, XX, 0));
467         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
468         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R_OTP, 0));
469         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 4));
470         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITEND, DA, R_OTP, R0, 0));
471         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
472         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_REC, R1, XX, 0));
473         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
474         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
475         rvm_codegen_redefinelabel(co->cg, exp.endidx);
476         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
477         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
478         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
479
480         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
481         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
482         rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
483         rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
484
485         return 0;
486 }
487
488
489 rint rpa_compiler_exp_begin(rpa_compiler_t *co, ruint flags)
490 {
491         rpa_ruledef_t exp;
492
493         exp.flags = flags;
494         exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
495         exp.start = rvm_codegen_getcodesize(co->cg);
496         exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
497         exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
498         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
499         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
500         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
501         r_array_add(co->expressions, &exp);
502         return 0;
503 }
504
505
506 rint rpa_compiler_exp_end(rpa_compiler_t *co)
507 {
508         rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
509
510         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
511         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
512         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
513         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
514         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
515         rvm_codegen_redefinelabel(co->cg, exp.endidx);
516         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
517         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
518         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
519         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
520         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
521         rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
522         rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
523         return 0;
524 }
525
526
527 rint rpa_compiler_altexp_begin(rpa_compiler_t *co, ruint flags)
528 {
529         rpa_ruledef_t exp;
530
531         exp.flags = flags;
532         exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
533         exp.start = rvm_codegen_getcodesize(co->cg);
534         exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
535         exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
536         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
537         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
538
539         r_array_add(co->expressions, &exp);
540         return 0;
541 }
542
543
544 rint rpa_compiler_altexp_end(rpa_compiler_t *co)
545 {
546         rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
547
548         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
549         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
550         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
551         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
552         rvm_codegen_redefinelabel(co->cg, exp.endidx);
553         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
554         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
555
556         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
557         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
558
559         rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
560         rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
561         return 0;
562 }
563
564
565 rint rpa_compiler_branch_begin(rpa_compiler_t *co, ruint flags)
566 {
567         rpa_ruledef_t exp;
568
569         exp.flags = flags;
570         exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
571         exp.start = rvm_codegen_getcodesize(co->cg);
572         exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
573         exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
574         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
575         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
576         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
577
578         r_array_add(co->expressions, &exp);
579         return 0;
580 }
581
582
583 rint rpa_compiler_branch_end(rpa_compiler_t *co)
584 {
585         rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
586
587         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
588         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
589         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
590         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
591         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
592         rvm_codegen_redefinelabel(co->cg, exp.endidx);
593         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
594         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
595         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
596         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
597         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
598         rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
599         rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
600         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
601
602         return 0;
603 }
604
605
606 rint rpa_compiler_nonloopybranch_begin(rpa_compiler_t *co, ruint flags)
607 {
608         rpa_ruledef_t exp;
609
610         exp.flags = flags;
611         exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
612         exp.start = rvm_codegen_getcodesize(co->cg);
613         exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
614         exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
615         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
616         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
617         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
618         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R_LOO, DA, XX, 0));
619         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
620         r_array_add(co->expressions, &exp);
621         return 0;
622
623 }
624
625
626 rint rpa_compiler_nonloopybranch_end(rpa_compiler_t *co)
627 {
628         rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
629
630         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
631         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
632         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
633         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
634         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_LOO, R0, XX, 0));
635         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
636         rvm_codegen_redefinelabel(co->cg, exp.endidx);
637         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
638         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
639         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
640         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
641         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
642         rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
643         rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
644         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
645
646         return 0;
647 }
648
649
650 rint rpa_compiler_class_begin(rpa_compiler_t *co, ruint flags)
651 {
652         rpa_ruledef_t exp;
653
654         exp.flags = flags;
655         exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
656         exp.start = rvm_codegen_getcodesize(co->cg);
657         exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
658         exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
659         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
660         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
661
662         r_array_add(co->expressions, &exp);
663         return 0;
664 }
665
666
667 rint rpa_compiler_class_end(rpa_compiler_t *co)
668 {
669         rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
670
671         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
672         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
673         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
674         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
675         rvm_codegen_redefinelabel(co->cg, exp.endidx);
676         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
677         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
678         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
679         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
680
681         rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
682         rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
683         return 0;
684 }
685
686
687 rint rpa_compiler_notexp_begin(rpa_compiler_t *co, ruint flags)
688 {
689         rpa_ruledef_t exp;
690
691         exp.flags = flags;
692         exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
693         exp.start = rvm_codegen_getcodesize(co->cg);
694         exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
695         exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
696         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
697         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
698         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
699
700         r_array_add(co->expressions, &exp);
701         return 0;
702 }
703
704
705 rint rpa_compiler_notexp_end(rpa_compiler_t *co)
706 {
707         rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
708
709         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
710         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
711         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
712         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
713         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
714         rvm_codegen_redefinelabel(co->cg, exp.endidx);
715         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
716         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
717         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
718         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHSPCHR_NAN, DA, XX, XX, '.'));
719         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
720
721         rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
722         rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
723         return 0;
724 }
725
726
727 rint rpa_compiler_negexp_begin(rpa_compiler_t *co, ruint flags)
728 {
729         rpa_ruledef_t exp;
730
731         exp.flags = flags;
732         exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
733         exp.start = rvm_codegen_getcodesize(co->cg);
734         exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
735         exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
736         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
737         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
738         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
739
740         r_array_add(co->expressions, &exp);
741         return 0;
742
743 }
744
745
746 rint rpa_compiler_negexp_end(rpa_compiler_t *co)
747 {
748         rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
749
750         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
751         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
752         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
753         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
754         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
755         rvm_codegen_redefinelabel(co->cg, exp.endidx);
756         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
757         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
758         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
759         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHSPCHR_NAN, DA, XX, XX, '.'));
760         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
761         rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
762         rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
763         return 0;
764 }