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 = 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)
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);
443 rvm_codegen_addins(co->cg, rvm_asm(RPA_CHECKCACHE, DA, R_TOP, XX, exp.start));
444 rvm_codegen_addins(co->cg, rvm_asm(RVM_BXNEQ, LR, XX, XX, 0));
445 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
446 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
447 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
448 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_EMITRECORD)) {
449 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
452 r_array_add(co->expressions, &exp);
457 int rpa_compiler_rule_begin_s(rpa_compiler_t *co, const char *name)
459 return rpa_compiler_rule_begin(co, name, r_strlen(name));
463 int rpa_compiler_rule_end(rpa_compiler_t *co)
465 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
467 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
468 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_OTP, XX, XX, 0));
469 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
470 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R_OTP, 0));
472 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_EMITRECORD)) {
473 rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 4));
474 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITEND, DA, R_OTP, R0, 0));
476 rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 3));
478 rvm_codegen_addins(co->cg, rvm_asml(RPA_SETCACHE, DA, R1, R_REC, exp.start));
479 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
480 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_REC, R1, XX, 0));
481 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
482 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_ABORTONFAIL)) {
483 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_ABORT, DA, R_OTP, R0, 0));
485 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
486 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
487 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
488 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
489 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
490 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_OTP, R_TOP, XX, 0));
491 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
492 rvm_codegen_addins(co->cg, rvm_asml(RPA_SETCACHE, DA, R_REC, R_REC, exp.start));
493 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_ABORTONFAIL)) {
494 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_ABORT, DA, R_OTP, R0, 0));
496 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
501 int rpa_compiler_inlinerule_begin(rpa_compiler_t *co, const char *name, unsigned int namesize, unsigned int flags)
506 unsigned long ruleflags = 0;
508 r_memset(&exp, 0, sizeof(exp));
509 exp.rulepref = rpa_compiler_rulepref_lookup(co, name, namesize);
511 ruleflags = exp.rulepref->flags;
512 ruleuid = exp.rulepref->ruleuid;
513 ruleid = exp.rulepref->ruleid;
516 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
517 exp.start = rvm_codegen_getcodesize(co->cg);
518 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__inlined", exp.start);
519 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
520 exp.dataidx = rpa_compiler_addblob(co, ruleid, ruleuid, ruleflags, name, namesize);
522 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
523 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
524 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
525 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_EMITRECORD)) {
526 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
528 r_array_add(co->expressions, &exp);
533 int rpa_compiler_inlinerule_begin_s(rpa_compiler_t *co, const char *name, unsigned int flags)
535 return rpa_compiler_inlinerule_begin(co, name, r_strlen(name), flags);
539 int rpa_compiler_inlinerule_end(rpa_compiler_t *co)
541 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
543 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
544 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_OTP, XX, XX, 0));
545 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
546 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R_OTP, 0));
547 if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_EMITRECORD)) {
548 rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 3));
549 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_EMITEND, DA, R_OTP, R0, 0));
551 rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 2));
553 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
554 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_REC, R1, XX, 0));
555 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
556 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
557 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
558 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
559 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
560 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
561 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
562 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
563 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
564 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
570 int rpa_compiler_exp_begin(rpa_compiler_t *co, unsigned int flags)
575 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
576 exp.start = rvm_codegen_getcodesize(co->cg);
577 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
578 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
579 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
580 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
581 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
582 r_array_add(co->expressions, &exp);
587 int rpa_compiler_exp_end(rpa_compiler_t *co)
589 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
591 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
592 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
593 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
594 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
595 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
596 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
597 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
598 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
599 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
600 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
601 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
602 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
603 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
608 int rpa_compiler_altexp_begin(rpa_compiler_t *co, unsigned int flags)
613 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
614 exp.start = rvm_codegen_getcodesize(co->cg);
615 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
616 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
617 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
618 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
620 r_array_add(co->expressions, &exp);
625 int rpa_compiler_altexp_end(rpa_compiler_t *co)
627 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
629 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
630 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
631 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
632 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
633 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
634 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
635 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
637 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
638 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
640 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
641 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
646 int rpa_compiler_branch_begin(rpa_compiler_t *co, unsigned int flags)
651 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
652 exp.start = rvm_codegen_getcodesize(co->cg);
653 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
654 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
655 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
656 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
657 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
659 r_array_add(co->expressions, &exp);
664 int rpa_compiler_branch_end(rpa_compiler_t *co)
666 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
668 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
669 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
670 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
671 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
672 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
673 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
674 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
675 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
676 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
677 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
678 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
679 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
680 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
681 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
687 int rpa_compiler_nonloopybranch_begin(rpa_compiler_t *co, unsigned int 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 rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R_LOO, DA, XX, 0));
700 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
701 r_array_add(co->expressions, &exp);
707 int rpa_compiler_nonloopybranch_end(rpa_compiler_t *co)
709 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
711 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
712 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
713 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
714 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
715 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_LOO, R0, XX, 0));
716 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
717 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
718 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
719 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
720 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
721 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
722 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
723 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
724 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
725 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
731 int rpa_compiler_class_begin(rpa_compiler_t *co, unsigned int flags)
736 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
737 exp.start = rvm_codegen_getcodesize(co->cg);
738 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
739 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
740 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
741 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
743 r_array_add(co->expressions, &exp);
748 int rpa_compiler_class_end(rpa_compiler_t *co)
750 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
752 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
753 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
754 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
755 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
756 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
757 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
758 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
759 rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
760 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
762 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
763 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
768 int rpa_compiler_notexp_begin(rpa_compiler_t *co, unsigned int flags)
773 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
774 exp.start = rvm_codegen_getcodesize(co->cg);
775 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
776 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
777 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
778 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
779 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
781 r_array_add(co->expressions, &exp);
786 int rpa_compiler_notexp_end(rpa_compiler_t *co)
788 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
790 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
791 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
792 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
793 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
794 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
795 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
796 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
797 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
798 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
799 rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHSPCHR_NAN, DA, XX, XX, '.'));
800 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
802 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
803 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));
808 int rpa_compiler_negexp_begin(rpa_compiler_t *co, unsigned int flags)
813 exp.branch = rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));
814 exp.start = rvm_codegen_getcodesize(co->cg);
815 exp.startidx = rpa_codegen_add_numlabel_s(co->cg, "__begin", exp.start);
816 exp.endidx = rpa_codegen_invalid_add_numlabel_s(co->cg, "__end", exp.start);
817 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_REC, XX, XX, 0));
818 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R_TOP, XX, XX, 0));
819 rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
821 r_array_add(co->expressions, &exp);
827 int rpa_compiler_negexp_end(rpa_compiler_t *co)
829 rpa_ruledef_t exp = r_array_pop(co->expressions, rpa_ruledef_t);
831 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
832 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
833 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_REC, XX, XX, 0));
834 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
835 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
836 rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
837 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
838 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R_TOP, XX, XX, 0));
839 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R0, XX, XX, 0));
840 rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHSPCHR_NAN, DA, XX, XX, '.'));
841 rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
842 rvm_codegen_replaceins(co->cg, exp.branch, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - exp.branch));
843 rpa_compiler_index_reference(co, exp.startidx, (exp.flags & RPA_MATCH_MASK));