diff options
| -rw-r--r-- | src/copyjit.c | 17 | ||||
| -rw-r--r-- | src/copyjit.h | 12 | ||||
| -rwxr-xr-x | tests/check | bin | 1261584 -> 1269672 bytes | |||
| -rw-r--r-- | tests/check.c | 41 |
4 files changed, 68 insertions, 2 deletions
diff --git a/src/copyjit.c b/src/copyjit.c index 393c8e1..0de85d3 100644 --- a/src/copyjit.c +++ b/src/copyjit.c @@ -471,6 +471,23 @@ void compile_start(ctx_t *ctx) ctx->pc = ctx->buf; } +reloc_t compile_placeholder(ctx_t *ctx, compile_callback_t call) +{ + reloc_t r = {0}; + r.addr = call(ctx, 0); + + /* the immediate is the last sizeof(uintptr_t) bytes of the generated + * instruction + * (at least we assume, the user could've passed anything to our callback) */ + r.imm = ((uintptr_t *)ctx->pc) - 1; + return r; +} + +void compile_patch(reloc_t reloc, void *addr) +{ + *reloc.imm = (uintptr_t)addr; +} + void compile_finish(ctx_t *ctx) { __builtin___clear_cache(ctx->buf, ctx->buf + ctx->size); diff --git a/src/copyjit.h b/src/copyjit.h index d752144..8170204 100644 --- a/src/copyjit.h +++ b/src/copyjit.h @@ -3,12 +3,21 @@ #ifndef HMMJIT_H #define HMMJIT_H +#include <stdint.h> + typedef struct { char *pc; char *buf; size_t size; } ctx_t; +typedef struct { + void *addr; + uintptr_t *imm; +} reloc_t; + +typedef void *(*compile_callback_t)(ctx_t *, unsigned long); + #include "../lib/op_decls.h" #include "../lib/imm_decls.h" @@ -30,6 +39,9 @@ void *compile_sly(ctx_t *ctx, unsigned long i); /** @todo add in placeholders (for example for load immediate but we don't know * what the immediate is yet) */ +reloc_t compile_placeholder(ctx_t *ctx, compile_callback_t call); +void compile_patch(reloc_t reloc, void *addr); + void compile_start(ctx_t *ctx); void compile_finish(ctx_t *ctx); unsigned long run(ctx_t *ctx); diff --git a/tests/check b/tests/check Binary files differindex b079a57..a904b37 100755 --- a/tests/check +++ b/tests/check diff --git a/tests/check.c b/tests/check.c index 8f4c6de..f6e775c 100644 --- a/tests/check.c +++ b/tests/check.c @@ -138,8 +138,45 @@ static void check_add() static void check_branch() { - /* oh yeah, I don't support forward references (yet), so this is a bit - * tricky */ + for (size_t i = 0; i < 2; ++i) { + ctx_t ctx; + compile_start(&ctx); + + compile_fast_lia(&ctx, i); + reloc_t r = compile_placeholder(&ctx, compile_lio); + compile_ban(&ctx); + + compile_lix(&ctx, 0); + compile_end(&ctx); + + void *skip = compile_lix(&ctx, 1); + compile_end(&ctx); + compile_patch(r, skip); + + compile_finish(&ctx); + + assert(run(&ctx) == (i != 0)); + } + + for (size_t i = 0; i < 2; ++i) { + ctx_t ctx; + compile_start(&ctx); + + compile_fast_lia(&ctx, i); + reloc_t r = compile_placeholder(&ctx, compile_lio); + compile_baz(&ctx); + + compile_lix(&ctx, 0); + compile_end(&ctx); + + void *skip = compile_lix(&ctx, 1); + compile_end(&ctx); + compile_patch(r, skip); + + compile_finish(&ctx); + + assert(run(&ctx) == (i == 0)); + } } int main() |
