diff options
| author | kr.angelov <kr.angelov@gmail.com> | 2014-08-11 10:59:10 +0000 |
|---|---|---|
| committer | kr.angelov <kr.angelov@gmail.com> | 2014-08-11 10:59:10 +0000 |
| commit | 584d589041f63fdd3ea777019679275657902c2d (patch) | |
| tree | 6150ef1da26bc76e0c3e14954e080f9a801b45f4 /src/runtime/c | |
| parent | 02dda1e66f80047f0a8718557a8bf7cc84c16625 (diff) | |
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.
Diffstat (limited to 'src/runtime/c')
| -rw-r--r-- | src/runtime/c/Makefile.am | 1 | ||||
| -rw-r--r-- | src/runtime/c/pgf/data.h | 20 | ||||
| -rw-r--r-- | src/runtime/c/pgf/evaluator.c | 44 | ||||
| -rw-r--r-- | src/runtime/c/pgf/jit.c | 386 | ||||
| -rw-r--r-- | src/runtime/c/pgf/jit.h | 16 | ||||
| -rw-r--r-- | src/runtime/c/pgf/pgf.h | 32 | ||||
| -rw-r--r-- | src/runtime/c/pgf/reader.c | 72 | ||||
| -rw-r--r-- | src/runtime/c/pgf/reader.h | 51 |
8 files changed, 430 insertions, 192 deletions
diff --git a/src/runtime/c/Makefile.am b/src/runtime/c/Makefile.am index 75bd0a253..c7abd96cb 100644 --- a/src/runtime/c/Makefile.am +++ b/src/runtime/c/Makefile.am @@ -33,7 +33,6 @@ guinclude_HEADERS = \ pgfincludedir=$(includedir)/pgf pgfinclude_HEADERS = \ pgf/expr.h \ - pgf/reader.h \ pgf/linearizer.h \ pgf/parser.h \ pgf/literals.h \ diff --git a/src/runtime/c/pgf/data.h b/src/runtime/c/pgf/data.h index d75b17f85..552856995 100644 --- a/src/runtime/c/pgf/data.h +++ b/src/runtime/c/pgf/data.h @@ -76,6 +76,7 @@ typedef struct { PgfEquations* defns; // maybe null PgfExprProb ep; void* predicate; + void* function; } PgfAbsFun; extern GU_DECLARE_TYPE(PgfAbsFun, abstract); @@ -102,6 +103,25 @@ typedef struct { PgfAbsFun* abs_lin_fun; } PgfAbstr; +typedef enum { + PGF_INSTR_EVAL, + PGF_INSTR_CASE, + PGF_INSTR_CASE_INT, + PGF_INSTR_CASE_STR, + PGF_INSTR_CASE_FLT, + PGF_INSTR_ALLOC, + PGF_INSTR_PUT_CONSTR, + PGF_INSTR_PUT_CLOSURE, + PGF_INSTR_PUT_INT, + PGF_INSTR_PUT_STR, + PGF_INSTR_PUT_FLT, + PGF_INSTR_SET_VALUE, + PGF_INSTR_SET_VARIABLE, + PGF_INSTR_TAIL_CALL, + PGF_INSTR_FAIL, + PGF_INSTR_RET +} PgfInstruction; + struct PgfPGF { uint16_t major_version; uint16_t minor_version; diff --git a/src/runtime/c/pgf/evaluator.c b/src/runtime/c/pgf/evaluator.c index 7c4598a86..ee2bd8511 100644 --- a/src/runtime/c/pgf/evaluator.c +++ b/src/runtime/c/pgf/evaluator.c @@ -1,17 +1,18 @@ #include "pgf/pgf.h" #include "pgf/data.h" +#include "pgf/evaluator.h" typedef struct PgfEnv PgfEnv; -typedef struct PgfClosure PgfClosure; -typedef struct PgfEvalState PgfEvalState; struct PgfEnv { PgfEnv* next; PgfClosure* closure; }; +typedef PgfClosure* (*PgfFunction)(PgfEvalState* state, PgfClosure* val); + struct PgfClosure { - PgfClosure* (*code)(PgfEvalState* state, PgfClosure* val); + PgfFunction code; }; typedef struct { @@ -28,7 +29,6 @@ typedef struct { typedef struct { PgfClosure header; PgfAbsFun* absfun; - size_t n_args; PgfClosure* args[]; } PgfValue; @@ -52,13 +52,6 @@ typedef struct { PgfLiteral lit; } PgfValueLit; -struct PgfEvalState { - PgfPGF* pgf; - GuPool* pool; - GuExn* err; - GuBuf* stack; -}; - static PgfClosure* pgf_evaluate_indirection(PgfEvalState* state, PgfClosure* closure) { @@ -66,20 +59,20 @@ pgf_evaluate_indirection(PgfEvalState* state, PgfClosure* closure) return indir->val; } -static PgfClosure* +PgfClosure* pgf_evaluate_value(PgfEvalState* state, PgfClosure* closure) { PgfValue* val = (PgfValue*) closure; - size_t n_args = val->n_args + gu_buf_length(state->stack); + size_t n_args = gu_seq_length(val->absfun->type->hypos) + + gu_buf_length(state->stack); PgfValue* new_val = gu_new_flex(state->pool, PgfValue, args, n_args); new_val->header.code = pgf_evaluate_value; new_val->absfun = val->absfun; - new_val->n_args = n_args; size_t i = 0; - while (i < val->n_args) { + while (i < gu_seq_length(val->absfun->type->hypos)) { new_val->args[i] = val->args[i]; i++; } @@ -236,15 +229,18 @@ pgf_evaluate_expr_thunk(PgfEvalState* state, PgfClosure* closure) return NULL; } - size_t n_args = gu_buf_length(state->stack); + PgfValue* val; + if (absfun->function != NULL) { + val = (PgfValue*) ((PgfFunction) absfun->function)(state, closure); + } else { + size_t n_args = gu_buf_length(state->stack); - PgfValue* val = - gu_new_flex(state->pool, PgfValue, args, n_args); - val->header.code = pgf_evaluate_value; - val->absfun = absfun; - val->n_args = n_args; - for (size_t i = 0; i < n_args; i++) { - val->args[i] = gu_buf_pop(state->stack, PgfClosure*); + val = gu_new_flex(state->pool, PgfValue, args, n_args); + val->header.code = pgf_evaluate_value; + val->absfun = absfun; + for (size_t i = 0; i < n_args; i++) { + val->args[i] = gu_buf_pop(state->stack, PgfClosure*); + } } PgfIndirection* indir = (PgfIndirection*) closure; @@ -309,7 +305,7 @@ pgf_value2expr(PgfEvalState* state, int level, PgfClosure* clos, GuPool* pool) PgfValue* val = (PgfValue*) clos; expr = val->absfun->ep.expr; - n_args = val->n_args; + n_args = gu_seq_length(val->absfun->type->hypos); args = val->args; } else if (clos->code == pgf_evaluate_value_gen) { PgfValueGen* val = (PgfValueGen*) clos; diff --git a/src/runtime/c/pgf/jit.c b/src/runtime/c/pgf/jit.c index 250b5a3a6..ba7788a1a 100644 --- a/src/runtime/c/pgf/jit.c +++ b/src/runtime/c/pgf/jit.c @@ -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); + + PgfAbsFun* absfun = + gu_map_get(abstr->funs, name, PgfAbsFun*); + assert(absfun != NULL); - state->save_ip_ptr = jit_get_ip().ptr; + 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); } diff --git a/src/runtime/c/pgf/jit.h b/src/runtime/c/pgf/jit.h deleted file mode 100644 index 04265547a..000000000 --- a/src/runtime/c/pgf/jit.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PGF_JIT_H_ -#define PGF_JIT_H_ - -typedef struct PgfJitState PgfJitState; - -PgfJitState* -pgf_jit_init(GuPool* tmp_pool, GuPool* pool); - -void -pgf_jit_done(PgfJitState* state, PgfAbstr* abstr); - -void -pgf_jit_predicate(PgfJitState* state, PgfCIdMap* abscats, - PgfAbsCat* abscat, GuBuf* functions); - -#endif diff --git a/src/runtime/c/pgf/pgf.h b/src/runtime/c/pgf/pgf.h index bc9fb7d99..16444985f 100644 --- a/src/runtime/c/pgf/pgf.h +++ b/src/runtime/c/pgf/pgf.h @@ -17,44 +17,24 @@ extern GU_DECLARE_TYPE(PgfExn, abstract); extern GU_DECLARE_TYPE(PgfParseError, abstract); extern GU_DECLARE_TYPE(PgfTypeError, abstract); -/// @name PGF Grammar objects -/// @{ - typedef struct PgfPGF PgfPGF; typedef struct PgfConcr PgfConcr; - -/**< A representation of a PGF grammar. - */ - #include <pgf/expr.h> #include <pgf/graphviz.h> -/// An enumeration of #PgfExpr elements. typedef GuEnum PgfExprEnum; PgfPGF* pgf_read(const char* fpath, GuPool* pool, GuExn* err); -/**< Read a grammar from a PGF file. - * - * @param from PGF input stream. - * The stream must be positioned in the beginning of a binary - * PGF representation. After a succesful invocation, the stream is - * still open and positioned at the end of the representation. - * - * @param[out] err_out Raised error. - * If non-\c NULL, \c *err_out should be \c NULL. Then, upon - * failure, \c *err_out is set to point to a newly allocated - * error object, which the caller must free with #g_exn_free - * or #g_exn_propagate. - * - * @return A new PGF object, or \c NULL upon failure. The returned - * object must later be freed with #pgf_free. - * - */ +void +pgf_concrete_load(PgfConcr* concr, GuIn* in, GuExn* err); + +void +pgf_concrete_unload(PgfConcr* concr); GuString pgf_abstract_name(PgfPGF*); @@ -176,8 +156,6 @@ pgf_concr_add_literal(PgfConcr *concr, PgfCId cat, PgfLiteralCallback* callback, GuExn* err); -/// @} - void pgf_print(PgfPGF* pgf, GuOut* out, GuExn* err); diff --git a/src/runtime/c/pgf/reader.c b/src/runtime/c/pgf/reader.c index afbd42242..20dfd6e6c 100644 --- a/src/runtime/c/pgf/reader.c +++ b/src/runtime/c/pgf/reader.c @@ -2,7 +2,6 @@ #include "expr.h" #include "literals.h" #include "reader.h" -#include "jit.h" #include <gu/defs.h> #include <gu/map.h> @@ -22,14 +21,6 @@ // PgfReader // -struct PgfReader { - GuIn* in; - GuExn* err; - GuPool* opool; - GuPool* tmp_pool; - PgfJitState* jit_state; -}; - typedef struct PgfReadTagExn PgfReadTagExn; struct PgfReadTagExn { @@ -41,13 +32,13 @@ static GU_DEFINE_TYPE(PgfReadTagExn, abstract, _); static GU_DEFINE_TYPE(PgfReadExn, abstract, _); -static uint8_t +uint8_t pgf_read_tag(PgfReader* rdr) { return gu_in_u8(rdr->in, rdr->err); } -static uint32_t +uint32_t pgf_read_uint(PgfReader* rdr) { uint32_t u = 0; @@ -62,14 +53,14 @@ pgf_read_uint(PgfReader* rdr) return u; } -static int32_t +int32_t pgf_read_int(PgfReader* rdr) { uint32_t u = pgf_read_uint(rdr); return gu_decode_2c32(u, rdr->err); } -static GuLength +size_t pgf_read_len(PgfReader* rdr) { int32_t len = pgf_read_int(rdr); @@ -88,23 +79,29 @@ pgf_read_len(PgfReader* rdr) return 0; } - return (GuLength) len; + return len; } -static PgfCId +PgfCId pgf_read_cid(PgfReader* rdr, GuPool* pool) { size_t len = pgf_read_len(rdr); return gu_string_read_latin1(len, pool, rdr->in, rdr->err); } -static GuString +GuString pgf_read_string(PgfReader* rdr) { GuLength len = pgf_read_len(rdr); return gu_string_read(len, rdr->opool, rdr->in, rdr->err); } +double +pgf_read_double(PgfReader* rdr) +{ + return gu_in_f64be(rdr->in, rdr->err); +} + static void pgf_read_tag_error(PgfReader* rdr) { @@ -149,7 +146,7 @@ pgf_read_literal(PgfReader* rdr) gu_new_variant(PGF_LITERAL_FLT, PgfLiteralFlt, &lit, rdr->opool); - lit_flt->val = gu_in_f64be(rdr->in, rdr->err); + lit_flt->val = pgf_read_double(rdr); break; } default: @@ -417,7 +414,7 @@ pgf_read_patt(PgfReader* rdr) } static PgfAbsFun* -pgf_read_absfun(PgfReader* rdr) +pgf_read_absfun(PgfReader* rdr, PgfAbstr* abstr) { PgfAbsFun* absfun = gu_new(PgfAbsFun, rdr->opool); @@ -444,6 +441,7 @@ pgf_read_absfun(PgfReader* rdr) switch (tag) { case 0: absfun->defns = NULL; + absfun->function = NULL; break; case 1: { GuLength length = pgf_read_len(rdr); @@ -468,6 +466,8 @@ pgf_read_absfun(PgfReader* rdr) data[i] = equ; } + + // pgf_jit_function(rdr, abstr, absfun); break; } default: @@ -475,13 +475,13 @@ pgf_read_absfun(PgfReader* rdr) break; } - absfun->ep.prob = - log(gu_in_f64be(rdr->in, rdr->err)); + absfun->ep.prob = - log(pgf_read_double(rdr)); return absfun; } static PgfCIdMap* -pgf_read_absfuns(PgfReader* rdr) +pgf_read_absfuns(PgfReader* rdr, PgfAbstr* abstr) { GuMapType* map_type = (GuMapType*) GU_TYPE_LIT(GuStringMap, _, @@ -493,7 +493,7 @@ pgf_read_absfuns(PgfReader* rdr) gu_return_on_exn(rdr->err, NULL); for (size_t i = 0; i < len; i++) { - PgfAbsFun* absfun = pgf_read_absfun(rdr); + PgfAbsFun* absfun = pgf_read_absfun(rdr, abstr); gu_return_on_exn(rdr->err, NULL); gu_map_put(absfuns, absfun->name, PgfAbsFun*, absfun); @@ -519,27 +519,9 @@ pgf_read_abscat(PgfReader* rdr, PgfAbstr* abstr, PgfCIdMap* abscats) gu_return_on_exn(rdr->err, NULL); } - GuBuf* functions = gu_new_buf(PgfAbsFun*, rdr->tmp_pool); - - size_t n_functions = pgf_read_len(rdr); - gu_return_on_exn(rdr->err, NULL); - - for (size_t i = 0; i < n_functions; i++) { - 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); - - PgfAbsFun* absfun = - gu_map_get(abstr->funs, name, PgfAbsFun*); - assert(absfun != NULL); - gu_buf_push(functions, PgfAbsFun*, absfun); - } - - abscat->prob = - log(gu_in_f64be(rdr->in, rdr->err)); + pgf_jit_predicate(rdr, abstr, abscat); - pgf_jit_predicate(rdr->jit_state, abscats, abscat, functions); + abscat->prob = - log(pgf_read_double(rdr)); return abscat; } @@ -552,7 +534,7 @@ pgf_read_abscats(PgfReader* rdr, PgfAbstr* abstr) gu_ptr_type(PgfAbsCat), &gu_null_struct); PgfCIdMap* abscats = gu_map_type_make(map_type, rdr->opool); - + size_t len = pgf_read_len(rdr); gu_return_on_exn(rdr->err, NULL); @@ -575,7 +557,7 @@ pgf_read_abstract(PgfReader* rdr, PgfAbstr* abstract) abstract->aflags = pgf_read_flags(rdr); gu_return_on_exn(rdr->err, ); - abstract->funs = pgf_read_absfuns(rdr); + abstract->funs = pgf_read_absfuns(rdr, abstract); gu_return_on_exn(rdr->err, ); abstract->cats = pgf_read_abscats(rdr, abstract); @@ -1350,7 +1332,7 @@ pgf_new_reader(GuIn* in, GuPool* opool, GuPool* tmp_pool, GuExn* err) rdr->tmp_pool = tmp_pool; rdr->err = err; rdr->in = in; - rdr->jit_state = pgf_jit_init(tmp_pool, rdr->opool); + rdr->jit_state = pgf_new_jit(rdr); return rdr; } @@ -1360,5 +1342,5 @@ pgf_reader_done(PgfReader* rdr, PgfPGF* pgf) if (pgf == NULL) return; - pgf_jit_done(rdr->jit_state, &pgf->abstract); + pgf_jit_done(rdr, &pgf->abstract); } diff --git a/src/runtime/c/pgf/reader.h b/src/runtime/c/pgf/reader.h index 7011eea17..98042c330 100644 --- a/src/runtime/c/pgf/reader.h +++ b/src/runtime/c/pgf/reader.h @@ -5,21 +5,64 @@ #include <gu/mem.h> #include <gu/in.h> -typedef struct PgfReader PgfReader; +// general reader interface + +typedef struct { + GuIn* in; + GuExn* err; + GuPool* opool; + GuPool* tmp_pool; + struct PgfJitState* jit_state; +} PgfReader; PgfReader* pgf_new_reader(GuIn* in, GuPool* opool, GuPool* tmp_pool, GuExn* err); +uint8_t +pgf_read_tag(PgfReader* rdr); + +uint32_t +pgf_read_uint(PgfReader* rdr); + +int32_t +pgf_read_int(PgfReader* rdr); + +GuString +pgf_read_string(PgfReader* rdr); + +double +pgf_read_double(PgfReader* rdr); + +size_t +pgf_read_len(PgfReader* rdr); + +PgfCId +pgf_read_cid(PgfReader* rdr, GuPool* pool); + PgfPGF* pgf_read_pgf(PgfReader* rdr); void -pgf_concrete_load(PgfConcr* concr, GuIn* in, GuExn* err); +pgf_reader_done(PgfReader* rdr, PgfPGF* pgf); + + +// JIT specific interface + +typedef struct PgfJitState PgfJitState; + +PgfJitState* +pgf_new_jit(PgfReader* rdr); void -pgf_concrete_unload(PgfConcr* concr); +pgf_jit_predicate(PgfReader* rdr, PgfAbstr* abstr, + PgfAbsCat* abscat); void -pgf_reader_done(PgfReader* rdr, PgfPGF* pgf); +pgf_jit_function(PgfReader* rdr, PgfAbstr* abstr, + PgfAbsFun* absfun); + +void +pgf_jit_done(PgfReader* state, PgfAbstr* abstr); + #endif // READER_H_ |
