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