This commit is contained in:
2026-02-21 00:01:32 -05:00
parent 7ca83267ba
commit 7c1d721272

View File

@@ -57,13 +57,66 @@ global U8 log_buffer[16] = {0};
global U4 log_count = 0; global U4 log_count = 0;
global S4 scroll_y_offset = 0; global S4 scroll_y_offset = 0;
// New GDI log
#define GDI_LOG_MAX_LINES 10
#define GDI_LOG_MAX_LINE_LEN 128
global char gdi_log_buffer[GDI_LOG_MAX_LINES][GDI_LOG_MAX_LINE_LEN] = {0};
global U4 gdi_log_count = 0;
internal void debug_log(Str8 fmt, KTL_Str8 table) {
// A static buffer for our log lines.
LP_ UTF8 console_log_buffer[1024];
mem_zero(u8_(console_log_buffer), 1024);
// Format the string.
Str8 result = str8_fmt_ktl_buf(slice_ut_arr(console_log_buffer), table, fmt);
// Also write to our GDI log buffer
if (gdi_log_count < GDI_LOG_MAX_LINES) {
U4 len_to_copy = result.len < GDI_LOG_MAX_LINE_LEN - 1 ? result.len : GDI_LOG_MAX_LINE_LEN - 1;
mem_copy(u8_(gdi_log_buffer[gdi_log_count]), u8_(result.ptr), len_to_copy);
gdi_log_buffer[gdi_log_count][len_to_copy] = '\0';
gdi_log_count++;
}
// Get stdout handle.
MS_Handle stdout_handle = ms_get_std_handle(MS_STD_OUTPUT);
// Write the formatted string.
ms_write_console(stdout_handle, result.ptr, (U4)result.len, nullptr, 0);
// Write a newline.
ms_write_console(stdout_handle, (UTF8 const*r)"\n", 1, nullptr, 0);
}
void ms_builtin_print(U8 val) { void ms_builtin_print(U8 val) {
char val_hex[9];
u64_to_hex(val, val_hex, 8);
val_hex[8] = '\0';
KTL_Slot_Str8 log_table[] = {
{ ktl_str8_key("val"), str8(val_hex) },
};
debug_log(str8("ms_builtin_print called with: <val>"), ktl_str8_from_arr(log_table));
if (log_count < 16) log_buffer[log_count++] = val; if (log_count < 16) log_buffer[log_count++] = val;
} }
// Visual Linker & O(1) Dictionary // Visual Linker & O(1) Dictionary
global U4 tape_to_code_offset[65536] = {0}; global U4 tape_to_code_offset[65536] = {0};
// --- WinAPI Persistence ---
#define MS_GENERIC_READ 0x80000000
#define MS_GENERIC_WRITE 0x40000000
#define MS_CREATE_ALWAYS 2
#define MS_OPEN_EXISTING 3
#define MS_FILE_ATTRIBUTE_NORMAL 0x80
#define MS_VK_F1 0x70
#define MS_VK_F2 0x71
WinAPI void* ms_create_file_a(char const* lpFileName, U4 dwDesiredAccess, U4 dwShareMode, void* lpSecurityAttributes, U4 dwCreationDisposition, U4 dwFlagsAndAttributes, void* hTemplateFile) asm("CreateFileA");
WinAPI B4 ms_write_file(void* hFile, void const* lpBuffer, U4 nNumberOfBytesToWrite, U4* lpNumberOfBytesWritten, void* lpOverlapped) asm("WriteFile");
WinAPI B4 ms_read_file(void* hFile, void* lpBuffer, U4 nNumberOfBytesToRead, U4* lpNumberOfBytesRead, void* lpOverlapped) asm("ReadFile");
WinAPI B4 ms_close_handle(void* hObject) asm("CloseHandle");
#define PRIM_SWAP 1 #define PRIM_SWAP 1
#define PRIM_MULT 2 #define PRIM_MULT 2
#define PRIM_ADD 3 #define PRIM_ADD 3
@@ -73,6 +126,10 @@ global U4 tape_to_code_offset[65536] = {0};
#define PRIM_RET_Z 7 #define PRIM_RET_Z 7
#define PRIM_RET 8 #define PRIM_RET 8
#define PRIM_PRINT 9 #define PRIM_PRINT 9
#define PRIM_RET_S 10
#define PRIM_DUP 11
#define PRIM_DROP 12
#define PRIM_SUB 13
global const char* prim_names[] = { global const char* prim_names[] = {
"", "",
@@ -84,10 +141,45 @@ global const char* prim_names[] = {
"STORE ", "STORE ",
"RET_IF_Z", "RET_IF_Z",
"RETURN ", "RETURN ",
"PRINT " "PRINT ",
"RET_IF_S",
"DUP ",
"DROP ",
"SUB "
}; };
internal U4 resolve_name_to_index(const char* ref_name); internal U4 resolve_name_to_index(const char* ref_name);
internal void relink_tape(void);
IA_ void compile_and_run_tape(void);
internal void save_cartridge(void) {
void* hFile = ms_create_file_a("cartridge.bin", MS_GENERIC_WRITE, 0, nullptr, MS_CREATE_ALWAYS, MS_FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile != (void*)-1) {
U4 written = 0;
ms_write_file(hFile, & tape_arena.used, 8, & written, nullptr);
ms_write_file(hFile, & anno_arena.used, 8, & written, nullptr);
ms_write_file(hFile, & cursor_idx, 8, & written, nullptr);
ms_write_file(hFile, (void*)tape_arena.start, (U4)tape_arena.used, & written, nullptr);
ms_write_file(hFile, (void*)anno_arena.start, (U4)anno_arena.used, & written, nullptr);
ms_close_handle(hFile);
}
}
internal void load_cartridge(void) {
void* hFile = ms_create_file_a("cartridge.bin", MS_GENERIC_READ, 0, nullptr, MS_OPEN_EXISTING, MS_FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile != (void*)-1) {
U4 read = 0;
ms_read_file(hFile, & tape_arena.used, 8, & read, nullptr);
ms_read_file(hFile, & anno_arena.used, 8, & read, nullptr);
ms_read_file(hFile, & cursor_idx, 8, & read, nullptr);
ms_read_file(hFile, (void*)tape_arena.start, (U4)tape_arena.used, & read, nullptr);
ms_read_file(hFile, (void*)anno_arena.start, (U4)anno_arena.used, & read, nullptr);
ms_close_handle(hFile);
relink_tape();
compile_and_run_tape();
}
}
IA_ void scatter(U4 token, const char* anno_str) { IA_ void scatter(U4 token, const char* anno_str) {
if (tape_arena.used + sizeof(U4) <= tape_arena.capacity && anno_arena.used + sizeof(U8) <= anno_arena.capacity) { if (tape_arena.used + sizeof(U4) <= tape_arena.capacity && anno_arena.used + sizeof(U8) <= anno_arena.capacity) {
@@ -133,7 +225,8 @@ internal U4 resolve_name_to_index(const char* ref_name) {
U4*r tape_ptr = u4_r(tape_arena.start); U4*r tape_ptr = u4_r(tape_arena.start);
U8*r anno_ptr = u8_r(anno_arena.start); U8*r anno_ptr = u8_r(anno_arena.start);
for (int p = 1; p <= 9; p++) { U8 prim_count = array_len(prim_names);
for (int p = 1; p < prim_count; p++) {
int match = 1; int match = 1;
for (int c = 0; c < 8; c++) { for (int c = 0; c < 8; c++) {
char c1 = ref_name[c] ? ref_name[c] : ' '; char c1 = ref_name[c] ? ref_name[c] : ' ';
@@ -188,6 +281,10 @@ internal void compile_action(U4 val)
emit8(0x48); emit8(0x01); emit8(0xD0); emit8(0x48); emit8(0x01); emit8(0xD0);
pad32(); pad32();
return; return;
} else if (val == PRIM_SUB) {
emit8(0x48); emit8(0x29); emit8(0xD0);
pad32();
return;
} else if (val == PRIM_FETCH) { } else if (val == PRIM_FETCH) {
emit8(0x48); emit8(0x8B); emit8(0x04); emit8(0xC1); emit8(0x48); emit8(0x8B); emit8(0x04); emit8(0xC1);
pad32(); pad32();
@@ -206,21 +303,35 @@ internal void compile_action(U4 val)
emit8(0xC3); emit8(0xC3);
pad32(); pad32();
return; return;
} else if (val == PRIM_RET_S) {
emit8(0x48); emit8(0x85); emit8(0xC0);
emit8(0x79); emit8(0x01);
emit8(0xC3);
pad32();
return;
} else if (val == PRIM_RET) { } else if (val == PRIM_RET) {
emit8(0xC3); emit8(0xC3);
pad32(); pad32();
return; return;
} else if (val == PRIM_DUP) {
emit8(0x48); emit8(0x89); emit8(0xC2);
pad32();
return;
} else if (val == PRIM_DROP) {
emit8(0x48); emit8(0x89); emit8(0xD0);
pad32();
return;
} else if (val == PRIM_PRINT) { } else if (val == PRIM_PRINT) {
emit8(0x51); emit8(0x52); emit8(0x52); // push rdx
emit8(0x48); emit8(0x83); emit8(0xEC); emit8(0x20); emit8(0x48); emit8(0x83); emit8(0xEC); emit8(0x20); // sub rsp, 32 (shadow space)
emit8(0x48); emit8(0x89); emit8(0xC1); emit8(0x48); emit8(0x89); emit8(0xC1); // mov rcx, rax
emit8(0x49); emit8(0xB8); emit8(0x49); emit8(0xB8); // mov r8, ...
U8 addr = u8_(& ms_builtin_print); U8 addr = u8_(& ms_builtin_print);
emit32(u4_(addr & 0xFFFFFFFF)); emit32(u4_(addr & 0xFFFFFFFF));
emit32(u4_(addr >> 32)); emit32(u4_(addr >> 32));
emit8(0x41); emit8(0xFF); emit8(0xD0); emit8(0x41); emit8(0xFF); emit8(0xD0); // call r8
emit8(0x48); emit8(0x83); emit8(0xC4); emit8(0x20); emit8(0x48); emit8(0x83); emit8(0xC4); emit8(0x20); // add rsp, 32
emit8(0x5A); emit8(0x59); emit8(0x5A); // pop rdx
pad32(); pad32();
return; return;
} }
@@ -239,11 +350,13 @@ IA_ void compile_and_run_tape(void)
{ {
farena_reset(& code_arena); farena_reset(& code_arena);
log_count = 0; log_count = 0;
gdi_log_count = 0;
emit8(0x48); emit8(0x8B); emit8(0x41); emit8(0x70); emit8(0x48); emit8(0x8B); emit8(0x41); emit8(0x70);
emit8(0x48); emit8(0x8B); emit8(0x51); emit8(0x78); emit8(0x48); emit8(0x8B); emit8(0x51); emit8(0x78);
U4*r tape_ptr = u4_r(tape_arena.start); U4*r tape_ptr = u4_r(tape_arena.start);
U8*r anno_ptr = u8_r(anno_arena.start);
B4 in_def = false; B4 in_def = false;
U4 def_jmp_offset = 0; U4 def_jmp_offset = 0;
U8 end_idx = run_full ? (tape_arena.used / sizeof(U4)) : (cursor_idx + 1); U8 end_idx = run_full ? (tape_arena.used / sizeof(U4)) : (cursor_idx + 1);
@@ -251,6 +364,7 @@ IA_ void compile_and_run_tape(void)
{ {
U4 tag = unpack_tag(tape_ptr[i]); U4 tag = unpack_tag(tape_ptr[i]);
U4 val = unpack_val(tape_ptr[i]); U4 val = unpack_val(tape_ptr[i]);
if (tag == STag_Define) if (tag == STag_Define)
{ {
if (in_def == false) { if (in_def == false) {
@@ -270,18 +384,19 @@ IA_ void compile_and_run_tape(void)
emit8(0x48); emit8(0x87); emit8(0xC2); emit8(0x48); emit8(0x87); emit8(0xC2);
pad32(); pad32();
} }
else if (tag == STag_Call) else if (tag == STag_Call || tag == STag_Imm)
{ {
compile_action(val); char* name = (char*)&anno_ptr[i];
} char val_hex[9];
else if (tag == STag_Data) { u64_to_hex(val, val_hex, 8);
emit8(0x48); emit8(0x89); emit8(0xC2); val_hex[8] = '\0';
emit8(0x48); emit8(0xC7); emit8(0xC0); emit32(val); KTL_Slot_Str8 call_log_table[] = {
pad32(); { ktl_str8_key("name"), str8(name) },
} { ktl_str8_key("val"), str8(val_hex) },
else if (tag == STag_Imm) };
{ debug_log(str8("Compiling call: <name> (val: <val>)"), ktl_str8_from_arr(call_log_table));
if (in_def) {
if (tag == STag_Imm && in_def) {
emit8(0xC3); emit8(0xC3);
pad32(); pad32();
U4 current = code_arena.used; U4 current = code_arena.used;
@@ -290,6 +405,11 @@ IA_ void compile_and_run_tape(void)
} }
compile_action(val); compile_action(val);
} }
else if (tag == STag_Data) {
emit8(0x48); emit8(0x89); emit8(0xC2);
emit8(0x48); emit8(0xC7); emit8(0xC0); emit32(val);
pad32();
}
} }
if (in_def) { if (in_def) {
@@ -309,6 +429,18 @@ IA_ void compile_and_run_tape(void)
vm_rax = vm_globals[14]; vm_rax = vm_globals[14];
vm_rdx = vm_globals[15]; vm_rdx = vm_globals[15];
char rax_hex[9];
u64_to_hex(vm_rax, rax_hex, 8);
rax_hex[8] = '\0';
char rdx_hex[9];
u64_to_hex(vm_rdx, rdx_hex, 8);
rdx_hex[8] = '\0';
KTL_Slot_Str8 post_jit_log_table[] = {
{ ktl_str8_key("rax"), str8(rax_hex) },
{ ktl_str8_key("rdx"), str8(rdx_hex) },
};
debug_log(str8("JIT finished. RAX: <rax>, RDX: <rdx>"), ktl_str8_from_arr(post_jit_log_table));
} }
S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam)
@@ -359,6 +491,7 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam)
return 0; return 0;
} }
case MS_WM_KEYDOWN: { case MS_WM_KEYDOWN: {
if (wparam == 0x45 && editor_mode == MODE_NAV) { if (wparam == 0x45 && editor_mode == MODE_NAV) {
editor_mode = MODE_EDIT; editor_mode = MODE_EDIT;
mode_switch_now = true; mode_switch_now = true;
@@ -433,6 +566,8 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam)
if (wparam == MS_VK_PRIOR) { scroll_y_offset -= 100; if (scroll_y_offset < 0) scroll_y_offset = 0; } if (wparam == MS_VK_PRIOR) { scroll_y_offset -= 100; if (scroll_y_offset < 0) scroll_y_offset = 0; }
if (wparam == MS_VK_NEXT) { scroll_y_offset += 100; } if (wparam == MS_VK_NEXT) { scroll_y_offset += 100; }
if (wparam == MS_VK_F5) { run_full = !run_full; } if (wparam == MS_VK_F5) { run_full = !run_full; }
if (wparam == MS_VK_F1) { save_cartridge(); }
if (wparam == MS_VK_F2) { load_cartridge(); ms_invalidate_rect(hwnd, nullptr, true); }
if (wparam == MS_VK_TAB) { if (wparam == MS_VK_TAB) {
U4 t = tape_ptr[cursor_idx]; U4 t = tape_ptr[cursor_idx];
@@ -631,6 +766,18 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam)
ms_set_text_color(hdc, 0x0094BAA1); ms_set_text_color(hdc, 0x0094BAA1);
ms_text_out_a(hdc, 750, 550 + (i * 25), log_str, 8); ms_text_out_a(hdc, 750, 550 + (i * 25), log_str, 8);
} }
ms_set_text_color(hdc, 0x00C8C8C8);
ms_text_out_a(hdc, 40, 650, "Debug Log:", 10);
for (U4 i = 0; i < gdi_log_count; i++) {
U4 len = 0;
while(gdi_log_buffer[i][len] != '\0' && len < GDI_LOG_MAX_LINE_LEN) {
len++;
}
ms_set_text_color(hdc, 0x00AAAAAA);
ms_text_out_a(hdc, 40, 670 + (i * 20), gdi_log_buffer[i], len);
}
ms_select_object(hdc, hOldFont); ms_select_object(hdc, hOldFont);
ms_delete_object(hBgBrush); ms_delete_object(hBgBrush);
ms_delete_object(hBrushEdit); ms_delete_object(hBrushEdit);
@@ -699,6 +846,9 @@ int main(void) {
scatter(pack_token(STag_Imm, 0), "F_STEP "); scatter(pack_token(STag_Imm, 0), "F_STEP ");
relink_tape(); relink_tape();
run_full = true;
compile_and_run_tape();
run_full = false;
MS_WNDCLASSA wc; MS_WNDCLASSA wc;
mem_fill(u8_(& wc), 0, sizeof(wc)); mem_fill(u8_(& wc), 0, sizeof(wc));