start local declarations
This commit is contained in:
parent
d718819ee7
commit
ebe96b9e85
4 changed files with 187 additions and 8 deletions
|
@ -260,7 +260,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 (automatic/"register" storage duration), data1 = total bytes used by all local variables so far in this function including this one; data2,3,4 unused
|
; - STATEMENT_LOCAL_DECLARATION - declaring a local variable, data1 = rbp offset, data2 = size of 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
|
||||||
|
|
16
05/main.b
16
05/main.b
|
@ -58,14 +58,19 @@ global function_statements
|
||||||
; these have to be separated for reasons™
|
; these have to be separated for reasons™
|
||||||
global statement_datas
|
global statement_datas
|
||||||
global statement_datas_ends
|
global statement_datas_ends
|
||||||
; ident lists of addresses
|
; ident lists of (type << 32) | address
|
||||||
; block_static_variables[0] = static variables inside this function
|
; block_static_variables[0] = static variables inside this function
|
||||||
; block_static_variables[1] = static variables inside this block inside this function
|
; block_static_variables[1] = static variables inside this block inside this function
|
||||||
; etc.
|
; etc.
|
||||||
global block_static_variables
|
global block_static_variables
|
||||||
|
; ident lists of (type << 32) | rbp offset; one per block depth
|
||||||
|
global local_variables
|
||||||
global block_depth
|
global block_depth
|
||||||
global expressions
|
global expressions
|
||||||
global expressions_end
|
global expressions_end
|
||||||
|
; where to put the next local variable
|
||||||
|
global local_var_next_rbp_offset
|
||||||
|
|
||||||
|
|
||||||
#include util.b
|
#include util.b
|
||||||
#include idents.b
|
#include idents.b
|
||||||
|
@ -187,6 +192,8 @@ function main
|
||||||
statement_datas = memory
|
statement_datas = memory
|
||||||
statement_datas_ends = memory + 400
|
statement_datas_ends = memory + 400
|
||||||
block_static_variables = memory + 800
|
block_static_variables = memory + 800
|
||||||
|
local_variables = memory + 1200
|
||||||
|
|
||||||
p = statement_datas
|
p = statement_datas
|
||||||
q = statement_datas_ends
|
q = statement_datas_ends
|
||||||
i = 0
|
i = 0
|
||||||
|
@ -204,6 +211,13 @@ function main
|
||||||
p += 8
|
p += 8
|
||||||
i += 1
|
i += 1
|
||||||
if i < BLOCK_DEPTH_LIMIT goto bsv_alloc_loop
|
if i < BLOCK_DEPTH_LIMIT goto bsv_alloc_loop
|
||||||
|
p = local_variables
|
||||||
|
i = 0
|
||||||
|
:lv_alloc_loop
|
||||||
|
*8p = malloc(100000)
|
||||||
|
p += 8
|
||||||
|
i += 1
|
||||||
|
if i < BLOCK_DEPTH_LIMIT goto lv_alloc_loop
|
||||||
fill_in_powers_of_10()
|
fill_in_powers_of_10()
|
||||||
|
|
||||||
typedefs = ident_list_create(100000)
|
typedefs = ident_list_create(100000)
|
||||||
|
|
|
@ -12,12 +12,9 @@ int f(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int h(void) {
|
int h(void) {
|
||||||
static long x = 0x12345;
|
int y, r[3], s;
|
||||||
return x;
|
char d, e[5], f, g, *p;
|
||||||
{
|
int z = 3, R=12+459834-g;
|
||||||
static unsigned short x = 0x123f;
|
|
||||||
return x;
|
|
||||||
}{{{{{{{{{{{{{{static unsigned x = 0x1234567; return x;}}}}}}}}return x;}}}}}return x;}
|
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
168
05/parse.b
168
05/parse.b
|
@ -195,6 +195,8 @@ function parse_toplevel_declaration
|
||||||
global function_stmt_data ; initialized in main
|
global function_stmt_data ; initialized in main
|
||||||
global function_stmt_data_bytes_used
|
global function_stmt_data_bytes_used
|
||||||
|
|
||||||
|
local_var_next_rbp_offset = 0
|
||||||
|
|
||||||
p = function_stmt_data + function_stmt_data_bytes_used
|
p = function_stmt_data + function_stmt_data_bytes_used
|
||||||
out = p
|
out = p
|
||||||
parse_statement(&token, &out)
|
parse_statement(&token, &out)
|
||||||
|
@ -314,6 +316,7 @@ function parse_statement
|
||||||
local p
|
local p
|
||||||
local c
|
local c
|
||||||
local n
|
local n
|
||||||
|
local b
|
||||||
|
|
||||||
out = *8p_out
|
out = *8p_out
|
||||||
token = *8p_token
|
token = *8p_token
|
||||||
|
@ -344,6 +347,10 @@ function parse_statement
|
||||||
if c == KEYWORD_GOTO goto stmt_goto
|
if c == KEYWORD_GOTO goto stmt_goto
|
||||||
if c == KEYWORD_CASE goto stmt_case
|
if c == KEYWORD_CASE goto stmt_case
|
||||||
if c == KEYWORD_STATIC goto stmt_static_declaration
|
if c == KEYWORD_STATIC goto stmt_static_declaration
|
||||||
|
if c == KEYWORD_EXTERN goto stmt_extern_declaration
|
||||||
|
|
||||||
|
b = token_is_type(token)
|
||||||
|
if b != 0 goto stmt_local_declaration
|
||||||
|
|
||||||
token_error(token, .str_unrecognized_statement)
|
token_error(token, .str_unrecognized_statement)
|
||||||
:str_unrecognized_statement
|
:str_unrecognized_statement
|
||||||
|
@ -353,6 +360,89 @@ function parse_statement
|
||||||
*8p_token = token
|
*8p_token = token
|
||||||
*8p_out = out
|
*8p_out = out
|
||||||
return
|
return
|
||||||
|
:stmt_extern_declaration
|
||||||
|
token_error(token, .str_stmt_extern_declaration)
|
||||||
|
:str_stmt_extern_declaration
|
||||||
|
; @NONSTANDARD
|
||||||
|
string Local extern declarations are not supported.
|
||||||
|
byte 0
|
||||||
|
:stmt_local_declaration
|
||||||
|
local l_base_type
|
||||||
|
local l_prefix
|
||||||
|
local l_prefix_end
|
||||||
|
local l_suffix
|
||||||
|
local l_suffix_end
|
||||||
|
local l_type
|
||||||
|
local l_offset
|
||||||
|
local l_name
|
||||||
|
|
||||||
|
l_base_type = token
|
||||||
|
token = type_get_base_end(l_base_type)
|
||||||
|
:local_decl_loop
|
||||||
|
l_prefix = token
|
||||||
|
l_prefix_end = type_get_prefix_end(l_prefix)
|
||||||
|
if *1l_prefix_end != TOKEN_IDENTIFIER goto local_decl_no_ident
|
||||||
|
l_name = l_prefix_end + 8
|
||||||
|
l_name = *8l_name
|
||||||
|
l_suffix = l_prefix_end + 16
|
||||||
|
l_suffix_end = type_get_suffix_end(l_prefix)
|
||||||
|
l_type = types_bytes_used
|
||||||
|
parse_type_declarators(l_prefix, l_prefix_end, l_suffix, l_suffix_end)
|
||||||
|
parse_base_type(l_base_type)
|
||||||
|
write_statement_header(out, STATEMENT_LOCAL_DECLARATION, token)
|
||||||
|
out += 8
|
||||||
|
*8out = local_var_next_rbp_offset
|
||||||
|
out += 8
|
||||||
|
*8out = type_sizeof(l_type)
|
||||||
|
out += 24
|
||||||
|
p = local_variables
|
||||||
|
p += block_depth < 3
|
||||||
|
l_offset = local_var_next_rbp_offset
|
||||||
|
c = l_offset
|
||||||
|
c |= l_type < 32
|
||||||
|
ident_list_add(*8p, l_name, c)
|
||||||
|
|
||||||
|
; advance
|
||||||
|
local_var_next_rbp_offset += type_sizeof(l_type)
|
||||||
|
; align
|
||||||
|
local_var_next_rbp_offset += 7
|
||||||
|
local_var_next_rbp_offset >= 3
|
||||||
|
local_var_next_rbp_offset <= 3
|
||||||
|
|
||||||
|
token = l_suffix_end
|
||||||
|
:local_decl_continue
|
||||||
|
if *1token == SYMBOL_SEMICOLON goto local_decl_loop_end
|
||||||
|
if *1token == SYMBOL_EQ goto local_decl_initializer
|
||||||
|
if *1token != SYMBOL_COMMA goto local_decl_badsuffix
|
||||||
|
|
||||||
|
token += 16 ; skip comma
|
||||||
|
goto local_decl_loop
|
||||||
|
|
||||||
|
:local_decl_initializer
|
||||||
|
token += 16
|
||||||
|
if *1token == SYMBOL_LBRACE goto local_init_lbrace
|
||||||
|
n = token_next_semicolon_or_comma_not_in_brackets(token)
|
||||||
|
out -= 16
|
||||||
|
*8out = expressions_end
|
||||||
|
out += 16
|
||||||
|
expressions_end = parse_expression(token, n, expressions_end)
|
||||||
|
token = n
|
||||||
|
goto local_decl_continue
|
||||||
|
:local_init_lbrace
|
||||||
|
byte 0xcc ; @TODO
|
||||||
|
:local_decl_badsuffix
|
||||||
|
token_error(token, .str_local_decl_badsuffix)
|
||||||
|
:str_local_decl_badsuffix
|
||||||
|
string Expected equals, comma, or semicolon after variable declaration.
|
||||||
|
byte 0
|
||||||
|
:local_decl_loop_end
|
||||||
|
token += 16 ; skip semicolon
|
||||||
|
goto parse_statement_ret
|
||||||
|
:local_decl_no_ident
|
||||||
|
token_error(token, .str_local_decl_no_ident)
|
||||||
|
:str_local_decl_no_ident
|
||||||
|
string No identifier in declaration.
|
||||||
|
byte 0
|
||||||
:stmt_static_declaration
|
:stmt_static_declaration
|
||||||
p = block_static_variables
|
p = block_static_variables
|
||||||
p += block_depth < 3
|
p += block_depth < 3
|
||||||
|
@ -476,6 +566,9 @@ function parse_statement
|
||||||
p = block_static_variables
|
p = block_static_variables
|
||||||
p += block_depth < 3
|
p += block_depth < 3
|
||||||
ident_list_clear(*8p)
|
ident_list_clear(*8p)
|
||||||
|
p = local_variables
|
||||||
|
p += block_depth < 3
|
||||||
|
ident_list_clear(*8p)
|
||||||
|
|
||||||
block_depth -= 1
|
block_depth -= 1
|
||||||
|
|
||||||
|
@ -538,6 +631,7 @@ function print_statement_with_depth
|
||||||
if c == STATEMENT_GOTO goto print_stmt_goto
|
if c == STATEMENT_GOTO goto print_stmt_goto
|
||||||
if c == STATEMENT_LABEL goto print_stmt_label
|
if c == STATEMENT_LABEL goto print_stmt_label
|
||||||
if c == STATEMENT_CASE goto print_stmt_case
|
if c == STATEMENT_CASE goto print_stmt_case
|
||||||
|
if c == STATEMENT_LOCAL_DECLARATION goto print_stmt_local_decl
|
||||||
|
|
||||||
die(.pristmtNI)
|
die(.pristmtNI)
|
||||||
:pristmtNI
|
:pristmtNI
|
||||||
|
@ -575,6 +669,37 @@ function print_statement_with_depth
|
||||||
:print_ret_noexpr
|
:print_ret_noexpr
|
||||||
puts(.str_semicolon_newline)
|
puts(.str_semicolon_newline)
|
||||||
return
|
return
|
||||||
|
:print_stmt_local_decl
|
||||||
|
puts(.str_local_decl)
|
||||||
|
putn(dat1)
|
||||||
|
puts(.str_local_size)
|
||||||
|
putn(dat2)
|
||||||
|
if dat3 != 0 goto print_stmt_local_initializer
|
||||||
|
if dat4 != 0 goto print_stmt_local_copy_address
|
||||||
|
:stmt_local_decl_finish
|
||||||
|
puts(.str_semicolon_newline)
|
||||||
|
return
|
||||||
|
:print_stmt_local_initializer
|
||||||
|
putc(32)
|
||||||
|
putc(61) ; =
|
||||||
|
putc(32)
|
||||||
|
print_expression(dat3)
|
||||||
|
goto stmt_local_decl_finish
|
||||||
|
:print_stmt_local_copy_address
|
||||||
|
puts(.str_local_copyfrom)
|
||||||
|
putx32(dat4)
|
||||||
|
goto stmt_local_decl_finish
|
||||||
|
:str_local_decl
|
||||||
|
string local variable at rbp-
|
||||||
|
byte 0
|
||||||
|
:str_local_size
|
||||||
|
string size
|
||||||
|
byte 32
|
||||||
|
byte 0
|
||||||
|
:str_local_copyfrom
|
||||||
|
string copy from
|
||||||
|
byte 32
|
||||||
|
byte 0
|
||||||
:print_stmt_block
|
:print_stmt_block
|
||||||
putcln('{)
|
putcln('{)
|
||||||
depth += 1
|
depth += 1
|
||||||
|
@ -1023,6 +1148,49 @@ function token_next_semicolon_not_in_brackets
|
||||||
:str_next_semicolon_eof
|
:str_next_semicolon_eof
|
||||||
string End of file found while searching for semicolon.
|
string End of file found while searching for semicolon.
|
||||||
byte 0
|
byte 0
|
||||||
|
|
||||||
|
|
||||||
|
; return the next semicolon or comma not in parentheses, square brackets, or braces.
|
||||||
|
function token_next_semicolon_or_comma_not_in_brackets
|
||||||
|
argument token0
|
||||||
|
|
||||||
|
local token
|
||||||
|
local depth
|
||||||
|
local c
|
||||||
|
|
||||||
|
depth = 0
|
||||||
|
token = token0
|
||||||
|
:next_semicomma_loop
|
||||||
|
c = *1token
|
||||||
|
if c == TOKEN_EOF goto next_semicomma_eof
|
||||||
|
if depth != 0 goto next_semicomma_nocheck
|
||||||
|
if c == SYMBOL_SEMICOLON goto next_semicomma_loop_end
|
||||||
|
if c == SYMBOL_COMMA goto next_semicomma_loop_end
|
||||||
|
:next_semicomma_nocheck
|
||||||
|
token += 16
|
||||||
|
if c == SYMBOL_LPAREN goto next_semicomma_incdepth
|
||||||
|
if c == SYMBOL_RPAREN goto next_semicomma_decdepth
|
||||||
|
if c == SYMBOL_LSQUARE goto next_semicomma_incdepth
|
||||||
|
if c == SYMBOL_RSQUARE goto next_semicomma_decdepth
|
||||||
|
if c == SYMBOL_LBRACE goto next_semicomma_incdepth
|
||||||
|
if c == SYMBOL_RBRACE goto next_semicomma_decdepth
|
||||||
|
goto next_semicomma_loop
|
||||||
|
:next_semicomma_incdepth
|
||||||
|
depth += 1
|
||||||
|
goto next_semicomma_loop
|
||||||
|
:next_semicomma_decdepth
|
||||||
|
depth -= 1
|
||||||
|
goto next_semicomma_loop
|
||||||
|
:next_semicomma_loop_end
|
||||||
|
return token
|
||||||
|
:next_semicomma_eof
|
||||||
|
token_error(token0, .str_next_semicomma_eof)
|
||||||
|
:str_next_semicomma_eof
|
||||||
|
string End of file found while searching for semicolon or comma.
|
||||||
|
byte 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; we split types into base (B), prefix (P) and suffix (S)
|
; we split types into base (B), prefix (P) and suffix (S)
|
||||||
; struct Thing (*things[5])(void), *something_else[3];
|
; struct Thing (*things[5])(void), *something_else[3];
|
||||||
; BBBBBBBBBBBB PP SSSSSSSSSS P SSS
|
; BBBBBBBBBBBB PP SSSSSSSSSS P SSS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue