mirror of
https://github.com/danog/ir.git
synced 2024-11-30 04:39:43 +01:00
Allow emitting native code into preallocated buffer
This commit is contained in:
parent
5cafe50d36
commit
af4558e439
3
ir.c
3
ir.c
@ -306,6 +306,9 @@ void ir_init(ir_ctx *ctx, ir_ref consts_limit, ir_ref insns_limit)
|
||||
ctx->prev_insn_len = NULL;
|
||||
ctx->data = NULL;
|
||||
|
||||
ctx->code_buffer = NULL;
|
||||
ctx->code_buffer_size = 0;
|
||||
|
||||
ir_strtab_init(&ctx->strtab, 64, 4096);
|
||||
|
||||
buf = ir_mem_malloc((consts_limit + insns_limit) * sizeof(ir_insn));
|
||||
|
3
ir.h
3
ir.h
@ -439,6 +439,8 @@ typedef struct _ir_ctx {
|
||||
void *data;
|
||||
uint32_t rodata_offset;
|
||||
uint32_t jmp_table_offset;
|
||||
void *code_buffer;
|
||||
size_t code_buffer_size;
|
||||
ir_strtab strtab;
|
||||
ir_ref prev_insn_chain[IR_LAST_FOLDABLE_OP + 1];
|
||||
ir_ref prev_const_chain[IR_LAST_TYPE];
|
||||
@ -550,6 +552,7 @@ void ir_disasm_add_symbol(const char *name, uint64_t addr, uint64_t size);
|
||||
int ir_disasm(const char *name,
|
||||
const void *start,
|
||||
size_t size,
|
||||
bool asm_addr,
|
||||
uint32_t rodata_offset,
|
||||
uint32_t jmp_table_offset,
|
||||
FILE *f);
|
||||
|
@ -4188,7 +4188,7 @@ static void ir_calc_stack_frame_size(ir_ctx *ctx, ir_backend_data *data)
|
||||
|
||||
static void* dasm_labels[ir_lb_MAX];
|
||||
|
||||
void *ir_emit_code(ir_ctx *ctx, size_t *size)
|
||||
void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
|
||||
{
|
||||
int b, n, target;
|
||||
ir_block *bb;
|
||||
@ -4199,6 +4199,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size)
|
||||
dasm_State **Dst;
|
||||
int ret;
|
||||
void *entry;
|
||||
size_t size;
|
||||
|
||||
ctx->data = &data;
|
||||
data.ra_data.stack_frame_size = 0;
|
||||
@ -4468,14 +4469,23 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size)
|
||||
|.code
|
||||
}
|
||||
|
||||
ret = dasm_link(&data.dasm_state, size);
|
||||
ret = dasm_link(&data.dasm_state, size_ptr);
|
||||
if (ret != DASM_S_OK) {
|
||||
IR_ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
size = *size_ptr;
|
||||
|
||||
entry = ir_mem_mmap(4096);
|
||||
ir_mem_unprotect(entry, 4096);
|
||||
if (ctx->code_buffer != NULL) {
|
||||
if (IR_ALIGNED_SIZE(size, 16) > ctx->code_buffer_size) {
|
||||
return NULL;
|
||||
}
|
||||
entry = ctx->code_buffer;
|
||||
IR_ASSERT((uintptr_t)entry % 16 == 0);
|
||||
} else {
|
||||
entry = ir_mem_mmap(size);
|
||||
}
|
||||
ir_mem_unprotect(entry, size);
|
||||
|
||||
ret = dasm_encode(&data.dasm_state, entry);
|
||||
|
||||
@ -4494,13 +4504,15 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size)
|
||||
|
||||
if (ret != DASM_S_OK) {
|
||||
IR_ASSERT(0);
|
||||
ir_mem_unmap(entry, 4096);
|
||||
if (ctx->code_buffer == NULL) {
|
||||
ir_mem_unmap(entry, size);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
dasm_free(&data.dasm_state);
|
||||
|
||||
ir_mem_flush(entry, 4096);
|
||||
ir_mem_protect(entry, 4096);
|
||||
ir_mem_flush(entry, size);
|
||||
ir_mem_protect(entry, size);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
@ -458,6 +458,7 @@ static void ir_addrtab_sort(ir_addrtab *addrtab)
|
||||
int ir_disasm(const char *name,
|
||||
const void *start,
|
||||
size_t size,
|
||||
bool asm_addr,
|
||||
uint32_t rodata_offset,
|
||||
uint32_t jmp_table_offset,
|
||||
FILE *f)
|
||||
@ -579,7 +580,7 @@ int ir_disasm(const char *name,
|
||||
}
|
||||
|
||||
# ifdef HAVE_CAPSTONE_ITER
|
||||
if (0) {
|
||||
if (asm_addr) {
|
||||
fprintf(f, " %" PRIx64 ":", insn->address);
|
||||
}
|
||||
p = insn->op_str;
|
||||
@ -590,7 +591,7 @@ int ir_disasm(const char *name,
|
||||
fprintf(f, "\t%s ", insn->mnemonic);
|
||||
}
|
||||
# else
|
||||
if (0) {
|
||||
if (asm_addr) {
|
||||
fprintf(f, " %" PRIx64 ":", insn[i].address);
|
||||
}
|
||||
p = insn[i].op_str;
|
||||
|
6
ir_gdb.c
6
ir_gdb.c
@ -620,12 +620,6 @@ int ir_gdb_register(const char *name,
|
||||
return ir_gdb_register_code(&ctx.obj, ctx.objsize);
|
||||
}
|
||||
|
||||
int ir_gdb_unregister(void)
|
||||
{
|
||||
ir_gdb_unregister_all();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ir_gdb_init(void)
|
||||
{
|
||||
/* This might enable registration of all JIT-ed code, but unfortunately,
|
||||
|
@ -389,7 +389,7 @@ int main(int argc, char **argv)
|
||||
if (entry) {
|
||||
if (dump_asm) {
|
||||
ir_disasm_add_symbol("test", (uintptr_t)entry, size);
|
||||
ir_disasm("test", entry, size, ctx.rodata_offset, ctx.jmp_table_offset, stderr);
|
||||
ir_disasm("test", entry, size, 0, ctx.rodata_offset, ctx.jmp_table_offset, stderr);
|
||||
}
|
||||
if (run) {
|
||||
int (*func)(void) = entry;
|
||||
|
@ -208,7 +208,7 @@ int main(int argc, char **argv)
|
||||
void *entry = ir_emit_code(&ctx, &size);
|
||||
|
||||
if (entry) {
|
||||
ir_disasm("test", entry, size, ctx.rodata_offset, ctx.jmp_table_offset, stderr);
|
||||
ir_disasm("test", entry, size, 0, ctx.rodata_offset, ctx.jmp_table_offset, stderr);
|
||||
|
||||
ir_perf_map_register("test", entry, size);
|
||||
ir_perf_jitdump_open();
|
||||
|
48
ir_x86.dasc
48
ir_x86.dasc
@ -213,7 +213,7 @@
|
||||
|.macro ASM_REG_MREF_OP, _op, type, dst, src
|
||||
|| if (IR_IS_CONST_REF(src)) {
|
||||
|| ir_insn *_insn = &ctx->ir_base[src];
|
||||
|| IR_ASSERT(IR_IS_SIGNED_32BIT(_insn->val.i64));
|
||||
|| IR_ASSERT(IR_IS_32BIT(_insn->type, _insn->val));
|
||||
| ASM_REG_IMM_OP _op, type, dst, _insn->val.i32
|
||||
|| } else {
|
||||
|| int32_t offset = ir_ref_spill_slot(ctx, src);
|
||||
@ -295,7 +295,7 @@
|
||||
|.macro ASM_REG_MREF_IMUL, type, dst, src
|
||||
|| if (IR_IS_CONST_REF(src)) {
|
||||
|| ir_insn *_insn = &ctx->ir_base[src];
|
||||
|| IR_ASSERT(IR_IS_SIGNED_32BIT(_insn->val.i64));
|
||||
|| IR_ASSERT(IR_IS_32BIT(_insn->type, _insn->val));
|
||||
| ASM_REG_IMM_IMUL type, dst, _insn->val.i32
|
||||
|| } else {
|
||||
|| int32_t offset = ir_ref_spill_slot(ctx, src);
|
||||
@ -4976,11 +4976,16 @@ static void ir_emit_call(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
} else {
|
||||
addr = (void*)addr_insn->val.addr;
|
||||
}
|
||||
if (sizeof(void*) == 4 /*|| IR_IS_SIGNED_32BIT(addr)*/) { // TODO: 32-bit IP relative or 64-bit absolute address
|
||||
if (sizeof(void*) == 4 || (ctx->code_buffer_size
|
||||
&& IR_IS_SIGNED_32BIT((char*)addr - (char*)ctx->code_buffer_size))) {
|
||||
| call aword &addr
|
||||
} else {
|
||||
|.if X64
|
||||
| mov64 rax, ((ptrdiff_t)addr) // 0x48 0xb8 <imm-64-bit>
|
||||
if (IR_IS_SIGNED_32BIT(addr)) {
|
||||
| mov rax, ((ptrdiff_t)addr) // 0x48 0xc7 0xc0 <imm-32-bit>
|
||||
} else {
|
||||
| mov64 rax, ((ptrdiff_t)addr) // 0x48 0xb8 <imm-64-bit>
|
||||
}
|
||||
| call rax
|
||||
|.endif
|
||||
}
|
||||
@ -5062,11 +5067,16 @@ static void ir_emit_tailcall(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
} else {
|
||||
addr = (void*)addr_insn->val.addr;
|
||||
}
|
||||
if (sizeof(void*) == 4 /*|| IR_IS_SIGNED_32BIT(addr)*/) { // TODO: 32-bit IP relative or 64-bit absolute address
|
||||
if (sizeof(void*) == 4 || (ctx->code_buffer_size
|
||||
&& IR_IS_SIGNED_32BIT((char*)addr - (char*)ctx->code_buffer_size))) {
|
||||
| jmp aword &addr
|
||||
} else {
|
||||
|.if X64
|
||||
| mov64 rax, ((ptrdiff_t)addr) // 0x48 0xb8 <imm-64-bit>
|
||||
if (IR_IS_SIGNED_32BIT(addr)) {
|
||||
| mov rax, ((ptrdiff_t)addr) // 0x48 0xc7 0xc0 <imm-32-bit>
|
||||
} else {
|
||||
| mov64 rax, ((ptrdiff_t)addr) // 0x48 0xb8 <imm-64-bit>
|
||||
}
|
||||
| jmp rax
|
||||
|.endif
|
||||
}
|
||||
@ -5938,7 +5948,7 @@ static void ir_calc_stack_frame_size(ir_ctx *ctx, ir_backend_data *data)
|
||||
|
||||
static void* dasm_labels[ir_lb_MAX];
|
||||
|
||||
void *ir_emit_code(ir_ctx *ctx, size_t *size)
|
||||
void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
|
||||
{
|
||||
int b, n, target;
|
||||
ir_block *bb;
|
||||
@ -5949,6 +5959,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size)
|
||||
dasm_State **Dst;
|
||||
int ret;
|
||||
void *entry;
|
||||
size_t size;
|
||||
|
||||
ctx->data = &data;
|
||||
data.ra_data.stack_frame_size = 0;
|
||||
@ -6503,14 +6514,23 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size)
|
||||
|.code
|
||||
}
|
||||
|
||||
ret = dasm_link(&data.dasm_state, size);
|
||||
ret = dasm_link(&data.dasm_state, size_ptr);
|
||||
if (ret != DASM_S_OK) {
|
||||
IR_ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
size = *size_ptr;
|
||||
|
||||
entry = ir_mem_mmap(4096);
|
||||
ir_mem_unprotect(entry, 4096);
|
||||
if (ctx->code_buffer != NULL) {
|
||||
if (IR_ALIGNED_SIZE(size, 16) > ctx->code_buffer_size) {
|
||||
return NULL;
|
||||
}
|
||||
entry = ctx->code_buffer;
|
||||
IR_ASSERT((uintptr_t)entry % 16 == 0);
|
||||
} else {
|
||||
entry = ir_mem_mmap(size);
|
||||
}
|
||||
ir_mem_unprotect(entry, size);
|
||||
|
||||
ret = dasm_encode(&data.dasm_state, entry);
|
||||
|
||||
@ -6529,13 +6549,15 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size)
|
||||
|
||||
if (ret != DASM_S_OK) {
|
||||
IR_ASSERT(0);
|
||||
ir_mem_unmap(entry, 4096);
|
||||
if (ctx->code_buffer == NULL) {
|
||||
ir_mem_unmap(entry, size);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
dasm_free(&data.dasm_state);
|
||||
|
||||
ir_mem_flush(entry, 4096);
|
||||
ir_mem_protect(entry, 4096);
|
||||
ir_mem_flush(entry, size);
|
||||
ir_mem_protect(entry, size);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user