more fixes for codegen

This commit is contained in:
janis 2025-11-01 02:50:39 +01:00
parent a25dcdabbb
commit 105c052e95
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
3 changed files with 78 additions and 96 deletions

View file

@ -29,7 +29,7 @@ section .rdata
EPILOGUE_LEN equ $ - EPILOGUE EPILOGUE_LEN equ $ - EPILOGUE
MOV_RAX db "mov rax, " MOV_RAX db "mov rax, "
MOV_RAX_LEN equ $ - MOV_RAX MOV_RAX_LEN equ $ - MOV_RAX
JMP_EPILOGUE db 10, "jmp .epilogue", 10 JMP_EPILOGUE db "jmp .epilogue", 10
JMP_EPILOGUE_LEN equ $ - JMP_EPILOGUE JMP_EPILOGUE_LEN equ $ - JMP_EPILOGUE
DOT_ARGS db ".args:", 10 DOT_ARGS db ".args:", 10
DOT_ARGS_LEN equ $ - DOT_ARGS DOT_ARGS_LEN equ $ - DOT_ARGS
@ -39,11 +39,11 @@ section .rdata
DOT_PROLOGUE_LEN equ $ - DOT_PROLOGUE DOT_PROLOGUE_LEN equ $ - DOT_PROLOGUE
DOT_EPILOGUE db ".epilogue:", 10 DOT_EPILOGUE db ".epilogue:", 10
DOT_EPILOGUE_LEN equ $ - DOT_EPILOGUE DOT_EPILOGUE_LEN equ $ - DOT_EPILOGUE
JMP_ARGS db 10, "jmp .args", 10 JMP_ARGS db "jmp .args", 10
JMP_ARGS_LEN equ $ - JMP_ARGS JMP_ARGS_LEN equ $ - JMP_ARGS
JMP_BODY db 10, "jmp .body", 10 JMP_BODY db "jmp .body", 10
JMP_BODY_LEN equ $ - JMP_BODY JMP_BODY_LEN equ $ - JMP_BODY
JMP_PROLOGUE db 10, "jmp .prologue", 10 JMP_PROLOGUE db "jmp .prologue", 10
JMP_PROLOGUE_LEN equ $ - JMP_PROLOGUE JMP_PROLOGUE_LEN equ $ - JMP_PROLOGUE
SUB_RSP db "sub rsp, " SUB_RSP db "sub rsp, "
SUB_RSP_LEN equ $ - SUB_RSP SUB_RSP_LEN equ $ - SUB_RSP
@ -273,8 +273,8 @@ stackvar_cmp:
;; struct FunctionCtx { ;; struct FunctionCtx {
;; current_stack_size: u64, ;; current_stack_size: u64,
;; stack_vars: Vec<(u64, u64)>, ;; stack_vars: Vec<(u64, u64)>,
;; register_bitset: u128, ;; register_bitset: u16,
;; dirtied_register_bitset: u128, ;; dirtied_register_bitset: u16,
;; } ;; }
;; end-structs ;; end-structs
@ -296,41 +296,27 @@ codegen_allocate_register:
; dirtied registers are those that have been used in the function and need ; dirtied registers are those that have been used in the function and need
; to be saved/restored in the prologue/epilogue ; to be saved/restored in the prologue/epilogue
mov rax, [rdi + 48] ; register_bitset mov ax, word [rdi + 48] ; register_bitset
xor rcx, rcx xor rcx, rcx
; flip bits ; flip bits
not rax not ax
; find first set bit test ax, ax
bsf rcx, rax
test rcx, rcx
jnz .found
mov rax, [rdi + 56] ; higher 64 bits
not rax
bsf rcx, rax
test rcx, rcx
jz .panic jz .panic
add rcx, 8 ; find first set bit
bsf cx, ax
.found: .found:
mov rbx, rcx mov rbx, rcx
cmp rcx, 8 mov ax, word [rdi + 48] ; update register_bitset
jl .set_low bts ax, cx
sub rcx, 8 mov word [rdi + 48], ax ; update register_bitset
bts rax, rcx mov ax, word [rdi + 52] ; dirtied_register_bitset
mov [rdi + 56], rax ; update register_bitset bts ax, cx
mov rax, [rdi + 72] ; dirtied_register_bitset mov word [rdi + 52], ax ; update dirtied_register_bitset
bts rax, rcx
mov [rdi + 72], rax ; update dirtied_register_bitset
jmp .done
.set_low:
bts rax, rcx
mov [rdi + 48], rax ; update register_bitset
mov rax, [rdi + 64] ; dirtied_register_bitset
bts rax, rcx
mov [rdi + 64], rax ; update dirtied_register_bitset
.done: .done:
pop rax mov rax, rbx
pop rbx
pop rbp pop rbp
ret ret
.panic: .panic:
@ -349,8 +335,9 @@ codegen_function:
push r13 push r13
; scratch [104..120] ; scratch [104..120]
; dirtied-register-bitset [88..104] [a,b,c,d,si,di,bp,sp,8,9,10,11,12,13,14,15] ; scratch2 [80..104]
; register-bitset [72..88] [a,b,c,d,si,di,bp,sp,8,9,10,11,12,13,14,15] ; dirtied-register-bitset [76..80] [a,b,c,d,si,di,bp,sp,8,9,10,11,12,13,14,15]
; register-bitset [72..76] [a,b,c,d,si,di,bp,sp,8,9,10,11,12,13,14,15]
; stack-vars: Vec<(index, offset)> [32..72] ; stack-vars: Vec<(index, offset)> [32..72]
; current_stack_size: [24..32] ; current_stack_size: [24..32]
; func_idx [16..24] ; func_idx [16..24]
@ -369,8 +356,9 @@ codegen_function:
mov rcx, 16 ; initial capacity mov rcx, 16 ; initial capacity
call vec_init_with call vec_init_with
bts qword [rsp + 72], 7 ; mark rsp as used bts word [rsp + 72], 7 ; mark rsp as used
bts qword [rsp + 72], 6 ; mark rbp as used bts word [rsp + 72], 6 ; mark rbp as used
bts word [rsp + 72], 0 ; mark rax as used
; push "section .text\n" ; push "section .text\n"
mov rdi, [rsp] ; ctx mov rdi, [rsp] ; ctx
@ -502,7 +490,7 @@ codegen_function:
; "pop {dirtied registers}\n" ; "pop {dirtied registers}\n"
mov rdi, [rsp] ; ctx mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text lea rdi, [rdi + 8] ; &ctx.text
mov rsi, [rsp + 24] ; &function_ctx lea rsi, [rsp + 24] ; &function_ctx
mov rdx, 0 ; push = false mov rdx, 0 ; push = false
call codegen_push_pop_dirtied_registers call codegen_push_pop_dirtied_registers
@ -513,13 +501,20 @@ codegen_function:
mov rdx, ADD_RSP_LEN mov rdx, ADD_RSP_LEN
call vec_extend call vec_extend
mov rdi, [rsp + 24] ; &function_ctx lea rdi, [rsp + 24] ; &function_ctx
mov rdi, [rdi + 0] ; current_stack_size mov rdi, [rdi + 0] ; current_stack_size
lea rsi, [rsp + 104] ; scratch lea rsi, [rsp + 104] ; scratch
mov rdx, 16 ; buffer length mov rdx, 16 ; buffer length
mov rcx, 10 ; radix mov rcx, 10 ; radix
call int_to_str2 call int_to_str2
; ; push "\n"
; mov rdi, [rsp] ; ctx
; lea rdi, [rdi + 8] ; &ctx.text
; lea rsi, [rel COLON_NL]
; inc rsi
; call vec_push
mov rdi, [rsp] ; ctx mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rax + rdx] lea rsi, [rax + rdx]
@ -549,13 +544,20 @@ codegen_function:
mov rdx, SUB_RSP_LEN mov rdx, SUB_RSP_LEN
call vec_extend call vec_extend
mov rdi, [rsp + 24] ; &function_ctx lea rdi, [rsp + 24] ; &function_ctx
mov rdi, [rdi + 0] ; current_stack_size mov rdi, [rdi + 0] ; current_stack_size
lea rsi, [rsp + 104] ; scratch lea rsi, [rsp + 104] ; scratch
mov rdx, 16 ; buffer length mov rdx, 16 ; buffer length
mov rcx, 10 ; radix mov rcx, 10 ; radix
call int_to_str2 call int_to_str2
; ; push "\n"
; mov rdi, [rsp] ; ctx
; lea rdi, [rdi + 8] ; &ctx.text
; lea rsi, [rel COLON_NL]
; inc rsi
; call vec_push
mov rdi, [rsp] ; ctx mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rax + rdx] lea rsi, [rax + rdx]
@ -567,7 +569,7 @@ codegen_function:
; "push{dirtied registers}\n" ; "push{dirtied registers}\n"
mov rdi, [rsp] ; ctx mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text lea rdi, [rdi + 8] ; &ctx.text
mov rsi, [rsp + 24] ; &function_ctx lea rsi, [rsp + 24] ; &function_ctx
mov rdx, 1 ; push = false mov rdx, 1 ; push = false
call codegen_push_pop_dirtied_registers call codegen_push_pop_dirtied_registers
@ -578,10 +580,11 @@ codegen_function:
mov rdx, JMP_ARGS_LEN mov rdx, JMP_ARGS_LEN
call vec_extend call vec_extend
.epilogue:
add rsp, 120 add rsp, 120
push r13 pop r13
push r14 pop r14
push r15 pop r15
pop rbx pop rbx
pop rbp pop rbp
ret ret
@ -605,11 +608,11 @@ codegen_push_pop_dirtied_registers:
mov byte [rsp + 29 + 3], 10 ; newline mov byte [rsp + 29 + 3], 10 ; newline
mov qword [rsp + 16], -1 mov qword [rsp + 16], -1
mov rax, ' hsup' mov rax, 'push '
mov qword [rsp + 24], rax mov qword [rsp + 24], rax
test rdx, rdx test rdx, rdx
jz .skip_setup_pop jz .skip_setup_pop
mov rax, ' pop' mov rax, 'pop '
mov qword [rsp + 24], rax mov qword [rsp + 24], rax
mov rdi, [rsp] ; text mov rdi, [rsp] ; text
@ -617,53 +620,24 @@ codegen_push_pop_dirtied_registers:
mov [rsp + 16], rax mov [rsp + 16], rax
.skip_setup_pop: .skip_setup_pop:
; low: 0b01000000 high: 0b00001111 ; abcdsdpp_89abcdef
; 01000000_00001111
; preserved registers: ; preserved registers:
mov rax, [rsi + 48 + 16] ; dirtied_register_bitset low mov bx, word [rsi + 48 + 4] ; dirtied_register_bitset
mov rbx, 0b01000000 mov ax, 0b11110000_00000010
and rax, rbx and bx, ax
test rax, rax test bx, bx
jz .skip_rbp
mov rdi, 2
mov rsi, 8
lea rdx, [rsp + 29]
call get_register_name
mov rax, -1
cmp [rsp + 16], rax
jne .rbx_pop
mov rdi, [rsp] ; text
lea rsi, [rsp + 24]
mov rdx, 9
call vec_extend
jmp .skip_rbp
.rbx_pop:
mov rdi, [rsp] ; text
lea rsi, [rsp + 24]
mov rdx, 9
mov rcx, [rsp + 16] ; text.len()
call vec_insert_many
.skip_rbp:
mov rax, [rsi + 48 + 16 + 8] ; dirtied_register_bitset high
mov rbx, 0b00001111
and rax, rbx
test rax, rax
jz .done jz .done
mov r15, 8 mov r15, 16
xor r14, r14 xor r14, r14
.reg_loop: .reg_loop:
cmp r14, r15 cmp r14, r15
jge .done jge .done
bt rax, r14 bt bx, r14w
jnc .next_reg jnc .next_reg
mov rdi, 8 mov rdi, r14
add rdi, r14
mov rsi, 8 mov rsi, 8
lea rdx, [rsp + 29] lea rdx, [rsp + 29]
call get_register_name call get_register_name
@ -680,11 +654,11 @@ codegen_push_pop_dirtied_registers:
.reg_pop: .reg_pop:
mov rdi, [rsp] ; text mov rdi, [rsp] ; text
lea rsi, [rsp + 24] mov rsi, [rsp + 16] ; text.len()
mov rdx, 9 lea rdx, [rsp + 24]
mov rcx, [rsp + 16] ; text.len() mov rcx, 9
call vec_insert_many call vec_insert_many
nop
.next_reg: .next_reg:
inc r14 inc r14
@ -823,14 +797,14 @@ codegen_expr:
mov [rsp + 40], rdx mov [rsp + 40], rdx
mov rdi, [rsp] ; ctx mov rdi, [rsp] ; ctx
mov rdi, [rdi + 8] ; &ctx.text lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rsp + 32] ; dst lea rsi, [rsp + 32] ; dst
lea rdx, [rsp + 16] ; src lea rdx, [rsp + 16] ; src
call codegen_move_dst_src call codegen_move_dst_src
; push "jmp .epilogue\n" ; push "jmp .epilogue\n"
mov rdi, [rsp] ; ctx mov rdi, [rsp] ; ctx
mov rdi, [rdi + 8] ; &ctx.text lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rel JMP_EPILOGUE] lea rsi, [rel JMP_EPILOGUE]
mov rdx, JMP_EPILOGUE_LEN mov rdx, JMP_EPILOGUE_LEN
call vec_extend call vec_extend
@ -871,9 +845,9 @@ codegen_expr:
mov word [rsp + 34], 0 ; Operand.len = 0 mov word [rsp + 34], 0 ; Operand.len = 0
mov rdi, [rsp] ; ctx mov rdi, [rsp] ; ctx
mov rdi, [rdi + 8] ; &ctx.text lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rsp + 16] ; dst lea rsi, [rsp + 16] ; dst
lea rdx, [rsp + 16] ; src lea rdx, [rsp + 32] ; src
call codegen_move_dst_src call codegen_move_dst_src
mov rax, qword [rsp + 16] mov rax, qword [rsp + 16]
@ -1252,6 +1226,12 @@ codegen_move_dst_src:
call codegen_write_operand call codegen_write_operand
.epilogue: .epilogue:
mov rdi, [rsp] ; *text
lea rsi, [rel COLON_NL]
inc rsi
mov rdx, 1
call vec_extend
add rsp, 24 add rsp, 24
pop rbx pop rbx
pop rbp pop rbp

View file

@ -76,14 +76,16 @@ fn main() {
let mut codegen = util::defs::CodegenCtx { let mut codegen = util::defs::CodegenCtx {
ast: &mut ast, ast: &mut ast,
text: util::vec::Vec::new(), text: util::vec::Vec::new_with(1024),
}; };
util::defs::codegen_function(&mut codegen, expr_id); util::defs::codegen_function(&mut codegen, expr_id);
eprintln!("Code generation completed.");
println!( println!(
"Generated code:\n{}", "Generated code:\n{}",
core::str::from_utf8(codegen.text.as_slice()).unwrap() core::str::from_utf8_unchecked(codegen.text.as_slice())
); );
}; };
} }

View file

@ -216,8 +216,8 @@ pub struct CodegenCtx {
pub struct FunctionCtx { pub struct FunctionCtx {
pub current_stack_size: u64, pub current_stack_size: u64,
pub stack_vars: Vec<(u64, u64)>, pub stack_vars: Vec<(u64, u64)>,
pub register_bitset: u128, pub register_bitset: u16,
pub dirtied_register_bitset: u128, pub dirtied_register_bitset: u16,
} }
#[repr(C)] #[repr(C)]