function calls mostly working
This commit is contained in:
parent
dd8eaee987
commit
e0495afd42
4 changed files with 151 additions and 2 deletions
125
05/codegen.b
125
05/codegen.b
|
@ -108,6 +108,16 @@ function emit_mov_rbx_imm64
|
||||||
code_output += 8
|
code_output += 8
|
||||||
return
|
return
|
||||||
|
|
||||||
|
function emit_add_rax_imm32
|
||||||
|
; 48 05 IMM32
|
||||||
|
argument imm32
|
||||||
|
*2code_output = 0x0548
|
||||||
|
code_output += 2
|
||||||
|
*4code_output = imm32
|
||||||
|
code_output += 4
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
function emit_zero_rax
|
function emit_zero_rax
|
||||||
; 31 c0
|
; 31 c0
|
||||||
*2code_output = 0xc031
|
*2code_output = 0xc031
|
||||||
|
@ -1421,8 +1431,10 @@ function generate_push_expression
|
||||||
type = *4type
|
type = *4type
|
||||||
|
|
||||||
c = *1expr
|
c = *1expr
|
||||||
|
; @TODO : reorder from most to least common, probably
|
||||||
if c == EXPRESSION_CONSTANT_INT goto generate_int
|
if c == EXPRESSION_CONSTANT_INT goto generate_int
|
||||||
if c == EXPRESSION_CONSTANT_FLOAT goto generate_float
|
if c == EXPRESSION_CONSTANT_FLOAT goto generate_float
|
||||||
|
if c == EXPRESSION_FUNCTION goto generate_function_addr
|
||||||
if c == EXPRESSION_CAST goto generate_cast
|
if c == EXPRESSION_CAST goto generate_cast
|
||||||
if c == EXPRESSION_UNARY_PLUS goto generate_cast ; the unary plus operator just casts to the promoted type
|
if c == EXPRESSION_UNARY_PLUS goto generate_cast ; the unary plus operator just casts to the promoted type
|
||||||
if c == EXPRESSION_UNARY_MINUS goto generate_unary_minus
|
if c == EXPRESSION_UNARY_MINUS goto generate_unary_minus
|
||||||
|
@ -1447,6 +1459,9 @@ function generate_push_expression
|
||||||
if c == EXPRESSION_ARROW goto generate_dot_or_arrow
|
if c == EXPRESSION_ARROW goto generate_dot_or_arrow
|
||||||
if c == EXPRESSION_COMMA goto generate_comma
|
if c == EXPRESSION_COMMA goto generate_comma
|
||||||
if c == EXPRESSION_ASSIGN goto generate_assign
|
if c == EXPRESSION_ASSIGN goto generate_assign
|
||||||
|
if c == EXPRESSION_CALL goto generate_call
|
||||||
|
|
||||||
|
putnln(c)
|
||||||
|
|
||||||
die(.str_genpushexprNI)
|
die(.str_genpushexprNI)
|
||||||
:str_genpushexprNI
|
:str_genpushexprNI
|
||||||
|
@ -1456,6 +1471,27 @@ function generate_push_expression
|
||||||
expr += 8
|
expr += 8
|
||||||
expr = generate_push_expression_casted(statement, expr, type)
|
expr = generate_push_expression_casted(statement, expr, type)
|
||||||
return expr
|
return expr
|
||||||
|
:generate_function_addr
|
||||||
|
d = 0
|
||||||
|
expr += 8
|
||||||
|
if codegen_second_pass == 0 goto function_noaddr
|
||||||
|
d = ident_list_lookup(functions_addresses, *8expr)
|
||||||
|
if d == 0 goto no_such_function
|
||||||
|
:function_noaddr
|
||||||
|
expr += 8
|
||||||
|
emit_mov_rax_imm64(d)
|
||||||
|
emit_push_rax()
|
||||||
|
return expr
|
||||||
|
|
||||||
|
:no_such_function
|
||||||
|
print_statement_location(statement)
|
||||||
|
puts(.str_no_such_function)
|
||||||
|
putsln(*8expr)
|
||||||
|
exit(1)
|
||||||
|
:str_no_such_function
|
||||||
|
string : Error: No such function:
|
||||||
|
byte 32
|
||||||
|
byte 0
|
||||||
:generate_unary_minus
|
:generate_unary_minus
|
||||||
expr += 8
|
expr += 8
|
||||||
expr = generate_push_expression_casted(statement, expr, type)
|
expr = generate_push_expression_casted(statement, expr, type)
|
||||||
|
@ -1724,6 +1760,93 @@ function generate_push_expression
|
||||||
emit_add_rsp_imm32(c) ; add rsp, (size of expression value on stack)
|
emit_add_rsp_imm32(c) ; add rsp, (size of expression value on stack)
|
||||||
expr = generate_push_expression(statement, expr)
|
expr = generate_push_expression(statement, expr)
|
||||||
return expr
|
return expr
|
||||||
|
:generate_call
|
||||||
|
expr += 8
|
||||||
|
global 4000 expr_arg_ptrs_dat
|
||||||
|
local expr_arg_ptrs
|
||||||
|
expr_arg_ptrs = &expr_arg_ptrs_dat
|
||||||
|
local arg_idx
|
||||||
|
local call_function
|
||||||
|
local return_val_size
|
||||||
|
local args_size
|
||||||
|
|
||||||
|
return_val_size = type_sizeof(type)
|
||||||
|
return_val_size = round_up_to_8(return_val_size)
|
||||||
|
|
||||||
|
call_function = expr
|
||||||
|
expr = expression_get_end(expr)
|
||||||
|
|
||||||
|
args_size = 0
|
||||||
|
|
||||||
|
; we have to do a bit of work because the arguments are stored
|
||||||
|
; left to right, but pushed right to left
|
||||||
|
arg_idx = 0
|
||||||
|
p = expr_arg_ptrs
|
||||||
|
:find_call_args_loop
|
||||||
|
if *1expr == 0 goto find_call_args_loop_end
|
||||||
|
*8p = expr
|
||||||
|
|
||||||
|
c = expr + 4
|
||||||
|
c = type_sizeof(*4c)
|
||||||
|
c = round_up_to_8(c)
|
||||||
|
args_size += c
|
||||||
|
|
||||||
|
expr = expression_get_end(expr)
|
||||||
|
p += 8
|
||||||
|
arg_idx += 1
|
||||||
|
goto find_call_args_loop
|
||||||
|
:find_call_args_loop_end
|
||||||
|
expr += 8
|
||||||
|
|
||||||
|
:push_args_loop
|
||||||
|
if arg_idx == 0 goto push_args_loop_end
|
||||||
|
p -= 8
|
||||||
|
generate_push_expression(statement, *8p)
|
||||||
|
arg_idx -= 1
|
||||||
|
goto push_args_loop
|
||||||
|
:push_args_loop_end
|
||||||
|
|
||||||
|
; create space on stack for return value
|
||||||
|
emit_sub_rsp_imm32(return_val_size)
|
||||||
|
; put function in rax
|
||||||
|
generate_push_expression(statement, call_function)
|
||||||
|
emit_mov_rax_qword_rsp()
|
||||||
|
emit_add_rsp_imm32(8)
|
||||||
|
; call
|
||||||
|
emit_call_rax()
|
||||||
|
|
||||||
|
if return_val_size > 8 goto generate_big_return
|
||||||
|
emit_mov_rax_qword_rsp() ; mov rax, [rsp]
|
||||||
|
emit_add_rsp_imm32(args_size) ; add rsp, (size of arguments on stack)
|
||||||
|
emit_mov_qword_rsp_rax() ; mov [rsp], rax
|
||||||
|
return expr
|
||||||
|
|
||||||
|
:generate_big_return
|
||||||
|
; now we need to copy the return value to the proper place in the stack
|
||||||
|
; this is kind of annoying because that might overlap with the current position.
|
||||||
|
; so, we'll push a copy of the return value, then copy that over to the proper place.
|
||||||
|
local copy_offset
|
||||||
|
|
||||||
|
; first copy
|
||||||
|
copy_offset = 0 - return_val_size
|
||||||
|
emit_mov_reg(REG_RSI, REG_RSP)
|
||||||
|
emit_mov_reg(REG_RAX, REG_RSP)
|
||||||
|
emit_add_rax_imm32(copy_offset)
|
||||||
|
emit_mov_reg(REG_RDI, REG_RAX)
|
||||||
|
generate_copy_rsi_to_rdi_qwords(type)
|
||||||
|
|
||||||
|
; second copy
|
||||||
|
emit_mov_reg(REG_RAX, REG_RSP)
|
||||||
|
emit_add_rax_imm32(copy_offset)
|
||||||
|
emit_mov_reg(REG_RSI, REG_RAX)
|
||||||
|
emit_mov_reg(REG_RAX, REG_RSP)
|
||||||
|
emit_add_rax_imm32(args_size)
|
||||||
|
emit_mov_reg(REG_RDI, REG_RAX)
|
||||||
|
generate_copy_rsi_to_rdi_qwords(type)
|
||||||
|
|
||||||
|
emit_add_rsp_imm32(args_size)
|
||||||
|
return
|
||||||
|
|
||||||
function generate_statement
|
function generate_statement
|
||||||
argument statement
|
argument statement
|
||||||
local dat1
|
local dat1
|
||||||
|
@ -1868,7 +1991,7 @@ function generate_functions
|
||||||
:function_addr_mismatch
|
:function_addr_mismatch
|
||||||
; address of function on 2nd pass doesn't line up with 1st pass
|
; address of function on 2nd pass doesn't line up with 1st pass
|
||||||
puts(.str_function_addr_mismatch)
|
puts(.str_function_addr_mismatch)
|
||||||
puts(function_name)
|
putsln(function_name)
|
||||||
exit(1)
|
exit(1)
|
||||||
:str_function_addr_mismatch
|
:str_function_addr_mismatch
|
||||||
string Function address on first pass doesn't match 2nd pass:
|
string Function address on first pass doesn't match 2nd pass:
|
||||||
|
|
26
05/main.c
26
05/main.c
|
@ -1,4 +1,28 @@
|
||||||
|
typedef struct {
|
||||||
|
long a;
|
||||||
|
long aah[810];
|
||||||
|
long b;
|
||||||
|
} Structure;
|
||||||
|
|
||||||
|
Structure mkstruct(int x, int y) {
|
||||||
|
Structure s;
|
||||||
|
s.a = x;
|
||||||
|
s.b = y;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
Structure mkstruct1(int x) {
|
||||||
|
return mkstruct(x, x*2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Structure mkstruct_a() {
|
||||||
|
return mkstruct1(1033.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
long main(int argc, char **argv) {
|
long main(int argc, char **argv) {
|
||||||
return 43 >> 2;
|
Structure t;
|
||||||
|
t = mkstruct_a();
|
||||||
|
return t.b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ function token_is_type
|
||||||
if b != 0 goto return_1
|
if b != 0 goto return_1
|
||||||
goto return_0
|
goto return_0
|
||||||
|
|
||||||
|
|
||||||
function type_is_array
|
function type_is_array
|
||||||
argument type
|
argument type
|
||||||
local p
|
local p
|
||||||
|
|
|
@ -113,6 +113,7 @@ ax bx cx dx sp bp si di
|
||||||
├──────────────────────┼───────────────────┼────────────────────────────────────────┤
|
├──────────────────────┼───────────────────┼────────────────────────────────────────┤
|
||||||
│ mov rax, IMM64 │ 48 b8 IMM64 │ set rax to the 64-bit value IMM64 │
|
│ mov rax, IMM64 │ 48 b8 IMM64 │ set rax to the 64-bit value IMM64 │
|
||||||
│ mov rbx, IMM64 │ 48 bb IMM64 │ set rbx to the 64-bit value IMM64 │
|
│ mov rbx, IMM64 │ 48 bb IMM64 │ set rbx to the 64-bit value IMM64 │
|
||||||
|
| add rax, IMM32 | 48 05 IMM32 | add IMM32 (signed) to rax |
|
||||||
│ xor eax, eax │ 31 c0 │ set rax to 0 (shorter than mov rax, 0) │
|
│ xor eax, eax │ 31 c0 │ set rax to 0 (shorter than mov rax, 0) │
|
||||||
│ xor edx, edx │ 31 d2 │ set rdx to 0 │
|
│ xor edx, edx │ 31 d2 │ set rdx to 0 │
|
||||||
│ mov RDEST, RSRC │ 48 89 (DEST|SRC<<3|0xc0) │ set register DEST to current │
|
│ mov RDEST, RSRC │ 48 89 (DEST|SRC<<3|0xc0) │ set register DEST to current │
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue