2 * Regular Pattern Analyzer (RPA)
3 * Copyright (c) 2009-2010 Martin Stoilov
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * Martin Stoilov <martin@rpasearch.com>
21 #include "rlib/rmem.h"
22 #include "rpa/rpacompiler.h"
23 #include "rlib/rstring.h"
26 static long rpa_codegen_add_numlabel_s(rvm_codegen_t *cg, const char *alphaname, long numname)
30 * The alphaname and numname, might be used for
31 * debugging at some point, but not used for now
35 r_memset(label, 0, sizeof(label));
36 r_snprintf(label, sizeof(label) - 1, "L%07ld__%s:", numname, alphaname);
37 return rvm_codegen_addlabel_default_s(cg, label);
39 return rvm_codegen_addlabel_default_s(cg, NULL);
44 static long rpa_codegen_invalid_add_numlabel_s(rvm_codegen_t *cg, const char *alphaname, long numname)
48 * The alphaname and numname, might be used for
49 * debugging at some point, but not used for now
53 r_memset(label, 0, sizeof(label));
54 r_snprintf(label, sizeof(label) - 1, "L%07ld__%s:", numname, alphaname);
55 return rvm_codegen_invalid_addlabel_s(cg, label);
57 return rvm_codegen_invalid_addlabel_s(cg, NULL);
62 void rpa_compiler_index_reference_nan(rpa_compiler_t *co, unsigned long index)
64 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, index, rvm_asm(RVM_BL, DA, XX, XX, 0));
68 void rpa_compiler_reference_nan(rpa_compiler_t *co, const char *name, rsize_t namesize)
70 rpa_compiler_index_reference_nan(co, rvm_codemap_lookupadd(co->cg->codemap, name, namesize));
74 void rpa_compiler_reference_nan_s(rpa_compiler_t *co, const char *name)
76 rpa_compiler_reference_nan(co, name, r_strlen(name));
80 void rpa_compiler_index_reference_opt(rpa_compiler_t *co, unsigned long index)
82 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, index, rvm_asm(RVM_BL, DA, XX, XX, 0));
83 rvm_codegen_addins(co->cg, rvm_asml(RVM_MOVS, R0, R0, XX, 0));
84 rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 2));
85 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, 0));
89 void rpa_compiler_reference_opt(rpa_compiler_t *co, const char *name, rsize_t namesize)
91 rpa_compiler_index_reference_opt(co, rvm_codemap_lookupadd(co->cg->codemap, name, namesize));
95 void rpa_compiler_reference_opt_s(rpa_compiler_t *co, const char *name)
97 rpa_compiler_reference_opt(co, name, r_strlen(name));
101 void rpa_compiler_index_reference_mul(rpa_compiler_t *co, unsigned long index)
103 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
104 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, index, rvm_asm(RVM_BL, DA, XX, XX, 0));
105 rvm_codegen_addins(co->cg, rvm_asml(RVM_MOVS, R0, R0, XX, 0));
106 rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, -2));
107 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
108 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R0, 0));
109 rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 2));
110 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
114 void rpa_compiler_reference_mul(rpa_compiler_t *co, const char *name, rsize_t namesize)
116 rpa_compiler_index_reference_mul(co, rvm_codemap_lookupadd(co->cg->codemap, name, namesize));
121 void rpa_compiler_reference_mul_s(rpa_compiler_t *co, const char *name)
123 rpa_compiler_reference_mul(co, name, r_strlen(name));
127 void rpa_compiler_index_reference_mop(rpa_compiler_t *co, unsigned long index)
129 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
130 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, index, rvm_asm(RVM_BL, DA, XX, XX, 0));
131 rvm_codegen_addins(co->cg, rvm_asml(RVM_MOVS, R0, R0, XX, 0));
132 rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, -2));
133 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
134 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R0, 0));
135 rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 2));
136 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, 0));
140 void rpa_compiler_reference_mop(rpa_compiler_t *co, const char *name, rsize_t namesize)
142 rpa_compiler_index_reference_mop(co, rvm_codemap_lookupadd(co->cg->codemap, name, namesize));
146 void rpa_compiler_reference_mop_s(rpa_compiler_t *co, const char *name)
148 rpa_compiler_reference_mop(co, name, r_strlen(name));
152 void rpa_compiler_index_reference(rpa_compiler_t *co, unsigned long index, unsigned int qflag)
154 if (qflag == RPA_MATCH_OPTIONAL) {
155 rpa_compiler_index_reference_opt(co, index);
156 } else if (qflag == RPA_MATCH_MULTIPLE) {
157 rpa_compiler_index_reference_mul(co, index);
158 } else if (qflag == RPA_MATCH_MULTIOPT) {
159 rpa_compiler_index_reference_mop(co, index);
161 rpa_compiler_index_reference_nan(co, index);
166 void rpa_compiler_reference(rpa_compiler_t *co, const char *name, rsize_t namesize, unsigned int qflag)
168 rpa_compiler_index_reference(co, rvm_codemap_lookupadd(co->cg->codemap, name, namesize), qflag);
172 void rpa_compiler_reference_s(rpa_compiler_t *co, const char *name, unsigned int qflag)
174 rpa_compiler_reference(co, name, r_strlen(name), qflag);
178 rpa_compiler_t *rpa_compiler_create()
182 co = (rpa_compiler_t *)r_malloc(sizeof(*co));
183 r_memset(co, 0, sizeof(*co));
184 co->cg = rvm_codegen_create();
185 co->scope = rvm_scope_create();
186 co->expressions = r_array_create(sizeof(rpa_ruledef_t));
187 co->ruleprefs = r_harray_create(sizeof(rpa_rulepref_t));
192 void rpa_compiler_destroy(rpa_compiler_t *co)
195 rvm_codegen_destroy(co->cg);
196 rvm_scope_destroy(co->scope);
197 r_object_destroy((robject_t*)co->ruleprefs);
198 r_object_destroy((robject_t*)co->expressions);
204 rpa_rulepref_t *rpa_compiler_rulepref_lookup(rpa_compiler_t *co, const char *name, unsigned int namesize)
206 long index = r_harray_lookup(co->ruleprefs, name, namesize);
209 return (rpa_rulepref_t *)r_harray_slot(co->ruleprefs, index);
213 rpa_rulepref_t *rpa_compiler_rulepref_lookup_s(rpa_compiler_t *co, const char *name)
215 return rpa_compiler_rulepref_lookup(co, name, r_strlen(name));
219 rpa_rulepref_t *rpa_compiler_rulepref(rpa_compiler_t *co, const char *name, unsigned int namesize)
221 long index = r_harray_lookup(co->ruleprefs, name, namesize);
223 index = r_harray_add(co->ruleprefs, name, namesize, NULL);
224 return (rpa_rulepref_t *)r_harray_slot(co->ruleprefs, index);
228 rpa_rulepref_t *rpa_compiler_rulepref_s(rpa_compiler_t *co, const char *name)
230 return rpa_compiler_rulepref(co, name, r_strlen(name));
234 void rpa_compiler_rulepref_set_ruleid(rpa_compiler_t *co, const char *name, unsigned int namesize, long ruleid)
236 rpa_rulepref_t *rulepref = rpa_compiler_rulepref(co, name, namesize);
239 rulepref->ruleid = ruleid;
243 void rpa_compiler_rulepref_set_ruleid_s(rpa_compiler_t *co, const char *name, long ruleid)
245 rpa_compiler_rulepref_set_ruleid(co, name, r_strlen(name), ruleid);
249 void rpa_compiler_rulepref_set_ruleuid(rpa_compiler_t *co, const char *name, unsigned int namesize, long ruleuid)
251 rpa_rulepref_t *rulepref = rpa_compiler_rulepref(co, name, namesize);
254 rulepref->ruleuid = ruleuid;
258 void rpa_compiler_rulepref_set_ruleuid_s(rpa_compiler_t *co, const char *name, long ruleuid)
260 rpa_compiler_rulepref_set_ruleuid(co, name, r_strlen(name), ruleuid);
264 void rpa_compiler_rulepref_set_flag(rpa_compiler_t *co, const char *name, unsigned int namesize, unsigned long flag)
266 rpa_rulepref_t *rulepref = rpa_compiler_rulepref(co, name, namesize);
269 rulepref->flags |= flag;
273 void rpa_compiler_rulepref_set_flag_s(rpa_compiler_t *co, const char *name, unsigned long flag)
275 rpa_compiler_rulepref_set_flag(co, name, r_strlen(name), flag);
279 void rpa_compiler_rulepref_clear_flag(rpa_compiler_t *co, const char *name, unsigned int namesize, unsigned long flag)
281 rpa_rulepref_t *rulepref = rpa_compiler_rulepref(co, name, namesize);
284 rulepref->flags &= ~flag;
288 void rpa_compiler_rulepref_clear_flag_s(rpa_compiler_t *co, const char *name, unsigned long flag)
290 rpa_compiler_rulepref_clear_flag(co, name, r_strlen(name), flag);
294 void rpa_compiler_rulepref_set(rpa_compiler_t *co, const char *name, unsigned int namesize, long ruleid, long ruleuid, unsigned long flags)
296 rpa_rulepref_t *rulepref = rpa_compiler_rulepref(co, name, namesize);
299 rulepref->ruleid = ruleid;
300 rulepref->ruleuid = ruleuid;
301 rulepref->flags = flags;
305 void rpa_compiler_rulepref_set_s(rpa_compiler_t *co, const char *name, long ruleid, long ruleuid, unsigned long flags)
307 rpa_compiler_rulepref_set(co, name, r_strlen(name), ruleid, ruleuid, flags);
311 #define RPA_RULEBLOB_SIZE (RPA_RULENAME_MAXSIZE + sizeof(rpa_ruledata_t) + 2*sizeof(unsigned long))
313 long rpa_compiler_addblob(rpa_compiler_t *co, long ruleid, long ruleuid, unsigned long flags, const char *name, unsigned long namesize)
315 char blob[RPA_RULEBLOB_SIZE];
317 rpa_ruledata_t *pblob = (rpa_ruledata_t *)blob;
319 if (namesize >= RPA_RULENAME_MAXSIZE)
321 r_memset(pblob, 0, RPA_RULEBLOB_SIZE);
322 ptr = blob + sizeof(rpa_ruledata_t);
323 pblob->name = ptr - blob;
324 pblob->ruleid = ruleid;
325 pblob->ruleuid = ruleuid;
326 pblob->flags = flags;
327 pblob->namesize = namesize;
328 r_strncpy(ptr, name, namesize);
330 pblob->size = (long)(ptr - blob + 1);
331 return rvm_codegen_adddata_s(co->cg, NULL, pblob, pblob->size);
335 long rpa_compiler_addblob_s(rpa_compiler_t *co, long ruleid, long ruleuid, unsigned long flags, const char *name)
341 int rpa_compiler_loop_begin(rpa_compiler_t *co, const char *name, unsigned int namesize)
346 unsigned long flags = 0;
348 r_memset(&exp, 0, sizeof(exp));
349 exp.rulepref = rpa_compiler_rulepref_lookup(co, name, namesize);
351 flags = exp.rulepref->flags;
352 ruleuid = exp.rulepref->ruleuid;
353 ruleid = exp.rulepref->ruleid;
355 exp.start = rvm_codegen_getcodesize(co->cg);
356 exp.startidx = rvm_codegen_addlabel_default(co->cg, name, namesize);
357 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
358 exp.successidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__success", exp.start);
359 exp.failidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__fail", exp.start);
360 exp.againidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__again", exp.start);
361 exp.dataidx = rpa_compiler_addblob(co, ruleid, ruleuid, flags, name, namesize);
363 rvm_codegen_addins(co->cg, rvm_asm(RVM_CLR, R3, XX, XX, 0));
364 rvm_codegen_addins(co->cg, rvm_asm(RVM_CLR, R0, XX, XX, 0));
365 exp.loopidx = rpa_codegen_add_numlabel_s(co->cg, "__loop", exp.start);
366 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_REC)|BIT(R_LOO)|BIT(R_TOP)|BIT(LR)));
367 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
368 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_LOO, R3, XX, 0));
369 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_EMITRECORD)) {
370 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
372 r_array_add(co->expressions, &exp);
377 int rpa_compiler_loop_begin_s(rpa_compiler_t *co, const char *name)
379 return rpa_compiler_loop_begin(co, name, r_strlen(name));
383 int rpa_compiler_loop_end(rpa_compiler_t *co)
385 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
387 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R3, R_LOO, XX, 0)); // Save LOO to R3 before restoring the old one
388 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0)); // Pop the accumulated ret, although ignored here
389 rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_LOO)|BIT(R_OTP)|BIT(LR)));
390 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R_OTP, 0));
391 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.failidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0)); // ------------- R_TOP is the same
392 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_EMITRECORD)) { // |
393 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITEND, DA, R_OTP, R0, 0)); // |
395 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R3, R0, XX, 0)); // |
396 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_TOP, R_OTP, XX, 0)); // |
397 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.loopidx, rvm_asm(RVM_B, DA, XX, XX, 0)); // |
398 rvm_codegen_redefinelabel_default(co->cg, exp.failidx); // |
399 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_REC, R1, XX, 0)); // <-------------------------------------
400 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
401 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
406 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
407 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R3, R_LOO, XX, 0)); // Save LOO to R3 before restoring the old one
408 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
409 rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_REC)|BIT(R_LOO)|BIT(R_TOP)|BIT(LR)));
410 rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
411 rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 3));
412 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
413 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_ABORTONFAIL)) {
414 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_ABORT, DA, R_OTP, R0, 0));
416 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
418 rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, R_TOP, R_TOP, R3, 0));
419 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
424 int rpa_compiler_rule_begin(rpa_compiler_t *co, const char *name, unsigned int namesize, rpabitmap_t bitmap)
429 unsigned long flags = 0;
431 r_memset(&exp, 0, sizeof(exp));
432 exp.rulepref = rpa_compiler_rulepref_lookup(co, name, namesize);
434 flags = exp.rulepref->flags;
435 ruleuid = exp.rulepref->ruleuid;
436 ruleid = exp.rulepref->ruleid;
438 exp.start = rvm_codegen_getcodesize(co->cg);
439 exp.startidx = rvm_codegen_addlabel_default(co->cg, name, namesize);
440 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
441 exp.dataidx = rpa_compiler_addblob(co, ruleid, ruleuid, flags, name, namesize);
444 rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHBITMAP, DA, XX, XX, exp.bitmap));
445 rvm_codegen_addins(co->cg, rvm_asm(RVM_BXLES, LR, XX, XX, 0));
447 rvm_codegen_addins(co->cg, rvm_asm(RPA_CHECKCACHE, DA, R_TOP, XX, exp.start));
448 rvm_codegen_addins(co->cg, rvm_asm(RVM_BXNEQ, LR, XX, XX, 0));
449 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
450 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
451 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
452 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_EMITRECORD)) {
453 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
456 r_array_add(co->expressions, &exp);
461 int rpa_compiler_rule_begin_s(rpa_compiler_t *co, const char *name, rpabitmap_t bitmap)
463 return rpa_compiler_rule_begin(co, name, r_strlen(name), bitmap);
467 int rpa_compiler_rule_end(rpa_compiler_t *co)
469 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
471 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
472 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_OTP, XX, XX, 0));
473 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
474 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R_OTP, 0));
476 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_EMITRECORD)) {
477 rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 4));
478 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITEND, DA, R_OTP, R0, 0));
480 rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 3));
482 rvm_codegen_addins(co->cg, rvm_asml(RPA_SETCACHE, DA, R1, R_REC, exp.start));
483 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
484 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_REC, R1, XX, 0));
485 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
486 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_ABORTONFAIL)) {
487 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_ABORT, DA, R_OTP, R0, 0));
489 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
490 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
491 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
492 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
493 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
494 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_OTP, R_TOP, XX, 0));
495 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
496 rvm_codegen_addins(co->cg, rvm_asml(RPA_SETCACHE, DA, R_REC, R_REC, exp.start));
497 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_ABORTONFAIL)) {
498 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_ABORT, DA, R_OTP, R0, 0));
500 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
505 int rpa_compiler_inlinerule_begin(rpa_compiler_t *co, const char *name, unsigned int namesize, unsigned int flags)
510 unsigned long ruleflags = 0;
512 r_memset(&exp, 0, sizeof(exp));
513 exp.rulepref = rpa_compiler_rulepref_lookup(co, name, namesize);
515 ruleflags = exp.rulepref->flags;
516 ruleuid = exp.rulepref->ruleuid;
517 ruleid = exp.rulepref->ruleid;
520 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
521 exp.start = rvm_codegen_getcodesize(co->cg);
522 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__inlined", exp.start);
523 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
524 exp.dataidx = rpa_compiler_addblob(co, ruleid, ruleuid, ruleflags, name, namesize);
526 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
527 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
528 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
529 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_EMITRECORD)) {
530 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
532 r_array_add(co->expressions, &exp);
537 int rpa_compiler_inlinerule_begin_s(rpa_compiler_t *co, const char *name, unsigned int flags)
539 return rpa_compiler_inlinerule_begin(co, name, r_strlen(name), flags);
543 int rpa_compiler_inlinerule_end(rpa_compiler_t *co)
545 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
547 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
548 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_OTP, XX, XX, 0));
549 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
550 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R_OTP, 0));
551 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_EMITRECORD)) {
552 rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 3));
553 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITEND, DA, R_OTP, R0, 0));
555 rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 2));
557 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
558 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_REC, R1, XX, 0));
559 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
560 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
561 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
562 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
563 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
564 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
565 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
566 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
567 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
568 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
574 int rpa_compiler_exp_begin(rpa_compiler_t *co, unsigned int flags, rpabitmap_t bitmap)
579 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
580 exp.start = rvm_codegen_getcodesize(co->cg);
581 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
582 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
585 rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHBITMAP, DA, XX, XX, exp.bitmap));
586 rvm_codegen_addins(co->cg, rvm_asm(RVM_BXLES, LR, XX, XX, 0));
588 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
589 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
590 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
591 r_array_add(co->expressions, &exp);
596 int rpa_compiler_exp_end(rpa_compiler_t *co)
598 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
600 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
601 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
602 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
603 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
604 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
605 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
606 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
607 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
608 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
609 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
610 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
611 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
612 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
617 int rpa_compiler_altexp_begin(rpa_compiler_t *co, unsigned int flags, rpabitmap_t bitmap)
623 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
624 exp.start = rvm_codegen_getcodesize(co->cg);
625 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
626 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
629 rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHBITMAP, DA, XX, XX, exp.bitmap));
630 rvm_codegen_addins(co->cg, rvm_asm(RVM_BXLES, LR, XX, XX, 0));
632 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
633 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
635 r_array_add(co->expressions, &exp);
640 int rpa_compiler_altexp_end(rpa_compiler_t *co)
642 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
644 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
645 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
646 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
647 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
648 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
649 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
650 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
651 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
652 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
654 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
655 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
656 // rvm_codegen_addins(co->cg, rvm_asm(RPA_VERIFYBITMAP, DA, XX, XX, exp.bitmap));
661 int rpa_compiler_branch_begin(rpa_compiler_t *co, unsigned int flags, rpabitmap_t bitmap)
666 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
667 exp.start = rvm_codegen_getcodesize(co->cg);
668 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
669 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
672 rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHBITMAP, DA, XX, XX, exp.bitmap));
673 rvm_codegen_addins(co->cg, rvm_asm(RVM_BXLES, LR, XX, XX, 0));
675 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
676 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
677 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
679 r_array_add(co->expressions, &exp);
684 int rpa_compiler_branch_end(rpa_compiler_t *co)
686 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
688 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
689 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
690 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
691 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
692 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
693 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
694 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
695 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
696 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
697 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
698 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
699 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
700 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
701 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
707 int rpa_compiler_nonloopybranch_begin(rpa_compiler_t *co, unsigned int flags)
712 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
713 exp.start = rvm_codegen_getcodesize(co->cg);
714 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
715 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
716 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
717 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
718 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
719 rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R_LOO, DA, XX, 0));
720 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
721 r_array_add(co->expressions, &exp);
727 int rpa_compiler_nonloopybranch_end(rpa_compiler_t *co)
729 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
731 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
732 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
733 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
734 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
735 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_LOO, R0, XX, 0));
736 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
737 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
738 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
739 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
740 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
741 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
742 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
743 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
744 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
745 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
751 int rpa_compiler_class_begin(rpa_compiler_t *co, unsigned int flags)
756 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
757 exp.start = rvm_codegen_getcodesize(co->cg);
758 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
759 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
760 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
761 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
763 r_array_add(co->expressions, &exp);
768 int rpa_compiler_class_end(rpa_compiler_t *co)
770 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
772 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
773 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
774 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
775 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
776 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
777 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
778 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
779 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
780 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
782 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
783 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
788 int rpa_compiler_notexp_begin(rpa_compiler_t *co, unsigned int flags)
793 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
794 exp.start = rvm_codegen_getcodesize(co->cg);
795 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
796 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
797 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
798 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
799 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
801 r_array_add(co->expressions, &exp);
806 int rpa_compiler_notexp_end(rpa_compiler_t *co)
808 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
810 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
811 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
812 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
813 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
814 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
815 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
816 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
817 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
818 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
819 rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHSPCHR_NAN, DA, XX, XX, '.'));
820 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
822 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
823 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
828 int rpa_compiler_negexp_begin(rpa_compiler_t *co, unsigned int flags)
833 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
834 exp.start = rvm_codegen_getcodesize(co->cg);
835 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
836 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
837 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
838 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
839 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
841 r_array_add(co->expressions, &exp);
847 int rpa_compiler_negexp_end(rpa_compiler_t *co)
849 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
851 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
852 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
853 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
854 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
855 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
856 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
857 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
858 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
859 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
860 rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHSPCHR_NAN, DA, XX, XX, '.'));
861 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
862 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
863 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));