codegen call expr attempt 1
This commit is contained in:
parent
b1b48813d2
commit
d276dd9d88
|
|
@ -971,6 +971,244 @@ codegen_block:
|
||||||
pop rbp
|
pop rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;; rdi: ctx
|
||||||
|
;; rsi: &function_ctx
|
||||||
|
;; rdx: *AstCallExpr
|
||||||
|
;; define-fn: fn codegen_call_expr(ctx: *const CodegenCtx, function_ctx: &FunctionCtx, call_expr: *const AstCallExpr) -> (u64, bool)
|
||||||
|
codegen_call_expr:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
push rbx
|
||||||
|
push r15
|
||||||
|
push r14
|
||||||
|
|
||||||
|
; scratch [80..112]
|
||||||
|
; callee_operand [64..80]
|
||||||
|
; param_operands [24..64]
|
||||||
|
; *AstCallExpr [16..24]
|
||||||
|
; function_ctx [8..16]
|
||||||
|
; ctx [0..8]
|
||||||
|
sub rsp, 112
|
||||||
|
mov [rsp], rdi ; ctx
|
||||||
|
mov [rsp + 8], rsi ; &function_ctx
|
||||||
|
mov [rsp + 16], rdx ; *AstCallExpr
|
||||||
|
mov rbx, rdx ; copy of *AstCallExpr
|
||||||
|
|
||||||
|
; initialize param_operands
|
||||||
|
mov rcx, [rbx + 16] ; AstCallExpr.args_len
|
||||||
|
lea rdi, [rsp + 24] ; param_operands
|
||||||
|
mov rsi, 16 ; size_of::<Operand>
|
||||||
|
mov rdx, 0 ; drop = None
|
||||||
|
mov rcx, rbx ; initial capacity
|
||||||
|
call vec_init_with
|
||||||
|
|
||||||
|
; codegen callee
|
||||||
|
mov rdx, [rbx + 0] ; AstCallExpr.callee
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
mov rsi, [rsp + 8] ; &function_ctx
|
||||||
|
call codegen_expr
|
||||||
|
mov [rsp + 64], rax ; callee operand
|
||||||
|
mov [rsp + 72], rdx
|
||||||
|
|
||||||
|
; If callee is in a param-register, move to stack
|
||||||
|
cmp byte [rax], OPERAND_REGISTER
|
||||||
|
jne .arg_loop_init
|
||||||
|
mov rdx, 0b00000011_00111100
|
||||||
|
movzx rcx, byte [rax + 1] ; callee register
|
||||||
|
bt rdx, rcx
|
||||||
|
jnc .arg_loop_init
|
||||||
|
|
||||||
|
; allocate stack slot
|
||||||
|
mov rdi, [rsp + 8] ; &function_ctx
|
||||||
|
movzx rsi, word [rax + 2] ; Operand.width
|
||||||
|
call codegen_allocate_stack_value
|
||||||
|
mov [rsp + 80], rax ; new stack operand
|
||||||
|
mov [rsp + 88], rdx
|
||||||
|
|
||||||
|
; move from register to stack
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rsp + 80] ; dst
|
||||||
|
lea rdx, [rsp + 64] ; src
|
||||||
|
call codegen_move_dst_src
|
||||||
|
; free original callee operand
|
||||||
|
mov rdi, [rsp + 8] ; &function_ctx
|
||||||
|
lea rsi, [rsp + 64] ; callee operand
|
||||||
|
call codegen_free_operand
|
||||||
|
|
||||||
|
mov rax, [rsp + 80] ; callee operand = new stack operand
|
||||||
|
mov rdx, [rsp + 88]
|
||||||
|
mov [rsp + 64], rax
|
||||||
|
mov [rsp + 72], rdx
|
||||||
|
|
||||||
|
.arg_loop_init:
|
||||||
|
mov r15, [rbx + 16] ; AstCallExpr.args_len
|
||||||
|
xor r14, r14 ; arg index
|
||||||
|
.arg_loop:
|
||||||
|
cmp r14, r15
|
||||||
|
jge .arg_loop_done
|
||||||
|
mov rdx, [rbx + 8] ; AstCallExpr.args
|
||||||
|
lea rsi, [rdx + r14 * 8]
|
||||||
|
mov rdx, [rsi] ; arg ast index
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
mov rsi, [rsp + 8] ; &function_ctx
|
||||||
|
call codegen_expr
|
||||||
|
mov [rsp + 80], rax ; param operand
|
||||||
|
mov [rsp + 88], rdx
|
||||||
|
|
||||||
|
; store param operand
|
||||||
|
; if the operand is in a register, move it to the stack
|
||||||
|
; we know already that these are values
|
||||||
|
|
||||||
|
cmp byte [rax], OPERAND_REGISTER
|
||||||
|
jne .store_param
|
||||||
|
; allocate stack slot
|
||||||
|
mov rdi, [rsp + 8] ; &function_ctx
|
||||||
|
movzx rsi, word [rax + 2] ; Operand.width
|
||||||
|
call codegen_allocate_stack_value
|
||||||
|
mov [rsp + 96], rax ; new stack operand
|
||||||
|
mov [rsp + 104], rdx
|
||||||
|
|
||||||
|
; move from register to stack
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rsp + 96] ; dst
|
||||||
|
lea rdx, [rsp + 80] ; src
|
||||||
|
call codegen_move_dst_src
|
||||||
|
|
||||||
|
; free original param operand
|
||||||
|
mov rdi, [rsp + 8] ; &function_ctx
|
||||||
|
lea rsi, [rsp + 80] ; param operand
|
||||||
|
call codegen_free_operand
|
||||||
|
mov rax, [rsp + 96] ; param operand = new stack operand
|
||||||
|
mov rdx, [rsp + 104]
|
||||||
|
mov [rsp + 80], rax
|
||||||
|
mov [rsp + 88], rdx
|
||||||
|
|
||||||
|
.store_param:
|
||||||
|
; push param operand to param_operands
|
||||||
|
lea rdi, [rsp + 24] ; param_operands
|
||||||
|
lea rsi, [rsp + 80] ; ¶m operand
|
||||||
|
call vec_push
|
||||||
|
|
||||||
|
inc r14
|
||||||
|
jmp .arg_loop
|
||||||
|
.arg_loop_done:
|
||||||
|
|
||||||
|
; push volatile registers
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rsp + 8] ; &function_ctx
|
||||||
|
mov rdx, 0 ; pop = false
|
||||||
|
call codegen_push_pop_used_registers
|
||||||
|
|
||||||
|
; move params to appropriate registers/stack slots
|
||||||
|
; reverse order to allow freeing the allocated stack slots
|
||||||
|
mov r15, [rbx + 16] ; AstCallExpr.args_len
|
||||||
|
cmp r15, 6
|
||||||
|
jg .panic ; more than 6 params not supported yet
|
||||||
|
.param_move_loop:
|
||||||
|
dec r15
|
||||||
|
cmp r15, 0
|
||||||
|
jl .param_move_done
|
||||||
|
|
||||||
|
mov rdi, r15 ; param index
|
||||||
|
call codegen_arg_to_operand
|
||||||
|
mov [rsp + 80], rax ; target operand
|
||||||
|
mov [rsp + 88], rdx
|
||||||
|
|
||||||
|
lea rdi, [rsp + 24] ; param_operands
|
||||||
|
mov rsi, r15
|
||||||
|
call vec_get
|
||||||
|
mov r14, rax ; source operand
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rsp + 80] ; dst
|
||||||
|
mov rdx, r14 ; src
|
||||||
|
call codegen_move_dst_src
|
||||||
|
; free param operand
|
||||||
|
mov rdi, [rsp + 8] ; &function_ctx
|
||||||
|
mov rdx, r14 ; param operand
|
||||||
|
call codegen_free_operand
|
||||||
|
|
||||||
|
jmp .param_move_loop
|
||||||
|
.param_move_done:
|
||||||
|
|
||||||
|
; align stack
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rel ALIGN_STACK]
|
||||||
|
mov rdx, ALIGN_STACK_LEN
|
||||||
|
call vec_extend
|
||||||
|
; mov rax, rsp
|
||||||
|
; sub rsp, 8
|
||||||
|
; and rsp, -16
|
||||||
|
; mov [rsp], rax
|
||||||
|
|
||||||
|
; call callee
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rel CALL_]
|
||||||
|
mov rdx, CALL_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rsp + 64] ; callee operand
|
||||||
|
call codegen_write_operand
|
||||||
|
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rel NEWLINE]
|
||||||
|
call vec_push
|
||||||
|
|
||||||
|
; de-align stack
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rel RESTORE_STACK]
|
||||||
|
mov rdx, RESTORE_STACK_LEN
|
||||||
|
call vec_extend
|
||||||
|
|
||||||
|
; free callee operand
|
||||||
|
mov rdi, [rsp + 8] ; &function_ctx
|
||||||
|
lea rsi, [rsp + 64] ; callee operand
|
||||||
|
call codegen_free_operand
|
||||||
|
|
||||||
|
; pop volatile registers
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rsp + 8] ; &function_ctx
|
||||||
|
mov rdx, 1 ; pop = true
|
||||||
|
call codegen_push_pop_used_registers
|
||||||
|
|
||||||
|
; allocate return value operand
|
||||||
|
mov rdi, [rsp + 8] ; &function_ctx
|
||||||
|
mov rsi, 8 ; size_of::<u64>
|
||||||
|
call codegen_allocate_value
|
||||||
|
mov [rsp + 80], rax ; return value operand
|
||||||
|
mov [rsp + 88], rdx
|
||||||
|
|
||||||
|
; mov dst, rax
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
lea rdi, [rdi + 8] ; &ctx.text
|
||||||
|
lea rsi, [rsp + 80] ; dst
|
||||||
|
lea rdx, [rel OPERAND_RAX] ; src
|
||||||
|
call codegen_move_dst_src
|
||||||
|
|
||||||
|
; return return value operand
|
||||||
|
mov rax, [rsp + 80]
|
||||||
|
mov rdx, [rsp + 88]
|
||||||
|
|
||||||
|
add rsp, 112
|
||||||
|
pop r14
|
||||||
|
pop r15
|
||||||
|
pop rbx
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
.panic:
|
||||||
|
call panic
|
||||||
|
|
||||||
;; rdi: ctx
|
;; rdi: ctx
|
||||||
;; rsi: &function_ctx
|
;; rsi: &function_ctx
|
||||||
;; rdx: expr index
|
;; rdx: expr index
|
||||||
|
|
@ -1022,8 +1260,17 @@ codegen_expr:
|
||||||
je .address_of
|
je .address_of
|
||||||
cmp bl, AST_IF
|
cmp bl, AST_IF
|
||||||
je .if_expr
|
je .if_expr
|
||||||
|
cmp bl, AST_CALL
|
||||||
|
je .call_expr
|
||||||
jmp .panic
|
jmp .panic
|
||||||
|
|
||||||
|
.call_expr:
|
||||||
|
mov rdx, [rax + 8] ; AstNode.data = *AstCallExpr
|
||||||
|
mov rdi, [rsp] ; ctx
|
||||||
|
mov rsi, [rsp + 8] ; &function_ctx
|
||||||
|
call codegen_call_expr
|
||||||
|
jmp .done
|
||||||
|
|
||||||
.if_expr:
|
.if_expr:
|
||||||
mov rbx, [rax + 8] ; AstNode.data = *AstIfExpr
|
mov rbx, [rax + 8] ; AstNode.data = *AstIfExpr
|
||||||
mov [rsp + 16], rax ; scratch = AstNode
|
mov [rsp + 16], rax ; scratch = AstNode
|
||||||
|
|
@ -2545,4 +2792,12 @@ section .rdata
|
||||||
JE_B_len equ $ - JE_B
|
JE_B_len equ $ - JE_B
|
||||||
JMP_PHI dq "jmp .PHI"
|
JMP_PHI dq "jmp .PHI"
|
||||||
JMP_PHI_len equ $ - JMP_PHI
|
JMP_PHI_len equ $ - JMP_PHI
|
||||||
|
ALIGN_STACK db "mov rax, rsp", 10, "sub rsp, 8", 10, "and rsp, -16", 10, "mov [rsp], rax", 10
|
||||||
|
ALIGN_STACK_LEN equ $ - ALIGN_STACK
|
||||||
|
RESTORE_STACK db "pop rsp", 10
|
||||||
|
RESTORE_STACK_LEN equ $ - RESTORE_STACK
|
||||||
|
CALL_ dq "call "
|
||||||
|
CALL_LEN equ $ - CALL_
|
||||||
|
NEWLINE db 10
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,15 +99,26 @@ fn main() {
|
||||||
// |ast| unsafe { parse_func(ast) },
|
// |ast| unsafe { parse_func(ast) },
|
||||||
// );
|
// );
|
||||||
|
|
||||||
|
// print_ast(
|
||||||
|
// b"fn main(a: u32) -> void {
|
||||||
|
// let x: u32 = 10;
|
||||||
|
// if (a == 42) {
|
||||||
|
// x = 7;
|
||||||
|
// } else {
|
||||||
|
// x = 8;
|
||||||
|
// }
|
||||||
|
// return x;
|
||||||
|
// }",
|
||||||
|
// |ast| unsafe { parse_func(ast) },
|
||||||
|
// );
|
||||||
|
|
||||||
print_ast(
|
print_ast(
|
||||||
b"fn main(a: u32) -> void {
|
b"fn main(a: u32) -> void {
|
||||||
let x: u32 = 10;
|
|
||||||
if (a == 42) {
|
if (a == 42) {
|
||||||
x = 7;
|
return main(7);
|
||||||
} else {
|
} else {
|
||||||
x = 8;
|
return a;
|
||||||
}
|
}
|
||||||
return x;
|
|
||||||
}",
|
}",
|
||||||
|ast| unsafe { parse_func(ast) },
|
|ast| unsafe { parse_func(ast) },
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ unsafe extern "C" {
|
||||||
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) -> ();
|
||||||
pub unsafe fn codegen_push_pop_used_registers(text: *mut Vec<u8>, function_ctx: &FunctionCtx, pop: bool) -> u8;
|
pub unsafe fn codegen_push_pop_used_registers(text: *mut Vec<u8>, function_ctx: &FunctionCtx, pop: bool) -> u8;
|
||||||
|
pub unsafe fn codegen_call_expr(ctx: *const CodegenCtx, function_ctx: &FunctionCtx, call_expr: *const AstCallExpr) -> (u64, bool);
|
||||||
pub unsafe fn codegen_expr(ctx: *const CodegenCtx, function_ctx: &FunctionCtx, expr_idx: u64) -> (u64, bool);
|
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 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_insert_many(vec: *mut BlobVec, index: usize, data: *const u8, count: usize);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue