summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-02-13 14:24:38 -0500
committerpommicket <pommicket@gmail.com>2022-02-13 14:24:38 -0500
commit239a1a3c271d03e9202b9dc62d87e6ee631d0d40 (patch)
treeda50d62b0243fc40f16f30f1800d6e40524abb6d
parent24f260fa1649aeecae162b58eee1982fbce3a5ed (diff)
fixed local variables and also structs containing arrays
-rw-r--r--05/codegen.b45
-rw-r--r--05/constants.b4
-rw-r--r--05/main.b14
-rw-r--r--05/main.c12
-rw-r--r--05/parse.b45
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
diff --git a/05/main.b b/05/main.b
index 7d4df9e..4621a80 100644
--- a/05/main.b
+++ b/05/main.b
@@ -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)
diff --git a/05/main.c b/05/main.c
index f26c982..68140cf 100644
--- a/05/main.c
+++ b/05/main.c
@@ -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);
}
diff --git a/05/parse.b b/05/parse.b
index 37c9856..a4ba853 100644
--- a/05/parse.b
+++ b/05/parse.b
@@ -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)