it doesn't crash (crazy)
This commit is contained in:
parent
a93f7edd62
commit
8e1af956b0
|
|
@ -177,7 +177,9 @@ write_register_name:
|
||||||
|
|
||||||
|
|
||||||
;; rdi: arg index
|
;; rdi: arg index
|
||||||
;; Returns the `Operand` for the given argument index
|
;; Returns the input `Operand` for the given argument index:
|
||||||
|
;; On the SysV ABI, the first 6 integer/pointer args are passed in registers:
|
||||||
|
;; rdi, rsi, rdx, rcx, r8, r9
|
||||||
codegen_arg_to_operand:
|
codegen_arg_to_operand:
|
||||||
push rbp
|
push rbp
|
||||||
mov rbp, rsp
|
mov rbp, rsp
|
||||||
|
|
@ -222,6 +224,7 @@ codegen_arg_to_operand:
|
||||||
jmp .epilogue
|
jmp .epilogue
|
||||||
|
|
||||||
.stack_arg:
|
.stack_arg:
|
||||||
|
; TODO: use these offsets in stack-vars instead of copying into new stack slots
|
||||||
sub rdi, 6
|
sub rdi, 6
|
||||||
mov rax, 8
|
mov rax, 8
|
||||||
mul rdi
|
mul rdi
|
||||||
|
|
@ -235,9 +238,9 @@ codegen_arg_to_operand:
|
||||||
shl eax, 16
|
shl eax, 16
|
||||||
or eax, 8 ; Operand.width = 8
|
or eax, 8 ; Operand.width = 8
|
||||||
shl eax, 8
|
shl eax, 8
|
||||||
; or eax, 0 ; Operand.register = undef
|
; or eax, 0 ; Operand.register = undef
|
||||||
shl eax, 8
|
shl eax, 8
|
||||||
or eax, OPERAND_RBP_OFFSET ; Operand.kind
|
or eax, OPERAND_RBP_VALUE ; Operand.kind
|
||||||
|
|
||||||
.epilogue:
|
.epilogue:
|
||||||
pop rbp
|
pop rbp
|
||||||
|
|
@ -362,6 +365,22 @@ codegen_allocate_place:
|
||||||
pop rbp
|
pop rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;; rdi: *FunctionCtx
|
||||||
|
;; rsi: width
|
||||||
|
;; define-fn: fn codegen_allocate_stack_value(ctx: *mut FunctionCtx, width: u16) -> Operand
|
||||||
|
codegen_allocate_stack_value:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
|
||||||
|
call codegen_allocate_place
|
||||||
|
mov rsi, 0xF
|
||||||
|
not rsi
|
||||||
|
and rax, rsi ; clear kind to make it a value
|
||||||
|
and rax, OPERAND_RBP_VALUE ; Operand.kind = OPERAND_RBP_VALUE
|
||||||
|
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
;; rdi: *FunctionCtx
|
;; rdi: *FunctionCtx
|
||||||
;; rsi: width
|
;; rsi: width
|
||||||
;; define-fn: fn codegen_allocate_value(ctx: *mut FunctionCtx, width: u16) -> Operand
|
;; define-fn: fn codegen_allocate_value(ctx: *mut FunctionCtx, width: u16) -> Operand
|
||||||
|
|
@ -401,7 +420,7 @@ codegen_allocate_value:
|
||||||
jmp .done
|
jmp .done
|
||||||
|
|
||||||
.alloc_stack:
|
.alloc_stack:
|
||||||
call codegen_allocate_place
|
call codegen_allocate_stack_value
|
||||||
|
|
||||||
.done:
|
.done:
|
||||||
add rsp, 16
|
add rsp, 16
|
||||||
|
|
@ -422,10 +441,19 @@ codegen_free_operand:
|
||||||
mov [rsp + 8], rsi ; operand
|
mov [rsp + 8], rsi ; operand
|
||||||
|
|
||||||
mov al, byte [rsi] ; Operand.kind
|
mov al, byte [rsi] ; Operand.kind
|
||||||
|
xor rbx, rbx
|
||||||
cmp al, OPERAND_REGISTER
|
cmp al, OPERAND_REGISTER
|
||||||
je .free_reg
|
sete bl
|
||||||
cmp al, OPERAND_RBP_OFFSET
|
cmp al, OPERAND_REGISTER_PLACE
|
||||||
je .free_stack
|
sete bl
|
||||||
|
test bl, bl
|
||||||
|
jnz .free_reg
|
||||||
|
cmp al, OPERAND_RBP_VALUE
|
||||||
|
sete bl
|
||||||
|
cmp al, OPERAND_RBP_PLACE
|
||||||
|
sete bl
|
||||||
|
test bl, bl
|
||||||
|
jnz .free_stack
|
||||||
jmp .done
|
jmp .done
|
||||||
|
|
||||||
.free_stack:
|
.free_stack:
|
||||||
|
|
@ -1028,14 +1056,10 @@ codegen_expr:
|
||||||
; mov rax, {inner expr result}
|
; mov rax, {inner expr result}
|
||||||
mov [rsp + 16], rax
|
mov [rsp + 16], rax
|
||||||
mov [rsp + 24], rdx
|
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
|
||||||
lea rdi, [rdi + 8] ; &ctx.text
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
lea rsi, [rsp + 32] ; dst
|
lea rsi, [rel OPERAND_RAX] ; dst
|
||||||
lea rdx, [rsp + 16] ; src
|
lea rdx, [rsp + 16] ; src
|
||||||
call codegen_move_dst_src
|
call codegen_move_dst_src
|
||||||
|
|
||||||
|
|
@ -1057,14 +1081,8 @@ codegen_expr:
|
||||||
|
|
||||||
.number:
|
.number:
|
||||||
; rax = *AstNode
|
; rax = *AstNode
|
||||||
mov [rsp + 16], rax ; scratch = *AstNode
|
|
||||||
|
|
||||||
mov byte [rsp + 32], OPERAND_IMMEDIATE ; Operand.kind
|
|
||||||
mov byte [rsp + 33], 0 ; Operand.register = undef
|
|
||||||
mov word [rsp + 34], 8 ; Operand.width = 8
|
|
||||||
mov word [rsp + 36], 0 ; Operand.len = 0
|
|
||||||
mov rbx, [rax + 8] ; AstNode.data
|
mov rbx, [rax + 8] ; AstNode.data
|
||||||
mov [rsp + 40], rbx ; Operand.value
|
mov [rsp + 40], rbx ; Imm value
|
||||||
|
|
||||||
mov rdi, [rsp + 8] ; &function_ctx
|
mov rdi, [rsp + 8] ; &function_ctx
|
||||||
mov rsi, 8 ; width
|
mov rsi, 8 ; width
|
||||||
|
|
@ -1072,11 +1090,42 @@ codegen_expr:
|
||||||
mov [rsp + 16], rax
|
mov [rsp + 16], rax
|
||||||
mov [rsp + 24], rdx
|
mov [rsp + 24], rdx
|
||||||
|
|
||||||
|
mov rdx, [rsp + 40] ; Imm value
|
||||||
|
test rdx, rdx
|
||||||
|
jz .load_imm ; skip if zero
|
||||||
|
|
||||||
|
; fill bits
|
||||||
|
; !(!1u64 << imm.ilog2()) >> 1;
|
||||||
|
lzcnt rax, rdx
|
||||||
|
not al
|
||||||
|
mov rcx, -2
|
||||||
|
shlx rax, rcx, rax
|
||||||
|
not rax
|
||||||
|
shr rax, 1
|
||||||
|
; this gives a mask of the imm bits extended to the power of two bytes
|
||||||
|
movsx ecx, al ; sign-extend byte to word
|
||||||
|
movzx ecx, cx ; zero-extend to dword
|
||||||
|
movsx edx, ax ; sign-extend word to dword
|
||||||
|
or edx, ecx
|
||||||
|
mov eax, eax ; sign-extend dword to qword
|
||||||
|
or rdx, rax
|
||||||
|
je .load_imm ; skip if zero
|
||||||
|
; count bytes needed
|
||||||
|
; (z.ilog2() + 1) / 3
|
||||||
|
lzcnt rcx, rdx
|
||||||
|
mov edx, 64
|
||||||
|
sub edx, ecx
|
||||||
|
shr edx, 3
|
||||||
|
|
||||||
|
.load_imm:
|
||||||
|
test rdx, rdx
|
||||||
|
setz dl
|
||||||
mov rdi, [rsp] ; ctx
|
mov rdi, [rsp] ; ctx
|
||||||
lea rdi, [rdi + 8] ; &ctx.text
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
lea rsi, [rsp + 16] ; dst
|
lea rsi, [rsp + 16] ; dst
|
||||||
lea rdx, [rsp + 32] ; src
|
mov rcx, rdx ; byte count
|
||||||
call codegen_move_dst_src
|
mov rdx, [rsp + 40] ; immediate value
|
||||||
|
call codegen_load_imm
|
||||||
|
|
||||||
mov rax, qword [rsp + 16]
|
mov rax, qword [rsp + 16]
|
||||||
mov rdx, qword [rsp + 24]
|
mov rdx, qword [rsp + 24]
|
||||||
|
|
@ -1130,7 +1179,7 @@ codegen_expr:
|
||||||
; allocate scratch value for rdx
|
; allocate scratch value for rdx
|
||||||
mov rdi, [rsp + 8] ; &function_ctx
|
mov rdi, [rsp + 8] ; &function_ctx
|
||||||
mov rsi, 8 ; width
|
mov rsi, 8 ; width
|
||||||
call codegen_allocate_place
|
call codegen_allocate_value
|
||||||
mov [rsp + 64], rax
|
mov [rsp + 64], rax
|
||||||
mov [rsp + 72], rdx
|
mov [rsp + 72], rdx
|
||||||
|
|
||||||
|
|
@ -1143,9 +1192,9 @@ codegen_expr:
|
||||||
|
|
||||||
; check if rhs is rdx
|
; check if rhs is rdx
|
||||||
mov rax, [rsp + 48] ; right operand
|
mov rax, [rsp + 48] ; right operand
|
||||||
and rax, 0xFFF
|
and rax, 0xFFFF
|
||||||
mov rdx, [rel OPERAND_RDX]
|
mov rdx, [rel OPERAND_RDX]
|
||||||
and rdx, 0xFFF
|
and rdx, 0xFFFF
|
||||||
cmp rax, rdx
|
cmp rax, rdx
|
||||||
jne .after_spill_rdx
|
jne .after_spill_rdx
|
||||||
|
|
||||||
|
|
@ -1320,25 +1369,9 @@ codegen_expr:
|
||||||
call vec_get
|
call vec_get
|
||||||
mov rdx, [rax + 8] ; offset
|
mov rdx, [rax + 8] ; offset
|
||||||
neg rdx
|
neg rdx
|
||||||
mov rax, qword [rel OPERAND_RBP]
|
mov rax, qword [rel OPERAND_RBP_OFFS]
|
||||||
mov [rsp + 16], rax
|
jmp .done
|
||||||
mov [rsp + 24], rdx
|
|
||||||
|
|
||||||
; allocate value (?)
|
|
||||||
mov rdi, [rsp + 8] ; &function_ctx
|
|
||||||
mov rsi, 8 ; width = size_of::<* const()>
|
|
||||||
call codegen_allocate_value
|
|
||||||
mov [rsp + 32], rax ; dst
|
|
||||||
mov [rsp + 40], rdx
|
|
||||||
|
|
||||||
; lea dst, [rbp - offset]
|
|
||||||
mov rdi, [rsp] ; ctx
|
|
||||||
lea rsi, [rdi + 8] ; &ctx.text
|
|
||||||
mov rdi, [rsp + 8] ; &function_ctx
|
|
||||||
lea rdx, [rsp + 32] ; dst
|
|
||||||
lea rcx, [rsp + 16] ; src
|
|
||||||
mov r8, 'lea '
|
|
||||||
call codegen_binary_op_rm64_rm64
|
|
||||||
.place_to_value:
|
.place_to_value:
|
||||||
.assignment:
|
.assignment:
|
||||||
.value_to_place:
|
.value_to_place:
|
||||||
|
|
@ -1369,16 +1402,30 @@ codegen_expr:
|
||||||
;; or: register: u4, width: u4
|
;; or: register: u4, width: u4
|
||||||
section .rdata
|
section .rdata
|
||||||
;; start-consts
|
;; start-consts
|
||||||
|
; Register containing a Value
|
||||||
OPERAND_REGISTER equ 1 ; e.g. rax, rbx
|
OPERAND_REGISTER equ 1 ; e.g. rax, rbx
|
||||||
OPERAND_RBP_OFFSET equ 2 ; e.g. mov/lea [rbp - 8]
|
; RSP-relative stack-slot containing a Value, semantically not addressable
|
||||||
OPERAND_RSP_OFFSET equ 3 ; e.g. [rsp + 16]
|
OPERAND_RBP_VALUE equ 2 ; e.g. [rsp + 16]
|
||||||
OPERAND_ADDRESS equ 4 ; e.g. [rel OPERAND_ADDRESS]
|
; RBP-relative stack-slot containing a Value, but addressable (derived from a Place)
|
||||||
OPERAND_IMMEDIATE equ 5 ; e.g. 0x10
|
OPERAND_RBP_PVALUE equ 3 ; e.g. mov [rbp - 8]
|
||||||
OPERAND_CONSTANT equ 6 ; e.g. OPERAND_CONSTANT
|
; Static-slot containing a Value
|
||||||
OPERAND_LABEL equ 7 ; e.g. label_1234
|
OPERAND_ADDRESS_VALUE equ 4 ; e.g. mov [rel OPERAND_ADDRESS]
|
||||||
|
OPERAND_LAST_VALUE equ 5 ; operand kinds > this are places
|
||||||
|
; RBP-relative stack-slot containing a Value, semantically addressable
|
||||||
|
OPERAND_RBP_OFFSET equ 6 ; e.g. mov [rbp - 8], rax or lea rax, [rbp - 8]
|
||||||
|
; Address of a static-slot containing a Value
|
||||||
|
OPERAND_ADDRESS_PLACE equ 7 ; e.g. lea [rel OPERAND_ADDRESS]
|
||||||
|
; Register containing an address (Place)
|
||||||
OPERAND_REGISTER_PLACE equ 8 ; e.g. [rax]
|
OPERAND_REGISTER_PLACE equ 8 ; e.g. [rax]
|
||||||
|
; RBP-relative stack-slot containing an address (Place)
|
||||||
OPERAND_RBP_PLACE equ 9 ; e.g. mov rax, [rbp - 8]; mov [rax], src
|
OPERAND_RBP_PLACE equ 9 ; e.g. mov rax, [rbp - 8]; mov [rax], src
|
||||||
OPERAND_RBP_VALUE equ 10 ; e.g. mov [rbp - 8]
|
OPERAND_LAST_PLACE equ 10 ; operand kinds > this are not memory operands
|
||||||
|
; Immediate constant Value
|
||||||
|
OPERAND_IMMEDIATE equ 11 ; e.g. 0x10
|
||||||
|
|
||||||
|
; Special Operands whose semantics aren't fully defined yet
|
||||||
|
OPERAND_CONSTANT equ 12 ; e.g. OPERAND_CONSTANT
|
||||||
|
OPERAND_LABEL equ 13 ; e.g. label_1234
|
||||||
;; end-consts
|
;; end-consts
|
||||||
WIDTH_BYTE db 'byte '
|
WIDTH_BYTE db 'byte '
|
||||||
WIDTH_WORD db 'word '
|
WIDTH_WORD db 'word '
|
||||||
|
|
@ -1387,11 +1434,23 @@ section .rdata
|
||||||
|
|
||||||
; Operand { kind: REGISTER, register: 0, width: 8, len: 0, padding: 0, value: 0 }
|
; Operand { kind: REGISTER, register: 0, width: 8, len: 0, padding: 0, value: 0 }
|
||||||
align 8
|
align 8
|
||||||
|
OPERAND_IMM dq 0x0008_000b, 0
|
||||||
|
align 8
|
||||||
OPERAND_RAX dq 0x0008_0001, 0
|
OPERAND_RAX dq 0x0008_0001, 0
|
||||||
align 8
|
align 8
|
||||||
|
OPERAND_RAX_P dq 0x0008_0008, 0
|
||||||
|
align 8
|
||||||
OPERAND_RDX dq 0x0008_0301, 0
|
OPERAND_RDX dq 0x0008_0301, 0
|
||||||
align 8
|
align 8
|
||||||
OPERAND_RBP dq 0x0008_0002, 0
|
OPERAND_RDX_P dq 0x0008_0308, 0
|
||||||
|
align 8
|
||||||
|
OPERAND_RBP_OFFS dq 0x0008_0006, 0
|
||||||
|
align 8
|
||||||
|
OPERAND_RBP_PV dq 0x0008_0003, 0
|
||||||
|
align 8
|
||||||
|
OPERAND_RBP_V dq 0x0008_0002, 0
|
||||||
|
align 8
|
||||||
|
OPERAND_RBP_P dq 0x0008_0009, 0
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
|
|
||||||
|
|
@ -1414,9 +1473,13 @@ codegen_write_operand:
|
||||||
je .register
|
je .register
|
||||||
cmp bl, OPERAND_RBP_OFFSET
|
cmp bl, OPERAND_RBP_OFFSET
|
||||||
je .rbp_offset
|
je .rbp_offset
|
||||||
cmp bl, OPERAND_RSP_OFFSET
|
cmp bl, OPERAND_RBP_VALUE
|
||||||
je .rsp_offset
|
je .rbp_offset
|
||||||
cmp bl, OPERAND_ADDRESS
|
cmp bl, OPERAND_RBP_PVALUE
|
||||||
|
je .rbp_offset
|
||||||
|
cmp bl, OPERAND_ADDRESS_VALUE
|
||||||
|
je .address
|
||||||
|
cmp bl, OPERAND_ADDRESS_PLACE
|
||||||
je .address
|
je .address
|
||||||
cmp bl, OPERAND_IMMEDIATE
|
cmp bl, OPERAND_IMMEDIATE
|
||||||
je .immediate
|
je .immediate
|
||||||
|
|
@ -1466,7 +1529,6 @@ codegen_write_operand:
|
||||||
jmp .epilogue
|
jmp .epilogue
|
||||||
|
|
||||||
.rbp_offset:
|
.rbp_offset:
|
||||||
.rsp_offset:
|
|
||||||
; {width} [rbp {+/-} offset]
|
; {width} [rbp {+/-} offset]
|
||||||
mov rsi, [rsp + 8] ; op
|
mov rsi, [rsp + 8] ; op
|
||||||
movzx rsi, word [rsi + 2] ; Operand.width
|
movzx rsi, word [rsi + 2] ; Operand.width
|
||||||
|
|
@ -1608,6 +1670,8 @@ codegen_write_width:
|
||||||
cmp sil, 1
|
cmp sil, 1
|
||||||
lea rdx, [rel WIDTH_BYTE]
|
lea rdx, [rel WIDTH_BYTE]
|
||||||
je .write
|
je .write
|
||||||
|
cmp sil, 0
|
||||||
|
je .write
|
||||||
jmp .panic
|
jmp .panic
|
||||||
.write:
|
.write:
|
||||||
mov rsi, rdx
|
mov rsi, rdx
|
||||||
|
|
@ -1619,31 +1683,6 @@ codegen_write_width:
|
||||||
.panic:
|
.panic:
|
||||||
call 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], 0 ; Operand.register = undef
|
|
||||||
mov word [rsp + 2], 8 ; Operand.width = 8
|
|
||||||
mov word [rsp + 4], 0 ; Operand.len = 0
|
|
||||||
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: *function_ctx
|
;; rdi: *function_ctx
|
||||||
;; rsi: *text
|
;; rsi: *text
|
||||||
;; rdx: lhs: *Operand
|
;; rdx: lhs: *Operand
|
||||||
|
|
@ -1666,7 +1705,7 @@ codegen_binary_op_rm64_rm64:
|
||||||
; if lhs.kind == REGISTER || lhs.kind < ADDRESS && rhs.kind == REGISTER {
|
; if lhs.kind == REGISTER || lhs.kind < ADDRESS && rhs.kind == REGISTER {
|
||||||
cmp byte [rdx + 0], OPERAND_REGISTER
|
cmp byte [rdx + 0], OPERAND_REGISTER
|
||||||
je .simple
|
je .simple
|
||||||
cmp byte [rdx + 0], OPERAND_ADDRESS
|
cmp byte [rdx + 0], OPERAND_RBP_PVALUE
|
||||||
setb al
|
setb al
|
||||||
cmp byte [rcx + 0], OPERAND_REGISTER
|
cmp byte [rcx + 0], OPERAND_REGISTER
|
||||||
sete bl
|
sete bl
|
||||||
|
|
@ -1712,8 +1751,8 @@ codegen_binary_op_rm64_rm64:
|
||||||
jmp .epilogue
|
jmp .epilogue
|
||||||
; } else {
|
; } else {
|
||||||
.complex:
|
.complex:
|
||||||
; if lhs.kind < ADDRESS {
|
; if lhs.kind < RBP_PVALUE {
|
||||||
cmp byte [rdx + 0], OPERAND_ADDRESS
|
cmp byte [rdx + 0], OPERAND_RBP_PVALUE
|
||||||
jae .check_rhs
|
jae .check_rhs
|
||||||
|
|
||||||
; mov rax, rhs
|
; mov rax, rhs
|
||||||
|
|
@ -1741,8 +1780,8 @@ codegen_binary_op_rm64_rm64:
|
||||||
jmp .epilogue
|
jmp .epilogue
|
||||||
|
|
||||||
.check_rhs:
|
.check_rhs:
|
||||||
; } else if rhs.kind < ADDRESS {
|
; } else if rhs.kind < RBP_PVALUE {
|
||||||
cmp byte [rcx + 0], OPERAND_ADDRESS
|
cmp byte [rcx + 0], OPERAND_RBP_PVALUE
|
||||||
jae .allocate_dst
|
jae .allocate_dst
|
||||||
; mov rax, lhs
|
; mov rax, lhs
|
||||||
mov rdi, [rsp + 8] ; *text
|
mov rdi, [rsp + 8] ; *text
|
||||||
|
|
@ -1848,7 +1887,7 @@ codegen_binary_op_unchecked:
|
||||||
call codegen_write_operand
|
call codegen_write_operand
|
||||||
|
|
||||||
mov byte [rsp + 31], 10 ; newline
|
mov byte [rsp + 31], 10 ; newline
|
||||||
mov rdi, [rsp + 8] ; *text
|
mov rdi, [rsp] ; *text
|
||||||
lea rsi, [rsp + 31]
|
lea rsi, [rsp + 31]
|
||||||
call vec_push
|
call vec_push
|
||||||
|
|
||||||
|
|
@ -1856,6 +1895,59 @@ codegen_binary_op_unchecked:
|
||||||
pop rbp
|
pop rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;; rdi: *text
|
||||||
|
;; rsi: dst: *Operand
|
||||||
|
;; rdx: bits
|
||||||
|
;; rcx: width
|
||||||
|
codegen_load_imm:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
|
||||||
|
sub rsp, 32
|
||||||
|
mov [rsp], rdi ; *text
|
||||||
|
mov [rsp + 8], rsi ; dst
|
||||||
|
mov rax, [rel OPERAND_IMM]
|
||||||
|
mov [rsp + 16], rax ; Operand
|
||||||
|
mov [rsp + 24], rdx ; Operand.value
|
||||||
|
|
||||||
|
cmp byte [rsi + 0], OPERAND_LAST_VALUE
|
||||||
|
jg .panic ; unsupported dst kind
|
||||||
|
|
||||||
|
cmp rcx, 8
|
||||||
|
jl .direct
|
||||||
|
jg .panic ; unsupported immediate size
|
||||||
|
|
||||||
|
.indirect:
|
||||||
|
; mov rax, bits
|
||||||
|
; mov dst, rax
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rel OPERAND_RAX]
|
||||||
|
lea rdx, [rsp + 16] ; imm
|
||||||
|
mov rcx, 'mov '
|
||||||
|
call codegen_binary_op_unchecked
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
mov rsi, [rsp + 8] ; dst
|
||||||
|
lea rdx, [rel OPERAND_RAX]
|
||||||
|
mov rcx, 'mov '
|
||||||
|
call codegen_binary_op_unchecked
|
||||||
|
|
||||||
|
.direct:
|
||||||
|
; mov dst, bits
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
mov rsi, [rsp + 8] ; dst
|
||||||
|
lea rdx, [rsp + 16] ; imm
|
||||||
|
mov rcx, 'mov '
|
||||||
|
call codegen_binary_op_unchecked
|
||||||
|
|
||||||
|
add rsp, 32
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
.panic:
|
||||||
|
call panic
|
||||||
|
|
||||||
;; rdi: *text
|
;; rdi: *text
|
||||||
;; rsi: dst: *Operand
|
;; rsi: dst: *Operand
|
||||||
;; rdx: src: *Operand
|
;; rdx: src: *Operand
|
||||||
|
|
@ -1864,14 +1956,27 @@ codegen_move_dst_src:
|
||||||
mov rbp, rsp
|
mov rbp, rsp
|
||||||
push rbx
|
push rbx
|
||||||
|
|
||||||
sub rsp, 24
|
sub rsp, 32
|
||||||
mov [rsp], rdi ; *text
|
mov [rsp], rdi ; *text
|
||||||
mov [rsp + 8], rsi ; dst
|
mov [rsp + 8], rsi ; dst
|
||||||
mov [rsp + 16], rdx ; src
|
mov [rsp + 16], rdx ; src
|
||||||
|
mov qword [rsp + 24], 'mov ' ; op
|
||||||
|
|
||||||
cmp byte [rsi + 0], OPERAND_ADDRESS
|
cmp byte [rsi + 0], OPERAND_LAST_PLACE
|
||||||
jg .panic ; unsupported dst kind
|
jg .panic ; unsupported dst kind
|
||||||
|
cmp byte [rdx + 0], OPERAND_LAST_PLACE
|
||||||
|
jg .panic ; unsupported src kind
|
||||||
|
|
||||||
|
; op = src.is_place().then("lea ").else("mov ")
|
||||||
|
cmp byte [rdx + 0], OPERAND_LAST_VALUE
|
||||||
|
jb .mov
|
||||||
|
|
||||||
|
; an address stored in a stack slot has to be moved
|
||||||
|
cmp byte [rdx + 0], OPERAND_RBP_PLACE
|
||||||
|
je .mov
|
||||||
|
mov qword [rsp + 24], 'lea '
|
||||||
|
|
||||||
|
.mov:
|
||||||
; if dst.width != src.width
|
; if dst.width != src.width
|
||||||
mov cx, word [rsi + 2] ; dst.width
|
mov cx, word [rsi + 2] ; dst.width
|
||||||
mov bx, word [rdx + 2] ; src.width
|
mov bx, word [rdx + 2] ; src.width
|
||||||
|
|
@ -1888,55 +1993,70 @@ codegen_move_dst_src:
|
||||||
cmp byte [rsi + 0], OPERAND_REGISTER
|
cmp byte [rsi + 0], OPERAND_REGISTER
|
||||||
je .do_move ; if dst == register, do move
|
je .do_move ; if dst == register, do move
|
||||||
; If dst != register and src != register, we cannot move directly into memory:
|
; If dst != register and src != register, we cannot move directly into memory:
|
||||||
; there is no MOV m64, m64 or MOV m64, imm64 instruction.
|
; there is no MOV m64, m64 instruction.
|
||||||
; A smarter compiler could test for the immediate size and move most
|
|
||||||
; immediates directly into memory, but we are quite stupid!
|
|
||||||
cmp byte [rdx + 0], OPERAND_REGISTER
|
cmp byte [rdx + 0], OPERAND_REGISTER
|
||||||
jne .xchg_rax
|
jne .indirect_rax
|
||||||
jmp .do_move
|
jmp .do_move
|
||||||
|
|
||||||
.xchg_rax:
|
.indirect_rax:
|
||||||
; mov rax, [src]
|
cmp byte [rsi + 0], OPERAND_RBP_PLACE
|
||||||
|
je .indirect_xchg
|
||||||
|
; op rax, [src]
|
||||||
; mov [dst], rax
|
; mov [dst], rax
|
||||||
|
|
||||||
mov rdi, [rsp] ; *text
|
mov rdi, [rsp] ; *text
|
||||||
lea rsi, [rel OPERAND_RAX]
|
lea rsi, [rel OPERAND_RAX]
|
||||||
mov rdx, [rsp + 16] ; src
|
mov rdx, [rsp + 16] ; src
|
||||||
call codegen_move_dst_src
|
mov rcx, [rsp + 24] ; op
|
||||||
|
call codegen_binary_op_unchecked
|
||||||
|
|
||||||
mov rdi, [rsp] ; *text
|
mov rdi, [rsp] ; *text
|
||||||
mov rsi, [rsp + 8] ; src
|
mov rsi, [rsp + 8] ; dst
|
||||||
lea rdx, [rel OPERAND_RAX]
|
lea rdx, [rel OPERAND_RAX]
|
||||||
call codegen_move_dst_src
|
mov rcx, 'mov '
|
||||||
|
call codegen_binary_op_unchecked
|
||||||
|
jmp .epilogue
|
||||||
|
|
||||||
|
.indirect_xchg:
|
||||||
|
; xchg rdx, dst
|
||||||
|
; mov rax, src
|
||||||
|
; mov [rdx], rax
|
||||||
|
; xchg rdx, dst
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rel OPERAND_RDX] ; rdx
|
||||||
|
mov rdx, [rsp + 8] ; dst
|
||||||
|
mov rcx, 'xchg '
|
||||||
|
call codegen_binary_op_unchecked
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rel OPERAND_RAX]
|
||||||
|
mov rdx, [rsp + 16] ; src
|
||||||
|
mov rcx, [rsp + 24] ; op
|
||||||
|
call codegen_binary_op_unchecked
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rel OPERAND_RDX_P] ; [rdx]
|
||||||
|
lea rdx, [rel OPERAND_RAX] ; rax
|
||||||
|
mov rcx, 'mov '
|
||||||
|
call codegen_binary_op_unchecked
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; *text
|
||||||
|
lea rsi, [rel OPERAND_RDX] ; rdx
|
||||||
|
mov rdx, [rsp + 8] ; dst
|
||||||
|
mov rcx, 'xchg '
|
||||||
|
call codegen_binary_op_unchecked
|
||||||
jmp .epilogue
|
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 rdi, [rsp] ; *text
|
||||||
mov rsi, [rsp + 8] ; dst
|
mov rsi, [rsp + 8] ; dst
|
||||||
call codegen_write_operand
|
mov rdx, [rsp + 16] ; src
|
||||||
|
mov rcx, [rsp + 24] ; op
|
||||||
mov rdi, [rsp] ; *text
|
call codegen_binary_op_unchecked
|
||||||
lea rsi, [rel COMMA_RAX]
|
|
||||||
mov rdx, 2
|
|
||||||
call vec_extend
|
|
||||||
|
|
||||||
mov rdi, [rsp] ; *text
|
|
||||||
mov rsi, [rsp + 16] ; src
|
|
||||||
call codegen_write_operand
|
|
||||||
|
|
||||||
mov rdi, [rsp] ; *text
|
|
||||||
lea rsi, [rel COLON_NL]
|
|
||||||
inc rsi
|
|
||||||
call vec_push
|
|
||||||
|
|
||||||
.epilogue:
|
.epilogue:
|
||||||
|
add rsp, 32
|
||||||
add rsp, 24
|
|
||||||
pop rbx
|
pop rbx
|
||||||
pop rbp
|
pop rbp
|
||||||
ret
|
ret
|
||||||
|
|
|
||||||
|
|
@ -60,50 +60,57 @@ fn main() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
print_ast(
|
// print_ast(
|
||||||
b"fn main() -> void { return 1 * 2 + 3 * 4; }",
|
// b"fn main() -> void { return 1 * 2 + 3 * 4; }",
|
||||||
|ast| unsafe { parse_func(ast) },
|
// |ast| unsafe { parse_func(ast) },
|
||||||
);
|
// );
|
||||||
|
|
||||||
print_ast(b"3 + 4", |ast| unsafe { parse_expr(ast) });
|
// print_ast(b"3 + 4", |ast| unsafe { parse_expr(ast) });
|
||||||
print_ast(b"fn main() -> void { return 1 + 2; }", |ast| unsafe {
|
// print_ast(b"fn main() -> void { return 1 + 2; }", |ast| unsafe {
|
||||||
parse_func(ast)
|
// parse_func(ast)
|
||||||
});
|
// });
|
||||||
print_ast(
|
// print_ast(
|
||||||
b"fn main() -> void { ;;;return (1 + (2)); }",
|
// b"fn main() -> void { ;;;return (1 + (2)); }",
|
||||||
|ast| unsafe { parse_func(ast) },
|
// |ast| unsafe { parse_func(ast) },
|
||||||
);
|
// );
|
||||||
print_ast(
|
// print_ast(
|
||||||
b"fn main() -> void { return (1 + (2 * 3)) / 4; }",
|
// b"fn main() -> void { return (1 + (2 * 3)) / 4; }",
|
||||||
|ast| unsafe { parse_func(ast) },
|
// |ast| unsafe { parse_func(ast) },
|
||||||
);
|
// );
|
||||||
print_ast(b"fn main() -> void { return 1 + 2 * 3; }", |ast| unsafe {
|
// print_ast(b"fn main() -> void { return 1 + 2 * 3; }", |ast| unsafe {
|
||||||
parse_func(ast)
|
// parse_func(ast)
|
||||||
});
|
// });
|
||||||
|
|
||||||
print_ast(b"fn main() -> void { let x: u32 = 4; }", |ast| unsafe {
|
// print_ast(b"fn main() -> void { let x: u32 = 4; }", |ast| unsafe {
|
||||||
parse_func(ast)
|
// parse_func(ast)
|
||||||
});
|
// });
|
||||||
|
// print_ast(
|
||||||
|
// b"fn main(a: u32) -> void { let x: u32 = a + 4; }",
|
||||||
|
// |ast| unsafe { parse_func(ast) },
|
||||||
|
// );
|
||||||
|
// print_ast(
|
||||||
|
// b"fn main(a: u32) -> void {
|
||||||
|
// let y: u32 = a + 4;
|
||||||
|
// 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) },
|
||||||
|
// );
|
||||||
print_ast(
|
print_ast(
|
||||||
b"fn main(a: u32) -> void { let x: u32 = a + 4; }",
|
b"fn main(a: *u32, b: u32) -> void {
|
||||||
|ast| unsafe { parse_func(ast) },
|
*a = b;
|
||||||
);
|
a = &b;
|
||||||
print_ast(
|
|
||||||
b"fn main(a: u32) -> void {
|
|
||||||
let y: u32 = a + 4;
|
|
||||||
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) },
|
|ast| unsafe { parse_func(ast) },
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ unsafe extern "C" {
|
||||||
pub unsafe fn stackvar_cmp(a: *const (u64, u64), b: *const (u64, u64)) -> i32;
|
pub unsafe fn stackvar_cmp(a: *const (u64, u64), b: *const (u64, u64)) -> i32;
|
||||||
pub unsafe fn codegen_allocate_register(ctx: *mut FunctionCtx) -> u8;
|
pub unsafe fn codegen_allocate_register(ctx: *mut FunctionCtx) -> u8;
|
||||||
pub unsafe fn codegen_allocate_place(ctx: *mut FunctionCtx, width: u16) -> Operand;
|
pub unsafe fn codegen_allocate_place(ctx: *mut FunctionCtx, width: u16) -> Operand;
|
||||||
|
pub unsafe fn codegen_allocate_stack_value(ctx: *mut FunctionCtx, width: u16) -> Operand;
|
||||||
pub unsafe fn codegen_allocate_value(ctx: *mut FunctionCtx, width: u16) -> Operand;
|
pub unsafe fn codegen_allocate_value(ctx: *mut FunctionCtx, width: u16) -> Operand;
|
||||||
pub unsafe fn codegen_free_operand(ctx: *mut FunctionCtx, operand: *const Operand) -> ();
|
pub unsafe fn codegen_free_operand(ctx: *mut FunctionCtx, operand: *const Operand) -> ();
|
||||||
pub unsafe fn codegen_function(ast: *const CodegenCtx, func_idx: u64) -> ();
|
pub unsafe fn codegen_function(ast: *const CodegenCtx, func_idx: u64) -> ();
|
||||||
|
|
@ -58,14 +59,18 @@ pub const TYPE_U32: u8 = 4;
|
||||||
pub const TYPE_STR: u8 = 5;
|
pub const TYPE_STR: u8 = 5;
|
||||||
pub const TYPE_POINTER: u8 = 6;
|
pub const TYPE_POINTER: u8 = 6;
|
||||||
pub const OPERAND_REGISTER: u32 = 1;
|
pub const OPERAND_REGISTER: u32 = 1;
|
||||||
pub const OPERAND_RBP_OFFSET: u32 = 2;
|
pub const OPERAND_RBP_VALUE: u32 = 2;
|
||||||
pub const OPERAND_RSP_OFFSET: u32 = 3;
|
pub const OPERAND_RBP_PVALUE: u32 = 3;
|
||||||
pub const OPERAND_ADDRESS: u32 = 4;
|
pub const OPERAND_ADDRESS_VALUE: u32 = 4;
|
||||||
pub const OPERAND_IMMEDIATE: u32 = 5;
|
pub const OPERAND_LAST_VALUE: u32 = 5;
|
||||||
pub const OPERAND_CONSTANT: u32 = 6;
|
pub const OPERAND_RBP_OFFSET: u32 = 6;
|
||||||
pub const OPERAND_LABEL: u32 = 7;
|
pub const OPERAND_ADDRESS_PLACE: u32 = 7;
|
||||||
pub const OPERAND_REGISTER_PLACE: u32 = 8;
|
pub const OPERAND_REGISTER_PLACE: u32 = 8;
|
||||||
pub const OPERAND_RBP_PLACE: u32 = 9;
|
pub const OPERAND_RBP_PLACE: u32 = 9;
|
||||||
|
pub const OPERAND_LAST_PLACE: u32 = 10;
|
||||||
|
pub const OPERAND_IMMEDIATE: u32 = 11;
|
||||||
|
pub const OPERAND_CONSTANT: u32 = 12;
|
||||||
|
pub const OPERAND_LABEL: u32 = 13;
|
||||||
pub const TOKEN_EOF: u8 = 0;
|
pub const TOKEN_EOF: u8 = 0;
|
||||||
pub const TOKEN_LET: u8 = 1;
|
pub const TOKEN_LET: u8 = 1;
|
||||||
pub const TOKEN_IF: u8 = 2;
|
pub const TOKEN_IF: u8 = 2;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue