local variables

This commit is contained in:
pommicket 2022-02-12 12:03:00 -05:00
parent b69bd8be29
commit 0a14c8ca2a
4 changed files with 96 additions and 15 deletions

View file

@ -300,6 +300,29 @@ function emit_lea_rax_rbp_plus_imm32
code_output += 4 code_output += 4
return return
function emit_lea_rsp_rbp_plus_imm32
; 48 8d a5 IMM32
argument imm32
*2code_output = 0x8d48
code_output += 2
*1code_output = 0xa5
code_output += 1
*4code_output = imm32
code_output += 4
return
function emit_mov_rax_qword_rbp_plus_imm32
; 48 8b 85 IMM32
argument imm32
*2code_output = 0x8b48
code_output += 2
*1code_output = 0x85
code_output += 1
*4code_output = imm32
code_output += 4
return
function emit_rep_movsb function emit_rep_movsb
; f3 a4 ; f3 a4
*2code_output = 0xa4f3 *2code_output = 0xa4f3
@ -964,6 +987,7 @@ function generate_push_expression
if c == EXPRESSION_ADD goto generate_add if c == EXPRESSION_ADD goto generate_add
if c == EXPRESSION_SUB goto generate_sub if c == EXPRESSION_SUB goto generate_sub
if c == EXPRESSION_GLOBAL_VARIABLE goto generate_global_variable if c == EXPRESSION_GLOBAL_VARIABLE goto generate_global_variable
if c == EXPRESSION_LOCAL_VARIABLE goto generate_local_variable
die(.str_genpushexprNI) die(.str_genpushexprNI)
:str_genpushexprNI :str_genpushexprNI
@ -1083,6 +1107,39 @@ function generate_push_expression
emit_mov_rax_imm64(d) ; mov rax, (address) emit_mov_rax_imm64(d) ; mov rax, (address)
emit_push_rax() ; push rax emit_push_rax() ; push rax
return expr return expr
:generate_local_variable
expr += 8
d = *8expr ; rbp offset
expr += 8
b = type_is_array(type)
if b != 0 goto local_var_array
c = type_sizeof(type)
if c > 8 goto local_var_large
emit_mov_rax_qword_rbp_plus_imm32(d) ; mov rax, [rbp+X]
emit_push_rax() ; push rax
p = types + type
if *1p < TYPE_LONG goto local_var_needs_cast
return expr
:local_var_needs_cast
generate_cast_top_of_stack(statement, TYPE_UNSIGNED_LONG, type)
return expr
:local_var_large
; @TODO: test this
c = round_up_to_8(c)
emit_sub_rsp_imm32(c) ; sub rsp, (size)
emit_mov_reg(REG_RDI, REG_RSP) ; mov rdi, rsp
emit_lea_rax_rbp_plus_imm32(d) ; lea rax, [rbp+X]
emit_mov_reg(REG_RSI, REG_RAX) ; mov rsi, rax
emit_mov_rax_imm64(c) ; mov rax, (size)
emit_mov_reg(REG_RCX, REG_RAX) ; mov rcx, rax
emit_rep_movsb() ; rep movsb
return expr
:local_var_array
; push address of array instead of array
emit_lea_rax_rbp_plus_imm32(d) ; lea rax, [rbp+X]
emit_push_rax() ; push rax
return expr
byte 0xcc
:generate_float :generate_float
expr += 8 expr += 8
emit_mov_rax_imm64(*8expr) emit_mov_rax_imm64(*8expr)
@ -1120,6 +1177,7 @@ function generate_statement
if c == STATEMENT_BLOCK goto gen_block if c == STATEMENT_BLOCK goto gen_block
if c == STATEMENT_RETURN goto gen_return if c == STATEMENT_RETURN goto gen_return
if c == STATEMENT_LOCAL_DECLARATION goto gen_local_decl
; @TODO ; @TODO
die(.str_genstmtNI) die(.str_genstmtNI)
:str_genstmtNI :str_genstmtNI
@ -1145,6 +1203,27 @@ function generate_statement
:gen_return_noexpr :gen_return_noexpr
generate_return() generate_return()
return return
:gen_local_decl
c = type_sizeof(dat2)
c = round_up_to_8(c)
if dat3 != 0 goto gen_local_decl_initializer
; move the stack pointer to the start of the variable
dat1 += c
dat1 = 0 - dat1
emit_lea_rsp_rbp_plus_imm32(dat1)
if dat2 != 0 goto gen_local_decl_data_initializer
return
:gen_local_decl_initializer
dat1 = 0 - dat1
; move the stack pointer to the end of the variable
emit_lea_rsp_rbp_plus_imm32(dat1)
; push the expression
generate_push_expression_casted(statement, dat3, dat2)
return
:gen_local_decl_data_initializer
byte 0xcc ; @TODO
function generate_function function generate_function
argument function_name argument function_name

