codegen for binop
This commit is contained in:
parent
b9712dacfb
commit
6ebc6afb2b
|
|
@ -1,6 +1,7 @@
|
|||
default rel
|
||||
|
||||
%include "src/ast.inc"
|
||||
%include "src/tokeniser.inc"
|
||||
|
||||
extern panic
|
||||
extern vec_extend
|
||||
|
|
@ -10,6 +11,7 @@ extern vec_insert_sorted
|
|||
extern vec_insert_many
|
||||
extern vec_init_with
|
||||
extern int_to_str2
|
||||
extern strlen
|
||||
|
||||
global codegen_function
|
||||
global get_register_name
|
||||
|
|
@ -961,10 +963,10 @@ codegen_expr:
|
|||
push r15
|
||||
push r14
|
||||
|
||||
; scratch [16..48]
|
||||
; scratch [16..80]
|
||||
; function_ctx: [8..16]
|
||||
; ctx [0..8]
|
||||
sub rsp, 48
|
||||
sub rsp, 80
|
||||
mov [rsp], rdi ; ctx
|
||||
mov [rsp + 8], rsi ; &function_ctx
|
||||
|
||||
|
|
@ -1090,9 +1092,201 @@ codegen_expr:
|
|||
mov rdx, qword [rsp + 24]
|
||||
jmp .done
|
||||
|
||||
.binary_op:
|
||||
mov rax, [rax + 8] ; AstNode.data
|
||||
mov [rsp + 16], rax ; scratch = *AstBinaryOp
|
||||
|
||||
mov rdi, [rsp] ; ctx
|
||||
mov rsi, [rsp + 8] ; &function_ctx
|
||||
mov rdx, [rax + 0] ; left operand index
|
||||
call codegen_expr
|
||||
mov [rsp + 32], rax ; left operand
|
||||
mov [rsp + 40], rdx
|
||||
|
||||
mov rdi, [rsp] ; ctx
|
||||
mov rsi, [rsp + 8] ; &function_ctx
|
||||
mov rdx, [rsp + 16] ; *AstBinaryOp
|
||||
mov rdx, [rdx + 16] ; right operand index
|
||||
call codegen_expr
|
||||
mov [rsp + 48], rax ; right operand
|
||||
mov [rsp + 56], rdx
|
||||
|
||||
mov rax, [rsp + 16] ; *AstBinaryOp
|
||||
mov al, byte [rax + 8] ; operator
|
||||
mov rbx, -1
|
||||
cmp al, TOKEN_PLUS
|
||||
cmove rbx, [rel ADD_]
|
||||
cmp al, TOKEN_MINUS
|
||||
cmove rbx, [rel SUB_]
|
||||
cmp rbx, -1
|
||||
jne .gen_op
|
||||
cmp al, TOKEN_STAR
|
||||
cmove rbx, [rel MUL_]
|
||||
cmp al, TOKEN_SLASH
|
||||
cmove rbx, [rel DIV_]
|
||||
cmp al, TOKEN_PERCENT
|
||||
cmove rbx, [rel DIV_]
|
||||
cmp rbx, -1
|
||||
je .panic ; unknown operator
|
||||
.mul_div:
|
||||
; mul/div need to clobber rax:rdx
|
||||
|
||||
; TODO only check for div
|
||||
mov rax, [rsp + 8] ; &function_ctx
|
||||
mov ax, word [rax + 48] ; register_bitset
|
||||
bt ax, 3 ; is rdx used?
|
||||
jnc .after_spill_rdx
|
||||
|
||||
; allocate scratch value for rdx
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
mov rsi, 8 ; width
|
||||
call codegen_allocate_place
|
||||
mov [rsp + 64], rax
|
||||
mov [rsp + 72], rdx
|
||||
|
||||
; mov scratch, rdx
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rsp + 64] ; scratch value
|
||||
lea rdx, [rel OPERAND_RDX] ; rax
|
||||
call codegen_move_dst_src
|
||||
|
||||
; check if rhs is rdx
|
||||
mov rax, [rsp + 48] ; right operand
|
||||
and rax, 0xFFF
|
||||
mov rdx, [rel OPERAND_RDX]
|
||||
and rdx, 0xFFF
|
||||
cmp rax, rdx
|
||||
jne .after_spill_rdx
|
||||
|
||||
; free rhs
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
lea rsi, [rsp + 48] ; right operand
|
||||
call codegen_free_operand
|
||||
|
||||
mov rdx, [rsp + 48] ; right operand
|
||||
and rdx, 0xF000 ; Operand.width
|
||||
mov rax, [rsp + 64] ; scratch value
|
||||
or rax, rdx ; preserve width
|
||||
mov rdx, [rsp + 72]
|
||||
mov [rsp + 48], rax ; right operand
|
||||
mov [rsp + 56], rdx
|
||||
|
||||
.after_spill_rdx:
|
||||
mov rax, [rsp + 16] ; *AstBinaryOp
|
||||
mov al, byte [rax + 8] ; operator
|
||||
cmp al, TOKEN_STAR
|
||||
je .after_clear_rdx
|
||||
|
||||
; clear rdx for div
|
||||
; xor rdx, rdx
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rel XOR_RDX_RDX] ; rdx
|
||||
mov rdx, XOR_RDX_RDX_LEN
|
||||
call vec_extend
|
||||
|
||||
.after_clear_rdx:
|
||||
; mov rax, lhs
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rel OPERAND_RAX] ; rax
|
||||
lea rdx, [rsp + 32] ; left operand
|
||||
call codegen_move_dst_src
|
||||
|
||||
; op rhs
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
push rbx
|
||||
lea rsi, [rsp] ; op
|
||||
mov rdx, 4
|
||||
call vec_extend
|
||||
pop rbx
|
||||
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rsp + 48] ; left operand
|
||||
call codegen_write_operand
|
||||
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
mov rsi, 10
|
||||
push rsi
|
||||
lea rsi, [rsp] ; newline
|
||||
call vec_push
|
||||
pop rsi
|
||||
|
||||
mov rax, [rsp + 16] ; *AstBinaryOp
|
||||
mov al, byte [rax + 8] ; operator
|
||||
cmp al, TOKEN_PERCENT
|
||||
jne .after_rem
|
||||
|
||||
; mov rax, rdx // only for rem
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rel OPERAND_RAX] ; rax
|
||||
lea rdx, [rel OPERAND_RDX] ; rdx
|
||||
call codegen_move_dst_src
|
||||
|
||||
.after_rem:
|
||||
mov rax, [rsp + 8] ; &function_ctx
|
||||
mov ax, word [rax + 48] ; register_bitset
|
||||
bt ax, 3 ; is rdx used?
|
||||
jnc .after_unspill_rdx
|
||||
|
||||
; mov rdx, scratch
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rel OPERAND_RDX] ; rdx
|
||||
lea rdx, [rsp + 64] ; scratch value
|
||||
call codegen_move_dst_src
|
||||
|
||||
.after_unspill_rdx:
|
||||
; free [scratch, rhs, lhs]
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
lea rsi, [rsp + 64] ; scratch value
|
||||
call codegen_free_operand
|
||||
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
lea rsi, [rsp + 48] ; right operand
|
||||
call codegen_free_operand
|
||||
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
lea rsi, [rsp + 32] ; left operand
|
||||
call codegen_free_operand
|
||||
|
||||
; alloca dst
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
mov rsi, 8 ; width
|
||||
call codegen_allocate_value
|
||||
mov [rsp + 32], rax
|
||||
mov [rsp + 40], rdx
|
||||
|
||||
; mov dst, rax
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rsp + 32] ; dst
|
||||
lea rdx, [rel OPERAND_RAX] ; rax
|
||||
call codegen_move_dst_src
|
||||
|
||||
; return dst
|
||||
mov rax, [rsp + 32]
|
||||
mov rdx, [rsp + 40]
|
||||
jmp .done
|
||||
|
||||
.gen_op:
|
||||
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
mov rsi, [rsp] ; ctx
|
||||
lea rsi, [rsi + 8] ; &ctx.text
|
||||
lea rdx, [rsp + 32] ; left operand
|
||||
lea rcx, [rsp + 48] ; right operand
|
||||
mov r8, rbx ; operation
|
||||
call codegen_binary_op_rm64_rm64
|
||||
jmp .done
|
||||
|
||||
.var_decl:
|
||||
.var_ref:
|
||||
.binary_op:
|
||||
.assignment:
|
||||
.place_to_value:
|
||||
.value_to_place:
|
||||
|
|
@ -1101,7 +1295,7 @@ codegen_expr:
|
|||
; TODO
|
||||
|
||||
.done:
|
||||
add rsp, 48
|
||||
add rsp, 80
|
||||
pop r14
|
||||
pop r15
|
||||
pop rbx
|
||||
|
|
@ -1362,6 +1556,218 @@ codegen_move_rbp_slot_src:
|
|||
pop rbp
|
||||
ret
|
||||
|
||||
;; rdi: *function_ctx
|
||||
;; rsi: *text
|
||||
;; rdx: lhs: *Operand
|
||||
;; rcx: rhs: *Operand
|
||||
;; r8: op: [u8; 8]
|
||||
;; Generates: {op} {lhs}, {rhs} for a binary operation that has the encodings rN, rmN and rmN, rN
|
||||
codegen_binary_op_rm64_rm64:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
push rbx
|
||||
|
||||
; dst [32..48]
|
||||
sub rsp, 48
|
||||
mov [rsp], rdi ; *function_ctx
|
||||
mov [rsp + 8], rsi ; *text
|
||||
mov [rsp + 16], rdx ; lhs
|
||||
mov [rsp + 24], rcx ; rhs
|
||||
mov [rsp + 32], r8 ; op
|
||||
|
||||
; if lhs.kind == REGISTER || lhs.kind < ADDRESS && rhs.kind == REGISTER {
|
||||
cmp byte [rdx + 0], OPERAND_REGISTER
|
||||
je .simple
|
||||
cmp byte [rdx + 0], OPERAND_ADDRESS
|
||||
setb al
|
||||
cmp byte [rcx + 0], OPERAND_REGISTER
|
||||
sete bl
|
||||
test al, bl
|
||||
jne .simple
|
||||
jmp .complex
|
||||
.simple:
|
||||
; op lhs, rhs
|
||||
lea rdi, [rsp + 32] ; op
|
||||
call strlen
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
lea rsi, [rsp + 32] ; op
|
||||
mov rdx, rax ; op length
|
||||
call vec_extend
|
||||
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
mov rsi, [rsp + 16] ; lhs
|
||||
call codegen_write_operand
|
||||
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
lea rsi, [rel COMMA_RAX]
|
||||
mov rdx, 2
|
||||
call vec_extend
|
||||
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
mov rsi, [rsp + 24] ; rhs
|
||||
call codegen_write_operand
|
||||
|
||||
mov byte [rsp + 32], 10 ; newline
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
lea rsi, [rsp + 32]
|
||||
call vec_push
|
||||
|
||||
; free rhs
|
||||
mov rdi, [rsp] ; *function_ctx
|
||||
mov rsi, [rsp + 24] ; rhs
|
||||
call codegen_free_operand
|
||||
|
||||
; ret lhs
|
||||
mov rbx, [rsp + 16] ; lhs
|
||||
mov rax, [rbx]
|
||||
mov rdx, [rbx + 8]
|
||||
jmp .epilogue
|
||||
; } else {
|
||||
.complex:
|
||||
; if lhs.kind < ADDRESS {
|
||||
cmp byte [rdx + 0], OPERAND_ADDRESS
|
||||
jae .check_rhs
|
||||
|
||||
; mov rax, rhs
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
lea rsi, [rel OPERAND_RAX]
|
||||
mov rdx, [rsp + 24] ; rhs
|
||||
call codegen_move_dst_src
|
||||
|
||||
; op lhs, rax
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
mov rsi, [rsp + 16] ; lhs
|
||||
lea rdx, [rel OPERAND_RAX] ; rax
|
||||
mov rcx, [rsp + 32] ; op
|
||||
call codegen_binary_op_unchecked
|
||||
|
||||
; free rhs
|
||||
mov rdi, [rsp] ; *function_ctx
|
||||
mov rsi, [rsp + 24] ; rhs
|
||||
call codegen_free_operand
|
||||
|
||||
; ret lhs
|
||||
mov rbx, [rsp + 16] ; lhs
|
||||
mov rax, [rbx]
|
||||
mov rdx, [rbx + 8]
|
||||
jmp .epilogue
|
||||
|
||||
.check_rhs:
|
||||
; } else if rhs.kind < ADDRESS {
|
||||
cmp byte [rcx + 0], OPERAND_ADDRESS
|
||||
jae .allocate_dst
|
||||
; mov rax, lhs
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
lea rsi, [rel OPERAND_RAX]
|
||||
mov rdx, [rsp + 16] ; lhs
|
||||
call codegen_move_dst_src
|
||||
|
||||
; op rax, rhs
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
lea rsi, [rel OPERAND_RAX] ; rax
|
||||
mov rdx, [rsp + 24] ; rhs
|
||||
mov rcx, [rsp + 32] ; op
|
||||
call codegen_binary_op_unchecked
|
||||
|
||||
; mov rhs, rax
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
mov rsi, [rsp + 24] ; rhs
|
||||
lea rdx, [rel OPERAND_RAX]
|
||||
call codegen_move_dst_src
|
||||
|
||||
; free lhs
|
||||
mov rdi, [rsp] ; *function_ctx
|
||||
mov rsi, [rsp + 16] ; rhs
|
||||
call codegen_free_operand
|
||||
|
||||
; ret rhs
|
||||
mov rbx, [rsp + 24] ; rhs
|
||||
mov rax, [rbx]
|
||||
mov rdx, [rbx + 8]
|
||||
jmp .epilogue
|
||||
; } else {
|
||||
.allocate_dst:
|
||||
; dst = allocate_value
|
||||
mov rdi, [rsp] ; *function_ctx
|
||||
mov rsi, 8 ; width = 8
|
||||
call codegen_allocate_value
|
||||
mov [rsp + 32], rax ; dst
|
||||
mov [rsp + 40], rdx
|
||||
|
||||
; mov dst, lhs
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
lea rsi, [rsp + 32] ; dst
|
||||
mov rdx, [rsp + 16] ; lhs
|
||||
call codegen_move_dst_src
|
||||
|
||||
; mov rax, rhs
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
lea rsi, [rel OPERAND_RAX] ; rax
|
||||
mov rdx, [rsp + 24] ; rhs
|
||||
call codegen_move_dst_src
|
||||
|
||||
; op dst, rax
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
lea rsi, [rsp + 32] ; dst
|
||||
lea rdx, [rel OPERAND_RAX] ; rax
|
||||
mov rcx, [rsp + 32] ; op
|
||||
call codegen_binary_op_unchecked
|
||||
|
||||
; ret dst
|
||||
mov rax, [rsp + 32] ; dst
|
||||
mov rdx, [rsp + 40]
|
||||
; }
|
||||
|
||||
.epilogue:
|
||||
add rsp, 48
|
||||
pop rbx
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
;; rdi: *text
|
||||
;; rsi: lhs: *Operand
|
||||
;; rdx: rhs: *Operand
|
||||
;; rcx: op: [u8; 8]
|
||||
codegen_binary_op_unchecked:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
sub rsp, 32
|
||||
mov [rsp], rdi ; *text
|
||||
mov [rsp + 8], rsi ; lhs
|
||||
mov [rsp + 16], rdx ; rhs
|
||||
mov [rsp + 24], rcx ; op
|
||||
|
||||
; op lhs, rax
|
||||
lea rdi, [rsp + 24] ; op
|
||||
call strlen
|
||||
mov rdi, [rsp] ; *text
|
||||
lea rsi, [rsp + 24] ; op
|
||||
mov rdx, rax ; op length
|
||||
call vec_extend
|
||||
|
||||
mov rdi, [rsp] ; *text
|
||||
mov rsi, [rsp + 8] ; lhs
|
||||
call codegen_write_operand
|
||||
|
||||
mov rdi, [rsp] ; *text
|
||||
lea rsi, [rel COMMA_RAX]
|
||||
mov rdx, 2
|
||||
call vec_extend
|
||||
|
||||
mov rdi, [rsp] ; *text
|
||||
mov rsi, [rsp + 16] ; rhs
|
||||
call codegen_write_operand
|
||||
|
||||
mov byte [rsp + 31], 10 ; newline
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
lea rsi, [rsp + 31]
|
||||
call vec_push
|
||||
|
||||
add rsp, 32
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
;; rdi: *text
|
||||
;; rsi: dst: *Operand
|
||||
;; rdx: src: *Operand
|
||||
|
|
@ -1458,7 +1864,15 @@ section .rdata
|
|||
MOV_RAX_COMMA_LEN equ $ - MOV_RAX_COMMA
|
||||
COMMA_RAX db ", rax"
|
||||
COMMA_RAX_LEN equ $ - COMMA_RAX
|
||||
XOR_RDX_RDX db "xor rdx, rdx", 10
|
||||
XOR_RDX_RDX_LEN equ $ - XOR_RDX_RDX
|
||||
ADD_ dq "add "
|
||||
SUB_ dq "sub "
|
||||
MUL_ dq "mul "
|
||||
DIV_ dq "div "
|
||||
|
||||
|
||||
; Operand { kind: REGISTER, register: 0, width: 8, len: 0, padding: 0, value: 0 }
|
||||
align 8
|
||||
OPERAND_RAX dq 0x0000_8001, 0
|
||||
OPERAND_RDX dq 0x0000_8301, 0
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ fn main() {
|
|||
|
||||
print_ast(
|
||||
b"fn main(a: u32) -> void {
|
||||
return 4;
|
||||
return 2 * 3 + 4 * 5;
|
||||
}",
|
||||
|ast| unsafe { parse_func(ast) },
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue