it doesn't crash (crazy)
This commit is contained in:
parent
a93f7edd62
commit
8e1af956b0
|
|
@ -177,7 +177,9 @@ write_register_name:
|
|||
|
||||
|
||||
;; 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:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
|
@ -222,6 +224,7 @@ codegen_arg_to_operand:
|
|||
jmp .epilogue
|
||||
|
||||
.stack_arg:
|
||||
; TODO: use these offsets in stack-vars instead of copying into new stack slots
|
||||
sub rdi, 6
|
||||
mov rax, 8
|
||||
mul rdi
|
||||
|
|
@ -235,9 +238,9 @@ codegen_arg_to_operand:
|
|||
shl eax, 16
|
||||
or eax, 8 ; Operand.width = 8
|
||||
shl eax, 8
|
||||
; or eax, 0 ; Operand.register = undef
|
||||
; or eax, 0 ; Operand.register = undef
|
||||
shl eax, 8
|
||||
or eax, OPERAND_RBP_OFFSET ; Operand.kind
|
||||
or eax, OPERAND_RBP_VALUE ; Operand.kind
|
||||
|
||||
.epilogue:
|
||||
pop rbp
|
||||
|
|
@ -362,6 +365,22 @@ codegen_allocate_place:
|
|||
pop rbp
|
||||
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
|
||||
;; rsi: width
|
||||
;; define-fn: fn codegen_allocate_value(ctx: *mut FunctionCtx, width: u16) -> Operand
|
||||
|
|
@ -401,7 +420,7 @@ codegen_allocate_value:
|
|||
jmp .done
|
||||
|
||||
.alloc_stack:
|
||||
call codegen_allocate_place
|
||||
call codegen_allocate_stack_value
|
||||
|
||||
.done:
|
||||
add rsp, 16
|
||||
|
|
@ -422,10 +441,19 @@ codegen_free_operand:
|
|||
mov [rsp + 8], rsi ; operand
|
||||
|
||||
mov al, byte [rsi] ; Operand.kind
|
||||
xor rbx, rbx
|
||||
cmp al, OPERAND_REGISTER
|
||||
je .free_reg
|
||||
cmp al, OPERAND_RBP_OFFSET
|
||||
je .free_stack
|
||||
sete bl
|
||||
cmp al, OPERAND_REGISTER_PLACE
|
||||
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
|
||||
|
||||
.free_stack:
|
||||
|
|
@ -1028,14 +1056,10 @@ codegen_expr:
|
|||
; 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
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rsp + 32] ; dst
|
||||
lea rsi, [rel OPERAND_RAX] ; dst
|
||||
lea rdx, [rsp + 16] ; src
|
||||
call codegen_move_dst_src
|
||||
|
||||
|
|
@ -1057,14 +1081,8 @@ codegen_expr:
|
|||
|
||||
.number:
|
||||
; 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 [rsp + 40], rbx ; Operand.value
|
||||
mov [rsp + 40], rbx ; Imm value
|
||||
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
mov rsi, 8 ; width
|
||||
|
|
@ -1072,11 +1090,42 @@ codegen_expr:
|
|||
mov [rsp + 16], rax
|
||||
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
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rsp + 16] ; dst
|
||||
lea rdx, [rsp + 32] ; src
|
||||
call codegen_move_dst_src
|
||||
mov rcx, rdx ; byte count
|
||||
mov rdx, [rsp + 40] ; immediate value
|
||||
call codegen_load_imm
|
||||
|
||||
mov rax, qword [rsp + 16]
|
||||
mov rdx, qword [rsp + 24]
|
||||
|
|
@ -1130,7 +1179,7 @@ codegen_expr:
|
|||
; allocate scratch value for rdx
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
mov rsi, 8 ; width
|
||||
call codegen_allocate_place
|
||||
call codegen_allocate_value
|
||||
mov [rsp + 64], rax
|
||||
mov [rsp + 72], rdx
|
||||
|
||||
|
|
@ -1143,9 +1192,9 @@ codegen_expr:
|
|||
|
||||
; check if rhs is rdx
|
||||
mov rax, [rsp + 48] ; right operand
|
||||
and rax, 0xFFF
|
||||
and rax, 0xFFFF
|
||||
mov rdx, [rel OPERAND_RDX]
|
||||
and rdx, 0xFFF
|
||||
and rdx, 0xFFFF
|
||||
cmp rax, rdx
|
||||
jne .after_spill_rdx
|
||||
|
||||
|
|
@ -1320,25 +1369,9 @@ codegen_expr:
|
|||
call vec_get
|
||||
mov rdx, [rax + 8] ; offset
|
||||
neg rdx
|
||||
mov rax, qword [rel OPERAND_RBP]
|
||||
mov [rsp + 16], rax
|
||||
mov [rsp + 24], rdx
|
||||
mov rax, qword [rel OPERAND_RBP_OFFS]
|
||||
jmp .done
|
||||
|
||||
; 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:
|
||||
.assignment:
|
||||
.value_to_place:
|
||||
|
|
@ -1369,16 +1402,30 @@ codegen_expr:
|
|||
;; or: register: u4, width: u4
|
||||
section .rdata
|
||||
;; start-consts
|
||||
; Register containing a Value
|
||||
OPERAND_REGISTER equ 1 ; e.g. rax, rbx
|
||||
OPERAND_RBP_OFFSET equ 2 ; e.g. mov/lea [rbp - 8]
|
||||
OPERAND_RSP_OFFSET equ 3 ; e.g. [rsp + 16]
|
||||
OPERAND_ADDRESS equ 4 ; e.g. [rel OPERAND_ADDRESS]
|
||||
OPERAND_IMMEDIATE equ 5 ; e.g. 0x10
|
||||
OPERAND_CONSTANT equ 6 ; e.g. OPERAND_CONSTANT
|
||||
OPERAND_LABEL equ 7 ; e.g. label_1234
|
||||
; RSP-relative stack-slot containing a Value, semantically not addressable
|
||||
OPERAND_RBP_VALUE equ 2 ; e.g. [rsp + 16]
|
||||
; RBP-relative stack-slot containing a Value, but addressable (derived from a Place)
|
||||
OPERAND_RBP_PVALUE equ 3 ; e.g. mov [rbp - 8]
|
||||
; Static-slot containing a Value
|
||||
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]
|
||||
; RBP-relative stack-slot containing an address (Place)
|
||||
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
|
||||
WIDTH_BYTE db 'byte '
|
||||
WIDTH_WORD db 'word '
|
||||
|
|
@ -1387,11 +1434,23 @@ section .rdata
|
|||
|
||||
; Operand { kind: REGISTER, register: 0, width: 8, len: 0, padding: 0, value: 0 }
|
||||
align 8
|
||||
OPERAND_IMM dq 0x0008_000b, 0
|
||||
align 8
|
||||
OPERAND_RAX dq 0x0008_0001, 0
|
||||
align 8
|
||||
OPERAND_RAX_P dq 0x0008_0008, 0
|
||||
align 8
|
||||
OPERAND_RDX dq 0x0008_0301, 0
|
||||
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
|
||||
|
||||
|
|
@ -1414,9 +1473,13 @@ codegen_write_operand:
|
|||
je .register
|
||||
cmp bl, OPERAND_RBP_OFFSET
|
||||
je .rbp_offset
|
||||
cmp bl, OPERAND_RSP_OFFSET
|
||||
je .rsp_offset
|
||||
cmp bl, OPERAND_ADDRESS
|
||||
cmp bl, OPERAND_RBP_VALUE
|
||||
je .rbp_offset
|
||||
cmp bl, OPERAND_RBP_PVALUE
|
||||
je .rbp_offset
|
||||
cmp bl, OPERAND_ADDRESS_VALUE
|
||||
je .address
|
||||
cmp bl, OPERAND_ADDRESS_PLACE
|
||||
je .address
|
||||
cmp bl, OPERAND_IMMEDIATE
|
||||
je .immediate
|
||||
|
|
@ -1466,7 +1529,6 @@ codegen_write_operand:
|
|||
jmp .epilogue
|
||||
|
||||
.rbp_offset:
|
||||
.rsp_offset:
|
||||
; {width} [rbp {+/-} offset]
|
||||
mov rsi, [rsp + 8] ; op
|
||||
movzx rsi, word [rsi + 2] ; Operand.width
|
||||
|
|
@ -1608,6 +1670,8 @@ codegen_write_width:
|
|||
cmp sil, 1
|
||||
lea rdx, [rel WIDTH_BYTE]
|
||||
je .write
|
||||
cmp sil, 0
|
||||
je .write
|
||||
jmp .panic
|
||||
.write:
|
||||
mov rsi, rdx
|
||||
|
|
@ -1619,31 +1683,6 @@ codegen_write_width:
|
|||
.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
|
||||
;; rsi: *text
|
||||
;; rdx: lhs: *Operand
|
||||
|
|
@ -1666,7 +1705,7 @@ codegen_binary_op_rm64_rm64:
|
|||
; if lhs.kind == REGISTER || lhs.kind < ADDRESS && rhs.kind == REGISTER {
|
||||
cmp byte [rdx + 0], OPERAND_REGISTER
|
||||
je .simple
|
||||
cmp byte [rdx + 0], OPERAND_ADDRESS
|
||||
cmp byte [rdx + 0], OPERAND_RBP_PVALUE
|
||||
setb al
|
||||
cmp byte [rcx + 0], OPERAND_REGISTER
|
||||
sete bl
|
||||
|
|
@ -1712,8 +1751,8 @@ codegen_binary_op_rm64_rm64:
|
|||
jmp .epilogue
|
||||
; } else {
|
||||
.complex:
|
||||
; if lhs.kind < ADDRESS {
|
||||
cmp byte [rdx + 0], OPERAND_ADDRESS
|
||||
; if lhs.kind < RBP_PVALUE {
|
||||
cmp byte [rdx + 0], OPERAND_RBP_PVALUE
|
||||
jae .check_rhs
|
||||
|
||||
; mov rax, rhs
|
||||
|
|
@ -1741,8 +1780,8 @@ codegen_binary_op_rm64_rm64:
|
|||
jmp .epilogue
|
||||
|
||||
.check_rhs:
|
||||
; } else if rhs.kind < ADDRESS {
|
||||
cmp byte [rcx + 0], OPERAND_ADDRESS
|
||||
; } else if rhs.kind < RBP_PVALUE {
|
||||
cmp byte [rcx + 0], OPERAND_RBP_PVALUE
|
||||
jae .allocate_dst
|
||||
; mov rax, lhs
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
|
|
@ -1848,7 +1887,7 @@ codegen_binary_op_unchecked:
|
|||
call codegen_write_operand
|
||||
|
||||
mov byte [rsp + 31], 10 ; newline
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
mov rdi, [rsp] ; *text
|
||||
lea rsi, [rsp + 31]
|
||||
call vec_push
|
||||
|
||||
|
|
@ -1856,6 +1895,59 @@ codegen_binary_op_unchecked:
|
|||
pop rbp
|
||||
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
|
||||
;; rsi: dst: *Operand
|
||||
;; rdx: src: *Operand
|
||||
|
|
@ -1864,14 +1956,27 @@ codegen_move_dst_src:
|
|||
mov rbp, rsp
|
||||
push rbx
|
||||
|
||||
sub rsp, 24
|
||||
mov [rsp], rdi ; *text
|
||||
mov [rsp + 8], rsi ; dst
|
||||
mov [rsp + 16], rdx ; src
|
||||
sub rsp, 32
|
||||
mov [rsp], rdi ; *text
|
||||
mov [rsp + 8], rsi ; dst
|
||||
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
|
||||
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
|
||||
mov cx, word [rsi + 2] ; dst.width
|
||||
mov bx, word [rdx + 2] ; src.width
|
||||
|
|
@ -1888,55 +1993,70 @@ codegen_move_dst_src:
|
|||
cmp byte [rsi + 0], OPERAND_REGISTER
|
||||
je .do_move ; if dst == register, do move
|
||||
; If dst != register and src != register, we cannot move directly into memory:
|
||||
; there is no MOV m64, m64 or MOV m64, imm64 instruction.
|
||||
; A smarter compiler could test for the immediate size and move most
|
||||
; immediates directly into memory, but we are quite stupid!
|
||||
; there is no MOV m64, m64 instruction.
|
||||
cmp byte [rdx + 0], OPERAND_REGISTER
|
||||
jne .xchg_rax
|
||||
jne .indirect_rax
|
||||
jmp .do_move
|
||||
|
||||
.xchg_rax:
|
||||
; mov rax, [src]
|
||||
.indirect_rax:
|
||||
cmp byte [rsi + 0], OPERAND_RBP_PLACE
|
||||
je .indirect_xchg
|
||||
; op rax, [src]
|
||||
; mov [dst], rax
|
||||
|
||||
mov rdi, [rsp] ; *text
|
||||
lea rsi, [rel OPERAND_RAX]
|
||||
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 rsi, [rsp + 8] ; src
|
||||
mov rsi, [rsp + 8] ; dst
|
||||
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
|
||||
|
||||
.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
|
||||
|
||||
mov rdi, [rsp] ; *text
|
||||
lea rsi, [rel COLON_NL]
|
||||
inc rsi
|
||||
call vec_push
|
||||
mov rdx, [rsp + 16] ; src
|
||||
mov rcx, [rsp + 24] ; op
|
||||
call codegen_binary_op_unchecked
|
||||
|
||||
.epilogue:
|
||||
|
||||
add rsp, 24
|
||||
add rsp, 32
|
||||
pop rbx
|
||||
pop rbp
|
||||
ret
|
||||
|
|
|
|||
|
|
@ -60,50 +60,57 @@ fn main() {
|
|||
};
|
||||
}
|
||||
|
||||
print_ast(
|
||||
b"fn main() -> void { return 1 * 2 + 3 * 4; }",
|
||||
|ast| unsafe { parse_func(ast) },
|
||||
);
|
||||
// print_ast(
|
||||
// b"fn main() -> void { return 1 * 2 + 3 * 4; }",
|
||||
// |ast| unsafe { parse_func(ast) },
|
||||
// );
|
||||
|
||||
print_ast(b"3 + 4", |ast| unsafe { parse_expr(ast) });
|
||||
print_ast(b"fn main() -> void { return 1 + 2; }", |ast| unsafe {
|
||||
parse_func(ast)
|
||||
});
|
||||
print_ast(
|
||||
b"fn main() -> void { ;;;return (1 + (2)); }",
|
||||
|ast| unsafe { parse_func(ast) },
|
||||
);
|
||||
print_ast(
|
||||
b"fn main() -> void { return (1 + (2 * 3)) / 4; }",
|
||||
|ast| unsafe { parse_func(ast) },
|
||||
);
|
||||
print_ast(b"fn main() -> void { return 1 + 2 * 3; }", |ast| unsafe {
|
||||
parse_func(ast)
|
||||
});
|
||||
// print_ast(b"3 + 4", |ast| unsafe { parse_expr(ast) });
|
||||
// print_ast(b"fn main() -> void { return 1 + 2; }", |ast| unsafe {
|
||||
// parse_func(ast)
|
||||
// });
|
||||
// print_ast(
|
||||
// b"fn main() -> void { ;;;return (1 + (2)); }",
|
||||
// |ast| unsafe { parse_func(ast) },
|
||||
// );
|
||||
// print_ast(
|
||||
// b"fn main() -> void { return (1 + (2 * 3)) / 4; }",
|
||||
// |ast| unsafe { parse_func(ast) },
|
||||
// );
|
||||
// print_ast(b"fn main() -> void { return 1 + 2 * 3; }", |ast| unsafe {
|
||||
// parse_func(ast)
|
||||
// });
|
||||
|
||||
print_ast(b"fn main() -> void { let x: u32 = 4; }", |ast| unsafe {
|
||||
parse_func(ast)
|
||||
});
|
||||
// print_ast(b"fn main() -> void { let x: u32 = 4; }", |ast| unsafe {
|
||||
// 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(
|
||||
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;
|
||||
b"fn main(a: *u32, b: u32) -> void {
|
||||
*a = b;
|
||||
a = &b;
|
||||
}",
|
||||
|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 codegen_allocate_register(ctx: *mut FunctionCtx) -> u8;
|
||||
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_free_operand(ctx: *mut FunctionCtx, operand: *const Operand) -> ();
|
||||
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_POINTER: u8 = 6;
|
||||
pub const OPERAND_REGISTER: u32 = 1;
|
||||
pub const OPERAND_RBP_OFFSET: u32 = 2;
|
||||
pub const OPERAND_RSP_OFFSET: u32 = 3;
|
||||
pub const OPERAND_ADDRESS: u32 = 4;
|
||||
pub const OPERAND_IMMEDIATE: u32 = 5;
|
||||
pub const OPERAND_CONSTANT: u32 = 6;
|
||||
pub const OPERAND_LABEL: u32 = 7;
|
||||
pub const OPERAND_RBP_VALUE: u32 = 2;
|
||||
pub const OPERAND_RBP_PVALUE: u32 = 3;
|
||||
pub const OPERAND_ADDRESS_VALUE: u32 = 4;
|
||||
pub const OPERAND_LAST_VALUE: u32 = 5;
|
||||
pub const OPERAND_RBP_OFFSET: u32 = 6;
|
||||
pub const OPERAND_ADDRESS_PLACE: u32 = 7;
|
||||
pub const OPERAND_REGISTER_PLACE: u32 = 8;
|
||||
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_LET: u8 = 1;
|
||||
pub const TOKEN_IF: u8 = 2;
|
||||
|
|
|
|||
Loading…
Reference in a new issue