many small fixes
This commit is contained in:
parent
e43424b780
commit
a25dcdabbb
|
|
@ -7,7 +7,9 @@ extern vec_extend
|
||||||
extern vec_get
|
extern vec_get
|
||||||
extern vec_push
|
extern vec_push
|
||||||
extern vec_insert_sorted
|
extern vec_insert_sorted
|
||||||
|
extern vec_insert_many
|
||||||
extern vec_init_with
|
extern vec_init_with
|
||||||
|
extern int_to_str2
|
||||||
|
|
||||||
global codegen_function
|
global codegen_function
|
||||||
global get_register_name
|
global get_register_name
|
||||||
|
|
@ -29,9 +31,27 @@ section .rdata
|
||||||
MOV_RAX_LEN equ $ - MOV_RAX
|
MOV_RAX_LEN equ $ - MOV_RAX
|
||||||
JMP_EPILOGUE db 10, "jmp .epilogue", 10
|
JMP_EPILOGUE db 10, "jmp .epilogue", 10
|
||||||
JMP_EPILOGUE_LEN equ $ - JMP_EPILOGUE
|
JMP_EPILOGUE_LEN equ $ - JMP_EPILOGUE
|
||||||
|
DOT_ARGS db ".args:", 10
|
||||||
|
DOT_ARGS_LEN equ $ - DOT_ARGS
|
||||||
|
DOT_BODY db ".body:", 10
|
||||||
|
DOT_BODY_LEN equ $ - DOT_BODY
|
||||||
|
DOT_PROLOGUE db ".prologue:", 10
|
||||||
|
DOT_PROLOGUE_LEN equ $ - DOT_PROLOGUE
|
||||||
|
DOT_EPILOGUE db ".epilogue:", 10
|
||||||
|
DOT_EPILOGUE_LEN equ $ - DOT_EPILOGUE
|
||||||
|
JMP_ARGS db 10, "jmp .args", 10
|
||||||
|
JMP_ARGS_LEN equ $ - JMP_ARGS
|
||||||
|
JMP_BODY db 10, "jmp .body", 10
|
||||||
|
JMP_BODY_LEN equ $ - JMP_BODY
|
||||||
|
JMP_PROLOGUE db 10, "jmp .prologue", 10
|
||||||
|
JMP_PROLOGUE_LEN equ $ - JMP_PROLOGUE
|
||||||
|
SUB_RSP db "sub rsp, "
|
||||||
|
SUB_RSP_LEN equ $ - SUB_RSP
|
||||||
|
ADD_RSP db "add rsp, "
|
||||||
|
ADD_RSP_LEN equ $ - ADD_RSP
|
||||||
|
|
||||||
|
|
||||||
REGISTER_NAMES db "abcdsidibpspr8r9r10r11r12r13r14r15"
|
REGISTER_NAMES db "abcdsidibpspr8r9r10r11r12r13r14r15"
|
||||||
WIDTHS db "erxliwdbp"
|
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
|
|
||||||
|
|
@ -153,6 +173,73 @@ write_register_name:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;; rdi: arg index
|
||||||
|
;; Returns the `Operand` for the given argument index
|
||||||
|
codegen_arg_to_operand:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
|
||||||
|
cmp rdi, 6
|
||||||
|
jge .stack_arg
|
||||||
|
|
||||||
|
; register args in sysV make this strange movement through the canonical register indices:
|
||||||
|
; 3 2 1 0 4 5
|
||||||
|
; [a,b,c,d,si,di,bp,sp,8,9,10,11,12,13,14,15]
|
||||||
|
; at least there's 6 register args and not 4 line on win64..
|
||||||
|
|
||||||
|
cmp rdi, 2
|
||||||
|
jge .rdx
|
||||||
|
mov rax, 5
|
||||||
|
sub rax, rdi
|
||||||
|
jmp .reg_arg
|
||||||
|
|
||||||
|
.rdx:
|
||||||
|
cmp rdi, 4
|
||||||
|
jge .r8
|
||||||
|
mov rax, 5
|
||||||
|
sub rax, rdi
|
||||||
|
jmp .reg_arg
|
||||||
|
|
||||||
|
.r8:
|
||||||
|
add rdi, 4 ; offset to r8
|
||||||
|
mov rax, rdi
|
||||||
|
|
||||||
|
.reg_arg:
|
||||||
|
mov rdi, rax
|
||||||
|
|
||||||
|
xor rax, rax
|
||||||
|
mov eax, 0 ; Operand.len = 0
|
||||||
|
shl eax, 16
|
||||||
|
or eax, 8 ; Operand.width = 8
|
||||||
|
shl eax, 4
|
||||||
|
or eax, edi ; Operand.register
|
||||||
|
shl eax, 8
|
||||||
|
or eax, OPERAND_REGISTER ; Operand.kind
|
||||||
|
mov rdx, 0 ; Operand.value = 0
|
||||||
|
jmp .epilogue
|
||||||
|
|
||||||
|
.stack_arg:
|
||||||
|
sub rdi, 6
|
||||||
|
mov rax, 8
|
||||||
|
mul rdi
|
||||||
|
add rax, 16 ; return address + old rbp
|
||||||
|
|
||||||
|
; construct Operand
|
||||||
|
mov rdx, rax ; Operand.value = offset
|
||||||
|
|
||||||
|
xor rax, rax
|
||||||
|
mov eax, 0 ; Operand.len = 0
|
||||||
|
shl eax, 16
|
||||||
|
or eax, 8 ; Operand.width = 8
|
||||||
|
shl eax, 4
|
||||||
|
; or eax, 0 ; Operand.register = undef
|
||||||
|
shl eax, 8
|
||||||
|
or eax, OPERAND_RBP_OFFSET ; Operand.kind
|
||||||
|
|
||||||
|
.epilogue:
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
;; rdi: ctx
|
;; rdi: ctx
|
||||||
;; rsi: a: *const (index, offset)
|
;; rsi: a: *const (index, offset)
|
||||||
;; rdx: b: *const (index, offset)
|
;; rdx: b: *const (index, offset)
|
||||||
|
|
@ -259,6 +346,7 @@ codegen_function:
|
||||||
push rbx
|
push rbx
|
||||||
push r15
|
push r15
|
||||||
push r14
|
push r14
|
||||||
|
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]
|
; dirtied-register-bitset [88..104] [a,b,c,d,si,di,bp,sp,8,9,10,11,12,13,14,15]
|
||||||
|
|
@ -340,6 +428,21 @@ codegen_function:
|
||||||
; allocate args on stack
|
; allocate args on stack
|
||||||
; rbx = *AstFunction
|
; rbx = *AstFunction
|
||||||
|
|
||||||
|
|
||||||
|
; "jmp .prologue\n"
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rel JMP_PROLOGUE]
|
||||||
|
mov rdx, JMP_PROLOGUE_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
; ".args:\n"
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rel DOT_ARGS]
|
||||||
|
mov rdx, DOT_ARGS_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
mov r15, [rbx + 24] ; AstFunction.args_len
|
mov r15, [rbx + 24] ; AstFunction.args_len
|
||||||
xor r14, r14 ; arg index
|
xor r14, r14 ; arg index
|
||||||
.arg_loop:
|
.arg_loop:
|
||||||
|
|
@ -359,28 +462,126 @@ codegen_function:
|
||||||
mov rdx, stackvar_cmp
|
mov rdx, stackvar_cmp
|
||||||
mov rcx, 0
|
mov rcx, 0
|
||||||
call vec_insert_sorted
|
call vec_insert_sorted
|
||||||
|
|
||||||
|
; spill arg from register to newly allocated stack slot
|
||||||
|
; get source Operand
|
||||||
|
mov r13, [rsp + 112] ; current_stack_size before increment
|
||||||
|
mov rdi, [rsp + 104] ; arg index
|
||||||
|
call codegen_arg_to_operand
|
||||||
|
mov [rsp + 104], rax
|
||||||
|
mov [rsp + 112], rdx
|
||||||
|
mov rdx, r13 ; offset
|
||||||
|
neg rdx
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rsp + 104] ; src
|
||||||
|
call codegen_move_rbp_slot_src
|
||||||
|
|
||||||
inc r14
|
inc r14
|
||||||
jmp .arg_loop
|
jmp .arg_loop
|
||||||
|
|
||||||
.arg_loop_done:
|
.arg_loop_done:
|
||||||
|
|
||||||
|
; "jmp .body\n"
|
||||||
|
; ".body:\n"
|
||||||
|
|
||||||
mov rdi, [rsp] ; ctx
|
mov rdi, [rsp] ; ctx
|
||||||
lea rsi, [rsp + 24] ; &function_ctx
|
lea rsi, [rsp + 24] ; &function_ctx
|
||||||
mov rdx, [rbx + 48] ; AstFunction.body
|
mov rdx, [rbx + 48] ; AstFunction.body
|
||||||
call codegen_block
|
call codegen_expr
|
||||||
|
|
||||||
; TODO: generate function body
|
; TODO: generate function body
|
||||||
|
|
||||||
; push "ret\n"
|
; ".epilogue:\n"
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rel DOT_EPILOGUE]
|
||||||
|
mov rdx, DOT_EPILOGUE_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
; "pop {dirtied registers}\n"
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
mov rsi, [rsp + 24] ; &function_ctx
|
||||||
|
mov rdx, 0 ; push = false
|
||||||
|
call codegen_push_pop_dirtied_registers
|
||||||
|
|
||||||
|
; "add rsp, {current_stack_size}\n"
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rel ADD_RSP]
|
||||||
|
mov rdx, ADD_RSP_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov rdi, [rsp + 24] ; &function_ctx
|
||||||
|
mov rdi, [rdi + 0] ; current_stack_size
|
||||||
|
lea rsi, [rsp + 104] ; scratch
|
||||||
|
mov rdx, 16 ; buffer length
|
||||||
|
mov rcx, 10 ; radix
|
||||||
|
call int_to_str2
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rax + rdx]
|
||||||
|
mov byte [rsi], 10 ; add newline
|
||||||
|
mov rsi, rax
|
||||||
|
mov rdx, rdx ; length from int_to_str2
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
; "ret\n"
|
||||||
mov rdi, [rsp] ; ctx
|
mov rdi, [rsp] ; ctx
|
||||||
lea rdi, [rdi + 8] ; &ctx.text
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
lea rsi, [rel RET_NL]
|
lea rsi, [rel RET_NL]
|
||||||
mov rdx, RET_NL_LEN
|
mov rdx, RET_NL_LEN
|
||||||
call vec_extend
|
call vec_extend
|
||||||
|
|
||||||
|
; ".prologue:\n"
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rel DOT_PROLOGUE]
|
||||||
|
mov rdx, DOT_PROLOGUE_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
; "sub rsp, {current_stack_size}\n"
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rel SUB_RSP]
|
||||||
|
mov rdx, SUB_RSP_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov rdi, [rsp + 24] ; &function_ctx
|
||||||
|
mov rdi, [rdi + 0] ; current_stack_size
|
||||||
|
lea rsi, [rsp + 104] ; scratch
|
||||||
|
mov rdx, 16 ; buffer length
|
||||||
|
mov rcx, 10 ; radix
|
||||||
|
call int_to_str2
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rax + rdx]
|
||||||
|
mov byte [rsi], 10 ; add newline
|
||||||
|
mov rsi, rax
|
||||||
|
mov rdx, rdx ; length from int_to_str2
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
; "push{dirtied registers}\n"
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
mov rsi, [rsp + 24] ; &function_ctx
|
||||||
|
mov rdx, 1 ; push = false
|
||||||
|
call codegen_push_pop_dirtied_registers
|
||||||
|
|
||||||
|
; "jmp .args\n"
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rel JMP_ARGS]
|
||||||
|
mov rdx, JMP_ARGS_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
add rsp, 120
|
add rsp, 120
|
||||||
pop r15
|
push r13
|
||||||
pop r14
|
push r14
|
||||||
|
push r15
|
||||||
pop rbx
|
pop rbx
|
||||||
pop rbp
|
pop rbp
|
||||||
ret
|
ret
|
||||||
|
|
@ -388,6 +589,116 @@ codegen_function:
|
||||||
.panic:
|
.panic:
|
||||||
call panic
|
call panic
|
||||||
|
|
||||||
|
;; rdi: *text
|
||||||
|
;; rsi: &function_ctx
|
||||||
|
;; rdx: push: bool
|
||||||
|
codegen_push_pop_dirtied_registers:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
push rbx
|
||||||
|
push r15
|
||||||
|
push r14
|
||||||
|
|
||||||
|
sub rsp, 32
|
||||||
|
mov [rsp], rdi
|
||||||
|
mov [rsp + 8], rsi
|
||||||
|
|
||||||
|
mov byte [rsp + 29 + 3], 10 ; newline
|
||||||
|
mov qword [rsp + 16], -1
|
||||||
|
mov rax, ' hsup'
|
||||||
|
mov qword [rsp + 24], rax
|
||||||
|
test rdx, rdx
|
||||||
|
jz .skip_setup_pop
|
||||||
|
mov rax, ' pop'
|
||||||
|
mov qword [rsp + 24], rax
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; text
|
||||||
|
mov rax, [rdi + 8] ; text.len()
|
||||||
|
mov [rsp + 16], rax
|
||||||
|
.skip_setup_pop:
|
||||||
|
|
||||||
|
; low: 0b01000000 high: 0b00001111
|
||||||
|
; preserved registers:
|
||||||
|
mov rax, [rsi + 48 + 16] ; dirtied_register_bitset low
|
||||||
|
mov rbx, 0b01000000
|
||||||
|
and rax, rbx
|
||||||
|
test rax, rax
|
||||||
|
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
|
||||||
|
|
||||||
|
mov r15, 8
|
||||||
|
xor r14, r14
|
||||||
|
.reg_loop:
|
||||||
|
cmp r14, r15
|
||||||
|
jge .done
|
||||||
|
bt rax, r14
|
||||||
|
jnc .next_reg
|
||||||
|
|
||||||
|
mov rdi, 8
|
||||||
|
add rdi, r14
|
||||||
|
mov rsi, 8
|
||||||
|
lea rdx, [rsp + 29]
|
||||||
|
call get_register_name
|
||||||
|
|
||||||
|
mov rax, -1
|
||||||
|
cmp [rsp + 16], rax
|
||||||
|
jne .reg_pop
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; text
|
||||||
|
lea rsi, [rsp + 24]
|
||||||
|
mov rdx, 9
|
||||||
|
call vec_extend
|
||||||
|
jmp .next_reg
|
||||||
|
.reg_pop:
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; text
|
||||||
|
lea rsi, [rsp + 24]
|
||||||
|
mov rdx, 9
|
||||||
|
mov rcx, [rsp + 16] ; text.len()
|
||||||
|
call vec_insert_many
|
||||||
|
|
||||||
|
|
||||||
|
.next_reg:
|
||||||
|
inc r14
|
||||||
|
jmp .reg_loop
|
||||||
|
|
||||||
|
.done:
|
||||||
|
add rsp, 32
|
||||||
|
pop r14
|
||||||
|
pop r15
|
||||||
|
pop rbx
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
;; rdi: ctx
|
;; rdi: ctx
|
||||||
;; rsi: &function_ctx
|
;; rsi: &function_ctx
|
||||||
;; rdx: block index
|
;; rdx: block index
|
||||||
|
|
@ -405,17 +716,17 @@ codegen_block:
|
||||||
mov rdi, [rdi] ; ast
|
mov rdi, [rdi] ; ast
|
||||||
mov rsi, rdx ; block index
|
mov rsi, rdx ; block index
|
||||||
call vec_get
|
call vec_get
|
||||||
mov 15, [rax + 8] ; AstNode.extra
|
mov r15, [rax + 8] ; AstNode.extra
|
||||||
mov rbx, [rax + 0] ; AstNode.data
|
mov rbx, [rax + 0] ; AstNode.data
|
||||||
|
|
||||||
xor r14, r14 ; statement index
|
xor r14, r14 ; statement index
|
||||||
.stmt_loop:
|
.stmt_loop:
|
||||||
cmp r14, r15
|
cmp r14, r15
|
||||||
jge .stmt_loop_done
|
jge .stmt_loop_done
|
||||||
mov rdi, [rsp] ; ctx
|
mov rdi, [rsp] ; ctx
|
||||||
lea mov, [rsp + 8] ; &function_ctx
|
lea rbx, [rsp + 8] ; &function_ctx
|
||||||
mov rdx, [rbx + r14 * 8] ; statements[i]
|
mov rdx, [rbx + r14 * 8] ; statements[i]
|
||||||
call codegen_statement
|
call codegen_expr
|
||||||
inc r14
|
inc r14
|
||||||
jmp .stmt_loop
|
jmp .stmt_loop
|
||||||
|
|
||||||
|
|
@ -436,11 +747,13 @@ codegen_expr:
|
||||||
push rbp
|
push rbp
|
||||||
mov rbp, rsp
|
mov rbp, rsp
|
||||||
push rbx
|
push rbx
|
||||||
|
push r15
|
||||||
|
push r14
|
||||||
|
|
||||||
; scratch [16..32]
|
; scratch [16..48]
|
||||||
; function_ctx: [8..16]
|
; function_ctx: [8..16]
|
||||||
; ctx [0..8]
|
; ctx [0..8]
|
||||||
sub rsp, 32
|
sub rsp, 48
|
||||||
mov [rsp], rdi ; ctx
|
mov [rsp], rdi ; ctx
|
||||||
mov [rsp + 8], rsi ; &function_ctx
|
mov [rsp + 8], rsi ; &function_ctx
|
||||||
|
|
||||||
|
|
@ -475,52 +788,112 @@ codegen_expr:
|
||||||
je .address_of
|
je .address_of
|
||||||
jmp .panic
|
jmp .panic
|
||||||
|
|
||||||
|
.block:
|
||||||
|
mov rbx, [rax + 8] ; AstNode.data
|
||||||
|
mov r15, [rax + 16] ; AstNode.extra
|
||||||
|
|
||||||
|
xor r14, r14 ; statement index
|
||||||
|
.stmt_loop:
|
||||||
|
cmp r14, r15
|
||||||
|
jge .stmt_loop_done
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
mov rsi, [rsp + 8] ; &function_ctx
|
||||||
|
mov rdx, [rbx + r14 * 8] ; statements[i]
|
||||||
|
call codegen_expr
|
||||||
|
inc r14
|
||||||
|
jmp .stmt_loop
|
||||||
|
.stmt_loop_done:
|
||||||
|
xor rax, rax
|
||||||
|
xor rdx, rdx
|
||||||
|
jmp .done
|
||||||
|
|
||||||
.return:
|
.return:
|
||||||
; codegen inner expr
|
; codegen inner expr
|
||||||
mov rdi, [rsp] ; ctx
|
mov rdi, [rsp] ; ctx
|
||||||
mov rsi, [rsp + 8] ; &function_ctx
|
mov rsi, [rsp + 8] ; &function_ctx
|
||||||
mov rdx, [rax + 8] ; AstNode.data
|
mov rdx, [rax + 8] ; AstNode.data
|
||||||
call codegen_expr
|
call codegen_expr
|
||||||
mov rbx, rax
|
|
||||||
|
; mov rax, {inner expr result}
|
||||||
|
mov [rsp + 16], rax
|
||||||
|
mov [rsp + 24], rdx
|
||||||
|
mov rax, qword [rel OPERAND_RAX]
|
||||||
|
mov rdx, qword [rel OPERAND_RAX + 8]
|
||||||
|
mov [rsp + 32], rax
|
||||||
|
mov [rsp + 40], rdx
|
||||||
|
|
||||||
mov rdi, [rsp] ; ctx
|
mov rdi, [rsp] ; ctx
|
||||||
mov rdi, [rdi + 8] ; &ctx.text
|
mov rdi, [rdi + 8] ; &ctx.text
|
||||||
lea rsi, [rel MOV_RAX]
|
lea rsi, [rsp + 32] ; dst
|
||||||
mov rdx, MOV_RAX_LEN
|
lea rdx, [rsp + 16] ; src
|
||||||
call vec_extend
|
call codegen_move_dst_src
|
||||||
|
|
||||||
mov rdi, rbx
|
|
||||||
mov rsi, 8
|
|
||||||
lea rdx, [rsp + 16] ; scratch
|
|
||||||
call get_register_name
|
|
||||||
|
|
||||||
mov rdi, [rsp] ; ctx
|
|
||||||
mov rdi, [rdi + 8] ; &ctx.text
|
|
||||||
mov rsi, rax
|
|
||||||
call vec_extend
|
|
||||||
|
|
||||||
|
; push "jmp .epilogue\n"
|
||||||
mov rdi, [rsp] ; ctx
|
mov rdi, [rsp] ; ctx
|
||||||
mov rdi, [rdi + 8] ; &ctx.text
|
mov 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
|
||||||
|
|
||||||
mov rax, 0
|
; construct return operand
|
||||||
|
; Operand { kind: REGISTER, register_and_width: (register | (width << 4)), len: 0, value: 0 }
|
||||||
|
mov eax, 0 ; len = 0
|
||||||
|
shl eax, 16
|
||||||
|
or eax, 8 ; width = 8
|
||||||
|
shl eax, 4
|
||||||
|
or eax, 0 ; register = rax
|
||||||
|
shl eax, 8
|
||||||
|
or eax, OPERAND_REGISTER ; kind
|
||||||
|
mov rdx, 0 ; value = 0
|
||||||
jmp .done
|
jmp .done
|
||||||
|
|
||||||
.number:
|
.number:
|
||||||
; rax = *AstNode
|
; rax = *AstNode
|
||||||
mov [rsp + 16], rax ; scratch = *AstNode
|
mov [rsp + 16], rax ; scratch = *AstNode
|
||||||
|
mov rbx, [rax + 8] ; AstNode.data = value
|
||||||
|
mov [rsp + 40], rbx ; Operand.value
|
||||||
mov rdi, [rsp + 8] ; &function_ctx
|
mov rdi, [rsp + 8] ; &function_ctx
|
||||||
call codegen_allocate_register
|
call codegen_allocate_register
|
||||||
|
|
||||||
|
xor rbx, rbx
|
||||||
|
or rbx, 8 ; width = 8
|
||||||
|
shl rbx, 4
|
||||||
|
or rbx, rax ; register
|
||||||
|
shl rbx, 8
|
||||||
|
or rbx, OPERAND_REGISTER ; kind
|
||||||
|
mov [rsp + 16], rbx ;
|
||||||
|
mov qword [rsp + 24], 0 ; value = 0
|
||||||
|
|
||||||
|
mov byte [rsp + 32], OPERAND_IMMEDIATE ; Operand.kind
|
||||||
|
mov bl, 8 ; width = 8
|
||||||
|
shl bl, 4 ; register = undef
|
||||||
|
mov byte [rsp + 33], bl ; Operand.register_and_width
|
||||||
|
mov word [rsp + 34], 0 ; Operand.len = 0
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
mov rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rsp + 16] ; dst
|
||||||
|
lea rdx, [rsp + 16] ; src
|
||||||
|
call codegen_move_dst_src
|
||||||
|
|
||||||
|
mov rax, qword [rsp + 16]
|
||||||
|
mov rdx, qword [rsp + 24]
|
||||||
|
jmp .done
|
||||||
|
|
||||||
|
.var_decl:
|
||||||
|
.var_ref:
|
||||||
|
.binary_op:
|
||||||
|
.assignment:
|
||||||
|
.place_to_value:
|
||||||
|
.value_to_place:
|
||||||
|
.deref:
|
||||||
|
.address_of:
|
||||||
; TODO
|
; TODO
|
||||||
|
|
||||||
.done:
|
.done:
|
||||||
add rsp, 32
|
add rsp, 48
|
||||||
|
pop r14
|
||||||
|
pop r15
|
||||||
pop rbx
|
pop rbx
|
||||||
pop rbp
|
pop rbp
|
||||||
ret
|
ret
|
||||||
|
|
@ -539,19 +912,21 @@ codegen_expr:
|
||||||
;; or: register: u4, width: u4
|
;; or: register: u4, width: u4
|
||||||
section .rdata
|
section .rdata
|
||||||
;; start-consts
|
;; start-consts
|
||||||
OPERAND_REGISTER db 1 ; e.g. rax, rbx
|
OPERAND_REGISTER equ 1 ; e.g. rax, rbx
|
||||||
OPERAND_RBP_OFFSET db 2 ; e.g. [rbp - 8]
|
OPERAND_RBP_OFFSET equ 2 ; e.g. [rbp - 8]
|
||||||
OPERAND_RSP_OFFSET db 3 ; e.g. [rsp + 16]
|
OPERAND_RSP_OFFSET equ 3 ; e.g. [rsp + 16]
|
||||||
OPERAND_ADDRESS db 4 ; e.g. [rel OPERAND_ADDRESS]
|
OPERAND_ADDRESS equ 4 ; e.g. [rel OPERAND_ADDRESS]
|
||||||
OPERAND_IMMEDIATE db 5 ; e.g. 0x10
|
OPERAND_IMMEDIATE equ 5 ; e.g. 0x10
|
||||||
OPERAND_CONSTANT db 6 ; e.g. OPERAND_CONSTANT
|
OPERAND_CONSTANT equ 6 ; e.g. OPERAND_CONSTANT
|
||||||
OPERAND_LABEL db 7 ; e.g. label_1234
|
OPERAND_LABEL equ 7 ; e.g. label_1234
|
||||||
;; end-consts
|
;; end-consts
|
||||||
WIDTH_BYTE db 'byte '
|
WIDTH_BYTE db 'byte '
|
||||||
WIDTH_WORD db 'word '
|
WIDTH_WORD db 'word '
|
||||||
WIDTH_DWORD db 'dword '
|
WIDTH_DWORD db 'dword '
|
||||||
WIDTH_QWORD db 'qword '
|
WIDTH_QWORD db 'qword '
|
||||||
|
|
||||||
|
section .text
|
||||||
|
|
||||||
;; rdi: *text
|
;; rdi: *text
|
||||||
;; rsi: op: *Operand
|
;; rsi: op: *Operand
|
||||||
codegen_write_operand:
|
codegen_write_operand:
|
||||||
|
|
@ -587,7 +962,7 @@ codegen_write_operand:
|
||||||
mov rbx, rsi
|
mov rbx, rsi
|
||||||
mov rdi, [rbx + 1] ; register_and_width
|
mov rdi, [rbx + 1] ; register_and_width
|
||||||
mov rsi, rdi
|
mov rsi, rdi
|
||||||
mov dil, dil ; low 4 bits = register
|
and dil, 0x0F ; low 4 bits = register
|
||||||
shr rsi, 4 ; high 4 bits = width
|
shr rsi, 4 ; high 4 bits = width
|
||||||
lea rdx, [rsp + 16] ; buffer
|
lea rdx, [rsp + 16] ; buffer
|
||||||
call get_register_name
|
call get_register_name
|
||||||
|
|
@ -601,7 +976,7 @@ codegen_write_operand:
|
||||||
.rsp_offset:
|
.rsp_offset:
|
||||||
; {width} [rbp {+/-} offset]
|
; {width} [rbp {+/-} offset]
|
||||||
mov rsi, [rsp + 8] ; op
|
mov rsi, [rsp + 8] ; op
|
||||||
mov sil, byte [rsi + 1] ; register_and_width
|
mov sil, byte [rsi + 1] ; Operand.register_and_width
|
||||||
shr sil, 4 ; width
|
shr sil, 4 ; width
|
||||||
mov rdi, [rsp] ; *text
|
mov rdi, [rsp] ; *text
|
||||||
call codegen_write_width
|
call codegen_write_width
|
||||||
|
|
@ -614,10 +989,10 @@ codegen_write_operand:
|
||||||
|
|
||||||
; if op.kind == OPERAND_RBP_OFFSET
|
; if op.kind == OPERAND_RBP_OFFSET
|
||||||
mov rax, [rsp + 8] ; op
|
mov rax, [rsp + 8] ; op
|
||||||
mov al, byte [rax + 0] ; op.kind
|
mov al, byte [rax + 0] ; Operand.kind
|
||||||
cmp al, OPERAND_RBP_OFFSET
|
cmp al, OPERAND_RBP_OFFSET
|
||||||
jne .rsp_offset_write
|
jne .rsp_offset_write
|
||||||
mov qword [rsp + 16], ' pbr'
|
mov qword [rsp + 16], 'rbp '
|
||||||
mov rdi, [rsp] ; *text
|
mov rdi, [rsp] ; *text
|
||||||
lea rsi, [rsp + 16]
|
lea rsi, [rsp + 16]
|
||||||
mov rdx, 4
|
mov rdx, 4
|
||||||
|
|
@ -625,7 +1000,7 @@ codegen_write_operand:
|
||||||
jmp .check_sign
|
jmp .check_sign
|
||||||
|
|
||||||
.rsp_offset_write:
|
.rsp_offset_write:
|
||||||
mov qword [rsp + 16], ' psr'
|
mov qword [rsp + 16], 'rsp '
|
||||||
mov rdi, [rsp] ; *text
|
mov rdi, [rsp] ; *text
|
||||||
lea rsi, [rsp + 16]
|
lea rsi, [rsp + 16]
|
||||||
mov rdx, 4
|
mov rdx, 4
|
||||||
|
|
@ -637,11 +1012,12 @@ codegen_write_operand:
|
||||||
mov rdi, [rax + 8] ; op.value
|
mov rdi, [rax + 8] ; op.value
|
||||||
cmp rdi, 0
|
cmp rdi, 0
|
||||||
jl .skip_plus
|
jl .skip_plus
|
||||||
mov qword [rsp + 16], ' + '
|
mov qword [rsp + 16], ' + '
|
||||||
mov rdi, [rsp] ; *text
|
mov rdi, [rsp] ; *text
|
||||||
lea rsi, [rsp + 16]
|
lea rsi, [rsp + 16]
|
||||||
mov rdx, 3
|
mov rdx, 3
|
||||||
call vec_extend
|
call vec_extend
|
||||||
|
nop
|
||||||
.skip_plus:
|
.skip_plus:
|
||||||
|
|
||||||
; write offset
|
; write offset
|
||||||
|
|
@ -668,7 +1044,7 @@ codegen_write_operand:
|
||||||
lea rsi, [rsp + 16]
|
lea rsi, [rsp + 16]
|
||||||
call vec_push
|
call vec_push
|
||||||
|
|
||||||
mov qword [rsp + 16], ' ler'
|
mov qword [rsp + 16], 'rel '
|
||||||
mov rdi, [rsp] ; *text
|
mov rdi, [rsp] ; *text
|
||||||
lea rsi, [rsp + 16]
|
lea rsi, [rsp + 16]
|
||||||
mov rdx, 4
|
mov rdx, 4
|
||||||
|
|
@ -678,7 +1054,7 @@ codegen_write_operand:
|
||||||
mov rax, [rsp + 8] ; op
|
mov rax, [rsp + 8] ; op
|
||||||
mov rdi, [rsp] ; *text
|
mov rdi, [rsp] ; *text
|
||||||
mov rsi, [rax + 8] ; op.value
|
mov rsi, [rax + 8] ; op.value
|
||||||
mov rdx, [rax + 4] ; op.len
|
mov rdx, [rax + 2] ; op.len
|
||||||
mov dx, dx ; low 16 bits
|
mov dx, dx ; low 16 bits
|
||||||
call vec_extend
|
call vec_extend
|
||||||
|
|
||||||
|
|
@ -707,11 +1083,14 @@ codegen_write_operand:
|
||||||
mov rax, [rsp + 8] ; op
|
mov rax, [rsp + 8] ; op
|
||||||
mov rdi, [rsp] ; *text
|
mov rdi, [rsp] ; *text
|
||||||
mov rsi, [rax + 8] ; op.value
|
mov rsi, [rax + 8] ; op.value
|
||||||
mov rdx, [rax + 4] ; op.len
|
mov rdx, [rax + 2] ; op.len
|
||||||
mov dx, dx ; low 16 bits
|
mov dx, dx ; low 16 bits
|
||||||
call vec_extend
|
call vec_extend
|
||||||
jmp .epilogue
|
jmp .epilogue
|
||||||
|
|
||||||
|
.label:
|
||||||
|
jmp .panic
|
||||||
|
|
||||||
.epilogue:
|
.epilogue:
|
||||||
add rsp, 40
|
add rsp, 40
|
||||||
pop rbx
|
pop rbx
|
||||||
|
|
@ -745,7 +1124,33 @@ codegen_write_width:
|
||||||
call vec_extend
|
call vec_extend
|
||||||
pop rax ; length written
|
pop rax ; length written
|
||||||
ret
|
ret
|
||||||
|
.panic:
|
||||||
|
call panic
|
||||||
|
|
||||||
|
;; rdi: *text
|
||||||
|
;; rsi: src: *Operand
|
||||||
|
;; rdx: rbp offset
|
||||||
|
codegen_move_rbp_slot_src:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
|
||||||
|
sub rsp, 16
|
||||||
|
|
||||||
|
; construct dst Operand
|
||||||
|
|
||||||
|
mov byte [rsp + 0], OPERAND_RBP_OFFSET ; Operand.kind
|
||||||
|
mov byte [rsp + 1], 0x80 ; Operand.register_and_width (width=8)
|
||||||
|
mov word [rsp + 2], 0 ; Operand.len = 0
|
||||||
|
mov dword [rsp + 4], 0 ; padding
|
||||||
|
mov qword [rsp + 8], rdx ; Operand.value = rbp offset
|
||||||
|
|
||||||
|
mov rdx, rsi
|
||||||
|
lea rsi, [rsp + 0] ; dst
|
||||||
|
call codegen_move_dst_src
|
||||||
|
|
||||||
|
add rsp, 16
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
;; rdi: *text
|
;; rdi: *text
|
||||||
;; rsi: dst: *Operand
|
;; rsi: dst: *Operand
|
||||||
|
|
@ -764,8 +1169,8 @@ codegen_move_dst_src:
|
||||||
jg .panic ; unsupported dst kind
|
jg .panic ; unsupported dst kind
|
||||||
|
|
||||||
; if dst.width != src.width
|
; if dst.width != src.width
|
||||||
mov cl, byte [rsi + 2] ; dst.register_and_width
|
mov cl, byte [rsi + 1] ; dst.register_and_width
|
||||||
mov bl, byte [rdx + 2] ; src.register_and_width
|
mov bl, byte [rdx + 1] ; src.register_and_width
|
||||||
shr cl, 4
|
shr cl, 4
|
||||||
shr bl, 4
|
shr bl, 4
|
||||||
cmp cl, bl
|
cmp cl, bl
|
||||||
|
|
@ -788,13 +1193,80 @@ codegen_move_dst_src:
|
||||||
; xchg rax, [src]
|
; xchg rax, [src]
|
||||||
; mov [dst], rax
|
; mov [dst], rax
|
||||||
; xchg rax, [src]
|
; xchg rax, [src]
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rel XCHG_RAX]
|
||||||
|
mov rdx, XCHG_RAX_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
mov rsi, [rsp + 16] ; src
|
||||||
|
call codegen_write_operand
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rel COMMA_RAX]
|
||||||
|
mov rdx, COMMA_RAX_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rel MOV_RAX_COMMA]
|
||||||
|
mov rdx, 4
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
mov rsi, [rsp + 8] ; dst
|
||||||
|
call codegen_write_operand
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rel COMMA_RAX]
|
||||||
|
mov rdx, COMMA_RAX_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rel XCHG_RAX]
|
||||||
|
mov rdx, XCHG_RAX_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
mov rsi, [rsp + 16] ; src
|
||||||
|
call codegen_write_operand
|
||||||
|
jmp .epilogue
|
||||||
|
|
||||||
.do_move:
|
.do_move:
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rel MOV_RAX_COMMA]
|
||||||
|
mov rdx, 4
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
mov rsi, [rsp + 8] ; dst
|
||||||
|
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] ; src
|
||||||
|
call codegen_write_operand
|
||||||
|
|
||||||
.epilogue:
|
.epilogue:
|
||||||
add rsp, 24
|
add rsp, 24
|
||||||
pop rbx
|
pop rbx
|
||||||
pop rbp
|
pop rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.panic:
|
.panic:
|
||||||
call panic
|
call panic
|
||||||
|
|
||||||
|
section .rdata
|
||||||
|
XCHG_RAX db "xchg rax, "
|
||||||
|
XCHG_RAX_LEN equ $ - XCHG_RAX
|
||||||
|
MOV_RAX_COMMA db "mov rax, "
|
||||||
|
MOV_RAX_COMMA_LEN equ $ - MOV_RAX_COMMA
|
||||||
|
COMMA_RAX db ", rax"
|
||||||
|
COMMA_RAX_LEN equ $ - COMMA_RAX
|
||||||
|
|
||||||
|
; Operand { kind: REGISTER, register: 0, width: 8, len: 0, padding: 0, value: 0 }
|
||||||
|
align 8
|
||||||
|
OPERAND_RAX dq 0x0000_8001, 0
|
||||||
|
|
|
||||||
|
|
@ -90,12 +90,7 @@ fn main() {
|
||||||
|
|
||||||
print_ast(
|
print_ast(
|
||||||
b"fn main(a: u32) -> void {
|
b"fn main(a: u32) -> void {
|
||||||
let y: u32 = a + 4;
|
return 4;
|
||||||
{
|
|
||||||
let y: u32 = 10;
|
|
||||||
}
|
|
||||||
let y: *u32 = &y;
|
|
||||||
return *y;
|
|
||||||
}",
|
}",
|
||||||
|ast| unsafe { parse_func(ast) },
|
|ast| unsafe { parse_func(ast) },
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue