diff options
-rw-r--r-- | 05/main.c | 11 | ||||
-rw-r--r-- | 05/parse.b | 84 |
2 files changed, 84 insertions, 11 deletions
@@ -16,4 +16,13 @@ typedef struct A { long f; } A; -typedef int x[(unsigned)-3]; +typedef union B{ + int x; + struct { + int y; + struct {long z; } c; + } c; +}B; + +typedef int x[sizeof(A)]; +typedef int y[sizeof(struct B)]; @@ -30,6 +30,7 @@ function parse_tokens local ident local type local p + local b local base_type local base_type_end local prefix @@ -80,6 +81,9 @@ function parse_tokens print_type(type) putc(10) + b = ident_list_lookup(typedefs, ident) + if b != 0 goto typedef_redefinition + ident_list_add(typedefs, ident, type) token = suffix_end if *1token == SYMBOL_SEMICOLON goto typedef_loop_end @@ -90,15 +94,20 @@ function parse_tokens token += 16 ; skip semicolon goto parse_tokens_loop :typedef_no_ident - token_error(tokens, .str_typedef_no_ident) + token_error(token, .str_typedef_no_ident) :str_typedef_no_ident string No identifier in typedef declaration. byte 0 :bad_typedef - token_error(tokens, .str_bad_typedef) + token_error(token, .str_bad_typedef) :str_bad_typedef string Bad typedef. byte 0 + :typedef_redefinition + token_error(token, .str_typedef_redefinition) + :str_typedef_redefinition + string typedef redefinition. + byte 0 :parse_tokens_eof return @@ -618,7 +627,9 @@ function parse_base_type local offset offset = 0 + if *1struct_name == 0 goto struct_unnamed ident_list_add(structures, struct_name, struct) + :struct_unnamed :struct_defn_loop if *1p == SYMBOL_RBRACE goto struct_defn_loop_end @@ -825,7 +836,7 @@ function type_length n = type_length(type) return n + 9 :type_length_not_array - if *1p == TYPE_STRUCT goto return_5 + if *1p == TYPE_STRUCT goto return_9 if *1p != TYPE_FUNCTION goto type_length_not_function local start start = type @@ -1487,10 +1498,13 @@ function type_sizeof if c == TYPE_POINTER goto return_8 if c == TYPE_FUNCTION goto return_8 if c == TYPE_ARRAY goto sizeof_array - fputs(2, .str_sizeof_ni) ; @TODO + if c == TYPE_STRUCT goto sizeof_struct + + fputs(2, .str_sizeof_bad) ; @TODO exit(1) - :str_sizeof_ni - string type_sizeof for this type not implemented. + :str_sizeof_bad + string type_sizeof bad type. + byte 10 byte 0 :sizeof_array @@ -1502,6 +1516,33 @@ function type_sizeof c = type_sizeof(p) return n * c + :sizeof_struct + ; size of struct is offset of last member + size of last member, + ; rounded up to fit alignment + local align + local offset + local member + align = type_alignof(type) + p += 1 + member = *8p + :sizeof_struct_loop + if *1member == 0 goto sizeof_struct_loop_end + member = memchr(member, 0) ; don't care about name + member += 1 ; skip null terminator + c = *8member + member += 8 + offset = c & 0xffffffff + c >= 32 ; extract type + offset += type_sizeof(c) + goto sizeof_struct_loop + :sizeof_struct_loop_end + + offset += align - 1 + offset /= align + offset *= align + + return offset + function type_alignof argument type local p @@ -1522,12 +1563,35 @@ function type_alignof if c == TYPE_POINTER goto return_8 if c == TYPE_FUNCTION goto return_8 if c == TYPE_ARRAY goto alignof_array - fputs(2, .str_alignof_ni) ; @TODO + if c == TYPE_STRUCT goto alignof_struct + + fputs(2, .str_alignof_bad) exit(1) - :str_alignof_ni - string type_alignof for this type not implemented. + :str_alignof_bad + string type_alignof bad type. + byte 10 byte 0 - + :alignof_struct + ; alignment of struct is max alignment of members + local align + local member + local a + align = 1 + p += 1 + member = *8p + :alignof_struct_loop + if *1member == 0 goto alignof_struct_loop_end + member = memchr(member, 0) ; don't care about name + member += 1 ; skip null terminator + c = *8member + member += 8 + c >= 32 ; ignore offset + a = type_alignof(c) + if a <= align goto alignof_struct_loop + align = a + goto alignof_struct_loop + :alignof_struct_loop_end + return align :alignof_array p = type + 9 ; skip TYPE_ARRAY and size return type_alignof(p) |