Compare commits
2 commits
4f5579b6fd
...
a90a01bc28
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a90a01bc28 | ||
|
|
0e25f627a8 |
169
lang/src/ast.asm
169
lang/src/ast.asm
|
|
@ -4,11 +4,16 @@ default rel
|
|||
%include "src/ast.inc"
|
||||
|
||||
section .rdata
|
||||
PRECEDENCE_PIPE2 dw 10
|
||||
PRECEDENCE_AMP2 dw 20
|
||||
PRECEDENCE_PIPE dw 30
|
||||
PRECEDENCE_CARET dw 40
|
||||
PRECEDENCE_AMP dw 50
|
||||
PRECEDENCE_EQ dw 60
|
||||
PRECEDENCE_CMP dw 70
|
||||
PRECEDENCE_SHIFT dw 80
|
||||
PRECEDENCE_ADD dw 90
|
||||
PRECEDENCE_SUB dw 90
|
||||
PRECEDENCE_MUL dw 100
|
||||
PRECEDENCE_DIV dw 100
|
||||
PRECEDENCE_REM dw 100
|
||||
|
||||
section .text
|
||||
extern vec_init_with
|
||||
|
|
@ -42,6 +47,7 @@ global parse_args
|
|||
global parse_expr
|
||||
global parse_binary_expr
|
||||
global parse_primary_expr
|
||||
global parse_if_expr
|
||||
global parse_statement
|
||||
global parse_block
|
||||
global ast_build_symtable
|
||||
|
|
@ -446,11 +452,23 @@ parse_binary_expr:
|
|||
cmp al, TOKEN_PLUS
|
||||
cmove bx, word [rel PRECEDENCE_ADD]
|
||||
cmp al, TOKEN_MINUS
|
||||
cmove bx, word [rel PRECEDENCE_SUB]
|
||||
cmove bx, word [rel PRECEDENCE_ADD]
|
||||
cmp al, TOKEN_STAR
|
||||
cmove bx, word [rel PRECEDENCE_MUL]
|
||||
cmp al, TOKEN_SLASH
|
||||
cmove bx, word [rel PRECEDENCE_DIV]
|
||||
cmove bx, word [rel PRECEDENCE_MUL]
|
||||
cmp al, TOKEN_EQEQ
|
||||
cmove bx, word [rel PRECEDENCE_EQ]
|
||||
cmp al, TOKEN_BANGEQ
|
||||
cmove bx, word [rel PRECEDENCE_EQ]
|
||||
cmp al, TOKEN_LT
|
||||
cmove bx, word [rel PRECEDENCE_CMP]
|
||||
cmp al, TOKEN_LTEQ
|
||||
cmove bx, word [rel PRECEDENCE_CMP]
|
||||
cmp al, TOKEN_GT
|
||||
cmove bx, word [rel PRECEDENCE_CMP]
|
||||
cmp al, TOKEN_GTEQ
|
||||
cmove bx, word [rel PRECEDENCE_CMP]
|
||||
cmp bx, -1
|
||||
je .done
|
||||
mov byte [rsp + 18], bl
|
||||
|
|
@ -557,10 +575,20 @@ parse_statement:
|
|||
call peek_expect_token ; parse_block expects lbrace to still be there
|
||||
test rax, rax
|
||||
jnz .block
|
||||
mov dil, TOKEN_IF
|
||||
call peek_expect_token
|
||||
test rax, rax
|
||||
jnz .if_expr
|
||||
mov rdi, [rsp] ; Ast
|
||||
call parse_expr
|
||||
jmp .epilogue
|
||||
|
||||
.if_expr:
|
||||
mov rdi, [rsp] ; Ast
|
||||
call ast_parse_if_expr
|
||||
; If expressions don't require a trailing semicolon
|
||||
jmp .epilogue
|
||||
|
||||
.block:
|
||||
mov rdi, [rsp] ; Ast
|
||||
call parse_block
|
||||
|
|
@ -576,6 +604,12 @@ parse_statement:
|
|||
.return:
|
||||
mov rdi, [rsp] ; Ast
|
||||
call parse_expr
|
||||
; return expression requires a value
|
||||
|
||||
mov rdi, [rsp] ; Ast
|
||||
mov rsi, rax ; expr
|
||||
call ast_place_to_value
|
||||
|
||||
mov byte [rsp + 8], AST_RETURN_STATEMENT ; AstNode.kind
|
||||
mov [rsp + 16], rax ; AstNode.data
|
||||
mov qword [rsp + 24], 0 ; AstNode.extra
|
||||
|
|
@ -859,6 +893,116 @@ parse_assignment_expr:
|
|||
pop rbp
|
||||
ret
|
||||
|
||||
;; rdi: *mut Ast
|
||||
;; define-fn: fn ast_parse_switch_expr(ast: *mut Ast) -> (u64, bool)
|
||||
ast_parse_switch_expr:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
; start-structs
|
||||
; struct AstSwitch {
|
||||
; expr: u64,
|
||||
; cases: *const u64,
|
||||
; cases_len: usize,
|
||||
; }
|
||||
;
|
||||
; struct AstSwitchCase {
|
||||
; pattern: u64,
|
||||
; expr: u64,
|
||||
; }
|
||||
; end-structs
|
||||
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
;; rdi: *mut Ast
|
||||
;; define-fn: fn ast_parse_if_expr(ast: *mut Ast) -> (u64, bool)
|
||||
ast_parse_if_expr:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
; start-structs
|
||||
; struct AstIfExpr {
|
||||
; condition: u64,
|
||||
; then: u64,
|
||||
; else_: u64,
|
||||
; }
|
||||
; end-structs
|
||||
|
||||
; ast [0..8]
|
||||
sub rsp, 40
|
||||
mov [rsp], rdi ; Ast
|
||||
|
||||
call tokeniser_get_cursor
|
||||
mov [rsp + 32], rax ; span
|
||||
|
||||
mov dil, TOKEN_IF
|
||||
call unwrap_token
|
||||
|
||||
mov dil, TOKEN_LPARENS
|
||||
call unwrap_token
|
||||
|
||||
mov rdi, [rsp] ; Ast
|
||||
call parse_expr
|
||||
mov [rsp + 8], rax ; condition
|
||||
|
||||
mov dil, TOKEN_RPARENS
|
||||
call unwrap_token
|
||||
|
||||
mov rdi, [rsp] ; Ast
|
||||
call parse_block
|
||||
mov [rsp + 16], rax ; then
|
||||
|
||||
mov dil, TOKEN_ELSE
|
||||
call expect_token
|
||||
test rax, rax
|
||||
jz .no_else
|
||||
|
||||
mov dil, TOKEN_IF
|
||||
call peek_expect_token
|
||||
test rax, rax
|
||||
jnz .else_if
|
||||
|
||||
mov rdi, [rsp] ; Ast
|
||||
call parse_block
|
||||
mov [rsp + 24], rax ; else
|
||||
jmp .after_else
|
||||
|
||||
.else_if:
|
||||
mov rdi, [rsp] ; Ast
|
||||
call ast_parse_if_expr
|
||||
mov [rsp + 24], rax ; else
|
||||
jmp .after_else
|
||||
|
||||
.no_else:
|
||||
mov qword [rsp + 24], -1 ; else = None
|
||||
|
||||
.after_else:
|
||||
mov rdi, 24 ; size_of::<AstIfExpr>
|
||||
mov rsi, 8 ; align_of::<AstIfExpr>
|
||||
call bump_alloc
|
||||
|
||||
mov rdi, rax ; AstIfExpr ptr
|
||||
lea rsi, [rsp + 8] ; &AstIfExpr
|
||||
mov rdx, 24 ; size_of::<AstIfExpr>
|
||||
call memcpy
|
||||
|
||||
mov qword [rsp + 8], AST_IF ; AstNode.kind
|
||||
mov [rsp + 16], rdi ; AstNode.data
|
||||
mov qword [rsp + 24], 0 ; AstNode.extra
|
||||
|
||||
mov rdi, [rsp] ; Ast
|
||||
lea rsi, [rsp + 8] ; &AstNode
|
||||
call vec_push
|
||||
|
||||
mov rdi, [rsp] ; Ast
|
||||
mov rax, [rdi + 8] ; Ast.nodes.len()
|
||||
dec rax
|
||||
|
||||
add rsp, 40
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
;; rdi: *mut Ast
|
||||
;; define-fn: fn ast_parse_let(ast: *mut Ast) -> (u64, bool)
|
||||
ast_parse_let:
|
||||
|
|
@ -1441,6 +1585,8 @@ ast_walk_for_each:
|
|||
je .address_of
|
||||
cmp bl, AST_RETURN_STATEMENT
|
||||
je .return_statement
|
||||
cmp bl, AST_IF
|
||||
je .if_expr
|
||||
jmp .check_scope
|
||||
|
||||
.func:
|
||||
|
|
@ -1496,6 +1642,19 @@ ast_walk_for_each:
|
|||
push rdx ; push left index
|
||||
jmp .check_scope
|
||||
|
||||
.if_expr:
|
||||
mov rbx, [rax + 8] ; AstNode.data
|
||||
mov rdx, [rbx + 16] ; else index
|
||||
cmp rdx, -1
|
||||
je .no_else
|
||||
push rdx ; push else index
|
||||
.no_else:
|
||||
mov rdx, [rbx + 8] ; then index
|
||||
push rdx ; push then index
|
||||
mov rdx, [rbx + 0] ; condition index
|
||||
push rdx ; push condition index
|
||||
jmp .check_scope
|
||||
|
||||
.assignment:
|
||||
mov rbx, [rax + 8] ; AstNode.data = dest
|
||||
mov rdx, [rax + 16] ; AstNode.extra = source
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ section .rdata
|
|||
AST_VAR_DECL equ 12 ; :u8
|
||||
AST_VAR_REF equ 13 ; :u8
|
||||
AST_ARG equ 14 ; :u8
|
||||
AST_SWITCH equ 15 ; :u8
|
||||
AST_IF equ 16 ; :u8
|
||||
AST_ELSE equ 17 ; :u8
|
||||
AST_CALL equ 18 ; :u8
|
||||
|
||||
TYPE_VOID equ 1 ; :u8
|
||||
TYPE_BOOL equ 2 ; :u8
|
||||
|
|
@ -21,4 +25,4 @@ section .rdata
|
|||
TYPE_U32 equ 4 ; :u8
|
||||
TYPE_STR equ 5 ; :u8
|
||||
TYPE_POINTER equ 6 ; :u8
|
||||
;; end-consts
|
||||
;; end-consts
|
||||
|
|
|
|||
|
|
@ -1020,8 +1020,210 @@ codegen_expr:
|
|||
je .deref
|
||||
cmp bl, AST_ADDRESS_OF
|
||||
je .address_of
|
||||
cmp bl, AST_IF
|
||||
je .if_expr
|
||||
jmp .panic
|
||||
|
||||
.if_expr:
|
||||
mov rbx, [rax + 8] ; AstNode.data = *AstIfExpr
|
||||
mov [rsp + 16], rax ; scratch = AstNode
|
||||
|
||||
mov rdx, [rbx] ; AstIfExpr.cond
|
||||
mov rdi, [rsp] ; ctx
|
||||
mov rsi, [rsp + 8] ; &function_ctx
|
||||
call codegen_expr
|
||||
mov [rsp + 24], rax ; cond operand
|
||||
mov [rsp + 32], rdx
|
||||
|
||||
; cmp cond, 0
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rsp + 24] ; left = cond
|
||||
lea rdx, [rel OPERAND_ZERO] ; right = 0
|
||||
mov rcx, 'cmp '
|
||||
call codegen_binary_op_unchecked
|
||||
|
||||
; free cond
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
lea rsi, [rsp + 24] ; cond operand
|
||||
call codegen_free_operand
|
||||
|
||||
; je .branch_{else_}
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rel JE_B]
|
||||
mov rdx, JE_B_len
|
||||
call vec_extend
|
||||
|
||||
mov rdi, [rbx + 16] ; AstIfExpr.else
|
||||
lea rsi, [rsp + 24] ; scratch
|
||||
mov rdx, 30
|
||||
mov rcx, 16
|
||||
call int_to_str2
|
||||
mov byte [rax + rdx], 10
|
||||
inc rdx
|
||||
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
mov rsi, rax
|
||||
call vec_extend
|
||||
|
||||
; codegen then branch
|
||||
mov rdx, [rbx + 8] ; AstIfExpr.then
|
||||
mov rdi, [rsp] ; ctx
|
||||
mov rsi, [rsp + 8] ; &function_ctx
|
||||
call codegen_expr
|
||||
mov [rsp + 24], rax ; then
|
||||
mov [rsp + 32], rdx
|
||||
|
||||
cmp rax, 0
|
||||
je .if_skip_phi
|
||||
; mov rax, then
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rel OPERAND_RAX]
|
||||
lea rdx, [rsp + 24] ; src
|
||||
call codegen_move_dst_src
|
||||
|
||||
; free then
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
lea rsi, [rsp + 24] ; then operand
|
||||
call codegen_free_operand
|
||||
|
||||
.if_skip_phi:
|
||||
; jmp .branch_{if}
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rel JMP_PHI]
|
||||
mov rdx, JMP_PHI_len
|
||||
call vec_extend
|
||||
|
||||
mov rdi, [rbx + 0] ; AstIfExpr.cond
|
||||
lea rsi, [rsp + 24] ; scratch
|
||||
mov rdx, 30
|
||||
mov rcx, 16
|
||||
call int_to_str2
|
||||
mov byte [rax + rdx], 10
|
||||
inc rdx
|
||||
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
mov rsi, rax
|
||||
call vec_extend
|
||||
|
||||
; .branch_{else_}:
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rel JE_B]
|
||||
add rsi, 3
|
||||
mov rdx, 2
|
||||
call vec_extend
|
||||
|
||||
mov rdi, [rbx + 16] ; AstIfExpr.else
|
||||
lea rsi, [rsp + 24] ; scratch
|
||||
mov rdx, 30
|
||||
mov rcx, 16
|
||||
call int_to_str2
|
||||
mov byte [rax + rdx], ':'
|
||||
inc rdx
|
||||
mov byte [rax + rdx], 10
|
||||
inc rdx
|
||||
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
mov rsi, rax
|
||||
call vec_extend
|
||||
|
||||
; codegen else branch
|
||||
mov rdx, [rbx + 16] ; AstIfExpr.else
|
||||
mov rdi, [rsp] ; ctx
|
||||
mov rsi, [rsp + 8] ; &function_ctx
|
||||
call codegen_expr
|
||||
mov [rsp + 24], rax ; else
|
||||
mov [rsp + 32], rdx
|
||||
|
||||
cmp rax, 0
|
||||
je .if_skip_phi2
|
||||
; mov rax, else
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rel OPERAND_RAX]
|
||||
lea rdx, [rsp + 24] ; src
|
||||
call codegen_move_dst_src
|
||||
|
||||
; free else
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
lea rsi, [rsp + 24] ; else operand
|
||||
call codegen_free_operand
|
||||
|
||||
.if_skip_phi2:
|
||||
; .branch_{if}
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rel JMP_PHI]
|
||||
add rsi, 4
|
||||
mov rdx, 4
|
||||
call vec_extend
|
||||
|
||||
mov rdi, [rbx + 0] ; AstIfExpr.cond
|
||||
lea rsi, [rsp + 32] ; scratch
|
||||
mov rdx, 30
|
||||
mov rcx, 16
|
||||
call int_to_str2
|
||||
mov byte [rax + rdx], ':'
|
||||
inc rdx
|
||||
mov byte [rax + rdx], 10
|
||||
inc rdx
|
||||
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
mov rsi, rax
|
||||
call vec_extend
|
||||
|
||||
mov rax, qword [rsp + 24]
|
||||
cmp rax, 0
|
||||
je .if_no_value
|
||||
|
||||
; dst = allocate_value
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
mov rsi, 8 ; width
|
||||
call codegen_allocate_value
|
||||
mov [rsp + 40], rax
|
||||
mov [rsp + 48], rdx
|
||||
|
||||
cmp byte [rsp + 24], OPERAND_LAST_VALUE
|
||||
ja .if_phi_place
|
||||
|
||||
; preserve width of then/else value
|
||||
mov ax, word [rsp + 24 + 2] ; Operand.width
|
||||
mov word [rsp + 40 + 2], ax
|
||||
jmp .if_value
|
||||
|
||||
.if_phi_place:
|
||||
; turn dst into it's place equivalent
|
||||
cmp byte [rsp + 40], OPERAND_REGISTER
|
||||
cmove ax, word [rel OPERAND_REGISTER_PLACE]
|
||||
cmp byte [rsp + 40], OPERAND_RBP_VALUE
|
||||
cmove ax, word [rel OPERAND_RBP_PLACE]
|
||||
mov byte [rsp + 40], al
|
||||
|
||||
.if_value:
|
||||
; mov dst, rax
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rsp + 40] ; dst
|
||||
lea rdx, [rel OPERAND_RAX] ; rax (phi)
|
||||
call codegen_move_dst_src
|
||||
|
||||
mov rax, [rsp + 40]
|
||||
mov rdx, [rsp + 48]
|
||||
jmp .done
|
||||
|
||||
.if_no_value:
|
||||
xor rax, rax
|
||||
xor rdx, rdx
|
||||
jmp .done
|
||||
|
||||
.block:
|
||||
mov rbx, [rax + 8] ; AstNode.data
|
||||
mov r15, [rax + 16] ; AstNode.extra
|
||||
|
|
@ -1154,6 +1356,10 @@ codegen_expr:
|
|||
cmove rbx, [rel SUB_]
|
||||
cmp rbx, -1
|
||||
jne .gen_op
|
||||
cmp al, TOKEN_EQEQ
|
||||
je .binop_cmp
|
||||
cmp al, TOKEN_BANGEQ
|
||||
je .binop_cmp
|
||||
cmp al, TOKEN_STAR
|
||||
cmove rbx, [rel MUL_]
|
||||
cmp al, TOKEN_SLASH
|
||||
|
|
@ -1161,7 +1367,73 @@ codegen_expr:
|
|||
cmp al, TOKEN_PERCENT
|
||||
cmove rbx, [rel DIV_]
|
||||
cmp rbx, -1
|
||||
je .panic ; unknown operator
|
||||
jne .mul_div
|
||||
jmp .panic ; unknown operator
|
||||
|
||||
.binop_cmp:
|
||||
mov bl, al ; operator
|
||||
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, 'cmp '
|
||||
mov r9, 1
|
||||
call codegen_binary_op_rm64_rm64
|
||||
mov [rsp + 32], rax
|
||||
mov [rsp + 40], rdx
|
||||
|
||||
; free operand
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
lea rsi, [rsp + 32] ; left operand
|
||||
call codegen_free_operand
|
||||
|
||||
; dst = allocate_value(1)
|
||||
mov rdi, [rsp + 8] ; &function_ctx
|
||||
mov rsi, 1 ; width
|
||||
call codegen_allocate_value
|
||||
mov [rsp + 32], rax
|
||||
mov [rsp + 40], rdx
|
||||
|
||||
xor rax, rax
|
||||
cmp bl, TOKEN_EQEQ
|
||||
cmove rax, [rel SETE_]
|
||||
cmp bl, TOKEN_BANGEQ
|
||||
cmove rax, [rel SETNE_]
|
||||
cmp bl, TOKEN_LEQ
|
||||
cmove rax, [rel SETBE_]
|
||||
cmp bl, TOKEN_LT
|
||||
cmove rax, [rel SETB_]
|
||||
cmp bl, TOKEN_GEQ
|
||||
cmove rax, [rel SETAE_]
|
||||
cmp bl, TOKEN_GT
|
||||
cmove rax, [rel SETA_]
|
||||
cmp rax, 0
|
||||
je .panic ; unknown cmp operator
|
||||
mov [rsp + 48], rax
|
||||
|
||||
; "{rax} dst\n"
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rsp + 48] ; op
|
||||
mov rdx, 6
|
||||
call vec_extend
|
||||
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
lea rsi, [rsp + 32] ; dst
|
||||
call codegen_write_operand
|
||||
|
||||
mov rdi, [rsp] ; ctx
|
||||
lea rdi, [rdi + 8] ; &ctx.text
|
||||
mov byte [rsp + 48], 10 ; newline
|
||||
lea rsi, [rsp + 48]
|
||||
call vec_push
|
||||
|
||||
mov rax, [rsp + 32]
|
||||
mov rdx, [rsp + 40]
|
||||
jmp .done
|
||||
|
||||
.mul_div:
|
||||
; mul/div need to clobber rax:rdx
|
||||
|
||||
|
|
@ -1316,6 +1588,7 @@ codegen_expr:
|
|||
lea rdx, [rsp + 32] ; left operand
|
||||
lea rcx, [rsp + 48] ; right operand
|
||||
mov r8, rbx ; operation
|
||||
mov r9, 0
|
||||
call codegen_binary_op_rm64_rm64
|
||||
jmp .done
|
||||
|
||||
|
|
@ -1612,6 +1885,8 @@ section .rdata
|
|||
OPERAND_RBP_V dq 0x0008_0002, 0
|
||||
align 8
|
||||
OPERAND_RBP_P dq 0x0008_0009, 0
|
||||
align 8
|
||||
OPERAND_ZERO dq 0x0001_000b, 0
|
||||
|
||||
section .text
|
||||
|
||||
|
|
@ -1836,19 +2111,23 @@ codegen_write_width:
|
|||
;; rdx: lhs: *Operand
|
||||
;; rcx: rhs: *Operand
|
||||
;; r8: op: [u8; 8]
|
||||
;; r9: discard_result
|
||||
;; Generates: {op} {lhs}, {rhs} for a binary operation that has the encodings rN, rmN and rmN, rN
|
||||
;; define-fn: fn codegen_binary_op_rm64_rm64(function_ctx: *mut FunctionCtx, text: *mut BlobVec, lhs: *const Operand, rhs: *const Operand, op: [u8; 8], discard_result: bool) -> *const Operand
|
||||
codegen_binary_op_rm64_rm64:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
push rbx
|
||||
|
||||
; dst [32..48]
|
||||
sub rsp, 56
|
||||
; discard_result [56..57]
|
||||
; dst [40..56]
|
||||
sub rsp, 64
|
||||
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
|
||||
mov byte [rsp + 48], r9b ; discard_result
|
||||
|
||||
; match (lhs.kind, rhs.kind) {
|
||||
cmp byte [rdx + 0], OPERAND_REGISTER
|
||||
|
|
@ -1961,6 +2240,15 @@ codegen_binary_op_rm64_rm64:
|
|||
mov rsi, [rsp + 16] ; lhs
|
||||
call codegen_free_operand
|
||||
|
||||
cmp byte [rsp + 56], 0
|
||||
je .rax_rhs_done
|
||||
; mov rhs, rax
|
||||
mov rdi, [rsp + 8] ; *text
|
||||
mov rsi, [rsp + 24] ; rhs
|
||||
lea rdx, [rel OPERAND_RAX]
|
||||
call codegen_move_dst_src
|
||||
|
||||
.rax_rhs_done:
|
||||
; ret rhs
|
||||
mov rbx, [rsp + 24] ; rhs
|
||||
mov rax, [rbx]
|
||||
|
|
@ -2007,13 +2295,13 @@ codegen_binary_op_rm64_rm64:
|
|||
call codegen_free_operand
|
||||
|
||||
; ret dst
|
||||
mov rax, [rsp + 32] ; dst
|
||||
mov rdx, [rsp + 40]
|
||||
mov rax, [rsp + 40] ; dst
|
||||
mov rdx, [rsp + 48]
|
||||
; }
|
||||
|
||||
|
||||
.epilogue:
|
||||
add rsp, 56
|
||||
add rsp, 64
|
||||
pop rbx
|
||||
pop rbp
|
||||
ret
|
||||
|
|
@ -2243,4 +2531,18 @@ section .rdata
|
|||
SUB_ dq "sub "
|
||||
MUL_ dq "mul "
|
||||
DIV_ dq "div "
|
||||
SETE_ dq "sete "
|
||||
SETNE_ dq "setne "
|
||||
SETA_ dq "seta "
|
||||
SETAE_ dq "setae "
|
||||
SETB_ dq "setb "
|
||||
SETBE_ dq "setbe "
|
||||
SETL_ dq "setl "
|
||||
SETLE_ dq "setle "
|
||||
SETG_ dq "setg "
|
||||
SETGE_ dq "setge "
|
||||
JE_B dq "je .B"
|
||||
JE_B_len equ $ - JE_B
|
||||
JMP_PHI dq "jmp .PHI"
|
||||
JMP_PHI_len equ $ - JMP_PHI
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,11 @@ LEXEMES:
|
|||
dq LEX_DOT2
|
||||
dq LEX_DOT
|
||||
dq LEX_BACKTICK
|
||||
dq LEX_SWITCH
|
||||
dq LEX_AS
|
||||
dq LEX_MATCH
|
||||
dq LEX_WHILE
|
||||
dq LEX_FOR
|
||||
|
||||
align 8
|
||||
TOKENS:
|
||||
|
|
@ -126,6 +131,11 @@ TOKENS:
|
|||
db TOKEN_DOT2 ;; 53
|
||||
db TOKEN_DOT ;; 52
|
||||
db TOKEN_BACKTICK ;; 55
|
||||
db TOKEN_SWITCH
|
||||
db TOKEN_AS
|
||||
db TOKEN_MATCH
|
||||
db TOKEN_WHILE
|
||||
db TOKEN_FOR
|
||||
|
||||
align 8
|
||||
LEXEME_LENS:
|
||||
|
|
@ -190,9 +200,14 @@ LEXEME_LENS:
|
|||
dq LEX_DOT2_len
|
||||
dq LEX_DOT_len
|
||||
dq LEX_BACKTICK_len
|
||||
dq LEX_SWITCH_len
|
||||
dq LEX_AS_len
|
||||
dq LEX_MATCH_len
|
||||
dq LEX_WHILE_len
|
||||
dq LEX_FOR_len
|
||||
|
||||
align 8
|
||||
NUM_LEXEMES: dq 61
|
||||
NUM_LEXEMES: dq 66
|
||||
|
||||
LEX_NOT_A_LEXEME db "<not a lexeme>", 0
|
||||
LEX_LET db "let"
|
||||
|
|
@ -315,6 +330,16 @@ NUM_LEXEMES: dq 61
|
|||
LEX_DOT_len equ $ - LEX_DOT
|
||||
LEX_BACKTICK db "`"
|
||||
LEX_BACKTICK_len equ $ - LEX_BACKTICK
|
||||
LEX_SWITCH db "switch"
|
||||
LEX_SWITCH_len equ $ - LEX_SWITCH
|
||||
LEX_AS db "as"
|
||||
LEX_AS_len equ $ - LEX_AS
|
||||
LEX_MATCH db "match"
|
||||
LEX_MATCH_len equ $ - LEX_MATCH
|
||||
LEX_WHILE db "while"
|
||||
LEX_WHILE_len equ $ - LEX_WHILE
|
||||
LEX_FOR db "for"
|
||||
LEX_FOR_len equ $ - LEX_FOR
|
||||
LEX_IDENT db "<identifier>"
|
||||
LEX_IDENT_len equ $ - LEX_IDENT
|
||||
LEX_NUMBER db "<number>"
|
||||
|
|
@ -386,8 +411,13 @@ NUM_LEXEMES: dq 61
|
|||
TOKEN_DOT2 equ 58 ; :u8
|
||||
TOKEN_DOT equ 59 ; :u8
|
||||
TOKEN_BACKTICK equ 60 ; :u8
|
||||
TOKEN_IDENT equ 61 ; :u8
|
||||
TOKEN_NUMBER equ 62 ; :u8
|
||||
TOKEN_STRING equ 63 ; :u8
|
||||
TOKEN_COMMENT equ 64 ; :u8
|
||||
TOKEN_SWITCH equ 61 ; :u8
|
||||
TOKEN_AS equ 62 ; :u8
|
||||
TOKEN_MATCH equ 63 ; :u8
|
||||
TOKEN_WHILE equ 64 ; :u8
|
||||
TOKEN_FOR equ 65 ; :u8
|
||||
TOKEN_IDENT equ 66 ; :u8
|
||||
TOKEN_NUMBER equ 67 ; :u8
|
||||
TOKEN_STRING equ 68 ; :u8
|
||||
TOKEN_COMMENT equ 69 ; :u8
|
||||
;; end-consts
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ unsafe extern "C" {
|
|||
unsafe fn tokeniser_init_buf(bytes: *const u8, len: usize) -> ();
|
||||
}
|
||||
|
||||
use util::defs::{parse_func, Ast};
|
||||
use util::defs::{parse_expr, parse_func, Ast};
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
|
|
@ -58,57 +58,67 @@ 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(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() -> 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, b: u32) -> void {
|
||||
*a = b;
|
||||
a = &b;
|
||||
}",
|
||||
|ast| unsafe { parse_func(ast) },
|
||||
);
|
||||
print_ast(
|
||||
b"fn main(a: u32) -> void {
|
||||
if (a == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}",
|
||||
|ast| unsafe { parse_func(ast) },
|
||||
);
|
||||
|
|
|
|||
|
|
@ -91,10 +91,23 @@ fn main() {
|
|||
};
|
||||
}
|
||||
|
||||
// print_ast(
|
||||
// b"fn main(a: u32) -> void {
|
||||
// let b: *u32 = &a;
|
||||
// return 5 + *b;
|
||||
// }",
|
||||
// |ast| unsafe { parse_func(ast) },
|
||||
// );
|
||||
|
||||
print_ast(
|
||||
b"fn main(a: u32) -> void {
|
||||
let b: *u32 = &a;
|
||||
return 5 + *b;
|
||||
let x: u32 = 10;
|
||||
if (a == 42) {
|
||||
x = 7;
|
||||
} else {
|
||||
x = 8;
|
||||
}
|
||||
return x;
|
||||
}",
|
||||
|ast| unsafe { parse_func(ast) },
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ impl core::fmt::Display for util::defs::AstNode {
|
|||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
use util::defs::{
|
||||
BinaryExpr, AST_ADDRESS_OF, AST_ARG, AST_ASSIGNMENT, AST_BINARY_OP, AST_BLOCK,
|
||||
AST_DEREF, AST_FUNCTION, AST_NUMBER, AST_PLACE_TO_VALUE, AST_RETURN_STATEMENT,
|
||||
AST_DEREF, AST_FUNCTION, AST_IF, AST_NUMBER, AST_PLACE_TO_VALUE, AST_RETURN_STATEMENT,
|
||||
AST_VALUE_TO_PLACE, AST_VAR_DECL, AST_VAR_REF,
|
||||
};
|
||||
match self.kind {
|
||||
|
|
@ -98,6 +98,19 @@ impl core::fmt::Display for util::defs::AstNode {
|
|||
std::slice::from_raw_parts(self.data.cast::<u64>(), self.extra as usize)
|
||||
})
|
||||
}
|
||||
AST_IF => {
|
||||
let if_node = unsafe { self.data.cast::<util::defs::AstIfExpr>().read() };
|
||||
write!(
|
||||
f,
|
||||
"If(cond: {}, then_branch: {}, else_branch: {:?})",
|
||||
if_node.condition,
|
||||
if_node.then,
|
||||
match if_node.else_ {
|
||||
u64::MAX => None,
|
||||
v => Some(v),
|
||||
}
|
||||
)
|
||||
}
|
||||
AST_PLACE_TO_VALUE => {
|
||||
write!(f, "PlaceToValue(place: {})", self.data as usize)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ unsafe extern "C" {
|
|||
pub unsafe fn parse_type(ast: *mut Ast) -> Type;
|
||||
pub unsafe fn parse_prefix_expr(ast: *mut Ast) -> (u64, bool);
|
||||
pub unsafe fn parse_assignment(ast: *mut Ast) -> (u64, bool);
|
||||
pub unsafe fn ast_parse_switch_expr(ast: *mut Ast) -> (u64, bool);
|
||||
pub unsafe fn ast_parse_if_expr(ast: *mut Ast) -> (u64, bool);
|
||||
pub unsafe fn ast_parse_let(ast: *mut Ast) -> (u64, bool);
|
||||
pub unsafe fn symkey_cmp(a: *const SymKey, b: *const SymKey) -> i32;
|
||||
pub unsafe fn ast_build_symtable(ast: *mut Ast, root_index: u64, symtable: *mut core::mem::MaybeUninit<SymbolTable>);
|
||||
|
|
@ -27,6 +29,7 @@ unsafe extern "C" {
|
|||
pub unsafe fn codegen_function(ast: *const CodegenCtx, func_idx: u64) -> ();
|
||||
pub unsafe fn codegen_push_pop_used_registers(text: *mut Vec<u8>, function_ctx: &FunctionCtx, pop: bool) -> u8;
|
||||
pub unsafe fn codegen_expr(ctx: *const CodegenCtx, function_ctx: &FunctionCtx, expr_idx: u64) -> (u64, bool);
|
||||
pub unsafe fn codegen_binary_op_rm64_rm64(function_ctx: *mut FunctionCtx, text: *mut BlobVec, lhs: *const Operand, rhs: *const Operand, op: [u8; 8], discard_result: bool) -> *const Operand;
|
||||
pub unsafe fn vec_insert_many(vec: *mut BlobVec, index: usize, data: *const u8, count: usize);
|
||||
pub unsafe fn vec_extend(vec: *mut BlobVec, elements: *const u8, count: usize) -> ();
|
||||
}
|
||||
|
|
@ -52,6 +55,10 @@ pub const AST_ADDRESS_OF: u8 = 11;
|
|||
pub const AST_VAR_DECL: u8 = 12;
|
||||
pub const AST_VAR_REF: u8 = 13;
|
||||
pub const AST_ARG: u8 = 14;
|
||||
pub const AST_SWITCH: u8 = 15;
|
||||
pub const AST_IF: u8 = 16;
|
||||
pub const AST_ELSE: u8 = 17;
|
||||
pub const AST_CALL: u8 = 18;
|
||||
pub const TYPE_VOID: u8 = 1;
|
||||
pub const TYPE_BOOL: u8 = 2;
|
||||
pub const TYPE_I32: u8 = 3;
|
||||
|
|
@ -132,10 +139,15 @@ pub const TOKEN_DOT3: u8 = 57;
|
|||
pub const TOKEN_DOT2: u8 = 58;
|
||||
pub const TOKEN_DOT: u8 = 59;
|
||||
pub const TOKEN_BACKTICK: u8 = 60;
|
||||
pub const TOKEN_IDENT: u8 = 61;
|
||||
pub const TOKEN_NUMBER: u8 = 62;
|
||||
pub const TOKEN_STRING: u8 = 63;
|
||||
pub const TOKEN_COMMENT: u8 = 64;
|
||||
pub const TOKEN_SWITCH: u8 = 61;
|
||||
pub const TOKEN_AS: u8 = 62;
|
||||
pub const TOKEN_MATCH: u8 = 63;
|
||||
pub const TOKEN_WHILE: u8 = 64;
|
||||
pub const TOKEN_FOR: u8 = 65;
|
||||
pub const TOKEN_IDENT: u8 = 66;
|
||||
pub const TOKEN_NUMBER: u8 = 67;
|
||||
pub const TOKEN_STRING: u8 = 68;
|
||||
pub const TOKEN_COMMENT: u8 = 69;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
|
|
@ -194,6 +206,29 @@ pub struct BinaryExpr {
|
|||
pub right: u64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct AstSwitch {
|
||||
pub expr: u64,
|
||||
pub cases: *const u64,
|
||||
pub cases_len: usize,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct AstSwitchCase {
|
||||
pub pattern: u64,
|
||||
pub expr: u64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct AstIfExpr {
|
||||
pub condition: u64,
|
||||
pub then: u64,
|
||||
pub else_: u64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct AstVarDecl {
|
||||
|
|
|
|||
Loading…
Reference in a new issue