fixed local variables and also structs containing arrays

This commit is contained in:
pommicket 2022-02-13 14:24:38 -05:00
parent 24f260fa16
commit 239a1a3c27
5 changed files with 76 additions and 44 deletions

View file

@ -730,6 +730,7 @@ function generate_copy_rsi_to_rdi_qwords
argument type argument type
local n local n
n = type_sizeof(type) n = type_sizeof(type)
n = round_up_to_8(n) n = round_up_to_8(n)
if n == 8 goto rsi2rdi_qwords_simple if n == 8 goto rsi2rdi_qwords_simple
; this is a struct or something, use rep movsb ; this is a struct or something, use rep movsb
@ -744,6 +745,7 @@ function generate_copy_rsi_to_rdi_qwords
emit_movsq() emit_movsq()
return return
; cast whatever was just pushed onto the stack from from_type to to_type ; cast whatever was just pushed onto the stack from from_type to to_type
; `statement` is used for errors ; `statement` is used for errors
function generate_cast_top_of_stack function generate_cast_top_of_stack
@ -1479,7 +1481,7 @@ function generate_push_address_of_expression
:addrof_dot_cont :addrof_dot_cont
emit_mov_rax_qword_rsp() ; mov rax, [rsp] emit_mov_rax_qword_rsp() ; mov rax, [rsp]
emit_mov_reg(REG_RBX, REG_RAX) ; mov rbx, rax 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_add_rax_rbx() ; add rax, rbx
emit_mov_qword_rsp_rax() ; mov [rsp], rax emit_mov_qword_rsp_rax() ; mov [rsp], rax
expr += 8 expr += 8
@ -2375,8 +2377,13 @@ function generate_push_expression
; @NONSTANDARD: we require that the 1st operand to . be an lvalue ; @NONSTANDARD: we require that the 1st operand to . be an lvalue
; e.g. int thing = function_which_returns_struct().x; ; e.g. int thing = function_which_returns_struct().x;
; is not allowed ; is not allowed
p = expr + 8
p = expression_get_end(p)
p += 4
expr = generate_push_address_of_expression(statement, expr) expr = generate_push_address_of_expression(statement, expr)
if *4p == 1 goto member_array
generate_stack_dereference(statement, type) generate_stack_dereference(statement, type)
:member_array
return expr return expr
:generate_local_variable :generate_local_variable
expr += 8 expr += 8
@ -2630,30 +2637,32 @@ function generate_statement
generate_return() generate_return()
return return
:gen_local_decl :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 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 if dat4 != 0 goto gen_local_decl_data_initializer
return return
:gen_local_decl_initializer :gen_local_decl_initializer
dat1 = 0 - dat1 c = type_sizeof(dat2)
; move the stack pointer to the end of the variable c = round_up_to_8(c)
emit_lea_rsp_rbp_plus_imm32(dat1)
; push the expression ; push the expression
generate_push_expression_casted(statement, dat3, dat2) 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 return
:gen_local_decl_data_initializer :gen_local_decl_data_initializer
emit_mov_rax_imm64(dat4) ; mov rax, (data address) emit_mov_rax_imm64(dat4) ; mov rax, (data address)
emit_mov_reg(REG_RSI, REG_RAX) ; mov rsi, rax emit_mov_reg(REG_RSI, REG_RAX) ; mov rsi, rax
emit_mov_reg(REG_RDI, REG_RSP) ; mov rdi, rsp emit_lea_rax_rbp_plus_imm32(dat1) ; lea rax, [rbp+X]
emit_mov_rax_imm64(c) ; mov rax, (size) emit_mov_reg(REG_RDI, REG_RAX) ; mov rdi, rax
emit_mov_reg(REG_RCX, REG_RAX) ; mov rcx, rax generate_copy_rsi_to_rdi_qwords(dat2)
emit_rep_movsb() ; rep movsb
return return
:gen_stmt_expr :gen_stmt_expr
generate_push_expression_casted(statement, dat1, TYPE_VOID) generate_push_expression_casted(statement, dat1, TYPE_VOID)
@ -2878,6 +2887,7 @@ function generate_function
argument function_statement argument function_statement
local function_type local function_type
local out0 local out0
local n_stack_bytes
function_type = ident_list_lookup(function_types, function_name) function_type = ident_list_lookup(function_types, function_name)
@ -2896,6 +2906,9 @@ function generate_function
emit_mov_qword_rsp_rbp() emit_mov_qword_rsp_rbp()
emit_mov_reg(REG_RBP, REG_RSP) 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) generate_statement(function_statement)
; implicit return at end of function ; implicit return at end of function

View file

@ -160,7 +160,7 @@
; - for unary operators, the operand ; - for unary operators, the operand
; - for casts, the operand (type is given by type member) ; - for casts, the operand (type is given by type member)
; - for binary operators, the first operand followed by the second ; - 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 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 ; - 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. ; File/line number are not stored in expressions.
@ -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 - 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_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

@ -74,6 +74,9 @@ global local_var_rbp_offset
global function_param_names global function_param_names
; set to 1 by parse_type_declarators if at least one function parameter has no name. ; set to 1 by parse_type_declarators if at least one function parameter has no name.
global function_param_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 util.b
#include idents.b #include idents.b
@ -248,6 +251,7 @@ function main
functions_addresses = ident_list_create(800000) functions_addresses = ident_list_create(800000)
functions_labels = ident_list_create(800000) functions_labels = ident_list_create(800000)
function_types = 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 function_stmt_data = malloc(800000) ; should be at least 40 bytes * max # of functions
dat_banned_objmacros = 255 dat_banned_objmacros = 255
@ -292,8 +296,8 @@ function main
tokens = malloc(16000000) tokens = malloc(16000000)
p = tokenize(pptokens, tokens, input_filename, 1) p = tokenize(pptokens, tokens, input_filename, 1)
print_tokens(tokens, p) ;print_tokens(tokens, p)
print_separator() ;print_separator()
; NOTE: do NOT free pptokens; identifiers still reference them. ; NOTE: do NOT free pptokens; identifiers still reference them.
parse_tokens(tokens) parse_tokens(tokens)
@ -303,9 +307,9 @@ function main
munmap(output_file_data, RWDATA_END) munmap(output_file_data, RWDATA_END)
close(output_fd) close(output_fd)
ident_list_printx64(global_variables) ;ident_list_printx64(global_variables)
puts(.str_types_bytes_used) ;puts(.str_types_bytes_used)
putnln(types_bytes_used) ;putnln(types_bytes_used)
exit(0) exit(0)

View file

@ -28,14 +28,6 @@ int f() {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
int a = 5; return fibonacci(20);
switch(a++){
case 5: a++;
case 3: a++;
case 4: a++;
default: a++;
}
return a ;
} }

View file

@ -1,3 +1,6 @@
global curr_function_stack_space
; is this token the start of a type? ; is this token the start of a type?
function token_is_type function token_is_type
argument token argument token
@ -264,6 +267,9 @@ function parse_toplevel_declaration
:parse_function_definition :parse_function_definition
local ret_type local ret_type
local param_offset local param_offset
local f_name
f_name = name
if block_depth != 0 goto nested_function if block_depth != 0 goto nested_function
if function_param_has_no_name != 0 goto function_no_param_name if function_param_has_no_name != 0 goto function_no_param_name
@ -314,7 +320,10 @@ function parse_toplevel_declaration
parse_statement(&token, &out) parse_statement(&token, &out)
if block_depth != 0 goto blockdepth_internal_err if block_depth != 0 goto blockdepth_internal_err
function_stmt_data_bytes_used = out - function_stmt_data 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 goto parse_tld_ret
:function_no_param_name :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 ; 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 = round_up_to_8(local_var_rbp_offset)
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
@ -727,10 +742,7 @@ function parse_statement
*8out = l_type *8out = l_type
out += 24 out += 24
; advance curr_function_stack_space = local_var_rbp_offset
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
@ -2181,6 +2193,7 @@ function parse_base_type
ident_list_add(structures, struct_name, struct) ident_list_add(structures, struct_name, struct)
:struct_definition_fill_in :struct_definition_fill_in
*1out = TYPE_STRUCT *1out = TYPE_STRUCT
out += 1 out += 1
*8out = struct *8out = struct
@ -3031,10 +3044,15 @@ function parse_expression
p += 8 p += 8
c = ident_list_lookup(a, *8p) c = ident_list_lookup(a, *8p)
if c == 0 goto member_not_in_struct if c == 0 goto member_not_in_struct
*8out = c & 0xffffffff ; offset
*4type = c > 32 ; type *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 p += 8
if p != tokens_end goto bad_expression ; e.g. foo->bar hello if p != tokens_end goto bad_expression ; e.g. foo->bar hello
return out return out
:use_of_incomplete_struct :use_of_incomplete_struct
@ -4286,7 +4304,7 @@ function print_expression
expression += 8 expression += 8
expression = print_expression(expression) expression = print_expression(expression)
puts(.str_dot) puts(.str_dot)
putn(*8expression) putn(*4expression)
expression += 8 expression += 8
putc(41) putc(41)
return expression return expression
@ -4295,7 +4313,7 @@ function print_expression
expression += 8 expression += 8
expression = print_expression(expression) expression = print_expression(expression)
puts(.str_arrow) puts(.str_arrow)
putn(*8expression) putn(*4expression)
expression += 8 expression += 8
putc(41) putc(41)
return expression return expression
@ -4451,12 +4469,17 @@ function print_type
putc('[) putc('[)
type += 1 type += 1
c = types + type c = types + type
putn(*8c) ; UNALIGNED putn(*8c)
putc(']) putc('])
type += 8 type += 8
goto print_type_top goto print_type_top
:print_type_struct :print_type_struct
return puts(.str_struct) puts(.str_struct)
c = types + type
c += 1
putc('@)
putx64(*8c)
return
:print_type_function :print_type_function
type += 1 type += 1
putc(40) putc(40)