progress (need to review further)
This commit is contained in:
111
attempt_1/main.c
111
attempt_1/main.c
@@ -139,6 +139,9 @@ WinAPI B4 ms_close_handle(void* hObject) asm("CloseHandle");
|
||||
#define PRIM_DROP 12
|
||||
#define PRIM_SUB 13
|
||||
#define PRIM_EXECUTE 14
|
||||
#define PRIM_IF 15
|
||||
#define PRIM_END 16
|
||||
#define PRIM_RECURSE 17
|
||||
|
||||
global const char* prim_names[] = {
|
||||
"",
|
||||
@@ -155,7 +158,10 @@ global const char* prim_names[] = {
|
||||
"DUP ",
|
||||
"DROP ",
|
||||
"SUB ",
|
||||
"EXECUTE "
|
||||
"EXECUTE ",
|
||||
"[ ",
|
||||
"] ",
|
||||
"RECURSE "
|
||||
};
|
||||
|
||||
internal U4 resolve_name_to_index(const char* ref_name);
|
||||
@@ -460,6 +466,35 @@ IA_ void x64_CALL_RAX() {
|
||||
}
|
||||
IA_ void x64_RET() { emit8(x64_op_RET); } // RET
|
||||
|
||||
// Forward-jump placeholder: emits JMP rel32 with a zero displacement and writes
|
||||
// the offset of the displacement field into *offset_out so it can be patched later.
|
||||
IA_ void x64_JMP_fwd_placeholder(U4* offset_out) {
|
||||
emit8(x64_op_JMP_rel32);
|
||||
offset_out[0] = u4_(code_arena.used);
|
||||
emit32(0);
|
||||
}
|
||||
// Patch a previously emitted forward-jump placeholder.
|
||||
// offset is the value written by x64_JMP_fwd_placeholder; the displacement is
|
||||
// computed relative to the end of the 4-byte field (i.e. offset + 4).
|
||||
IA_ void x64_patch_fwd(U4 offset) {
|
||||
u4_r(code_arena.start + offset)[0] = u4_(code_arena.used) - (offset + 4);
|
||||
}
|
||||
|
||||
// Conditional Forward Jump (IF)
|
||||
IA_ void x64_JMP_IF_ZERO_fwd_placeholder(U4* offset_out) {
|
||||
x64_TEST_RAX_RAX();
|
||||
emit8(0x0F); emit8(0x84); // JZ rel32
|
||||
offset_out[0] = u4_(code_arena.used);
|
||||
emit32(0);
|
||||
}
|
||||
|
||||
// Unconditional Backward Jump (RECURSE)
|
||||
IA_ void x64_JMP_back(U4 target) {
|
||||
emit8(x64_op_JMP_rel32);
|
||||
S4 rel32 = s4_(target) - s4_(code_arena.used + 4);
|
||||
emit32(u4_(rel32));
|
||||
}
|
||||
|
||||
// JIT Entry Prologue: save RBX, load vm_globals ptr from RCX, restore RAX/RDX state
|
||||
// vm_globals[14] = RAX save slot (14 * 8 = 0x70)
|
||||
// vm_globals[15] = RDX save slot (15 * 8 = 0x78)
|
||||
@@ -623,10 +658,14 @@ IA_ void compile_and_run_tape(void)
|
||||
U8*r anno_ptr = u8_r(anno_arena.start);
|
||||
B4 in_def = false;
|
||||
U4 def_jmp_offset = 0;
|
||||
U4 current_def_idx = 0;
|
||||
|
||||
B4 in_lambda = false;
|
||||
U4 lambda_jmp_offset = 0;
|
||||
|
||||
U4 ctrl_stack[32] = {0};
|
||||
U4 ctrl_depth = 0;
|
||||
|
||||
U8 end_idx = run_full ? (tape_arena.used / sizeof(U4)) : (cursor_idx + 1);
|
||||
for (U8 i = 0; i < end_idx; i++)
|
||||
{
|
||||
@@ -638,27 +677,24 @@ IA_ void compile_and_run_tape(void)
|
||||
if (in_lambda && (is_terminator || tag == STag_Lambda)) {
|
||||
x64_RET();
|
||||
pad32();
|
||||
U4 current = code_arena.used;
|
||||
u4_r(code_arena.start + lambda_jmp_offset)[0] = current - (lambda_jmp_offset + 4);
|
||||
x64_patch_fwd(lambda_jmp_offset);
|
||||
in_lambda = false;
|
||||
}
|
||||
|
||||
if (in_def && is_terminator) {
|
||||
x64_RET();
|
||||
pad32();
|
||||
U4 current = code_arena.used;
|
||||
u4_r(code_arena.start + def_jmp_offset)[0] = current - (def_jmp_offset + 4);
|
||||
x64_patch_fwd(def_jmp_offset);
|
||||
in_def = false;
|
||||
}
|
||||
|
||||
if (tag == STag_Define)
|
||||
{
|
||||
pad32();
|
||||
emit8(x64_op_CALL_rel32 - 3); // E9 = JMP rel32
|
||||
def_jmp_offset = code_arena.used;
|
||||
emit32(0);
|
||||
x64_JMP_fwd_placeholder(& def_jmp_offset);
|
||||
pad32();
|
||||
in_def = true;
|
||||
current_def_idx = i;
|
||||
|
||||
tape_to_code_offset[i] = code_arena.used;
|
||||
|
||||
@@ -687,9 +723,7 @@ IA_ void compile_and_run_tape(void)
|
||||
pad32();
|
||||
|
||||
// jmp rel32 over lambda body
|
||||
emit8(x64_op_JMP_rel32);
|
||||
lambda_jmp_offset = code_arena.used;
|
||||
emit32(0);
|
||||
x64_JMP_fwd_placeholder(& lambda_jmp_offset);
|
||||
pad32();
|
||||
in_lambda = true;
|
||||
|
||||
@@ -699,7 +733,26 @@ IA_ void compile_and_run_tape(void)
|
||||
}
|
||||
else if (tag == STag_Call || tag == STag_Imm)
|
||||
{
|
||||
compile_action(val);
|
||||
if (val == 0x10000 + PRIM_IF) {
|
||||
x64_JMP_IF_ZERO_fwd_placeholder(& ctrl_stack[ctrl_depth++]);
|
||||
pad32();
|
||||
}
|
||||
else if (val == 0x10000 + PRIM_END) {
|
||||
if (ctrl_depth > 0) {
|
||||
U4 offset = ctrl_stack[--ctrl_depth];
|
||||
x64_patch_fwd(offset);
|
||||
}
|
||||
pad32();
|
||||
}
|
||||
else if (val == 0x10000 + PRIM_RECURSE) {
|
||||
if (in_def) {
|
||||
x64_JMP_back(tape_to_code_offset[current_def_idx]);
|
||||
}
|
||||
pad32();
|
||||
}
|
||||
else {
|
||||
compile_action(val);
|
||||
}
|
||||
}
|
||||
else if (tag == STag_Data)
|
||||
{
|
||||
@@ -715,14 +768,12 @@ IA_ void compile_and_run_tape(void)
|
||||
if (in_lambda) {
|
||||
x64_RET();
|
||||
pad32();
|
||||
U4 current = code_arena.used;
|
||||
u4_r(code_arena.start + lambda_jmp_offset)[0] = current - (lambda_jmp_offset + 4);
|
||||
x64_patch_fwd(lambda_jmp_offset);
|
||||
}
|
||||
if (in_def) {
|
||||
x64_RET();
|
||||
pad32();
|
||||
U4 current = code_arena.used;
|
||||
u4_r(code_arena.start + def_jmp_offset)[0] = current - (def_jmp_offset + 4);
|
||||
x64_patch_fwd(def_jmp_offset);
|
||||
}
|
||||
|
||||
x64_JIT_EPILOGUE();
|
||||
@@ -1279,11 +1330,31 @@ int main(void) {
|
||||
|
||||
scatter(pack_token(STag_Format, 0xA), 0);
|
||||
|
||||
scatter(pack_token(STag_Call, 0), "RECURSE ");
|
||||
scatter(pack_token(STag_Format, 0xA), 0);
|
||||
|
||||
scatter(pack_token(STag_Imm, 0), "F_STEP ");
|
||||
scatter(pack_token(STag_Imm, 0), "F_STEP ");
|
||||
scatter(pack_token(STag_Imm, 0), "F_STEP ");
|
||||
scatter(pack_token(STag_Imm, 0), "F_STEP ");
|
||||
scatter(pack_token(STag_Imm, 0), "F_STEP ");
|
||||
}
|
||||
|
||||
// IF TEST
|
||||
{
|
||||
scatter(pack_token(STag_Comment, 0), "IF TEST ");
|
||||
scatter(pack_token(STag_Format, 0xA), 0);
|
||||
scatter(pack_token(STag_Data, 0), 0);
|
||||
scatter(pack_token(STag_Call, 0), "[ ");
|
||||
scatter(pack_token(STag_Data, 99), 0);
|
||||
scatter(pack_token(STag_Call, 0), "PRINT ");
|
||||
scatter(pack_token(STag_Call, 0), "] ");
|
||||
scatter(pack_token(STag_Data, 11), 0);
|
||||
scatter(pack_token(STag_Call, 0), "PRINT ");
|
||||
scatter(pack_token(STag_Format, 0xA), 0);
|
||||
|
||||
scatter(pack_token(STag_Data, 1), 0);
|
||||
scatter(pack_token(STag_Call, 0), "[ ");
|
||||
scatter(pack_token(STag_Data, 22), 0);
|
||||
scatter(pack_token(STag_Call, 0), "PRINT ");
|
||||
scatter(pack_token(STag_Call, 0), "] ");
|
||||
scatter(pack_token(STag_Format, 0xA), 0);
|
||||
}
|
||||
|
||||
// Lambda test
|
||||
|
||||
Reference in New Issue
Block a user