mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-05-02 07:42:50 -06:00
a partial support for def rules in the C runtime
The def rules are now compiled to byte code by the compiler and then to native code by the JIT compiler in the runtime. Not all constructions are implemented yet. The partial implementation is now in the repository but it is not activated by default since this requires changes in the PGF format. I will enable it only after it is complete.
This commit is contained in:
@@ -1,23 +1,22 @@
|
||||
#include <gu/seq.h>
|
||||
#include <gu/file.h>
|
||||
#include <pgf/data.h>
|
||||
#include <pgf/jit.h>
|
||||
#include <pgf/reasoner.h>
|
||||
#include <pgf/evaluator.h>
|
||||
#include <pgf/reader.h>
|
||||
#include "lightning.h"
|
||||
|
||||
//#define PGF_JIT_DEBUG
|
||||
|
||||
|
||||
struct PgfJitState {
|
||||
GuPool* tmp_pool;
|
||||
GuPool* pool;
|
||||
jit_state jit;
|
||||
jit_insn *buf;
|
||||
char *save_ip_ptr;
|
||||
GuBuf* patches;
|
||||
};
|
||||
|
||||
#define _jit (state->jit)
|
||||
#define _jit (rdr->jit_state->jit)
|
||||
|
||||
typedef struct {
|
||||
PgfCId cid;
|
||||
@@ -27,7 +26,7 @@ typedef struct {
|
||||
// Between two calls to pgf_jit_make_space we are not allowed
|
||||
// to emit more that JIT_CODE_WINDOW bytes. This is not quite
|
||||
// safe but this is how GNU lightning is designed.
|
||||
#define JIT_CODE_WINDOW 128
|
||||
#define JIT_CODE_WINDOW 1280
|
||||
|
||||
typedef struct {
|
||||
GuFinalizer fin;
|
||||
@@ -42,7 +41,7 @@ pgf_jit_finalize_page(GuFinalizer* self)
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_jit_alloc_page(PgfJitState* state)
|
||||
pgf_jit_alloc_page(PgfReader* rdr)
|
||||
{
|
||||
void *page;
|
||||
|
||||
@@ -58,46 +57,63 @@ pgf_jit_alloc_page(PgfJitState* state)
|
||||
gu_fatal("Memory allocation failed");
|
||||
}
|
||||
|
||||
PgfPageFinalizer* fin = gu_new(PgfPageFinalizer, state->pool);
|
||||
PgfPageFinalizer* fin =
|
||||
gu_new(PgfPageFinalizer, rdr->opool);
|
||||
fin->fin.fn = pgf_jit_finalize_page;
|
||||
fin->page = page;
|
||||
gu_pool_finally(state->pool, &fin->fin);
|
||||
gu_pool_finally(rdr->opool, &fin->fin);
|
||||
|
||||
state->buf = page;
|
||||
jit_set_ip(state->buf);
|
||||
rdr->jit_state->buf = page;
|
||||
jit_set_ip(rdr->jit_state->buf);
|
||||
}
|
||||
|
||||
PgfJitState*
|
||||
pgf_jit_init(GuPool* tmp_pool, GuPool* pool)
|
||||
pgf_new_jit(PgfReader* rdr)
|
||||
{
|
||||
PgfJitState* state = gu_new(PgfJitState, tmp_pool);
|
||||
state->tmp_pool = tmp_pool;
|
||||
state->pool = pool;
|
||||
state->patches = gu_new_buf(PgfCallPatch, tmp_pool);
|
||||
|
||||
pgf_jit_alloc_page(state);
|
||||
state->save_ip_ptr = jit_get_ip().ptr;
|
||||
|
||||
PgfJitState* state = gu_new(PgfJitState, rdr->tmp_pool);
|
||||
state->patches = gu_new_buf(PgfCallPatch, rdr->tmp_pool);
|
||||
state->buf = NULL;
|
||||
state->save_ip_ptr = NULL;
|
||||
return state;
|
||||
}
|
||||
|
||||
static void
|
||||
pgf_jit_make_space(PgfJitState* state)
|
||||
pgf_jit_make_space(PgfReader* rdr)
|
||||
{
|
||||
assert (state->save_ip_ptr + JIT_CODE_WINDOW > jit_get_ip().ptr);
|
||||
|
||||
size_t page_size = getpagesize();
|
||||
if (jit_get_ip().ptr + JIT_CODE_WINDOW > ((char*) state->buf) + page_size) {
|
||||
jit_flush_code(state->buf, jit_get_ip().ptr);
|
||||
pgf_jit_alloc_page(state);
|
||||
if (rdr->jit_state->buf == NULL) {
|
||||
pgf_jit_alloc_page(rdr);
|
||||
} else {
|
||||
assert (rdr->jit_state->save_ip_ptr + JIT_CODE_WINDOW > jit_get_ip().ptr);
|
||||
|
||||
if (jit_get_ip().ptr + JIT_CODE_WINDOW > ((char*) rdr->jit_state->buf) + page_size) {
|
||||
jit_flush_code(rdr->jit_state->buf, jit_get_ip().ptr);
|
||||
pgf_jit_alloc_page(rdr);
|
||||
}
|
||||
}
|
||||
|
||||
rdr->jit_state->save_ip_ptr = jit_get_ip().ptr;
|
||||
}
|
||||
|
||||
static PgfAbsFun*
|
||||
pgf_jit_read_absfun(PgfReader* rdr, PgfAbstr* abstr)
|
||||
{
|
||||
gu_in_f64be(rdr->in, rdr->err); // ignore
|
||||
gu_return_on_exn(rdr->err, NULL);
|
||||
|
||||
PgfCId name = pgf_read_cid(rdr, rdr->tmp_pool);
|
||||
gu_return_on_exn(rdr->err, NULL);
|
||||
|
||||
state->save_ip_ptr = jit_get_ip().ptr;
|
||||
PgfAbsFun* absfun =
|
||||
gu_map_get(abstr->funs, name, PgfAbsFun*);
|
||||
assert(absfun != NULL);
|
||||
|
||||
return absfun;
|
||||
}
|
||||
|
||||
void
|
||||
pgf_jit_predicate(PgfJitState* state, PgfCIdMap* abscats,
|
||||
PgfAbsCat* abscat, GuBuf* functions)
|
||||
pgf_jit_predicate(PgfReader* rdr, PgfAbstr* abstr,
|
||||
PgfAbsCat* abscat)
|
||||
{
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
GuPool* tmp_pool = gu_new_pool();
|
||||
@@ -110,21 +126,24 @@ pgf_jit_predicate(PgfJitState* state, PgfCIdMap* abscats,
|
||||
int label = 0;
|
||||
#endif
|
||||
|
||||
size_t n_funs = gu_buf_length(functions);
|
||||
|
||||
pgf_jit_make_space(state);
|
||||
size_t n_funs = pgf_read_len(rdr);
|
||||
gu_return_on_exn(rdr->err, );
|
||||
|
||||
pgf_jit_make_space(rdr);
|
||||
|
||||
abscat->predicate = (PgfPredicate) jit_get_ip().ptr;
|
||||
|
||||
jit_prolog(2);
|
||||
|
||||
PgfAbsFun* absfun = NULL;
|
||||
PgfAbsFun* next_absfun = NULL;
|
||||
|
||||
if (n_funs > 0) {
|
||||
PgfAbsFun* absfun =
|
||||
gu_buf_get(functions, PgfAbsFun*, 0);
|
||||
next_absfun = pgf_jit_read_absfun(rdr, abstr);
|
||||
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_puts(" TRY_FIRST ", out, err);
|
||||
gu_string_write(absfun->name, out, err);
|
||||
gu_string_write(next_absfun->name, out, err);
|
||||
gu_puts("\n", out, err);
|
||||
#endif
|
||||
|
||||
@@ -135,7 +154,7 @@ pgf_jit_predicate(PgfJitState* state, PgfCIdMap* abscats,
|
||||
|
||||
// compile TRY_FIRST
|
||||
jit_prepare(3);
|
||||
jit_movi_p(JIT_V0,absfun);
|
||||
jit_movi_p(JIT_V0,next_absfun);
|
||||
jit_pusharg_p(JIT_V0);
|
||||
jit_pusharg_p(JIT_V2);
|
||||
jit_pusharg_p(JIT_V1);
|
||||
@@ -150,20 +169,15 @@ pgf_jit_predicate(PgfJitState* state, PgfCIdMap* abscats,
|
||||
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
if (n_funs > 0) {
|
||||
PgfAbsFun* absfun =
|
||||
gu_buf_get(functions, PgfAbsFun*, 0);
|
||||
|
||||
gu_string_write(absfun->name, out, err);
|
||||
gu_string_write(next_absfun->name, out, err);
|
||||
gu_puts(":\n", out, err);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < n_funs; i++) {
|
||||
PgfAbsFun* absfun =
|
||||
gu_buf_get(functions, PgfAbsFun*, i);
|
||||
|
||||
pgf_jit_make_space(state);
|
||||
pgf_jit_make_space(rdr);
|
||||
|
||||
absfun = next_absfun;
|
||||
absfun->predicate = (PgfPredicate) jit_get_ip().ptr;
|
||||
|
||||
jit_prolog(2);
|
||||
@@ -176,18 +190,17 @@ pgf_jit_predicate(PgfJitState* state, PgfCIdMap* abscats,
|
||||
|
||||
if (n_hypos > 0) {
|
||||
if (i+1 < n_funs) {
|
||||
PgfAbsFun* absfun =
|
||||
gu_buf_get(functions, PgfAbsFun*, i+1);
|
||||
next_absfun = pgf_jit_read_absfun(rdr, abstr); // i+1
|
||||
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_puts(" TRY_ELSE ", out, err);
|
||||
gu_string_write(absfun->name, out, err);
|
||||
gu_string_write(next_absfun->name, out, err);
|
||||
gu_puts("\n", out, err);
|
||||
#endif
|
||||
|
||||
// compile TRY_ELSE
|
||||
jit_prepare(3);
|
||||
jit_movi_p(JIT_V0, absfun);
|
||||
jit_movi_p(JIT_V0, next_absfun);
|
||||
jit_pusharg_p(JIT_V0);
|
||||
jit_pusharg_p(JIT_V2);
|
||||
jit_pusharg_p(JIT_V1);
|
||||
@@ -200,9 +213,6 @@ pgf_jit_predicate(PgfJitState* state, PgfCIdMap* abscats,
|
||||
jit_insn *ref;
|
||||
|
||||
// call the predicate for the category in hypo->type->cid
|
||||
PgfAbsCat* arg =
|
||||
gu_map_get(abscats, hypo->type->cid, PgfAbsCat*);
|
||||
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_puts(" CALL ", out, err);
|
||||
gu_string_write(hypo->type->cid, out, err);
|
||||
@@ -219,14 +229,11 @@ pgf_jit_predicate(PgfJitState* state, PgfCIdMap* abscats,
|
||||
jit_prepare(2);
|
||||
jit_pusharg_p(JIT_V2);
|
||||
jit_pusharg_p(JIT_V1);
|
||||
if (arg != NULL) {
|
||||
jit_finish(arg->predicate);
|
||||
} else {
|
||||
PgfCallPatch patch;
|
||||
patch.cid = hypo->type->cid;
|
||||
patch.ref = jit_finish(jit_forward());
|
||||
gu_buf_push(state->patches, PgfCallPatch, patch);
|
||||
}
|
||||
|
||||
PgfCallPatch patch;
|
||||
patch.cid = hypo->type->cid;
|
||||
patch.ref = jit_finish(jit_forward());
|
||||
gu_buf_push(rdr->jit_state->patches, PgfCallPatch, patch);
|
||||
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_puts(" RET\n", out, err);
|
||||
@@ -239,7 +246,7 @@ pgf_jit_predicate(PgfJitState* state, PgfCIdMap* abscats,
|
||||
jit_ret();
|
||||
|
||||
if (i+1 < n_hypos) {
|
||||
pgf_jit_make_space(state);
|
||||
pgf_jit_make_space(rdr);
|
||||
|
||||
jit_patch_movi(ref,jit_get_label());
|
||||
|
||||
@@ -254,18 +261,17 @@ pgf_jit_predicate(PgfJitState* state, PgfCIdMap* abscats,
|
||||
}
|
||||
} else {
|
||||
if (i+1 < n_funs) {
|
||||
PgfAbsFun* absfun =
|
||||
gu_buf_get(functions, PgfAbsFun*, i+1);
|
||||
next_absfun = pgf_jit_read_absfun(rdr, abstr); // i+1
|
||||
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_puts(" TRY_CONSTANT ", out, err);
|
||||
gu_string_write(absfun->name, out, err);
|
||||
gu_string_write(next_absfun->name, out, err);
|
||||
gu_puts("\n", out, err);
|
||||
#endif
|
||||
|
||||
// compile TRY_CONSTANT
|
||||
jit_prepare(3);
|
||||
jit_movi_p(JIT_V0, absfun);
|
||||
jit_movi_p(JIT_V0, next_absfun);
|
||||
jit_pusharg_p(JIT_V0);
|
||||
jit_pusharg_p(JIT_V2);
|
||||
jit_pusharg_p(JIT_V1);
|
||||
@@ -289,13 +295,10 @@ pgf_jit_predicate(PgfJitState* state, PgfCIdMap* abscats,
|
||||
// compile RET
|
||||
jit_ret();
|
||||
}
|
||||
|
||||
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
if (i+1 < n_funs) {
|
||||
PgfAbsFun* absfun =
|
||||
gu_buf_get(functions, PgfAbsFun*, i+1);
|
||||
|
||||
gu_string_write(absfun->name, out, err);
|
||||
gu_string_write(next_absfun->name, out, err);
|
||||
gu_puts(":\n", out, err);
|
||||
}
|
||||
#endif
|
||||
@@ -307,18 +310,251 @@ pgf_jit_predicate(PgfJitState* state, PgfCIdMap* abscats,
|
||||
}
|
||||
|
||||
void
|
||||
pgf_jit_done(PgfJitState* state, PgfAbstr* abstr)
|
||||
pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr,
|
||||
PgfAbsFun* absfun)
|
||||
{
|
||||
size_t n_patches = gu_buf_length(state->patches);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
GuPool* tmp_pool = gu_new_pool();
|
||||
GuOut* out = gu_file_out(stderr, tmp_pool);
|
||||
GuExn* err = gu_exn(NULL, type, tmp_pool);
|
||||
|
||||
gu_string_write(absfun->name, out, err);
|
||||
gu_puts(":\n", out, err);
|
||||
#endif
|
||||
|
||||
pgf_jit_make_space(rdr);
|
||||
|
||||
absfun->function = jit_get_ip().ptr;
|
||||
|
||||
jit_prolog(2);
|
||||
|
||||
int es_arg = jit_arg_p();
|
||||
int closure_arg = jit_arg_p();
|
||||
|
||||
size_t n_instrs = pgf_read_len(rdr);
|
||||
gu_return_on_exn(rdr->err, );
|
||||
|
||||
size_t curr_offset = 0;
|
||||
size_t curr_label = 0;
|
||||
|
||||
for (size_t i = 0; i < n_instrs; i++) {
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "%04d ", curr_label++);
|
||||
#endif
|
||||
|
||||
uint8_t opcode = pgf_read_tag(rdr);
|
||||
switch (opcode) {
|
||||
case PGF_INSTR_EVAL: {
|
||||
size_t index = pgf_read_int(rdr);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "EVAL %d\n", index);
|
||||
#endif
|
||||
|
||||
jit_getarg_p(JIT_V0, es_arg);
|
||||
jit_ldxi_p(JIT_V0, JIT_V0, offsetof(PgfEvalState,stack));
|
||||
jit_prepare(1);
|
||||
jit_pusharg_p(JIT_V0);
|
||||
jit_finish(gu_buf_length);
|
||||
jit_subi_i(JIT_V2, JIT_RET, index+1);
|
||||
jit_lshi_i(JIT_V2, JIT_V2, 2);
|
||||
jit_prepare(1);
|
||||
jit_pusharg_p(JIT_V0);
|
||||
jit_finish(gu_buf_data);
|
||||
jit_ldxr_p(JIT_V0, JIT_RET, JIT_V2);
|
||||
jit_prepare(2);
|
||||
jit_pusharg_p(JIT_V0);
|
||||
jit_getarg_p(JIT_V2, es_arg);
|
||||
jit_pusharg_p(JIT_V2);
|
||||
jit_ldr_p(JIT_V0, JIT_V0);
|
||||
jit_callr(JIT_V0);
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_CASE: {
|
||||
PgfCId id = pgf_read_cid(rdr, rdr->opool);
|
||||
int offset = pgf_read_int(rdr);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "CASE %s %04d\n", id, curr_label+offset);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_CASE_INT: {
|
||||
int n = pgf_read_int(rdr);
|
||||
int offset = pgf_read_int(rdr);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "CASE_INT %d %04d\n", n, curr_label+offset);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_CASE_STR: {
|
||||
GuString s = pgf_read_string(rdr);
|
||||
int offset = pgf_read_int(rdr);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "CASE_STR %s %04d\n", s, curr_label+offset);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_CASE_FLT: {
|
||||
double d = pgf_read_double(rdr);
|
||||
int offset = pgf_read_int(rdr);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "CASE_FLT %f %04d\n", d, curr_label+offset);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_ALLOC: {
|
||||
size_t size = pgf_read_int(rdr);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "ALLOC %d\n", size);
|
||||
#endif
|
||||
jit_prepare(2);
|
||||
jit_movi_ui(JIT_V0, size*sizeof(void*));
|
||||
jit_pusharg_ui(JIT_V0);
|
||||
jit_getarg_p(JIT_V0, es_arg);
|
||||
jit_ldxi_p(JIT_V0, JIT_V0, offsetof(PgfEvalState,pool));
|
||||
jit_pusharg_p(JIT_V0);
|
||||
jit_finish(gu_malloc);
|
||||
jit_retval_p(JIT_V1);
|
||||
|
||||
curr_offset = 0;
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_PUT_CONSTR: {
|
||||
PgfCId id = pgf_read_cid(rdr, rdr->tmp_pool);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "PUT_CONSTR %s\n", id);
|
||||
#endif
|
||||
|
||||
jit_movi_p(JIT_V0, pgf_evaluate_value);
|
||||
jit_stxi_p(curr_offset*sizeof(void*), JIT_V1, JIT_V0);
|
||||
curr_offset++;
|
||||
|
||||
PgfCallPatch patch;
|
||||
patch.cid = id;
|
||||
patch.ref = jit_movi_p(JIT_V0, jit_forward());
|
||||
jit_stxi_p(curr_offset*sizeof(void*), JIT_V1, JIT_V0);
|
||||
curr_offset++;
|
||||
|
||||
gu_buf_push(rdr->jit_state->patches, PgfCallPatch, patch);
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_PUT_CLOSURE: {
|
||||
size_t addr = pgf_read_int(rdr);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "PUT_CLOSURE %d\n", addr);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_PUT_INT: {
|
||||
size_t n = pgf_read_int(rdr);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "PUT_INT %d\n", n);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_PUT_STR: {
|
||||
size_t addr = pgf_read_int(rdr);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "PUT_STR %d\n", addr);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_PUT_FLT: {
|
||||
size_t addr = pgf_read_int(rdr);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "PUT_FLT %d\n", addr);
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_SET_VALUE: {
|
||||
size_t offset = pgf_read_int(rdr);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "SET_VALUE %d\n", offset);
|
||||
#endif
|
||||
jit_addi_p(JIT_V0, JIT_V1, offset*sizeof(void*));
|
||||
jit_stxi_p(curr_offset*sizeof(void*), JIT_V1, JIT_V0);
|
||||
curr_offset++;
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_SET_VARIABLE: {
|
||||
size_t index = pgf_read_int(rdr);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "SET_VARIABLE %d\n", index);
|
||||
#endif
|
||||
|
||||
jit_getarg_p(JIT_V0, es_arg);
|
||||
jit_ldxi_p(JIT_V0, JIT_V0, offsetof(PgfEvalState,stack));
|
||||
jit_prepare(1);
|
||||
jit_pusharg_p(JIT_V0);
|
||||
jit_finish(gu_buf_length);
|
||||
jit_subi_i(JIT_V2, JIT_RET, index+1);
|
||||
jit_lshi_i(JIT_V2, JIT_V2, 2);
|
||||
jit_prepare(1);
|
||||
jit_pusharg_p(JIT_V0);
|
||||
jit_finish(gu_buf_data);
|
||||
jit_ldxr_p(JIT_V0, JIT_RET, JIT_V2);
|
||||
jit_stxi_p(curr_offset*sizeof(void*), JIT_V1, JIT_V0);
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_TAIL_CALL: {
|
||||
PgfCId id = pgf_read_cid(rdr, rdr->tmp_pool);
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "TAIL_CALL %s\n", id);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case PGF_INSTR_FAIL:
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "FAIL\n");
|
||||
#endif
|
||||
break;
|
||||
case PGF_INSTR_RET: {
|
||||
size_t count = pgf_read_int(rdr);
|
||||
|
||||
#ifdef PGF_JIT_DEBUG
|
||||
gu_printf(out, err, "RET %d\n", count);
|
||||
#endif
|
||||
|
||||
jit_prepare(2);
|
||||
jit_movi_ui(JIT_V0, count);
|
||||
jit_pusharg_p(JIT_V0);
|
||||
jit_getarg_p(JIT_V0, es_arg);
|
||||
jit_ldxi_p(JIT_V0, JIT_V0, offsetof(PgfEvalState,stack));
|
||||
jit_pusharg_p(JIT_V0);
|
||||
jit_finish(gu_buf_trim_n);
|
||||
|
||||
jit_movr_p(JIT_RET, JIT_V1);
|
||||
jit_ret();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
gu_impossible();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pgf_jit_done(PgfReader* rdr, PgfAbstr* abstr)
|
||||
{
|
||||
size_t n_patches = gu_buf_length(rdr->jit_state->patches);
|
||||
for (size_t i = 0; i < n_patches; i++) {
|
||||
PgfCallPatch* patch =
|
||||
gu_buf_index(state->patches, PgfCallPatch, i);
|
||||
gu_buf_index(rdr->jit_state->patches, PgfCallPatch, i);
|
||||
|
||||
PgfAbsCat* arg =
|
||||
gu_map_get(abstr->cats, patch->cid, PgfAbsCat*);
|
||||
gu_assert(arg != NULL);
|
||||
|
||||
jit_patch_calli(patch->ref,(jit_insn*) arg->predicate);
|
||||
if (arg != NULL)
|
||||
jit_patch_calli(patch->ref,(jit_insn*) arg->predicate);
|
||||
else {
|
||||
PgfAbsFun* con =
|
||||
gu_map_get(abstr->funs, patch->cid, PgfAbsFun*);
|
||||
if (con != NULL)
|
||||
jit_patch_movi(patch->ref,con);
|
||||
else {
|
||||
gu_impossible();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jit_flush_code(state->buf, jit_get_ip().ptr);
|
||||
jit_flush_code(rdr->jit_state->buf, jit_get_ip().ptr);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user