View file

@ -271,7 +271,7 @@
; a type of 0 indicates the end of the block. ; a type of 0 indicates the end of the block.
; data layout for particular statements: ; data layout for particular statements:
; - STATEMENT_EXPRESSION - data1 is a pointer to expression data; data2,3,4 are unused ; - STATEMENT_EXPRESSION - data1 is a pointer to expression data; data2,3,4 are unused
; - STATEMENT_LOCAL_DECLARATION - declaring a local variable, data1 = rbp offset, data2 = size of type (ignored if dat4 is 0), data3 = initializer expression or 0, data4 = initializer memory address to copy from (for braced initializers) or 0 ; - STATEMENT_LOCAL_DECLARATION - declaring a local variable, data1 = rbp - rsp BEFORE variable is pushed, data2 = type, data3 = initializer expression or 0, data4 = initializer memory address to copy from (for braced initializers) or 0
; - STATEMENT_LABEL - data1 is a pointer to the name of the label; data2,3,4 are unused ; - STATEMENT_LABEL - data1 is a pointer to the name of the label; data2,3,4 are unused
; - STATEMENT_BLOCK - data1 is a pointer to an array of statements; data2,3,4 are unused ; - STATEMENT_BLOCK - data1 is a pointer to an array of statements; data2,3,4 are unused
; - STATEMENT_IF - data1 is a pointer to the condition, data2 is a pointer to the `if' branch statement, data3 is a pointer to the `else' branch statement, or 0 if there is none; data4 is unused ; - STATEMENT_IF - data1 is a pointer to the condition, data2 is a pointer to the `if' branch statement, data3 is a pointer to the `else' branch statement, or 0 if there is none; data4 is unused

View file

@ -1,5 +1,7 @@
static int x = -2; static char x = -2;
long main(int argc, char **argv) { long main(int argc, char **argv) {
return x + 17.3; int y = 38;
int z = y + x;
return z + x;
} }

View file

@ -704,18 +704,18 @@ function parse_statement
; we need to calculate the size of the type here, because of stuff like ; we need to calculate the size of the type here, because of stuff like
; int x[] = {1,2,3}; ; int x[] = {1,2,3};
n = type_sizeof(l_type) n = type_sizeof(l_type)
; advance
local_var_rbp_offset += n
; align
local_var_rbp_offset += 7
local_var_rbp_offset >= 3
local_var_rbp_offset <= 3
write_statement_header(out, STATEMENT_LOCAL_DECLARATION, token) write_statement_header(out, STATEMENT_LOCAL_DECLARATION, token)
out += 8 out += 8
*8out = local_var_rbp_offset *8out = local_var_rbp_offset
out += 8 out += 8
*8out = n *8out = l_type
out += 24 out += 24
; advance
local_var_rbp_offset += n
; align
local_var_rbp_offset = round_up_to_8(local_var_rbp_offset)
p = local_variables p = local_variables
p += block_depth < 3 p += block_depth < 3
; local variables are stored below rbp ; local variables are stored below rbp
@ -1102,8 +1102,8 @@ function print_statement_with_depth
:print_stmt_local_decl :print_stmt_local_decl
puts(.str_local_decl) puts(.str_local_decl)
putn(dat1) putn(dat1)
puts(.str_local_size) puts(.str_local_type)
putn(dat2) print_type(dat2)
if dat3 != 0 goto print_stmt_local_initializer if dat3 != 0 goto print_stmt_local_initializer
if dat4 != 0 goto print_stmt_local_copy_address if dat4 != 0 goto print_stmt_local_copy_address
:stmt_local_decl_finish :stmt_local_decl_finish
@ -1122,8 +1122,8 @@ function print_statement_with_depth
:str_local_decl :str_local_decl
string local variable at rbp- string local variable at rbp-
byte 0 byte 0
:str_local_size :str_local_type
string size string type
byte 32 byte 32
byte 0 byte 0
:str_local_copyfrom :str_local_copyfrom