diff options
-rw-r--r-- | 05/codegen.b | 81 | ||||
-rw-r--r-- | 05/constants.b | 2 | ||||
-rw-r--r-- | 05/main.c | 6 | ||||
-rw-r--r-- | 05/parse.b | 22 |
4 files changed, 96 insertions, 15 deletions
diff --git a/05/codegen.b b/05/codegen.b index ff4687a..a67a9db 100644 --- a/05/codegen.b +++ b/05/codegen.b @@ -300,6 +300,29 @@ function emit_lea_rax_rbp_plus_imm32 code_output += 4 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 ; f3 a4 *2code_output = 0xa4f3 @@ -964,6 +987,7 @@ function generate_push_expression if c == EXPRESSION_ADD goto generate_add if c == EXPRESSION_SUB goto generate_sub if c == EXPRESSION_GLOBAL_VARIABLE goto generate_global_variable + if c == EXPRESSION_LOCAL_VARIABLE goto generate_local_variable die(.str_genpushexprNI) :str_genpushexprNI @@ -1083,6 +1107,39 @@ function generate_push_expression emit_mov_rax_imm64(d) ; mov rax, (address) emit_push_rax() ; push rax 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 expr += 8 emit_mov_rax_imm64(*8expr) @@ -1120,6 +1177,7 @@ function generate_statement if c == STATEMENT_BLOCK goto gen_block if c == STATEMENT_RETURN goto gen_return + if c == STATEMENT_LOCAL_DECLARATION goto gen_local_decl ; @TODO die(.str_genstmtNI) :str_genstmtNI @@ -1145,7 +1203,28 @@ function generate_statement :gen_return_noexpr generate_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 argument function_name argument function_statement diff --git a/05/constants.b b/05/constants.b index 2f28cd5..79cd8e5 100644 --- a/05/constants.b +++ b/05/constants.b @@ -271,7 +271,7 @@ ; a type of 0 indicates the end of the block. ; data layout for particular statements: ; - 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_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 @@ -1,5 +1,7 @@ -static int x = -2; +static char x = -2; long main(int argc, char **argv) { - return x + 17.3; + int y = 38; + int z = y + x; + return z + x; } @@ -704,18 +704,18 @@ function parse_statement ; we need to calculate the size of the type here, because of stuff like ; int x[] = {1,2,3}; 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) out += 8 *8out = local_var_rbp_offset out += 8 - *8out = n + *8out = l_type 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 += block_depth < 3 ; local variables are stored below rbp @@ -1102,8 +1102,8 @@ function print_statement_with_depth :print_stmt_local_decl puts(.str_local_decl) putn(dat1) - puts(.str_local_size) - putn(dat2) + puts(.str_local_type) + print_type(dat2) if dat3 != 0 goto print_stmt_local_initializer if dat4 != 0 goto print_stmt_local_copy_address :stmt_local_decl_finish @@ -1122,8 +1122,8 @@ function print_statement_with_depth :str_local_decl string local variable at rbp- byte 0 - :str_local_size - string size + :str_local_type + string type byte 32 byte 0 :str_local_copyfrom |