diff options
author | pommicket <pommicket@gmail.com> | 2022-02-13 14:24:38 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-02-13 14:24:38 -0500 |
commit | 239a1a3c271d03e9202b9dc62d87e6ee631d0d40 (patch) | |
tree | da50d62b0243fc40f16f30f1800d6e40524abb6d | |
parent | 24f260fa1649aeecae162b58eee1982fbce3a5ed (diff) |
fixed local variables and also structs containing arrays
-rw-r--r-- | 05/codegen.b | 45 | ||||
-rw-r--r-- | 05/constants.b | 4 | ||||
-rw-r--r-- | 05/main.b | 14 | ||||
-rw-r--r-- | 05/main.c | 12 | ||||
-rw-r--r-- | 05/parse.b | 45 |
5 files changed, 76 insertions, 44 deletions
diff --git a/05/codegen.b b/05/codegen.b index 2c0ceaf..d33eb3e 100644 --- a/05/codegen.b +++ b/05/codegen.b @@ -730,6 +730,7 @@ function generate_copy_rsi_to_rdi_qwords argument type local n n = type_sizeof(type) + n = round_up_to_8(n) if n == 8 goto rsi2rdi_qwords_simple ; this is a struct or something, use rep movsb @@ -743,6 +744,7 @@ function generate_copy_rsi_to_rdi_qwords ; this is a little "optimization" over rep movsb with rcx = 8, mainly it just makes debugging easier (otherwise you'd need 8 `stepi`s in gdb to skip over the instruction) emit_movsq() return + ; cast whatever was just pushed onto the stack from from_type to to_type ; `statement` is used for errors @@ -1479,7 +1481,7 @@ function generate_push_address_of_expression :addrof_dot_cont emit_mov_rax_qword_rsp() ; mov rax, [rsp] emit_mov_reg(REG_RBX, REG_RAX) ; mov rbx, rax - emit_mov_rax_imm64(*8expr) ; mov rax, (offset to member) + emit_mov_rax_imm64(*4expr) ; mov rax, (offset to member) emit_add_rax_rbx() ; add rax, rbx emit_mov_qword_rsp_rax() ; mov [rsp], rax expr += 8 @@ -2375,8 +2377,13 @@ function generate_push_expression ; @NONSTANDARD: we require that the 1st operand to . be an lvalue ; e.g. int thing = function_which_returns_struct().x; ; is not allowed + p = expr + 8 + p = expression_get_end(p) + p += 4 expr = generate_push_address_of_expression(statement, expr) + if *4p == 1 goto member_array generate_stack_dereference(statement, type) + :member_array return expr :generate_local_variable expr += 8 @@ -2630,30 +2637,32 @@ function generate_statement 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 dat3 != 0 goto gen_local_decl_initializer if dat4 != 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) + c = type_sizeof(dat2) + c = round_up_to_8(c) + ; push the expression generate_push_expression_casted(statement, dat3, dat2) + ; copy it to where the variable's supposed to be + emit_mov_reg(REG_RSI, REG_RSP) ; mov rsi, rsp + emit_lea_rax_rbp_plus_imm32(dat1) ; lea rax, [rbp+X] + emit_mov_reg(REG_RDI, REG_RAX) ; mov rdi, rax + generate_copy_rsi_to_rdi_qwords(dat2) + ; pop the expression + emit_add_rsp_imm32(c) ; add rsp, (size) return :gen_local_decl_data_initializer - emit_mov_rax_imm64(dat4) ; mov rax, (data address) - emit_mov_reg(REG_RSI, REG_RAX) ; mov rsi, rax - emit_mov_reg(REG_RDI, REG_RSP) ; mov rdi, rsp - emit_mov_rax_imm64(c) ; mov rax, (size) - emit_mov_reg(REG_RCX, REG_RAX) ; mov rcx, rax - emit_rep_movsb() ; rep movsb + emit_mov_rax_imm64(dat4) ; mov rax, (data address) + emit_mov_reg(REG_RSI, REG_RAX) ; mov rsi, rax + emit_lea_rax_rbp_plus_imm32(dat1) ; lea rax, [rbp+X] + emit_mov_reg(REG_RDI, REG_RAX) ; mov rdi, rax + generate_copy_rsi_to_rdi_qwords(dat2) return :gen_stmt_expr generate_push_expression_casted(statement, dat1, TYPE_VOID) @@ -2878,6 +2887,7 @@ function generate_function argument function_statement local function_type local out0 + local n_stack_bytes function_type = ident_list_lookup(function_types, function_name) @@ -2896,6 +2906,9 @@ function generate_function emit_mov_qword_rsp_rbp() emit_mov_reg(REG_RBP, REG_RSP) + n_stack_bytes = ident_list_lookup(functions_required_stack_space, function_name) + emit_sub_rsp_imm32(n_stack_bytes) + generate_statement(function_statement) ; implicit return at end of function diff --git a/05/constants.b b/05/constants.b index f02ffaf..7bcc2aa 100644 --- a/05/constants.b +++ b/05/constants.b @@ -160,7 +160,7 @@ ; - for unary operators, the operand ; - for casts, the operand (type is given by type member) ; - for binary operators, the first operand followed by the second -; - for the operators . and ->, the first argument is the expression on the left-hand side, and the second argument is a 64-bit offset. +; - for the operators . and ->, first the expression on the left-hand side, then the 32-bit offset, then a 32-bit number which is 1 if the member is an array ; - for the ternary operator ? :, the first followed by the second followed by the third ; - for function calls, the function, followed by each of the arguments to the function, followed by 8 bytes of zeros ; File/line number are not stored in expressions. @@ -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 - 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_LOCAL_DECLARATION - declaring a local variable, data1 = signed offset from rbp of variable, 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 @@ -74,6 +74,9 @@ global local_var_rbp_offset global function_param_names ; set to 1 by parse_type_declarators if at least one function parameter has no name. global function_param_has_no_name +; ident list of number of bytes of stack space needed by local variables in each function +global functions_required_stack_space + #include util.b #include idents.b @@ -248,6 +251,7 @@ function main functions_addresses = ident_list_create(800000) functions_labels = ident_list_create(800000) function_types = ident_list_create(800000) + functions_required_stack_space = ident_list_create(800000) function_stmt_data = malloc(800000) ; should be at least 40 bytes * max # of functions dat_banned_objmacros = 255 @@ -292,8 +296,8 @@ function main tokens = malloc(16000000) p = tokenize(pptokens, tokens, input_filename, 1) - print_tokens(tokens, p) - print_separator() + ;print_tokens(tokens, p) + ;print_separator() ; NOTE: do NOT free pptokens; identifiers still reference them. parse_tokens(tokens) @@ -303,9 +307,9 @@ function main munmap(output_file_data, RWDATA_END) close(output_fd) - ident_list_printx64(global_variables) - puts(.str_types_bytes_used) - putnln(types_bytes_used) + ;ident_list_printx64(global_variables) + ;puts(.str_types_bytes_used) + ;putnln(types_bytes_used) exit(0) @@ -27,15 +27,7 @@ int f() { lb: goto lb; } -int main(int argc, char **argv) { - int a = 5; - switch(a++){ - case 5: a++; - case 3: a++; - case 4: a++; - default: a++; - } - - return a ; +int main(int argc, char **argv) { + return fibonacci(20); } @@ -1,3 +1,6 @@ + +global curr_function_stack_space + ; is this token the start of a type? function token_is_type argument token @@ -264,6 +267,9 @@ function parse_toplevel_declaration :parse_function_definition local ret_type local param_offset + local f_name + + f_name = name if block_depth != 0 goto nested_function if function_param_has_no_name != 0 goto function_no_param_name @@ -314,7 +320,10 @@ function parse_toplevel_declaration parse_statement(&token, &out) if block_depth != 0 goto blockdepth_internal_err function_stmt_data_bytes_used = out - function_stmt_data - print_statement(out0) + + ident_list_add(functions_required_stack_space, f_name, curr_function_stack_space) + + ;print_statement(out0) goto parse_tld_ret :function_no_param_name @@ -720,6 +729,12 @@ 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 = round_up_to_8(local_var_rbp_offset) + write_statement_header(out, STATEMENT_LOCAL_DECLARATION, token) out += 8 *8out = local_var_rbp_offset @@ -727,10 +742,7 @@ function parse_statement *8out = l_type out += 24 - ; advance - local_var_rbp_offset += n - ; align - local_var_rbp_offset = round_up_to_8(local_var_rbp_offset) + curr_function_stack_space = local_var_rbp_offset p = local_variables p += block_depth < 3 @@ -2181,6 +2193,7 @@ function parse_base_type ident_list_add(structures, struct_name, struct) :struct_definition_fill_in + *1out = TYPE_STRUCT out += 1 *8out = struct @@ -3031,10 +3044,15 @@ function parse_expression p += 8 c = ident_list_lookup(a, *8p) if c == 0 goto member_not_in_struct - *8out = c & 0xffffffff ; offset + *4type = c > 32 ; type - out += 8 + *4type = type_create_copy(*4type) + *4out = c & 0xffffffff ; offset + out += 4 + *4out = type_is_array(*4type) + out += 4 p += 8 + if p != tokens_end goto bad_expression ; e.g. foo->bar hello return out :use_of_incomplete_struct @@ -4286,7 +4304,7 @@ function print_expression expression += 8 expression = print_expression(expression) puts(.str_dot) - putn(*8expression) + putn(*4expression) expression += 8 putc(41) return expression @@ -4295,7 +4313,7 @@ function print_expression expression += 8 expression = print_expression(expression) puts(.str_arrow) - putn(*8expression) + putn(*4expression) expression += 8 putc(41) return expression @@ -4451,12 +4469,17 @@ function print_type putc('[) type += 1 c = types + type - putn(*8c) ; UNALIGNED + putn(*8c) putc(']) type += 8 goto print_type_top :print_type_struct - return puts(.str_struct) + puts(.str_struct) + c = types + type + c += 1 + putc('@) + putx64(*8c) + return :print_type_function type += 1 putc(40) |