From da2a298baf7644a0a3afa6cfbb0bf24b6d1fea60 Mon Sep 17 00:00:00 2001 From: janis Date: Fri, 31 Oct 2025 17:14:20 +0100 Subject: [PATCH] get-register-name from width and index --- lang/src/codegen.asm | 176 ++++++++++++++++++++++++++++++++++++-- lang/tests/codegen.rs | 63 +++++++++++--- lang/tests/shared/defs.rs | 4 + 3 files changed, 224 insertions(+), 19 deletions(-) diff --git a/lang/src/codegen.asm b/lang/src/codegen.asm index 6c9d9d8..597e42f 100644 --- a/lang/src/codegen.asm +++ b/lang/src/codegen.asm @@ -5,9 +5,11 @@ default rel extern panic extern vec_extend extern vec_get +extern vec_push extern vec_init_with global codegen_function +global get_register_name section .rdata SECTION_TEXT db "section .text", 10 @@ -20,10 +22,132 @@ section .rdata RET_NL_LEN equ $ - RET_NL PROLOGUE db "push rbp", 10, "mov rbp, rsp", 10 PROLOGUE_LEN equ $ - PROLOGUE + EPILOGUE db "mov rsp, rbp", 10, "pop rbp", 10, "ret", 10 + EPILOGUE_LEN equ $ - EPILOGUE + + REGISTER_NAMES db "abcdsidibpspr8r9r10r11r12r13r14r15" + WIDTHS db "erxliwdbp" section .text +;; ```rust +;; use super::FFISlice; +;; ``` +;; rdi: register index +;; rsi: register width (1=byte,2=word,4=dword,8=qword) +;; rdx: *mut u8 (buffer, at least 4 bytes) +;; define-fn: fn get_register_name(reg_idx: u8, width: u8, buffer: *mut u8) -> FFISlice +get_register_name: + push rbp + mov rbp, rsp + push rdx + push rdi + + cmp rdi, 8 + jge .skip_prefix + mov rcx, 0 + cmp rsi, 8 + mov rax, 'r' + cmove rcx, rax + cmp rsi, 4 + mov rax, 'e' + cmove rcx, rax + cmp cl, 0 + je .skip_prefix + mov byte [rdx], cl + inc rdx +.skip_prefix: + push rsi + call write_register_name + pop rsi + mov rdi, [rsp] + + cmp rdi, 4 + jge .check81 + cmp rsi, 2 + jl .check81 + mov byte [rdx], 'x' + inc rdx + jmp .done +.check81: + cmp rdi, 8 + jge .ext_suffix + cmp rsi, 1 + jne .done + mov byte [rdx], 'l' + inc rdx + jmp .done +.ext_suffix: + mov rcx, 0 + cmp rsi, 4 + mov rax, 'd' + cmove rcx, rax + cmp rsi, 2 + mov rax, 'w' + cmove rcx, rax + cmp rsi, 1 + mov rax, 'b' + cmove rcx, rax + cmp rcx, 0 + je .done + mov byte [rdx], cl + inc rdx + +.done: + pop rdi + pop rax + xchg rax, rdx + sub rax, rdx + xchg rax, rdx + pop rbp + ret +.panic: + call panic + +;; rdi: register index +;; rdx: *mut u8 (buffer, at least 2 bytes) +write_register_name: + cmp rdi, 4 + jl .abcd + cmp rdi, 10 + jl .two_digit + ; 10,11,12,13,14,15 + lea rsi, [rel REGISTER_NAMES + 16] + sub rdi, 10 + lea rsi, [rsi + rdi * 2] + add rsi, rdi + mov al, [rsi + 0] + mov [rdx], al + inc rdx + mov al, [rsi + 1] + mov [rdx], al + inc rdx + mov al, [rsi + 2] + mov [rdx], al + inc rdx + jmp .done +.two_digit: + lea rsi, [rel REGISTER_NAMES + 4] + sub rdi, 4 + lea rsi, [rsi + rdi * 2] + mov al, [rsi + 0] + mov [rdx], al + inc rdx + mov al, [rsi + 1] + mov [rdx], al + inc rdx + jmp .done +.abcd: + lea rsi, [rel REGISTER_NAMES + 0] + lea rsi, [rsi + rdi * 1] + mov al, [rsi + 0] + mov [rdx], al + inc rdx +.done: + ret + + ;; rdi: ctx ;; rsi: a: *const (index, offset) ;; rdx: b: *const (index, offset) @@ -63,19 +187,22 @@ codegen_function: push rbp mov rbp, rsp push rbx + push r15 + push r14 - ; register-bitset [72..88] [a,b,c,d,di,si,sp,bp,8,9,10,11,12,13,14,15] + ; scratch [88..104] + ; register-bitset [72..88] [a,b,c,d,si,di,bp,sp,8,9,10,11,12,13,14,15] ; stack-vars: Vec<(index, offset)> [32..72] ; current_stack_size: [24..32] ; func_idx [16..24] ; ast [8..16] ; ctx [0..8] - sub rsp, 88 + sub rsp, 104 mov [rsp], rdi ; ctx mov rax, [rdi] mov [rsp + 8], rax ; ast mov [rsp + 16], rsi ; func_idx - mov [rsp + 24], 0 ; current_stack_size = 0 + mov qword [rsp + 24], 0 ; current_stack_size = 0 lea rdi, [rsp + 32] ; stack-vars mov rsi, 16 ; size_of::<(u64, u64)> @@ -83,8 +210,8 @@ codegen_function: mov rcx, 16 ; initial capacity call vec_init_with - bts qword [rsp + 72], 7 ; mark rbp as used - bts qword [rsp + 72], 6 ; mark rsp as used + bts qword [rsp + 72], 7 ; mark rsp as used + bts qword [rsp + 72], 6 ; mark rbp as used ; push "section .text\n" mov rdi, [rsp] ; ctx @@ -139,6 +266,36 @@ codegen_function: mov rdx, PROLOGUE_LEN call vec_extend + ; allocate args on stack + ; rbx = *AstFunction + + mov r15, [rbx + 24] ; AstFunction.args_len + xor r14, r14 ; arg index +.arg_loop: + cmp r14, r15 + jge .arg_loop_done + mov rax, [rbx + 16] ; AstFunction.args + lea rsi, [rax + r14 * 8] ; + mov rsi, [rsi] ; AstFunction.args[i] + + mov [rsp + 88], rsi + mov rax, [rsp + 24] ; current_stack_size + mov [rsp + 96], rax + add rax, 8 ; size_of:: + mov [rsp + 24], rax ; current_stack_size += size_of:: + lea rdi, [rsp + 32] ; stack-vars + lea rsi, [rsp + 88] ; &(index, offset) + call vec_push + inc r14 + jmp .arg_loop + + .arg_loop_done: + + mov rdi, [rsp] ; ctx + lea rsi, [rsp + 24] ; &function_ctx + call codegen_block + + ; TODO: generate function body ; push "ret\n" @@ -148,10 +305,17 @@ codegen_function: mov rdx, RET_NL_LEN call vec_extend - add rsp, 88 + add rsp, 104 + pop r15 + pop r14 pop rbx pop rbp ret .panic: call panic + +;; rdi: ctx +;; rsi: &function_ctx +codegen_block: + ret diff --git a/lang/tests/codegen.rs b/lang/tests/codegen.rs index d43383e..bb21698 100644 --- a/lang/tests/codegen.rs +++ b/lang/tests/codegen.rs @@ -19,8 +19,45 @@ fn main() { bump_init(); } println!("Bump allocator initialized."); - - let src = b"3 + 4"; + unsafe { + let mut buf = [0u8; 4]; + assert_eq!( + util::defs::get_register_name(0, 4, buf.as_mut_ptr()).as_str(), + "eax" + ); + assert_eq!( + util::defs::get_register_name(7, 8, buf.as_mut_ptr()).as_str(), + "rsp" + ); + assert_eq!( + util::defs::get_register_name(7, 4, buf.as_mut_ptr()).as_str(), + "esp" + ); + assert_eq!( + util::defs::get_register_name(7, 2, buf.as_mut_ptr()).as_str(), + "sp" + ); + assert_eq!( + util::defs::get_register_name(7, 1, buf.as_mut_ptr()).as_str(), + "spl" + ); + assert_eq!( + util::defs::get_register_name(9, 1, buf.as_mut_ptr()).as_str(), + "r9b" + ); + assert_eq!( + util::defs::get_register_name(12, 1, buf.as_mut_ptr()).as_str(), + "r12b" + ); + assert_eq!( + util::defs::get_register_name(12, 4, buf.as_mut_ptr()).as_str(), + "r12d" + ); + assert_eq!( + util::defs::get_register_name(8, 2, buf.as_mut_ptr()).as_str(), + "r8w" + ); + } fn print_ast(src: &[u8], parser: impl FnOnce(&mut Ast) -> u64) { unsafe { @@ -51,15 +88,15 @@ fn main() { }; } - print_ast( - b"fn main(a: u32) -> void { -let y: u32 = a + 4; -{ - let y: u32 = 10; -} -let y: *u32 = &y; -return *y; -}", - |ast| unsafe { parse_func(ast) }, - ); + // print_ast( + // b"fn main(a: u32) -> void { + // let y: u32 = a + 4; + // { + // let y: u32 = 10; + // } + // let y: *u32 = &y; + // return *y; + // }", + // |ast| unsafe { parse_func(ast) }, + // ); } diff --git a/lang/tests/shared/defs.rs b/lang/tests/shared/defs.rs index e4a83cf..a405790 100644 --- a/lang/tests/shared/defs.rs +++ b/lang/tests/shared/defs.rs @@ -17,6 +17,8 @@ unsafe extern "C" { pub unsafe fn ast_build_symtable(ast: *mut Ast, root_index: u64, symtable: *mut core::mem::MaybeUninit); pub unsafe fn ast_walk_for_each(ast: *mut Ast, start_index: u64, ctx: *mut (), for_each: unsafe extern "C" fn(ctx: *mut (), *mut Ast, node_index: u64, scope: u64)); pub unsafe fn ast_resolve_var_refs(ast: *mut Ast, ctx: *mut SymbolTable, root_index: u64); + pub unsafe fn get_register_name(reg_idx: u8, width: u8, buffer: *mut u8) -> FFISlice; + pub unsafe fn stackvar_cmp(a: *const (u64, u64), b: *const (u64, u64)) -> i32; pub unsafe fn codegen_function(ast: *const CodegenCtx, func_idx: u64) -> (); pub unsafe fn vec_extend(vec: *mut BlobVec, elements: *const u8, count: usize) -> (); } @@ -210,3 +212,5 @@ pub struct BlobVec { } use super::vec::Vec; + +use super::FFISlice;