From ecb4a83153586985ce6923b4fd8c6212e80b748f Mon Sep 17 00:00:00 2001 From: janis Date: Sat, 1 Nov 2025 16:18:01 +0100 Subject: [PATCH] allocate/free operand methods --- lang/src/codegen.asm | 117 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 2 deletions(-) diff --git a/lang/src/codegen.asm b/lang/src/codegen.asm index 9e74725..087614d 100644 --- a/lang/src/codegen.asm +++ b/lang/src/codegen.asm @@ -301,7 +301,7 @@ codegen_allocate_register: ; flip bits not ax test ax, ax - jz .panic + jz .no_regs ; find first set bit bsf cx, ax @@ -313,14 +313,127 @@ codegen_allocate_register: mov ax, word [rdi + 52] ; dirtied_register_bitset bts ax, cx mov word [rdi + 52], ax ; update dirtied_register_bitset + jmp .done + +.no_regs: + ; return -1u64 to indicate no free registers + ; the caller should panic or allocate a stack slot instead + mov rbx, -1 .done: mov rax, rbx pop rbx pop rbp ret + +;; rdi: *FunctionCtx +;; rsi: width +;; define-fn: fn codegen_allocate_value(ctx: *mut FunctionCtx, width: u16) -> Operand +codegen_allocate_value: + push rbp + mov rbp, rsp + push rbx + + ; width [8..16] + ; *FunctionCtx [0..8] + sub rsp, 16 + + mov [rsp], rdi ; ctx + mov [rsp + 8], rsi ; width + + cmp rsi, 8 + jg .alloc_stack + +.alloc_reg: + call codegen_allocate_register + cmp rax, -1 + je .alloc_stack + + mov rbx, rax + + ; construct Operand + xor rax, rax + mov eax, 0 ; Operand.len = 0 + shl eax, 16 + mov rsi, [rsp + 8] ; width + or eax, esi ; Operand.width + shl eax, 4 + or eax, rbx ; Operand.register + shl eax, 8 + or eax, OPERAND_REGISTER ; Operand.kind + mov rdx, 0 ; Operand.value = 0 + jmp .done + +.alloc_stack: + mov rdi, [rsp] ; ctx + mov rdx, [rdi + 0] ; current_stack_size + add rdx, [rsp + 8] ; width + mov [rdi + 0], rdx ; current_stack_size += width + + ; construct Operand + xor rax, rax + mov eax, 0 ; Operand.len = 0 + shl eax, 16 + mov rsi, [rsp + 8] ; width + or eax, esi ; Operand.width + shl eax, 4 + ; or eax, 0 ; Operand.register = undef + shl eax, 8 + or eax, OPERAND_RBP_OFFSET ; Operand.kind + +.done: + add rsp, 16 + pop rbx + pop rbp + ret + +;; rdi: *FunctionCtx +;; rsi: *Operand +;; define-fn: fn codegen_free_operand(ctx: *mut FunctionCtx, operand: *const Operand) -> () +codegen_free_operand: + push rbp + mov rbp, rsp + push rbx + + sub rsp, 16 + mov [rsp], rdi ; ctx + mov [rsp + 8], rsi ; operand + + mov al, byte [rsi] ; Operand.kind + cmp al, OPERAND_REGISTER + je .free_reg + cmp al, OPERAND_RBP_OFFSET + je .free_stack + jmp .done + +.free_stack: + mov rbx, [rdi + 0] ; current_stack_size + mov rax, [rsi + 8] ; Operand.value + cmp rbx, rax + jne .done ; operand not at top of stack, can't free + + mov al, byte [rsi + 1] ; Operand.width + shl al, 4 + movzx rax, al + sub rbx, rax + mov [rdi + 0], rbx ; current_stack_size -= width + jmp .done + +.free_reg: + xor rax, rax + mov al, byte [rsi + 1] ; Operand.register_and_width + and al, 0x0F ; get register index + mov bx, word [rdi + 48] ; register_bitset + btr bx, ax + jnc .panic ; trying to free unallocated register + mov word [rdi + 48], bx ; update register_bitset + +.done: + add rsp, 16 + pop rbx + pop rbp + ret .panic: - ; no free registers! call panic ;; rdi: *Ctx