fixed local variables and also structs containing arrays
This commit is contained in:
parent
24f260fa16
commit
239a1a3c27
5 changed files with 76 additions and 44 deletions
41
05/codegen.b
41
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
|
||||
|
@ -744,6 +745,7 @@ function generate_copy_rsi_to_rdi_qwords
|
|||
emit_movsq()
|
||||
return
|
||||
|
||||
|
||||
; cast whatever was just pushed onto the stack from from_type to to_type
|
||||
; `statement` is used for errors
|
||||
function generate_cast_top_of_stack
|
||||
|
@ -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_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
|
||||
|
|
|
@ -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
|
||||
|
|
14
05/main.b
14
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)
|
||||
|
||||
|
|
10
05/main.c
10
05/main.c
|
@ -28,14 +28,6 @@ int f() {
|
|||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int a = 5;
|
||||
switch(a++){
|
||||
case 5: a++;
|
||||
case 3: a++;
|
||||
case 4: a++;
|
||||
default: a++;
|
||||
}
|
||||
|
||||
return a ;
|
||||
return fibonacci(20);
|
||||
}
|
||||
|
||||
|
|
45
05/parse.b
45
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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue