RPA Toolkit
Fixed the hash function for the cache - one NOP instruction in the rpa_compiler_rule_...
[rpatk.git] / rpa2 / rpacompiler.c
1 #include "rmem.h"
2 #include "rpacompiler.h"
3 #include "rstring.h"
4
5 #define OPTIMIZE_MNODE_NAN 1
6
7 static rlong rpa_codegen_add_numlabel_s(rvm_codegen_t *cg, const rchar *alphaname, rlong numname)
8 {
9         rchar label[128];
10
11         r_memset(label, 0, sizeof(label));
12         r_snprintf(label, sizeof(label) - 1, "L%07ld__%s:", numname, alphaname);
13         return rvm_codegen_addlabel_s(cg, label);
14 }
15
16
17 static rlong rpa_codegen_invalid_add_numlabel_s(rvm_codegen_t *cg, const rchar *alphaname, rlong numname)
18 {
19         rchar label[128];
20
21         r_memset(label, 0, sizeof(label));
22         r_snprintf(label, sizeof(label) - 1, "L%07ld__%s:", numname, alphaname);
23         return rvm_codegen_invalid_addlabel_s(cg, label);
24 }
25
26
27 void rpa_compiler_index_reference_nan(rpa_compiler_t *co, rulong index)
28 {
29         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, index, rvm_asm(RVM_BL, DA, XX, XX, 0));
30 }
31
32
33 void rpa_compiler_reference_nan(rpa_compiler_t *co, const rchar *name, rsize_t namesize)
34 {
35         rpa_compiler_index_reference_nan(co, rvm_codemap_lookup(co->cg->codemap, name, namesize));
36 }
37
38
39 void rpa_compiler_reference_nan_s(rpa_compiler_t *co, const rchar *name)
40 {
41         rpa_compiler_reference_nan(co, name, r_strlen(name));
42 }
43
44
45 void rpa_compiler_index_reference_opt(rpa_compiler_t *co, rulong index)
46 {
47         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, index, rvm_asm(RVM_BL, DA, XX, XX, 0));
48         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOVS, R0, R0, XX, 0));
49         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 2));
50         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, 0));
51 }
52
53
54 void rpa_compiler_reference_opt(rpa_compiler_t *co, const rchar *name, rsize_t namesize)
55 {
56         rpa_compiler_index_reference_opt(co, rvm_codemap_lookup(co->cg->codemap, name, namesize));
57 }
58
59
60 void rpa_compiler_reference_opt_s(rpa_compiler_t *co, const rchar *name)
61 {
62         rpa_compiler_reference_opt(co, name, r_strlen(name));
63 }
64
65
66 void rpa_compiler_index_reference_mul(rpa_compiler_t *co, rulong index)
67 {
68         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
69         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, index, rvm_asm(RVM_BL, DA, XX, XX, 0));
70         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOVS, R0, R0, XX, 0));
71         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, -2));
72         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
73         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R0, 0));
74         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 2));
75         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
76 }
77
78
79 void rpa_compiler_reference_mul(rpa_compiler_t *co, const rchar *name, rsize_t namesize)
80 {
81         rpa_compiler_index_reference_mul(co, rvm_codemap_lookup(co->cg->codemap, name, namesize));
82
83 }
84
85
86 void rpa_compiler_reference_mul_s(rpa_compiler_t *co, const rchar *name)
87 {
88         rpa_compiler_reference_mul(co, name, r_strlen(name));
89 }
90
91
92 void rpa_compiler_index_reference_mop(rpa_compiler_t *co, rulong index)
93 {
94         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
95         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, index, rvm_asm(RVM_BL, DA, XX, XX, 0));
96         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOVS, R0, R0, XX, 0));
97         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, -2));
98         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
99         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R0, 0));
100         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 2));
101         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, 0));
102 }
103
104
105 void rpa_compiler_reference_mop(rpa_compiler_t *co, const rchar *name, rsize_t namesize)
106 {
107         rpa_compiler_index_reference_mop(co, rvm_codemap_lookup(co->cg->codemap, name, namesize));
108 }
109
110
111 void rpa_compiler_reference_mop_s(rpa_compiler_t *co, const rchar *name)
112 {
113         rpa_compiler_reference_mop(co, name, r_strlen(name));
114 }
115
116
117 void rpa_compiler_index_reference(rpa_compiler_t *co, rulong index, ruint qflag)
118 {
119         if (qflag == RPA_MATCH_OPTIONAL) {
120                 rpa_compiler_index_reference_opt(co, index);
121         } else if (qflag == RPA_MATCH_MULTIPLE) {
122                 rpa_compiler_index_reference_mul(co, index);
123         } else if (qflag == RPA_MATCH_MULTIOPT) {
124                 rpa_compiler_index_reference_mop(co, index);
125         } else {
126                 rpa_compiler_index_reference_nan(co, index);
127         }
128 }
129
130
131 void rpa_compiler_reference(rpa_compiler_t *co, const rchar *name, rsize_t namesize, ruint qflag)
132 {
133         rpa_compiler_index_reference(co, rvm_codemap_lookup(co->cg->codemap, name, namesize), qflag);
134 }
135
136
137 void rpa_compiler_reference_s(rpa_compiler_t *co, const rchar *name, ruint qflag)
138 {
139         rpa_compiler_reference(co, name, r_strlen(name), qflag);
140 }
141
142
143 rpa_compiler_t *rpa_compiler_create()
144 {
145         rpa_compiler_t *co;
146
147         co = (rpa_compiler_t *)r_malloc(sizeof(*co));
148         r_memset(co, 0, sizeof(*co));
149         co->cg = rvm_codegen_create();
150         co->scope = rvm_scope_create();
151         co->expressions = r_array_create(sizeof(rpa_ruledef_t));
152         co->ruleprefs = r_harray_create(sizeof(rpa_rulepref_t));
153         return co;
154 }
155
156
157 void rpa_compiler_destroy(rpa_compiler_t *co)
158 {
159         if (co) {
160                 rvm_codegen_destroy(co->cg);
161                 rvm_scope_destroy(co->scope);
162                 r_object_destroy((robject_t*)co->ruleprefs);
163                 r_object_destroy((robject_t*)co->expressions);
164                 r_free(co);
165         }
166 }
167
168
169 rpa_rulepref_t *rpa_compiler_rulepref_lookup(rpa_compiler_t *co, const rchar *name, ruint namesize)
170 {
171         rlong index = r_harray_lookup(co->ruleprefs, name, namesize);
172         if (index < 0)
173                 return NULL;
174         return (rpa_rulepref_t *)r_harray_slot(co->ruleprefs, index);
175 }
176
177
178 rpa_rulepref_t *rpa_compiler_rulepref_lookup_s(rpa_compiler_t *co, const rchar *name)
179 {
180         return rpa_compiler_rulepref_lookup(co, name, r_strlen(name));
181 }
182
183
184 rpa_rulepref_t *rpa_compiler_rulepref(rpa_compiler_t *co, const rchar *name, ruint namesize)
185 {
186         rlong index = r_harray_lookup(co->ruleprefs, name, namesize);
187         if (index < 0)
188                 index = r_harray_add(co->ruleprefs, name, namesize, NULL);
189         return (rpa_rulepref_t *)r_harray_slot(co->ruleprefs, index);
190 }
191
192
193 rpa_rulepref_t *rpa_compiler_rulepref_s(rpa_compiler_t *co, const rchar *name)
194 {
195         return rpa_compiler_rulepref(co, name, r_strlen(name));
196 }
197
198
199 void rpa_compiler_rulepref_set_ruleuid(rpa_compiler_t *co, const rchar *name, ruint namesize, rlong ruleuid)
200 {
201         rpa_rulepref_t *rulepref = rpa_compiler_rulepref(co, name, namesize);
202
203         R_ASSERT(rulepref);
204         rulepref->ruleuid = ruleuid;
205 }
206
207
208 void rpa_compiler_rulepref_set_ruleuid_s(rpa_compiler_t *co, const rchar *name, rlong ruleuid)
209 {
210         rpa_compiler_rulepref_set_ruleuid(co, name, r_strlen(name), ruleuid);
211 }
212
213
214 void rpa_compiler_rulepref_set_flag(rpa_compiler_t *co, const rchar *name, ruint namesize, rulong flag)
215 {
216         rpa_rulepref_t *rulepref = rpa_compiler_rulepref(co, name, namesize);
217
218         R_ASSERT(rulepref);
219         rulepref->flags |= flag;
220 }
221
222
223 void rpa_compiler_rulepref_set_flag_s(rpa_compiler_t *co, const rchar *name, rulong flag)
224 {
225         rpa_compiler_rulepref_set_flag(co, name, r_strlen(name), flag);
226 }
227
228
229 void rpa_compiler_rulepref_clear_flag(rpa_compiler_t *co, const rchar *name, ruint namesize, rulong flag)
230 {
231         rpa_rulepref_t *rulepref = rpa_compiler_rulepref(co, name, namesize);
232
233         R_ASSERT(rulepref);
234         rulepref->flags &= ~flag;
235 }
236
237
238 void rpa_compiler_rulepref_clear_flag_s(rpa_compiler_t *co, const rchar *name, rulong flag)
239 {
240         rpa_compiler_rulepref_clear_flag(co, name, r_strlen(name), flag);
241 }
242
243
244 void rpa_compiler_rulepref_set_ruleuid_flags(rpa_compiler_t *co, const rchar *name, ruint namesize, rlong ruleuid, rulong flags)
245 {
246         rpa_rulepref_t *rulepref = rpa_compiler_rulepref(co, name, namesize);
247
248         R_ASSERT(rulepref);
249         rulepref->ruleuid = ruleuid;
250         rulepref->flags = flags;
251 }
252
253
254 void rpa_compiler_rulepref_set_ruleuid_flags_s(rpa_compiler_t *co, const rchar *name, rlong ruleuid, rulong flags)
255 {
256         rpa_compiler_rulepref_set_ruleuid_flags(co, name, r_strlen(name), ruleuid, flags);
257 }
258
259
260 #define RPA_RULEBLOB_SIZE (RPA_RULENAME_MAXSIZE + sizeof(rpa_ruledata_t) + 2*sizeof(rulong))
261
262 rlong rpa_compiler_addblob(rpa_compiler_t *co, rlong ruleid, rlong ruleuid, rulong flags, const rchar *name, rulong namesize)
263 {
264         rchar blob[RPA_RULEBLOB_SIZE];
265         rchar *ptr;
266         rpa_ruledata_t *pblob = (rpa_ruledata_t *)blob;
267
268         if (namesize >= RPA_RULENAME_MAXSIZE)
269                 return -1;
270         r_memset(pblob, 0, RPA_RULEBLOB_SIZE);
271         ptr = blob + sizeof(rpa_ruledata_t);
272         pblob->name = ptr - blob;
273         pblob->ruleid = ruleid;
274         pblob->ruleuid = ruleuid;
275         pblob->flags = flags;
276         pblob->namesize = namesize;
277         r_strncpy(ptr, name, namesize);
278         ptr += namesize;
279         pblob->size = ptr - blob + 1;
280         return rvm_codegen_adddata_s(co->cg, NULL, pblob, pblob->size);
281 }
282
283
284 rlong rpa_compiler_addblob_s(rpa_compiler_t *co, rlong ruleid, rlong ruleuid, rulong flags, const rchar *name)
285 {
286         return 0;
287 }
288
289
290 rint rpa_compiler_loop_begin(rpa_compiler_t *co, const rchar *name, ruint namesize)
291 {
292         rpa_ruledef_t exp;
293         rlong ruleuid = RPA_RECORD_INVALID_UID;
294         rulong flags = 0;
295         rpa_rulepref_t *rulepref = rpa_compiler_rulepref_lookup(co, name, namesize);
296
297         if (rulepref) {
298                 flags = rulepref->flags;
299                 ruleuid = rulepref->ruleuid;
300         }
301
302         r_memset(&exp, 0, sizeof(exp));
303         exp.start = rvm_codegen_getcodesize(co->cg);
304         exp.startidx = rvm_codegen_addlabel(co->cg, name, namesize);
305         exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
306         exp.successidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__success", exp.start);
307         exp.failidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__fail", exp.start);
308         exp.againidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__again", exp.start);
309         exp.dataidx = rpa_compiler_addblob(co, exp.start, ruleuid, flags, name, namesize);
310
311         rvm_codegen_addins(co->cg, rvm_asm(RVM_CLR, R3, XX, XX, 0));
312         rvm_codegen_addins(co->cg, rvm_asm(RVM_CLR, R0, XX, XX, 0));
313         exp.loopidx = rpa_codegen_add_numlabel_s(co->cg, "__loop", exp.start);
314         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_REC)|BIT(R_LOO)|BIT(R_TOP)|BIT(LR)));
315         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
316         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_LOO, R3, XX, 0));
317         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
318
319         r_array_add(co->expressions, &exp);
320         return 0;
321 }
322
323
324 rint rpa_compiler_loop_begin_s(rpa_compiler_t *co, const rchar *name)
325 {
326         return rpa_compiler_loop_begin(co, name, r_strlen(name));
327 }
328
329
330 rint rpa_compiler_loop_end(rpa_compiler_t *co)
331 {
332         rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
333
334         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R3, R_LOO, XX, 0));         // Save LOO to R3 before restoring the old one
335         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));            // Pop the accumulated ret, although ignored here
336         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_LOO)|BIT(R_OTP)|BIT(LR)));
337         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R_OTP, 0));
338         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.failidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));  // ------------- R_TOP is the same
339         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITEND, DA, R_OTP, R0, 0));     //          |
340         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R3, R0, XX, 0));                                                                                            //          |
341         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_TOP, R_OTP, XX, 0));                                                                                      //          |
342         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.loopidx, rvm_asm(RVM_B, DA, XX, XX, 0));            //          |
343         rvm_codegen_redefinelabel(co->cg, exp.failidx);                                                                                 //          |
344         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_REC, R1, XX, 0));                 //        <-------------------------------------
345         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
346         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
347
348         /*
349          *  END FAILED:
350          */
351         rvm_codegen_redefinelabel(co->cg, exp.endidx);
352         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R3, R_LOO, XX, 0));         // Save LOO to R3 before restoring the old one
353         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
354         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_REC)|BIT(R_LOO)|BIT(R_TOP)|BIT(LR)));
355         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
356         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 3));
357         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
358         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
359         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, R_TOP, R_TOP, R3, 0));
360         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
361         return 0;
362 }
363
364
365 rint rpa_compiler_rule_begin(rpa_compiler_t *co, const rchar *name, ruint namesize)
366 {
367         rpa_ruledef_t exp;
368         rlong ruleuid = RPA_RECORD_INVALID_UID;
369         rulong flags = 0;
370         rpa_rulepref_t *rulepref = rpa_compiler_rulepref_lookup(co, name, namesize);
371
372         if (rulepref) {
373                 flags = rulepref->flags;
374                 ruleuid = rulepref->ruleuid;
375         }
376
377         r_memset(&exp, 0, sizeof(exp));
378         exp.start = rvm_codegen_getcodesize(co->cg);
379         exp.startidx = rvm_codegen_addlabel(co->cg, name, namesize);
380         exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
381         exp.dataidx = rpa_compiler_addblob(co, exp.start, ruleuid, flags, name, namesize);
382
383         rvm_codegen_addins(co->cg, rvm_asm(RPA_CHECKCACHE, DA, R_TOP, XX, exp.start));
384         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXGRE, LR, XX, XX, 0));
385         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
386         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
387         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
388         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
389
390         r_array_add(co->expressions, &exp);
391         return 0;
392 }
393
394
395 rint rpa_compiler_rule_begin_s(rpa_compiler_t *co, const rchar *name)
396 {
397         return rpa_compiler_rule_begin(co, name, r_strlen(name));
398 }
399
400
401 rint rpa_compiler_rule_end(rpa_compiler_t *co)
402 {
403         rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
404
405         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
406         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_OTP, XX, XX, 0));
407         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
408         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R_OTP, 0));
409         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 4));
410         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITEND, DA, R_OTP, R0, 0));
411         rvm_codegen_addins(co->cg, rvm_asml(RPA_SETCACHE, DA, R1, R_REC, exp.start));
412         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
413         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_REC, R1, XX, 0));
414         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
415         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
416         rvm_codegen_redefinelabel(co->cg, exp.endidx);
417         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
418         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
419         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
420 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
421         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
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 = rvm_codegen_addlabel(co->cg, name, namesize);
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 }