summaryrefslogtreecommitdiff
path: root/ujit_compile.c
diff options
context:
space:
mode:
authorMaxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>2020-09-16 10:33:34 -0400
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:23 -0400
commit16ddb422eb83cc8223a8e93297aef4d6ab273238 (patch)
treef97ecbf48cb28e80795e29deb398c3f5427f7df6 /ujit_compile.c
parentb0b7d0a87e3d9f6dce2eded0f45c95b125f569c3 (diff)
Complete refactoring to codegen functions
Diffstat (limited to 'ujit_compile.c')
-rw-r--r--ujit_compile.c176
1 files changed, 81 insertions, 95 deletions
diff --git a/ujit_compile.c b/ujit_compile.c
index 62a98481ba..2a99a85e45 100644
--- a/ujit_compile.c
+++ b/ujit_compile.c
@@ -14,6 +14,9 @@
// Code generation context
typedef struct ctx_struct
{
+ // Current PC
+ VALUE* pc;
+
// TODO: virtual stack pointer handling
} ctx_t;
@@ -65,11 +68,26 @@ addr2insn_bookkeeping(void *code_ptr, int insn)
}
}
-// Generate a chunk of machine code for one individual bytecode instruction
-// Eventually, this will handle multiple instructions in a sequence
-//
-// MicroJIT code gets a pointer to the cfp as the first argument in RSI
-// See rb_ujit_empty_func(rb_control_frame_t *cfp) in iseq.c
+// Get the current instruction opcode from the context object
+int ctx_get_opcode(ctx_t* ctx)
+{
+ return (int)(*ctx->pc);
+}
+
+// Get an instruction argument from the context object
+VALUE ctx_get_arg(ctx_t* ctx, size_t arg_idx)
+{
+ assert (arg_idx + 1 < insn_len(ctx_get_opcode(ctx)));
+ return *(ctx->pc + arg_idx + 1);
+}
+
+/*
+Generate a chunk of machine code for one individual bytecode instruction
+Eventually, this will handle multiple instructions in a sequence
+
+MicroJIT code gets a pointer to the cfp as the first argument in RSI
+See rb_ujit_empty_func(rb_control_frame_t *cfp) in iseq.c
+*/
uint8_t *
ujit_compile_insn(rb_iseq_t *iseq, size_t insn_idx)
{
@@ -84,9 +102,12 @@ ujit_compile_insn(rb_iseq_t *iseq, size_t insn_idx)
rb_bug("out of executable memory");
}
+ // Get a pointer to the current write position in the code block
+ uint8_t *code_ptr = &cb->mem_block[cb->write_pos];
+ //printf("write pos: %ld\n", cb->write_pos);
+
int insn = (int)iseq->body->iseq_encoded[insn_idx];
int len = insn_len(insn);
-
//const char* name = insn_name(insn);
//printf("%s\n", name);
@@ -99,22 +120,20 @@ ujit_compile_insn(rb_iseq_t *iseq, size_t insn_idx)
codegen_fn gen_fn = (codegen_fn)st_gen_fn;
- // Compute the address of the next instruction
- void *next_pc = &iseq->body->iseq_encoded[insn_idx + len];
-
- // Get a pointer to the current write position in the code block
- uint8_t *code_ptr = &cb->mem_block[cb->write_pos];
- //printf("write pos: %ld\n", cb->write_pos);
-
// Write the pre call bytes
ujit_instr_entry(cb);
- // TODO: create codegen context
+ // Create codegen context
+ ctx_t ctx;
+
+ // Set the current PC
+ ctx.pc = &iseq->body->iseq_encoded[insn_idx];
// Call the code generation function
- gen_fn(cb, NULL);
+ gen_fn(cb, &ctx);
// Directly return the next PC, which is a constant
+ void *next_pc = &iseq->body->iseq_encoded[insn_idx + len];
mov(cb, RAX, const_ptr_opnd(next_pc));
// Write the post call bytes
@@ -123,102 +142,66 @@ ujit_compile_insn(rb_iseq_t *iseq, size_t insn_idx)
addr2insn_bookkeeping(code_ptr, insn);
return code_ptr;
+}
+void gen_nop(codeblock_t* cb, ctx_t* ctx)
+{
+}
+void gen_pop(codeblock_t* cb, ctx_t* ctx)
+{
+ // Decrement SP
+ sub(cb, mem_opnd(64, RDI, 8), imm_opnd(8));
+}
+void gen_putobject_int2fix(codeblock_t* cb, ctx_t* ctx)
+{
+ // Load current SP into RAX
+ mov(cb, RAX, mem_opnd(64, RDI, 8));
+ // Write constant at SP
+ int opcode = ctx_get_opcode(ctx);
+ int cst_val = (opcode == BIN(putobject_INT2FIX_0_))? 0:1;
+ mov(cb, mem_opnd(64, RAX, 0), imm_opnd(INT2FIX(cst_val)));
+ // Load incremented SP into RCX
+ lea(cb, RCX, mem_opnd(64, RAX, 8));
+ // Write back incremented SP
+ mov(cb, mem_opnd(64, RDI, 8), RCX);
+}
- /*
- if (insn == BIN(putobject_INT2FIX_0_) || insn == BIN(putobject_INT2FIX_1_))
- {
- // Load current SP into RAX
- mov(cb, RAX, mem_opnd(64, RDI, 8));
-
- // Write constant at SP
- int cst_val = (insn == BIN(putobject_INT2FIX_0_))? 0:1;
- mov(cb, mem_opnd(64, RAX, 0), imm_opnd(INT2FIX(cst_val)));
-
- // Load incremented SP into RCX
- lea(cb, RCX, mem_opnd(64, RAX, 8));
-
- // Write back incremented SP
- mov(cb, mem_opnd(64, RDI, 8), RCX);
-
- // Directly return the next PC, which is a constant
- mov(cb, RAX, const_ptr_opnd(next_pc));
-
- // Write the post call bytes
- ujit_instr_exit(cb);
-
- addr2insn_bookkeeping(code_ptr, insn);
-
- return code_ptr;
- }
- */
-
- // TODO: implement putself
- /*
- if (insn == BIN(putself))
- {
- }
- */
-
- // TODO: implement putobject
- /*
- if (insn == BIN(putobject))
- {
- }
- */
-
- /*
- if (insn == BIN(getlocal_WC_0))
- {
- //printf("compiling getlocal_WC_0\n");
-
- // Load current SP from CFP
- mov(cb, RAX, mem_opnd(64, RDI, 8));
-
- // Load block pointer from CFP
- mov(cb, RDX, mem_opnd(64, RDI, 32));
-
- // TODO: we may want a macro or helper function to get insn operands
- // Compute the offset from BP to the local
- int32_t opnd0 = (int)iseq->body->iseq_encoded[insn_idx+1];
- const int32_t offs = -8 * opnd0;
+// TODO: putnil
+// could we reuse code from putobject_int2fix here?
- // Load the local from the block
- mov(cb, RCX, mem_opnd(64, RDX, offs));
+// TODO: implement putself
- // Write the local at SP
- mov(cb, mem_opnd(64, RAX, 0), RCX);
+// TODO: implement putobject
- // Compute address of incremented SP
- lea(cb, RCX, mem_opnd(64, RAX, 8));
+void gen_getlocal_wc0(codeblock_t* cb, ctx_t* ctx)
+{
+ // Load current SP from CFP
+ mov(cb, RAX, mem_opnd(64, RDI, 8));
- // Write back incremented SP
- mov(cb, mem_opnd(64, RDI, 8), RCX);
+ // Load block pointer from CFP
+ mov(cb, RDX, mem_opnd(64, RDI, 32));
- // Directly return the next PC, which is a constant
- mov(cb, RAX, const_ptr_opnd(next_pc));
+ // TODO: we may want a macro or helper function to get insn operands
+ // Compute the offset from BP to the local
+ int32_t local_idx = (int32_t)ctx_get_arg(ctx, 0);
+ const int32_t offs = -8 * local_idx;
- // Write the post call bytes
- ujit_instr_exit(cb);
+ // Load the local from the block
+ mov(cb, RCX, mem_opnd(64, RDX, offs));
- addr2insn_bookkeeping(code_ptr, insn);
- }
- */
-}
+ // Write the local at SP
+ mov(cb, mem_opnd(64, RAX, 0), RCX);
-void gen_nop(codeblock_t* cb, ctx_t* ctx)
-{
-}
+ // Compute address of incremented SP
+ lea(cb, RCX, mem_opnd(64, RAX, 8));
-void gen_pop(codeblock_t* cb, ctx_t* ctx)
-{
- // Decrement SP
- sub(cb, mem_opnd(64, RDI, 8), imm_opnd(8));
+ // Write back incremented SP
+ mov(cb, mem_opnd(64, RDI, 8), RCX);
}
static void ujit_init()
@@ -233,4 +216,7 @@ static void ujit_init()
// Map YARV opcodes to the corresponding codegen functions
st_insert(gen_fns, (st_data_t)BIN(nop), (st_data_t)&gen_nop);
st_insert(gen_fns, (st_data_t)BIN(pop), (st_data_t)&gen_pop);
+ st_insert(gen_fns, (st_data_t)BIN(putobject_INT2FIX_0_), (st_data_t)&gen_putobject_int2fix);
+ st_insert(gen_fns, (st_data_t)BIN(putobject_INT2FIX_1_), (st_data_t)&gen_putobject_int2fix);
+ st_insert(gen_fns, (st_data_t)BIN(getlocal_WC_0), (st_data_t)&gen_getlocal_wc0);
}