1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Introduce version_t struct. Will be needed for code invalidation.

This commit is contained in:
Maxime Chevalier-Boisvert 2021-01-12 14:56:43 -05:00 committed by Alan Wu
parent a251059070
commit 3a74011ff8
7 changed files with 187 additions and 172 deletions

View file

@ -14,7 +14,7 @@
#include "ujit_asm.h" #include "ujit_asm.h"
// Compute the number of bits needed to encode a signed value // Compute the number of bits needed to encode a signed value
size_t sig_imm_size(int64_t imm) uint32_t sig_imm_size(int64_t imm)
{ {
// Compute the smallest size this immediate fits in // Compute the smallest size this immediate fits in
if (imm >= -128 && imm <= 127) if (imm >= -128 && imm <= 127)
@ -28,7 +28,7 @@ size_t sig_imm_size(int64_t imm)
} }
// Compute the number of bits needed to encode an unsigned value // Compute the number of bits needed to encode an unsigned value
size_t unsig_imm_size(uint64_t imm) uint32_t unsig_imm_size(uint64_t imm)
{ {
// Compute the smallest size this immediate fits in // Compute the smallest size this immediate fits in
if (imm <= 255) if (imm <= 255)
@ -41,7 +41,7 @@ size_t unsig_imm_size(uint64_t imm)
return 64; return 64;
} }
x86opnd_t mem_opnd(size_t num_bits, x86opnd_t base_reg, int32_t disp) x86opnd_t mem_opnd(uint32_t num_bits, x86opnd_t base_reg, int32_t disp)
{ {
bool is_iprel = base_reg.as.reg.reg_type == REG_IP; bool is_iprel = base_reg.as.reg.reg_type == REG_IP;
@ -54,7 +54,7 @@ x86opnd_t mem_opnd(size_t num_bits, x86opnd_t base_reg, int32_t disp)
return opnd; return opnd;
} }
x86opnd_t resize_opnd(x86opnd_t opnd, size_t num_bits) x86opnd_t resize_opnd(x86opnd_t opnd, uint32_t num_bits)
{ {
assert (num_bits % 8 == 0); assert (num_bits % 8 == 0);
x86opnd_t sub = opnd; x86opnd_t sub = opnd;
@ -85,7 +85,7 @@ x86opnd_t const_ptr_opnd(const void *ptr)
} }
// Allocate a block of executable memory // Allocate a block of executable memory
uint8_t* alloc_exec_mem(size_t mem_size) uint8_t* alloc_exec_mem(uint32_t mem_size)
{ {
#ifndef _WIN32 #ifndef _WIN32
// Map the memory as executable // Map the memory as executable
@ -112,7 +112,7 @@ uint8_t* alloc_exec_mem(size_t mem_size)
} }
// Initialize a code block object // Initialize a code block object
void cb_init(codeblock_t* cb, uint8_t* mem_block, size_t mem_size) void cb_init(codeblock_t* cb, uint8_t* mem_block, uint32_t mem_size)
{ {
cb->mem_block = mem_block; cb->mem_block = mem_block;
cb->mem_size = mem_size; cb->mem_size = mem_size;
@ -122,30 +122,30 @@ void cb_init(codeblock_t* cb, uint8_t* mem_block, size_t mem_size)
} }
// Align the current write position to a multiple of bytes // Align the current write position to a multiple of bytes
void cb_align_pos(codeblock_t* cb, size_t multiple) void cb_align_pos(codeblock_t* cb, uint32_t multiple)
{ {
// Compute the pointer modulo the given alignment boundary // Compute the pointer modulo the given alignment boundary
uint8_t* ptr = &cb->mem_block[cb->write_pos]; uint8_t* ptr = &cb->mem_block[cb->write_pos];
size_t rem = ((size_t)ptr) % multiple; uint32_t rem = ((uint32_t)ptr) % multiple;
// If the pointer is already aligned, stop // If the pointer is already aligned, stop
if (rem != 0) if (rem != 0)
return; return;
// Pad the pointer by the necessary amount to align it // Pad the pointer by the necessary amount to align it
size_t pad = multiple - rem; uint32_t pad = multiple - rem;
cb->write_pos += pad; cb->write_pos += pad;
} }
// Set the current write position // Set the current write position
void cb_set_pos(codeblock_t* cb, size_t pos) void cb_set_pos(codeblock_t* cb, uint32_t pos)
{ {
assert (pos < cb->mem_size); assert (pos < cb->mem_size);
cb->write_pos = pos; cb->write_pos = pos;
} }
// Get a direct pointer into the executable memory block // Get a direct pointer into the executable memory block
uint8_t* cb_get_ptr(codeblock_t* cb, size_t index) uint8_t* cb_get_ptr(codeblock_t* cb, uint32_t index)
{ {
assert (index < cb->mem_size); assert (index < cb->mem_size);
return &cb->mem_block[index]; return &cb->mem_block[index];
@ -160,12 +160,12 @@ void cb_write_byte(codeblock_t* cb, uint8_t byte)
} }
// Write multiple bytes starting from the current position // Write multiple bytes starting from the current position
void cb_write_bytes(codeblock_t* cb, size_t num_bytes, ...) void cb_write_bytes(codeblock_t* cb, uint32_t num_bytes, ...)
{ {
va_list va; va_list va;
va_start(va, num_bytes); va_start(va, num_bytes);
for (size_t i = 0; i < num_bytes; ++i) for (uint32_t i = 0; i < num_bytes; ++i)
{ {
uint8_t byte = va_arg(va, int); uint8_t byte = va_arg(va, int);
cb_write_byte(cb, byte); cb_write_byte(cb, byte);
@ -175,7 +175,7 @@ void cb_write_bytes(codeblock_t* cb, size_t num_bytes, ...)
} }
// Write a signed integer over a given number of bits at the current position // Write a signed integer over a given number of bits at the current position
void cb_write_int(codeblock_t* cb, uint64_t val, size_t num_bits) void cb_write_int(codeblock_t* cb, uint64_t val, uint32_t num_bits)
{ {
assert (num_bits > 0); assert (num_bits > 0);
assert (num_bits % 8 == 0); assert (num_bits % 8 == 0);
@ -210,10 +210,10 @@ void cb_write_int(codeblock_t* cb, uint64_t val, size_t num_bits)
default: default:
{ {
// Compute the size in bytes // Compute the size in bytes
size_t num_bytes = num_bits / 8; uint32_t num_bytes = num_bits / 8;
// Write out the bytes // Write out the bytes
for (size_t i = 0; i < num_bytes; ++i) for (uint32_t i = 0; i < num_bytes; ++i)
{ {
uint8_t byte_val = (uint8_t)(val & 0xFF); uint8_t byte_val = (uint8_t)(val & 0xFF);
cb_write_byte(cb, byte_val); cb_write_byte(cb, byte_val);
@ -224,7 +224,7 @@ void cb_write_int(codeblock_t* cb, uint64_t val, size_t num_bits)
} }
// Allocate a new label with a given name // Allocate a new label with a given name
size_t cb_new_label(codeblock_t* cb, const char* name) uint32_t cb_new_label(codeblock_t* cb, const char* name)
{ {
//if (hasASM) //if (hasASM)
// writeString(to!string(label) ~ ":"); // writeString(to!string(label) ~ ":");
@ -232,7 +232,7 @@ size_t cb_new_label(codeblock_t* cb, const char* name)
assert (cb->num_labels < MAX_LABELS); assert (cb->num_labels < MAX_LABELS);
// Allocate the new label // Allocate the new label
size_t label_idx = cb->num_labels++; uint32_t label_idx = cb->num_labels++;
// This label doesn't have an address yet // This label doesn't have an address yet
cb->label_addrs[label_idx] = 0; cb->label_addrs[label_idx] = 0;
@ -242,14 +242,14 @@ size_t cb_new_label(codeblock_t* cb, const char* name)
} }
// Write a label at the current address // Write a label at the current address
void cb_write_label(codeblock_t* cb, size_t label_idx) void cb_write_label(codeblock_t* cb, uint32_t label_idx)
{ {
assert (label_idx < MAX_LABELS); assert (label_idx < MAX_LABELS);
cb->label_addrs[label_idx] = cb->write_pos; cb->label_addrs[label_idx] = cb->write_pos;
} }
// Add a label reference at the current write position // Add a label reference at the current write position
void cb_label_ref(codeblock_t* cb, size_t label_idx) void cb_label_ref(codeblock_t* cb, uint32_t label_idx)
{ {
assert (label_idx < MAX_LABELS); assert (label_idx < MAX_LABELS);
assert (cb->num_refs < MAX_LABEL_REFS); assert (cb->num_refs < MAX_LABEL_REFS);
@ -262,17 +262,17 @@ void cb_label_ref(codeblock_t* cb, size_t label_idx)
// Link internal label references // Link internal label references
void cb_link_labels(codeblock_t* cb) void cb_link_labels(codeblock_t* cb)
{ {
size_t orig_pos = cb->write_pos; uint32_t orig_pos = cb->write_pos;
// For each label reference // For each label reference
for (size_t i = 0; i < cb->num_refs; ++i) for (uint32_t i = 0; i < cb->num_refs; ++i)
{ {
size_t ref_pos = cb->label_refs[i].pos; uint32_t ref_pos = cb->label_refs[i].pos;
size_t label_idx = cb->label_refs[i].label_idx; uint32_t label_idx = cb->label_refs[i].label_idx;
assert (ref_pos < cb->mem_size); assert (ref_pos < cb->mem_size);
assert (label_idx < MAX_LABELS); assert (label_idx < MAX_LABELS);
size_t label_addr = cb->label_addrs[label_idx]; uint32_t label_addr = cb->label_addrs[label_idx];
assert (label_addr < cb->mem_size); assert (label_addr < cb->mem_size);
// Compute the offset from the reference's end to the label // Compute the offset from the reference's end to the label
@ -327,7 +327,7 @@ bool sib_needed(x86opnd_t opnd)
} }
// Compute the size of the displacement field needed for a memory operand // Compute the size of the displacement field needed for a memory operand
size_t disp_size(x86opnd_t opnd) uint32_t disp_size(x86opnd_t opnd)
{ {
assert (opnd.type == OPND_MEM); assert (opnd.type == OPND_MEM);
@ -340,7 +340,7 @@ size_t disp_size(x86opnd_t opnd)
// Compute the required displacement size // Compute the required displacement size
if (opnd.as.mem.disp != 0) if (opnd.as.mem.disp != 0)
{ {
size_t num_bits = sig_imm_size(opnd.as.mem.disp); uint32_t num_bits = sig_imm_size(opnd.as.mem.disp);
assert (num_bits <= 32 && "displacement does not fit in 32 bits"); assert (num_bits <= 32 && "displacement does not fit in 32 bits");
// x86 can only encode 8-bit and 32-bit displacements // x86 can only encode 8-bit and 32-bit displacements
@ -400,7 +400,7 @@ void cb_write_rm(
x86opnd_t r_opnd, x86opnd_t r_opnd,
x86opnd_t rm_opnd, x86opnd_t rm_opnd,
uint8_t opExt, uint8_t opExt,
size_t op_len, uint32_t op_len,
...) ...)
{ {
assert (op_len > 0 && op_len <= 3); assert (op_len > 0 && op_len <= 3);
@ -455,7 +455,7 @@ void cb_write_rm(
// Write the opcode bytes to the code block // Write the opcode bytes to the code block
va_list va; va_list va;
va_start(va, op_len); va_start(va, op_len);
for (size_t i = 0; i < op_len; ++i) for (uint32_t i = 0; i < op_len; ++i)
{ {
uint8_t byte = va_arg(va, int); uint8_t byte = va_arg(va, int);
cb_write_byte(cb, byte); cb_write_byte(cb, byte);
@ -479,7 +479,7 @@ void cb_write_rm(
} }
else else
{ {
size_t dsize = disp_size(rm_opnd); uint32_t dsize = disp_size(rm_opnd);
if (dsize == 0 || rm_opnd.as.mem.is_iprel) if (dsize == 0 || rm_opnd.as.mem.is_iprel)
mod = 0; mod = 0;
else if (dsize == 8) else if (dsize == 8)
@ -547,7 +547,7 @@ void cb_write_rm(
// Add the displacement // Add the displacement
if (rm_opnd.type == OPND_MEM) if (rm_opnd.type == OPND_MEM)
{ {
size_t dsize = disp_size(rm_opnd); uint32_t dsize = disp_size(rm_opnd);
if (dsize > 0) if (dsize > 0)
cb_write_int(cb, rm_opnd.as.mem.disp, dsize); cb_write_int(cb, rm_opnd.as.mem.disp, dsize);
} }
@ -566,7 +566,7 @@ void write_rm_unary(
//cb.writeASM(mnem, opnd); //cb.writeASM(mnem, opnd);
// Check the size of opnd0 // Check the size of opnd0
size_t opndSize; uint32_t opndSize;
if (opnd.type == OPND_REG || opnd.type == OPND_MEM) if (opnd.type == OPND_REG || opnd.type == OPND_MEM)
opndSize = opnd.num_bits; opndSize = opnd.num_bits;
else else
@ -608,7 +608,7 @@ void cb_write_rm_multi(
*/ */
// Check the size of opnd0 // Check the size of opnd0
size_t opndSize = opnd0.num_bits; uint32_t opndSize = opnd0.num_bits;
// Check the size of opnd1 // Check the size of opnd1
if (opnd1.type == OPND_REG || opnd1.type == OPND_MEM) if (opnd1.type == OPND_REG || opnd1.type == OPND_MEM)
@ -696,7 +696,7 @@ void cb_write_shift(
//cb.writeASM(mnem, opnd0, opnd1); //cb.writeASM(mnem, opnd0, opnd1);
// Check the size of opnd0 // Check the size of opnd0
size_t opndSize; uint32_t opndSize;
if (opnd0.type == OPND_REG || opnd0.type == OPND_MEM) if (opnd0.type == OPND_REG || opnd0.type == OPND_MEM)
opndSize = opnd0.num_bits; opndSize = opnd0.num_bits;
else else
@ -733,7 +733,7 @@ void cb_write_shift(
// Encode a relative jump to a label (direct or conditional) // Encode a relative jump to a label (direct or conditional)
// Note: this always encodes a 32-bit offset // Note: this always encodes a 32-bit offset
void cb_write_jcc(codeblock_t* cb, const char* mnem, uint8_t op0, uint8_t op1, size_t label_idx) void cb_write_jcc(codeblock_t* cb, const char* mnem, uint8_t op0, uint8_t op1, uint32_t label_idx)
{ {
//cb.writeASM(mnem, label); //cb.writeASM(mnem, label);
@ -857,7 +857,7 @@ void call_ptr(codeblock_t* cb, x86opnd_t scratch_reg, uint8_t* dst_ptr)
} }
/// call - Call to label with 32-bit offset /// call - Call to label with 32-bit offset
void call_label(codeblock_t* cb, size_t label_idx) void call_label(codeblock_t* cb, uint32_t label_idx)
{ {
//cb.writeASM("call", label); //cb.writeASM("call", label);
@ -1049,37 +1049,37 @@ void imul(CodeBlock cb, X86Opnd opnd0, X86Opnd opnd1, X86Opnd opnd2)
*/ */
/// jcc - relative jumps to a label /// jcc - relative jumps to a label
void ja (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "ja" , 0x0F, 0x87, label_idx); } void ja (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "ja" , 0x0F, 0x87, label_idx); }
void jae (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jae" , 0x0F, 0x83, label_idx); } void jae (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jae" , 0x0F, 0x83, label_idx); }
void jb (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jb" , 0x0F, 0x82, label_idx); } void jb (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jb" , 0x0F, 0x82, label_idx); }
void jbe (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jbe" , 0x0F, 0x86, label_idx); } void jbe (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jbe" , 0x0F, 0x86, label_idx); }
void jc (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jc" , 0x0F, 0x82, label_idx); } void jc (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jc" , 0x0F, 0x82, label_idx); }
void je (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "je" , 0x0F, 0x84, label_idx); } void je (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "je" , 0x0F, 0x84, label_idx); }
void jg (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jg" , 0x0F, 0x8F, label_idx); } void jg (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jg" , 0x0F, 0x8F, label_idx); }
void jge (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jge" , 0x0F, 0x8D, label_idx); } void jge (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jge" , 0x0F, 0x8D, label_idx); }
void jl (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jl" , 0x0F, 0x8C, label_idx); } void jl (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jl" , 0x0F, 0x8C, label_idx); }
void jle (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jle" , 0x0F, 0x8E, label_idx); } void jle (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jle" , 0x0F, 0x8E, label_idx); }
void jna (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jna" , 0x0F, 0x86, label_idx); } void jna (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jna" , 0x0F, 0x86, label_idx); }
void jnae(codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jnae", 0x0F, 0x82, label_idx); } void jnae(codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jnae", 0x0F, 0x82, label_idx); }
void jnb (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jnb" , 0x0F, 0x83, label_idx); } void jnb (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jnb" , 0x0F, 0x83, label_idx); }
void jnbe(codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jnbe", 0x0F, 0x87, label_idx); } void jnbe(codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jnbe", 0x0F, 0x87, label_idx); }
void jnc (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jnc" , 0x0F, 0x83, label_idx); } void jnc (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jnc" , 0x0F, 0x83, label_idx); }
void jne (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jne" , 0x0F, 0x85, label_idx); } void jne (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jne" , 0x0F, 0x85, label_idx); }
void jng (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jng" , 0x0F, 0x8E, label_idx); } void jng (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jng" , 0x0F, 0x8E, label_idx); }
void jnge(codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jnge", 0x0F, 0x8C, label_idx); } void jnge(codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jnge", 0x0F, 0x8C, label_idx); }
void jnl (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jnl" , 0x0F, 0x8D, label_idx); } void jnl (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jnl" , 0x0F, 0x8D, label_idx); }
void jnle(codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jnle", 0x0F, 0x8F, label_idx); } void jnle(codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jnle", 0x0F, 0x8F, label_idx); }
void jno (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jno" , 0x0F, 0x81, label_idx); } void jno (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jno" , 0x0F, 0x81, label_idx); }
void jnp (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jnp" , 0x0F, 0x8b, label_idx); } void jnp (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jnp" , 0x0F, 0x8b, label_idx); }
void jns (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jns" , 0x0F, 0x89, label_idx); } void jns (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jns" , 0x0F, 0x89, label_idx); }
void jnz (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jnz" , 0x0F, 0x85, label_idx); } void jnz (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jnz" , 0x0F, 0x85, label_idx); }
void jo (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jo" , 0x0F, 0x80, label_idx); } void jo (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jo" , 0x0F, 0x80, label_idx); }
void jp (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jp" , 0x0F, 0x8A, label_idx); } void jp (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jp" , 0x0F, 0x8A, label_idx); }
void jpe (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jpe" , 0x0F, 0x8A, label_idx); } void jpe (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jpe" , 0x0F, 0x8A, label_idx); }
void jpo (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jpo" , 0x0F, 0x8B, label_idx); } void jpo (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jpo" , 0x0F, 0x8B, label_idx); }
void js (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "js" , 0x0F, 0x88, label_idx); } void js (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "js" , 0x0F, 0x88, label_idx); }
void jz (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jz" , 0x0F, 0x84, label_idx); } void jz (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jz" , 0x0F, 0x84, label_idx); }
void jmp (codeblock_t* cb, size_t label_idx) { cb_write_jcc(cb, "jmp" , 0xFF, 0xE9, label_idx); } void jmp (codeblock_t* cb, uint32_t label_idx) { cb_write_jcc(cb, "jmp" , 0xFF, 0xE9, label_idx); }
/// jcc - relative jumps to a pointer (32-bit offset) /// jcc - relative jumps to a pointer (32-bit offset)
void ja_ptr (codeblock_t* cb, uint8_t* ptr) { cb_write_jcc_ptr(cb, "ja" , 0x0F, 0x87, ptr); } void ja_ptr (codeblock_t* cb, uint8_t* ptr) { cb_write_jcc_ptr(cb, "ja" , 0x0F, 0x87, ptr); }
@ -1233,13 +1233,13 @@ void movzx(codeblock_t* cb, x86opnd_t dst, x86opnd_t src)
{ {
cb.writeASM("movzx", dst, src); cb.writeASM("movzx", dst, src);
size_t dstSize; uint32_t dstSize;
if (dst.isReg) if (dst.isReg)
dstSize = dst.reg.size; dstSize = dst.reg.size;
else else
assert (false, "movzx dst must be a register"); assert (false, "movzx dst must be a register");
size_t srcSize; uint32_t srcSize;
if (src.isReg) if (src.isReg)
srcSize = src.reg.size; srcSize = src.reg.size;
else if (src.isMem) else if (src.isMem)
@ -1281,7 +1281,7 @@ void neg(codeblock_t* cb, x86opnd_t opnd)
} }
// nop - Noop, one or multiple bytes long // nop - Noop, one or multiple bytes long
void nop(codeblock_t* cb, size_t length) void nop(codeblock_t* cb, uint32_t length)
{ {
switch (length) switch (length)
{ {
@ -1335,7 +1335,7 @@ void nop(codeblock_t* cb, size_t length)
default: default:
{ {
size_t written = 0; uint32_t written = 0;
while (written + 9 <= length) while (written + 9 <= length)
{ {
nop(cb, 9); nop(cb, 9);

View file

@ -15,10 +15,10 @@
typedef struct LabelRef typedef struct LabelRef
{ {
// Position in the code block where the label reference exists // Position in the code block where the label reference exists
size_t pos; uint32_t pos;
// Label which this refers to // Label which this refers to
size_t label_idx; uint32_t label_idx;
} labelref_t; } labelref_t;
@ -29,13 +29,13 @@ typedef struct CodeBlock
uint8_t* mem_block; uint8_t* mem_block;
// Memory block size // Memory block size
size_t mem_size; uint32_t mem_size;
/// Current writing position /// Current writing position
size_t write_pos; uint32_t write_pos;
// Table of registered label addresses // Table of registered label addresses
size_t label_addrs[MAX_LABELS]; uint32_t label_addrs[MAX_LABELS];
// Table of registered label names // Table of registered label names
// Note that these should be constant strings only // Note that these should be constant strings only
@ -45,10 +45,10 @@ typedef struct CodeBlock
labelref_t label_refs[MAX_LABEL_REFS]; labelref_t label_refs[MAX_LABEL_REFS];
// Number of labels registeered // Number of labels registeered
size_t num_labels; uint32_t num_labels;
// Number of references to labels // Number of references to labels
size_t num_refs; uint32_t num_refs;
// TODO: system for disassembly/comment strings, indexed by position // TODO: system for disassembly/comment strings, indexed by position
@ -214,7 +214,7 @@ static const x86opnd_t R15B = { OPND_REG, 8, .as.reg = { REG_GP, 15 }};
#define C_ARG_REGS ( (x86opnd_t[]){ RDI, RSI, RDX, RCX, R8, R9 } ) #define C_ARG_REGS ( (x86opnd_t[]){ RDI, RSI, RDX, RCX, R8, R9 } )
// Memory operand with base register and displacement/offset // Memory operand with base register and displacement/offset
x86opnd_t mem_opnd(size_t num_bits, x86opnd_t base_reg, int32_t disp); x86opnd_t mem_opnd(uint32_t num_bits, x86opnd_t base_reg, int32_t disp);
// Immediate number operand // Immediate number operand
x86opnd_t imm_opnd(int64_t val); x86opnd_t imm_opnd(int64_t val);
@ -238,24 +238,24 @@ x86opnd_t const_ptr_opnd(const void *ptr);
) )
// Code block methods // Code block methods
uint8_t* alloc_exec_mem(size_t mem_size); uint8_t* alloc_exec_mem(uint32_t mem_size);
void cb_init(codeblock_t* cb, uint8_t* mem_block, size_t mem_size); void cb_init(codeblock_t* cb, uint8_t* mem_block, uint32_t mem_size);
void cb_align_pos(codeblock_t* cb, size_t multiple); void cb_align_pos(codeblock_t* cb, uint32_t multiple);
void cb_set_pos(codeblock_t* cb, size_t pos); void cb_set_pos(codeblock_t* cb, uint32_t pos);
uint8_t* cb_get_ptr(codeblock_t* cb, size_t index); uint8_t* cb_get_ptr(codeblock_t* cb, uint32_t index);
void cb_write_byte(codeblock_t* cb, uint8_t byte); void cb_write_byte(codeblock_t* cb, uint8_t byte);
void cb_write_bytes(codeblock_t* cb, size_t num_bytes, ...); void cb_write_bytes(codeblock_t* cb, uint32_t num_bytes, ...);
void cb_write_int(codeblock_t* cb, uint64_t val, size_t num_bits); void cb_write_int(codeblock_t* cb, uint64_t val, uint32_t num_bits);
size_t cb_new_label(codeblock_t* cb, const char* name); uint32_t cb_new_label(codeblock_t* cb, const char* name);
void cb_write_label(codeblock_t* cb, size_t label_idx); void cb_write_label(codeblock_t* cb, uint32_t label_idx);
void cb_label_ref(codeblock_t* cb, size_t label_idx); void cb_label_ref(codeblock_t* cb, uint32_t label_idx);
void cb_link_labels(codeblock_t* cb); void cb_link_labels(codeblock_t* cb);
// Encode individual instructions into a code block // Encode individual instructions into a code block
void add(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1); void add(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1);
void and(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1); void and(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1);
void call_ptr(codeblock_t* cb, x86opnd_t scratch_reg, uint8_t* dst_ptr); void call_ptr(codeblock_t* cb, x86opnd_t scratch_reg, uint8_t* dst_ptr);
void call_label(codeblock_t* cb, size_t label_idx); void call_label(codeblock_t* cb, uint32_t label_idx);
void call(codeblock_t* cb, x86opnd_t opnd); void call(codeblock_t* cb, x86opnd_t opnd);
void cmova(codeblock_t* cb, x86opnd_t dst, x86opnd_t src); void cmova(codeblock_t* cb, x86opnd_t dst, x86opnd_t src);
void cmovae(codeblock_t* cb, x86opnd_t dst, x86opnd_t src); void cmovae(codeblock_t* cb, x86opnd_t dst, x86opnd_t src);
@ -291,36 +291,36 @@ void cmp(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1);
void cdq(codeblock_t* cb); void cdq(codeblock_t* cb);
void cqo(codeblock_t* cb); void cqo(codeblock_t* cb);
void int3(codeblock_t* cb); void int3(codeblock_t* cb);
void ja(codeblock_t* cb, size_t label_idx); void ja(codeblock_t* cb, uint32_t label_idx);
void jae(codeblock_t* cb, size_t label_idx); void jae(codeblock_t* cb, uint32_t label_idx);
void jb(codeblock_t* cb, size_t label_idx); void jb(codeblock_t* cb, uint32_t label_idx);
void jbe(codeblock_t* cb, size_t label_idx); void jbe(codeblock_t* cb, uint32_t label_idx);
void jc(codeblock_t* cb, size_t label_idx); void jc(codeblock_t* cb, uint32_t label_idx);
void je(codeblock_t* cb, size_t label_idx); void je(codeblock_t* cb, uint32_t label_idx);
void jg(codeblock_t* cb, size_t label_idx); void jg(codeblock_t* cb, uint32_t label_idx);
void jge(codeblock_t* cb, size_t label_idx); void jge(codeblock_t* cb, uint32_t label_idx);
void jl(codeblock_t* cb, size_t label_idx); void jl(codeblock_t* cb, uint32_t label_idx);
void jle(codeblock_t* cb, size_t label_idx); void jle(codeblock_t* cb, uint32_t label_idx);
void jna(codeblock_t* cb, size_t label_idx); void jna(codeblock_t* cb, uint32_t label_idx);
void jnae(codeblock_t* cb, size_t label_idx); void jnae(codeblock_t* cb, uint32_t label_idx);
void jnb(codeblock_t* cb, size_t label_idx); void jnb(codeblock_t* cb, uint32_t label_idx);
void jnbe(codeblock_t* cb, size_t label_idx); void jnbe(codeblock_t* cb, uint32_t label_idx);
void jnc(codeblock_t* cb, size_t label_idx); void jnc(codeblock_t* cb, uint32_t label_idx);
void jne(codeblock_t* cb, size_t label_idx); void jne(codeblock_t* cb, uint32_t label_idx);
void jng(codeblock_t* cb, size_t label_idx); void jng(codeblock_t* cb, uint32_t label_idx);
void jnge(codeblock_t* cb, size_t label_idx); void jnge(codeblock_t* cb, uint32_t label_idx);
// void jnl(codeblock_t* cb, size_t label_idx); // this conflicts with jnl(3) // void jnl(codeblock_t* cb, uint32_t label_idx); // this conflicts with jnl(3)
void jnle(codeblock_t* cb, size_t label_idx); void jnle(codeblock_t* cb, uint32_t label_idx);
void jno(codeblock_t* cb, size_t label_idx); void jno(codeblock_t* cb, uint32_t label_idx);
void jnp(codeblock_t* cb, size_t label_idx); void jnp(codeblock_t* cb, uint32_t label_idx);
void jns(codeblock_t* cb, size_t label_idx); void jns(codeblock_t* cb, uint32_t label_idx);
void jnz(codeblock_t* cb, size_t label_idx); void jnz(codeblock_t* cb, uint32_t label_idx);
void jo(codeblock_t* cb, size_t label_idx); void jo(codeblock_t* cb, uint32_t label_idx);
void jp(codeblock_t* cb, size_t label_idx); void jp(codeblock_t* cb, uint32_t label_idx);
void jpe(codeblock_t* cb, size_t label_idx); void jpe(codeblock_t* cb, uint32_t label_idx);
void jpo(codeblock_t* cb, size_t label_idx); void jpo(codeblock_t* cb, uint32_t label_idx);
void js(codeblock_t* cb, size_t label_idx); void js(codeblock_t* cb, uint32_t label_idx);
void jz(codeblock_t* cb, size_t label_idx); void jz(codeblock_t* cb, uint32_t label_idx);
void ja_ptr(codeblock_t* cb, uint8_t* ptr); void ja_ptr(codeblock_t* cb, uint8_t* ptr);
void jae_ptr(codeblock_t* cb, uint8_t* ptr); void jae_ptr(codeblock_t* cb, uint8_t* ptr);
void jb_ptr(codeblock_t* cb, uint8_t* ptr); void jb_ptr(codeblock_t* cb, uint8_t* ptr);
@ -351,7 +351,7 @@ void jpe_ptr(codeblock_t* cb, uint8_t* ptr);
void jpo_ptr(codeblock_t* cb, uint8_t* ptr); void jpo_ptr(codeblock_t* cb, uint8_t* ptr);
void js_ptr(codeblock_t* cb, uint8_t* ptr); void js_ptr(codeblock_t* cb, uint8_t* ptr);
void jz_ptr(codeblock_t* cb, uint8_t* ptr); void jz_ptr(codeblock_t* cb, uint8_t* ptr);
void jmp(codeblock_t* cb, size_t label_idx); void jmp(codeblock_t* cb, uint32_t label_idx);
void jmp_ptr(codeblock_t* cb, uint8_t* ptr); void jmp_ptr(codeblock_t* cb, uint8_t* ptr);
void jmp_rm(codeblock_t* cb, x86opnd_t opnd); void jmp_rm(codeblock_t* cb, x86opnd_t opnd);
void jmp32(codeblock_t* cb, int32_t offset); void jmp32(codeblock_t* cb, int32_t offset);
@ -359,7 +359,7 @@ void lea(codeblock_t* cb, x86opnd_t dst, x86opnd_t src);
void mov(codeblock_t* cb, x86opnd_t dst, x86opnd_t src); void mov(codeblock_t* cb, x86opnd_t dst, x86opnd_t src);
void movsx(codeblock_t* cb, x86opnd_t dst, x86opnd_t src); void movsx(codeblock_t* cb, x86opnd_t dst, x86opnd_t src);
void neg(codeblock_t* cb, x86opnd_t opnd); void neg(codeblock_t* cb, x86opnd_t opnd);
void nop(codeblock_t* cb, size_t length); void nop(codeblock_t* cb, uint32_t length);
void not(codeblock_t* cb, x86opnd_t opnd); void not(codeblock_t* cb, x86opnd_t opnd);
void or(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1); void or(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1);
void pop(codeblock_t* cb, x86opnd_t reg); void pop(codeblock_t* cb, x86opnd_t reg);

View file

@ -7,7 +7,7 @@
// Print the bytes in a code block // Print the bytes in a code block
void print_bytes(codeblock_t* cb) void print_bytes(codeblock_t* cb)
{ {
for (size_t i = 0; i < cb->write_pos; ++i) for (uint32_t i = 0; i < cb->write_pos; ++i)
{ {
printf("%02X", (int)cb->mem_block[i]); printf("%02X", (int)cb->mem_block[i]);
} }
@ -26,7 +26,7 @@ void check_bytes(codeblock_t* cb, const char* bytes)
if (cb->write_pos != num_bytes) if (cb->write_pos != num_bytes)
{ {
fprintf(stderr, "incorrect encoding length, expected %ld, got %ld\n", fprintf(stderr, "incorrect encoding length, expected %ld, got %d\n",
num_bytes, num_bytes,
cb->write_pos cb->write_pos
); );
@ -35,7 +35,7 @@ void check_bytes(codeblock_t* cb, const char* bytes)
exit(-1); exit(-1);
} }
for (size_t i = 0; i < num_bytes; ++i) for (uint32_t i = 0; i < num_bytes; ++i)
{ {
char byte_str[] = {0, 0, 0, 0}; char byte_str[] = {0, 0, 0, 0};
strncpy(byte_str, bytes + (2 * i), 2); strncpy(byte_str, bytes + (2 * i), 2);
@ -46,7 +46,7 @@ void check_bytes(codeblock_t* cb, const char* bytes)
if (cb_byte != byte) if (cb_byte != byte)
{ {
fprintf(stderr, "incorrect encoding at position %ld, expected %02X, got %02X\n", fprintf(stderr, "incorrect encoding at position %d, expected %02X, got %02X\n",
i, i,
(int)byte, (int)byte,
(int)cb_byte (int)cb_byte
@ -92,7 +92,7 @@ void run_tests()
// call // call
{ {
cb_set_pos(cb, 0); cb_set_pos(cb, 0);
size_t fn_label = cb_new_label(cb, "foo"); uint32_t fn_label = cb_new_label(cb, "foo");
call_label(cb, fn_label); call_label(cb, fn_label);
cb_link_labels(cb); cb_link_labels(cb);
check_bytes(cb, "E8FBFFFFFF"); check_bytes(cb, "E8FBFFFFFF");
@ -131,14 +131,14 @@ void run_tests()
// jcc // jcc
{ {
cb_set_pos(cb, 0); cb_set_pos(cb, 0);
size_t loop_label = cb_new_label(cb, "loop"); uint32_t loop_label = cb_new_label(cb, "loop");
jge(cb, loop_label); jge(cb, loop_label);
cb_link_labels(cb); cb_link_labels(cb);
check_bytes(cb, "0F8DFAFFFFFF"); check_bytes(cb, "0F8DFAFFFFFF");
} }
{ {
cb_set_pos(cb, 0); cb_set_pos(cb, 0);
size_t loop_label = cb_new_label(cb, "loop"); uint32_t loop_label = cb_new_label(cb, "loop");
jo(cb, loop_label); jo(cb, loop_label);
cb_link_labels(cb); cb_link_labels(cb);
check_bytes(cb, "0F80FAFFFFFF"); check_bytes(cb, "0F80FAFFFFFF");

View file

@ -154,7 +154,7 @@ uint8_t* ujit_compile_entry(const rb_iseq_t *iseq, uint32_t insn_idx)
/* /*
Compile a sequence of bytecode instructions starting at `insn_idx`. Compile a sequence of bytecode instructions starting at `insn_idx`.
*/ */
uint8_t * void
ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx, uint32_t* num_instrs) ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx, uint32_t* num_instrs)
{ {
assert (cb != NULL); assert (cb != NULL);
@ -170,16 +170,14 @@ ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx, uint32_
rb_bug("out of executable memory (outlined block)"); rb_bug("out of executable memory (outlined block)");
} }
// Get a pointer to the current write position in the code block
uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos);
// Last operation that was successfully compiled // Last operation that was successfully compiled
opdesc_t* p_last_op = NULL; opdesc_t* p_last_op = NULL;
// Initialize JIT state object // Initialize JIT state object
jitstate_t jit = { 0 }; jitstate_t jit = {
jit.iseq = iseq; iseq,
jit.start_idx = insn_idx; insn_idx
};
// For each instruction to compile // For each instruction to compile
for (;;) { for (;;) {
@ -236,8 +234,6 @@ ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx, uint32_
pc += insn_len(opcode); pc += insn_len(opcode);
} }
} }
return code_ptr;
} }
static bool static bool
@ -1055,7 +1051,7 @@ void
ujit_init_codegen(void) ujit_init_codegen(void)
{ {
// Initialize the code blocks // Initialize the code blocks
size_t mem_size = 128 * 1024 * 1024; uint32_t mem_size = 128 * 1024 * 1024;
uint8_t* mem_block = alloc_exec_mem(mem_size); uint8_t* mem_block = alloc_exec_mem(mem_size);
cb = &block; cb = &block;
cb_init(cb, mem_block, mem_size/2); cb_init(cb, mem_block, mem_size/2);

View file

@ -15,7 +15,7 @@ typedef struct JITState
const rb_iseq_t *iseq; const rb_iseq_t *iseq;
// Index in the iseq of the opcode we are replacing // Index in the iseq of the opcode we are replacing
uint32_t start_idx; const uint32_t start_idx;
// Index of the current instruction being compiled // Index of the current instruction being compiled
uint32_t insn_idx; uint32_t insn_idx;
@ -42,7 +42,7 @@ typedef struct OpDesc
uint8_t* ujit_compile_entry(const rb_iseq_t *iseq, uint32_t insn_idx); uint8_t* ujit_compile_entry(const rb_iseq_t *iseq, uint32_t insn_idx);
uint8_t *ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx, uint32_t* num_instrs); void ujit_compile_block(const rb_iseq_t *iseq, uint32_t insn_idx, ctx_t* ctx, uint32_t* num_instrs);
void ujit_init_codegen(void); void ujit_init_codegen(void);

View file

@ -70,12 +70,12 @@ ctx_stack_opnd(ctx_t* ctx, int32_t idx)
} }
// Retrieve a basic block version for an (iseq, idx) tuple // Retrieve a basic block version for an (iseq, idx) tuple
uint8_t* find_block_version(blockid_t block, const ctx_t* ctx) version_t* find_block_version(blockid_t block, const ctx_t* ctx)
{ {
// If there exists a version for this block id // If there exists a version for this block id
st_data_t st_version; st_data_t st_version;
if (rb_st_lookup(version_tbl, (st_data_t)&block, &st_version)) { if (rb_st_lookup(version_tbl, (st_data_t)&block, &st_version)) {
return (uint8_t*)st_version; return (version_t*)st_version;
} }
// //
@ -86,23 +86,24 @@ uint8_t* find_block_version(blockid_t block, const ctx_t* ctx)
} }
// Compile a new block version immediately // Compile a new block version immediately
uint8_t* gen_block_version(blockid_t blockid, const ctx_t* ctx) version_t* gen_block_version(blockid_t blockid, const ctx_t* ctx)
{ {
// Copy the context object to avoid modifying it // Allocate a version object
version_t* p_version = malloc(sizeof(version_t));
memcpy(&p_version->blockid, &blockid, sizeof(blockid_t));
memcpy(&p_version->ctx, ctx, sizeof(ctx_t));
// Compile the block version
ctx_t ctx_copy = *ctx; ctx_t ctx_copy = *ctx;
uint32_t num_instrs = 0; uint32_t num_instrs = 0;
uint8_t* p_block = ujit_compile_block(blockid.iseq, blockid.idx, &ctx_copy, &num_instrs); p_version->start_pos = cb->write_pos;
ujit_compile_block(blockid.iseq, blockid.idx, &ctx_copy, &num_instrs);
// Need to allocate the blockid on the heap p_version->end_pos = cb->write_pos;
// to store it in the hash table
blockid_t* p_blockid = (blockid_t*)malloc(sizeof(blockid_t));
memcpy(p_blockid, &blockid, sizeof(blockid_t));
// Keep track of the new block version // Keep track of the new block version
st_insert(version_tbl, (st_data_t)p_blockid, (st_data_t)p_block); st_insert(version_tbl, (st_data_t)&p_version->blockid, (st_data_t)p_version);
return p_block; return p_version;
} }
// Called by the generated code when a branch stub is executed // Called by the generated code when a branch stub is executed
@ -132,31 +133,29 @@ uint8_t* branch_stub_hit(uint32_t branch_idx, uint32_t target_idx)
} }
// Try to find a compiled version of this block // Try to find a compiled version of this block
uint8_t* block_ptr = find_block_version(target, target_ctx); version_t* p_version = find_block_version(target, target_ctx);
// If this block hasn't yet been compiled // If this block hasn't yet been compiled
if (!block_ptr) if (!p_version)
{ {
//fprintf(stderr, "compiling block\n"); p_version = gen_block_version(target, target_ctx);
block_ptr = gen_block_version(target, target_ctx);
} }
// Update the branch target address // Update the branch target address
branch->dst_addrs[target_idx] = block_ptr; uint8_t* dst_addr = cb_get_ptr(cb, p_version->start_pos);
branch->dst_addrs[target_idx] = dst_addr;
//fprintf(stderr, "rewrite branch at %d\n", branch->start_pos);
// Rewrite the branch with the new jump target address // Rewrite the branch with the new jump target address
assert (branch->dst_addrs[0] != NULL); assert (branch->dst_addrs[0] != NULL);
assert (branch->dst_addrs[1] != NULL); assert (branch->dst_addrs[1] != NULL);
size_t cur_pos = cb->write_pos; uint32_t cur_pos = cb->write_pos;
cb_set_pos(cb, branch->start_pos); cb_set_pos(cb, branch->start_pos);
branch->gen_fn(cb, branch->dst_addrs[0], branch->dst_addrs[1], branch->shape); branch->gen_fn(cb, branch->dst_addrs[0], branch->dst_addrs[1], branch->shape);
assert (cb->write_pos <= branch->end_pos); assert (cb->write_pos <= branch->end_pos);
cb_set_pos(cb, cur_pos); cb_set_pos(cb, cur_pos);
// Return a pointer to the compiled block version // Return a pointer to the compiled block version
return block_ptr; return dst_addr;
} }
// Get a version or stub corresponding to a branch target // Get a version or stub corresponding to a branch target
@ -169,10 +168,12 @@ uint8_t* get_branch_target(
uint32_t target_idx uint32_t target_idx
) )
{ {
uint8_t* block_code = find_block_version(target, ctx); version_t* p_version = find_block_version(target, ctx);
if (block_code) if (p_version)
return block_code; {
return cb_get_ptr(cb, p_version->start_pos);
}
// Generate an outlined stub that will call // Generate an outlined stub that will call
// branch_stub_hit(uint32_t branch_idx, uint32_t target_idx) // branch_stub_hit(uint32_t branch_idx, uint32_t target_idx)
@ -216,12 +217,10 @@ void gen_branch(
uint8_t* dst_addr0 = get_branch_target(target0, ctx0, ocb, num_branches, 0); uint8_t* dst_addr0 = get_branch_target(target0, ctx0, ocb, num_branches, 0);
uint8_t* dst_addr1 = get_branch_target(target1, ctx1, ocb, num_branches, 1); uint8_t* dst_addr1 = get_branch_target(target1, ctx1, ocb, num_branches, 1);
uint32_t start_pos = (uint32_t)cb->write_pos;
// Call the branch generation function // Call the branch generation function
uint32_t start_pos = cb->write_pos;
gen_fn(cb, dst_addr0, dst_addr1, SHAPE_DEFAULT); gen_fn(cb, dst_addr0, dst_addr1, SHAPE_DEFAULT);
uint32_t end_pos = cb->write_pos;
uint32_t end_pos = (uint32_t)cb->write_pos;
// Register this branch entry // Register this branch entry
branch_t branch_entry = { branch_t branch_entry = {

View file

@ -45,6 +45,26 @@ typedef struct BlockId
// Null block id constant // Null block id constant
static const blockid_t BLOCKID_NULL = { 0, 0 }; static const blockid_t BLOCKID_NULL = { 0, 0 };
// Basic block version
typedef struct BlockVersion
{
// Basic block this is a version of
blockid_t blockid;
// Context at the start of the block
ctx_t ctx;
// Positions where the generated code starts and ends
uint32_t start_pos;
uint32_t end_pos;
// TODO
// TODO: list of incoming branches, branch entries
// TODO
// incoming;
} version_t;
/// Branch code shape enumeration /// Branch code shape enumeration
enum uint8_t enum uint8_t
{ {
@ -90,8 +110,8 @@ x86opnd_t ctx_stack_push(ctx_t* ctx, size_t n);
x86opnd_t ctx_stack_pop(ctx_t* ctx, size_t n); x86opnd_t ctx_stack_pop(ctx_t* ctx, size_t n);
x86opnd_t ctx_stack_opnd(ctx_t* ctx, int32_t idx); x86opnd_t ctx_stack_opnd(ctx_t* ctx, int32_t idx);
uint8_t* find_block_version(blockid_t block, const ctx_t* ctx); version_t* find_block_version(blockid_t block, const ctx_t* ctx);
uint8_t* gen_block_version(blockid_t block, const ctx_t* ctx); version_t* gen_block_version(blockid_t block, const ctx_t* ctx);
void gen_branch( void gen_branch(
const ctx_t* src_ctx, const ctx_t* src_ctx,