sizeof working?

This commit is contained in:
pommicket 2022-01-24 13:22:16 -05:00
parent 6af5b34295
commit 46635e5748
4 changed files with 142 additions and 40 deletions

View file

@ -17,6 +17,48 @@ global function_macros_size
global object_macros
global function_macros
; powers of 10, stored in the following format:
; ulong significand
; ulong exponent
; where for i = -1023..1023, powers_of_10 + 16*i points to an entry where
; 10^i = significand * 2^exponent
global powers_of_10
global types
global types_bytes_used
; ident list of type IDs
global typedefs
#include util.b
#include idents.b
#include constants.b
#include preprocess.b
#include tokenize.b
#include parse.b
function types_init
argument _types
argument ptypes_bytes_used
local i
local p
i = 0
p = _types
:fill_initial_types_loop
*1p = i
p += 1
i += 1
if i <= 16 goto fill_initial_types_loop
p = _types + TYPE_POINTER_TO_CHAR
*1p = TYPE_POINTER
p += 1
*1p = TYPE_CHAR
p += 1
*8ptypes_bytes_used = p - types
return
function fprint_token_location
argument fd
argument token
@ -86,24 +128,6 @@ function compile_warning
byte 32
byte 0
; powers of 10, stored in the following format:
; ulong significand
; ulong exponent
; where for i = -1023..1023, powers_of_10 + 16*i points to an entry where
; 10^i = significand * 2^exponent
global powers_of_10
global types
global types_bytes_used
; ident list of type IDs
global typedefs
#include util.b
#include idents.b
#include constants.b
#include preprocess.b
#include tokenize.b
#include parse.b
function main
argument argv2
@ -131,21 +155,7 @@ function main
function_macros = malloc(4000000)
types = malloc(16000000)
i = 0
p = types
:fill_initial_types_loop
*1p = i
p += 1
i += 1
if i <= 16 goto fill_initial_types_loop
p = types + TYPE_POINTER_TO_CHAR
*1p = TYPE_POINTER
p += 1
*1p = TYPE_CHAR
p += 1
types_bytes_used = p - types
types_init(types, &types_bytes_used)
input_filename = .str_default_input_filename
output_filename = .str_default_output_filename

View file

@ -3,5 +3,5 @@
long double d;
} (*x)(void);
*/
typedef long int unsigned Foo[0?5?0:32:0?7:8];
typedef long int unsigned Foo[sizeof"hello"+sizeof(double[sizeof(int) * sizeof 3])];
/* */

View file

@ -1,3 +1,29 @@
; is this token the start of a type?
function token_is_type
argument token
local c
c = *1token
if c == TOKEN_IDENTIFIER goto token_is_ident_type
if c == KEYWORD_UNSIGNED goto return_1
if c == KEYWORD_CHAR goto return_1
if c == KEYWORD_SHORT goto return_1
if c == KEYWORD_INT goto return_1
if c == KEYWORD_LONG goto return_1
if c == KEYWORD_FLOAT goto return_1
if c == KEYWORD_DOUBLE goto return_1
if c == KEYWORD_VOID goto return_1
if c == KEYWORD_STRUCT goto return_1
if c == KEYWORD_UNION goto return_1
if c == KEYWORD_ENUM goto return_1
goto return_0
:token_is_ident_type
token += 8
c = *8token
local b
b = ident_list_lookup(typedefs, c)
if b != 0 goto return_1
goto return_0
function parse_tokens
argument tokens
local token
@ -268,8 +294,6 @@ function parse_type_to
byte 0
:parse_function_type
p = suffix + 16
local RRR
RRR = out
*1out = TYPE_FUNCTION
out += 1
:function_type_loop
@ -743,7 +767,7 @@ function parse_expression
:parse_expr_unary
if c == KEYWORD_SIZEOF goto parse_expr_sizeof
if c == KEYWORD_SIZEOF goto parse_sizeof
*1out = unary_op_to_expression_type(c)
c = *1out
out += 8
@ -798,8 +822,44 @@ function parse_expression
byte 32
byte 0
:parse_expr_sizeof
byte 0xcc ; @TODO
:parse_sizeof
; little hack to avoid screwing up types like double[sizeof(int)]
; temporarily switch out types array to parse the sizeof's type
local prev_types
local prev_types_bytes_used
prev_types = types
prev_types_bytes_used = types_bytes_used
types = malloc(4000)
types_init(types, &types_bytes_used)
*1out = EXPRESSION_CONSTANT_INT
out += 4
*1out = TYPE_UNSIGNED_LONG
out += 4
p = best + 16
if *1p != SYMBOL_LPAREN goto parse_sizeof_expr
p += 16
b = token_is_type(p)
if b == 0 goto parse_sizeof_expr
; it's a type, e.g. sizeof(int)
a = parse_type(&p, &c)
if c != 0 goto bad_expression ; e.g. sizeof(int x)
*8out = type_sizeof(a)
goto parse_sizeof_finish
:parse_sizeof_expr
; it's an expression, e.g. sizeof(x+3)
local temp
temp = malloc(4000)
p = best + 16
parse_expression(p, tokens_end, temp)
p = temp + 4
*8out = type_sizeof(*4p)
free(temp)
:parse_sizeof_finish
free(types)
types = prev_types
types_bytes_used = prev_types_bytes_used
out += 8
return out
:parse_expr_member ; -> or .
p = best + 16
@ -978,6 +1038,37 @@ function parse_expression
:return_type_double
return TYPE_DOUBLE
function type_sizeof
argument type
local p
local c
p = types + type
c = *1p
if c == TYPE_CHAR goto return_1
if c == TYPE_UNSIGNED_CHAR goto return_1
if c == TYPE_SHORT goto return_2
if c == TYPE_UNSIGNED_SHORT goto return_2
if c == TYPE_INT goto return_4
if c == TYPE_UNSIGNED_INT goto return_4
if c == TYPE_LONG goto return_8
if c == TYPE_UNSIGNED_LONG goto return_8
if c == TYPE_FLOAT goto return_4
if c == TYPE_DOUBLE goto return_8
if c == TYPE_VOID goto return_1
if c == TYPE_POINTER goto return_8
if c == TYPE_FUNCTION goto return_8
if c == TYPE_ARRAY goto sizeof_array
byte 0xcc ; @TODO
:sizeof_array
local n
p += 1
n = *8p
p += 8
p -= types
c = type_sizeof(p)
return n * c
; evaluate an expression which can be the size of an array, e.g.
; enum { A, B, C };
; int x[A * sizeof(float) + 3 << 5];

View file

@ -843,6 +843,7 @@ function translation_phase_4
macro_replacement_to_terminator(filename, line_number, &in, &p, 10)
;@TODO: there's no point in doing this until we have parsing
; we'll have to evaluate constant expressions anyways for array declarations
free(if_pptokens)
fputs(2, .str_if_not_implemented)
byte 0xcc
:str_if_not_implemented