start top level decls - also oops forgot about sizeless arrays
This commit is contained in:
parent
01b8a4d728
commit
217794afce
5 changed files with 173 additions and 25 deletions
|
@ -6,6 +6,7 @@
|
||||||
; note that file offsets and runtime addresses are the same.
|
; note that file offsets and runtime addresses are the same.
|
||||||
; you should be able to change these constants without breaking anything:
|
; you should be able to change these constants without breaking anything:
|
||||||
#define RODATA_ADDR 0x800000
|
#define RODATA_ADDR 0x800000
|
||||||
|
#define RWDATA_ADDR 0xc00000
|
||||||
#define RWDATA_END 0x1000000
|
#define RWDATA_END 0x1000000
|
||||||
#define EXECUTABLE_SIZE 0x1000000
|
#define EXECUTABLE_SIZE 0x1000000
|
||||||
|
|
||||||
|
|
33
05/idents.b
33
05/idents.b
|
@ -111,8 +111,39 @@ function ident_list_print
|
||||||
putc(32)
|
putc(32)
|
||||||
list = memchr(list, 0)
|
list = memchr(list, 0)
|
||||||
list += 1
|
list += 1
|
||||||
putn(*8list)
|
putnln(*8list)
|
||||||
list += 8
|
list += 8
|
||||||
goto ilist_print_loop
|
goto ilist_print_loop
|
||||||
:ilist_print_loop_end
|
:ilist_print_loop_end
|
||||||
return
|
return
|
||||||
|
|
||||||
|
function ident_list_printx64
|
||||||
|
argument list
|
||||||
|
:ilist_printx64_loop
|
||||||
|
if *1list == 0 goto ilist_printx64_loop_end
|
||||||
|
puts(list)
|
||||||
|
putc(':)
|
||||||
|
putc(32)
|
||||||
|
list = memchr(list, 0)
|
||||||
|
list += 1
|
||||||
|
putx64ln(*8list)
|
||||||
|
list += 8
|
||||||
|
goto ilist_printx64_loop
|
||||||
|
:ilist_printx64_loop_end
|
||||||
|
return
|
||||||
|
|
||||||
|
function ident_list_printx32
|
||||||
|
argument list
|
||||||
|
:ilist_printx32_loop
|
||||||
|
if *1list == 0 goto ilist_printx32_loop_end
|
||||||
|
puts(list)
|
||||||
|
putc(':)
|
||||||
|
putc(32)
|
||||||
|
list = memchr(list, 0)
|
||||||
|
list += 1
|
||||||
|
putx32ln(*8list)
|
||||||
|
list += 8
|
||||||
|
goto ilist_printx32_loop
|
||||||
|
:ilist_printx32_loop_end
|
||||||
|
return
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,11 @@ global structures
|
||||||
global structures_bytes_used
|
global structures_bytes_used
|
||||||
; file offset/runtime address to write next piece of read-only data; initialized in main
|
; file offset/runtime address to write next piece of read-only data; initialized in main
|
||||||
global rodata_end_addr
|
global rodata_end_addr
|
||||||
|
; file offset/runtime address to write next piece of read-write data; initialized in main
|
||||||
|
global rwdata_end_addr
|
||||||
global output_file_data
|
global output_file_data
|
||||||
|
; ident list of addresses of global variables.
|
||||||
|
global global_variables
|
||||||
|
|
||||||
#include util.b
|
#include util.b
|
||||||
#include idents.b
|
#include idents.b
|
||||||
|
@ -157,6 +161,7 @@ function main
|
||||||
typedefs = ident_list_create(100000)
|
typedefs = ident_list_create(100000)
|
||||||
enumerators = ident_list_create(4000000)
|
enumerators = ident_list_create(4000000)
|
||||||
structures = ident_list_create(4000000)
|
structures = ident_list_create(4000000)
|
||||||
|
global_variables = ident_list_create(4000000)
|
||||||
|
|
||||||
dat_banned_objmacros = 255
|
dat_banned_objmacros = 255
|
||||||
dat_banned_fmacros = 255
|
dat_banned_fmacros = 255
|
||||||
|
@ -178,6 +183,7 @@ function main
|
||||||
:have_filenames
|
:have_filenames
|
||||||
output_fd = open_rw(output_filename, 493)
|
output_fd = open_rw(output_filename, 493)
|
||||||
rodata_end_addr = RODATA_ADDR
|
rodata_end_addr = RODATA_ADDR
|
||||||
|
rwdata_end_addr = RWDATA_ADDR
|
||||||
|
|
||||||
ftruncate(output_fd, RWDATA_END)
|
ftruncate(output_fd, RWDATA_END)
|
||||||
output_file_data = mmap(0, RWDATA_END, PROT_READ_WRITE, MAP_SHARED, output_fd, 0)
|
output_file_data = mmap(0, RWDATA_END, PROT_READ_WRITE, MAP_SHARED, output_fd, 0)
|
||||||
|
@ -206,6 +212,8 @@ function main
|
||||||
munmap(output_file_data, RWDATA_END)
|
munmap(output_file_data, RWDATA_END)
|
||||||
close(output_fd)
|
close(output_fd)
|
||||||
|
|
||||||
|
ident_list_printx32(global_variables)
|
||||||
|
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
:mmap_output_fd_failed
|
:mmap_output_fd_failed
|
||||||
|
|
45
05/main.c
45
05/main.c
|
@ -7,22 +7,33 @@
|
||||||
/* R,S,T */
|
/* R,S,T */
|
||||||
/* } *Foo[sizeof(unsigned long)]; */
|
/* } *Foo[sizeof(unsigned long)]; */
|
||||||
/* typedef int A[T]; */
|
/* typedef int A[T]; */
|
||||||
|
/* */
|
||||||
|
/* typedef struct A { */
|
||||||
|
/* int x, y; */
|
||||||
|
/* long double c; */
|
||||||
|
/* unsigned long d; */
|
||||||
|
/* char e[3]; */
|
||||||
|
/* long f; */
|
||||||
|
/* } A; */
|
||||||
|
/* */
|
||||||
|
/* typedef union B{ */
|
||||||
|
/* int x; */
|
||||||
|
/* struct { */
|
||||||
|
/* int y; */
|
||||||
|
/* struct {long z; } c; */
|
||||||
|
/* } c; */
|
||||||
|
/* }B; */
|
||||||
|
/* */
|
||||||
|
/* typedef int x[sizeof(A)+sizeof"hello"]; */
|
||||||
|
/* typedef int y[sizeof(struct B)]; */
|
||||||
|
|
||||||
typedef struct A {
|
static unsigned int x;
|
||||||
int x, y;
|
static unsigned int y;
|
||||||
long double c;
|
static unsigned int z[1000];
|
||||||
unsigned long d;
|
static unsigned int w;
|
||||||
char e[3];
|
|
||||||
long f;
|
|
||||||
} A;
|
|
||||||
|
|
||||||
typedef union B{
|
/*
|
||||||
int x;
|
NOTE: THIS MUST WORK
|
||||||
struct {
|
int x[] = {1,2,3}
|
||||||
int y;
|
sizeof x
|
||||||
struct {long z; } c;
|
*/
|
||||||
} c;
|
|
||||||
}B;
|
|
||||||
|
|
||||||
typedef int x[sizeof(A)+sizeof"hello"];
|
|
||||||
typedef int y[sizeof(struct B)];
|
|
||||||
|
|
109
05/parse.b
109
05/parse.b
|
@ -33,20 +33,105 @@ function parse_tokens
|
||||||
local b
|
local b
|
||||||
local base_type
|
local base_type
|
||||||
local base_type_end
|
local base_type_end
|
||||||
|
local name
|
||||||
local prefix
|
local prefix
|
||||||
local prefix_end
|
local prefix_end
|
||||||
local suffix
|
local suffix
|
||||||
local suffix_end
|
local suffix_end
|
||||||
|
local is_extern
|
||||||
|
|
||||||
token = tokens
|
token = tokens
|
||||||
:parse_tokens_loop
|
:parse_tokens_loop
|
||||||
|
is_extern = 0
|
||||||
if *1token == TOKEN_EOF goto parse_tokens_eof
|
if *1token == TOKEN_EOF goto parse_tokens_eof
|
||||||
|
if *1token == KEYWORD_STATIC goto parse_static_toplevel_decl
|
||||||
|
if *1token == KEYWORD_EXTERN goto parse_extern_toplevel_decl
|
||||||
if *1token == KEYWORD_TYPEDEF goto parse_typedef
|
if *1token == KEYWORD_TYPEDEF goto parse_typedef
|
||||||
|
|
||||||
die(.str_parse_tokens_ni)
|
b = token_is_type(token)
|
||||||
:str_parse_tokens_ni
|
if b != 0 goto parse_toplevel_decl
|
||||||
string parse_tokens not implemented.
|
|
||||||
|
die(.str_bad_statement)
|
||||||
|
:str_bad_statement
|
||||||
|
string Bad statement.
|
||||||
byte 0
|
byte 0
|
||||||
|
:parse_static_toplevel_decl
|
||||||
|
token += 16 ; we don't care that this is static
|
||||||
|
goto parse_toplevel_decl
|
||||||
|
:parse_extern_toplevel_decl
|
||||||
|
token += 16
|
||||||
|
is_extern = 1
|
||||||
|
goto parse_toplevel_decl
|
||||||
|
:parse_toplevel_decl
|
||||||
|
base_type = token
|
||||||
|
base_type_end = type_get_base_end(token)
|
||||||
|
token = base_type_end
|
||||||
|
:tl_decl_loop
|
||||||
|
prefix = token
|
||||||
|
prefix_end = type_get_prefix_end(prefix)
|
||||||
|
if *1prefix_end != TOKEN_IDENTIFIER goto tl_decl_no_ident
|
||||||
|
name = prefix_end + 8
|
||||||
|
name = *8name
|
||||||
|
suffix = prefix_end + 16
|
||||||
|
suffix_end = type_get_suffix_end(prefix)
|
||||||
|
type = types_bytes_used
|
||||||
|
parse_type_declarators(prefix, prefix_end, suffix, suffix_end)
|
||||||
|
parse_base_type(base_type, base_type_end)
|
||||||
|
token = suffix_end
|
||||||
|
if *1token == SYMBOL_LBRACE goto parse_function_definition
|
||||||
|
if *1token == SYMBOL_SEMICOLON goto parse_tld_no_initializer
|
||||||
|
if *1token == SYMBOL_COMMA goto parse_tld_no_initializer
|
||||||
|
if *1token == SYMBOL_EQ goto parse_tld_initializer
|
||||||
|
token_error(token, .str_unrecognized_stuff_after_declaration)
|
||||||
|
:str_unrecognized_stuff_after_declaration
|
||||||
|
string Declaration should be followed by one of: { , =
|
||||||
|
byte 32
|
||||||
|
byte 59 ; semicolon
|
||||||
|
byte 0
|
||||||
|
:parse_tl_decl_cont
|
||||||
|
if *1token == SYMBOL_SEMICOLON goto tl_decl_loop_done
|
||||||
|
if *1token != SYMBOL_COMMA goto tld_bad_stuff_after_decl
|
||||||
|
goto tl_decl_loop
|
||||||
|
:tl_decl_loop_done
|
||||||
|
token += 16 ; skip semicolon
|
||||||
|
goto parse_tokens_loop
|
||||||
|
|
||||||
|
:tl_decl_no_ident
|
||||||
|
token_error(prefix_end, .str_tl_decl_no_ident)
|
||||||
|
:str_tl_decl_no_ident
|
||||||
|
string No identifier in top-level declaration.
|
||||||
|
byte 0
|
||||||
|
:tld_bad_stuff_after_decl
|
||||||
|
token_error(token, .str_tld_bad_stuff_after_decl)
|
||||||
|
:str_tld_bad_stuff_after_decl
|
||||||
|
string Declarations should be immediately followed by a comma or semicolon.
|
||||||
|
byte 0
|
||||||
|
:parse_tld_no_initializer
|
||||||
|
p = types + type
|
||||||
|
if *1p == TYPE_FUNCTION goto parse_tl_decl_cont ; ignore function declarations -- we do two passes anyways
|
||||||
|
ident_list_add(global_variables, name, rwdata_end_addr)
|
||||||
|
; just skip forward by the size of this variable -- it'll automatically be filled with 0s.
|
||||||
|
rwdata_end_addr += type_sizeof(type)
|
||||||
|
goto parse_tl_decl_cont
|
||||||
|
:parse_tld_initializer
|
||||||
|
die(.str_tldinNI) ; @TODO
|
||||||
|
:str_tldinNI
|
||||||
|
string tld initializer not implemented.
|
||||||
|
byte 10
|
||||||
|
byte 0
|
||||||
|
:parse_function_definition
|
||||||
|
p = types + type
|
||||||
|
if *1p != TYPE_FUNCTION goto lbrace_after_declaration
|
||||||
|
die(.str_fdNI) ; @TODO
|
||||||
|
:str_fdNI
|
||||||
|
string function definitions not implemented.
|
||||||
|
byte 10
|
||||||
|
byte 0
|
||||||
|
:lbrace_after_declaration
|
||||||
|
token_error(token, .str_lbrace_after_declaration)
|
||||||
|
:str_lbrace_after_declaration
|
||||||
|
string Opening { after declaration of non-function.
|
||||||
|
byte 0
|
||||||
:parse_typedef
|
:parse_typedef
|
||||||
base_type = token + 16
|
base_type = token + 16
|
||||||
base_type_end = type_get_base_end(base_type)
|
base_type_end = type_get_base_end(base_type)
|
||||||
|
@ -359,6 +444,11 @@ function parse_type_declarators
|
||||||
*1out = TYPE_ARRAY
|
*1out = TYPE_ARRAY
|
||||||
types_bytes_used += 1
|
types_bytes_used += 1
|
||||||
|
|
||||||
|
p = suffix
|
||||||
|
token_skip_to_matching_rsquare(&p)
|
||||||
|
suffix += 16 ; skip [
|
||||||
|
if *1suffix == SYMBOL_RSQUARE goto array_no_size
|
||||||
|
|
||||||
; little hack to avoid screwing up types like double[sizeof(int)]
|
; little hack to avoid screwing up types like double[sizeof(int)]
|
||||||
; temporarily pretend we're using a lot more of types
|
; temporarily pretend we're using a lot more of types
|
||||||
local prev_types_bytes_used
|
local prev_types_bytes_used
|
||||||
|
@ -366,9 +456,7 @@ function parse_type_declarators
|
||||||
types_bytes_used += 4000
|
types_bytes_used += 4000
|
||||||
|
|
||||||
expr = malloc(4000)
|
expr = malloc(4000)
|
||||||
p = suffix
|
|
||||||
token_skip_to_matching_rsquare(&p)
|
|
||||||
suffix += 16 ; skip [
|
|
||||||
parse_expression(suffix, p, expr)
|
parse_expression(suffix, p, expr)
|
||||||
;print_expression(expr)
|
;print_expression(expr)
|
||||||
;putc(10)
|
;putc(10)
|
||||||
|
@ -389,6 +477,13 @@ function parse_type_declarators
|
||||||
:str_bad_array_size
|
:str_bad_array_size
|
||||||
string Very large or negative array size.
|
string Very large or negative array size.
|
||||||
byte 0
|
byte 0
|
||||||
|
:array_no_size
|
||||||
|
; e.g. int x[] = {1,2,3};
|
||||||
|
out = types + types_bytes_used
|
||||||
|
*8out = 0
|
||||||
|
types_bytes_used += 8
|
||||||
|
suffix += 16
|
||||||
|
goto type_declarators_loop
|
||||||
:parse_function_type
|
:parse_function_type
|
||||||
local param_base_type
|
local param_base_type
|
||||||
local param_prefix
|
local param_prefix
|
||||||
|
@ -605,6 +700,8 @@ function parse_base_type
|
||||||
out += 1
|
out += 1
|
||||||
goto base_type_done
|
goto base_type_done
|
||||||
:base_type_struct_definition
|
:base_type_struct_definition
|
||||||
|
; @NONSTANDARD: we don't handle bit-fields.
|
||||||
|
|
||||||
local member_base_type
|
local member_base_type
|
||||||
local member_prefix
|
local member_prefix
|
||||||
local member_prefix_end
|
local member_prefix_end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue