struct/union definitions
This commit is contained in:
parent
387d650cab
commit
d036dcc5ac
6 changed files with 217 additions and 35 deletions
26
05/idents.b
26
05/idents.b
|
@ -1,15 +1,21 @@
|
||||||
; an "identifier list" is a list of identifiers and 64-bit values associated with them.
|
; an "identifier list" is a list of identifiers and 64-bit values associated with them.
|
||||||
|
; they are stored as
|
||||||
|
; null-terminated string
|
||||||
|
; 64-bit value (unaligned)
|
||||||
|
; ...
|
||||||
|
; null-terminated string
|
||||||
|
; 64-bit value (unaligned)
|
||||||
|
; 0 byte
|
||||||
|
|
||||||
function ident_list_create
|
function ident_list_create
|
||||||
argument nbytes
|
argument nbytes
|
||||||
local list
|
local list
|
||||||
list = malloc(nbytes)
|
list = malloc(nbytes)
|
||||||
*1list = 255
|
|
||||||
return list
|
return list
|
||||||
|
|
||||||
function ident_list_clear
|
function ident_list_clear
|
||||||
argument list
|
argument list
|
||||||
*1list = 255
|
*1list = 0
|
||||||
return
|
return
|
||||||
|
|
||||||
function ident_list_free
|
function ident_list_free
|
||||||
|
@ -22,7 +28,7 @@ function ident_list_len
|
||||||
local len
|
local len
|
||||||
len = 0
|
len = 0
|
||||||
:ilist_len_loop
|
:ilist_len_loop
|
||||||
if *1list == 255 goto ilist_len_ret
|
if *1list == 0 goto ilist_len_ret
|
||||||
list = memchr(list, 0)
|
list = memchr(list, 0)
|
||||||
list += 9 ; skip null byte and value
|
list += 9 ; skip null byte and value
|
||||||
len += 1
|
len += 1
|
||||||
|
@ -34,7 +40,7 @@ function ident_list_value_at_index
|
||||||
argument list
|
argument list
|
||||||
argument idx
|
argument idx
|
||||||
:ilist_vai_loop
|
:ilist_vai_loop
|
||||||
if *1list == 255 goto return_0
|
if *1list == 0 goto return_0
|
||||||
list = memchr(list, 0)
|
list = memchr(list, 0)
|
||||||
list += 1
|
list += 1
|
||||||
if idx <= 0 goto ilist_vai_ret
|
if idx <= 0 goto ilist_vai_ret
|
||||||
|
@ -50,10 +56,8 @@ function ident_list_add
|
||||||
argument ident
|
argument ident
|
||||||
argument value
|
argument value
|
||||||
|
|
||||||
; note: we can't just do list = memchr(list, 255) because values
|
|
||||||
; might have a 255 byte.
|
|
||||||
:ilist_add_go_to_end_loop
|
:ilist_add_go_to_end_loop
|
||||||
if *1list == 255 goto ilist_add_found_end
|
if *1list == 0 goto ilist_add_found_end
|
||||||
list = memchr(list, 0)
|
list = memchr(list, 0)
|
||||||
list += 9 ; skip null byte and value
|
list += 9 ; skip null byte and value
|
||||||
goto ilist_add_go_to_end_loop
|
goto ilist_add_go_to_end_loop
|
||||||
|
@ -62,7 +66,7 @@ function ident_list_add
|
||||||
list += 1
|
list += 1
|
||||||
*8list = value ; UNALIGNED
|
*8list = value ; UNALIGNED
|
||||||
list += 8
|
list += 8
|
||||||
*1list = 255
|
*1list = 0
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -72,7 +76,7 @@ function ident_list_lookup
|
||||||
argument ident
|
argument ident
|
||||||
local b
|
local b
|
||||||
:ilist_lookup_loop
|
:ilist_lookup_loop
|
||||||
if *1list == 255 goto return_0
|
if *1list == 0 goto return_0
|
||||||
b = str_equals(list, ident)
|
b = str_equals(list, ident)
|
||||||
list = memchr(list, 0)
|
list = memchr(list, 0)
|
||||||
list += 9 ; skip null byte and value
|
list += 9 ; skip null byte and value
|
||||||
|
@ -88,7 +92,7 @@ function ident_list_lookup_check
|
||||||
argument pvalue
|
argument pvalue
|
||||||
local b
|
local b
|
||||||
:ilist_lookcheck_loop
|
:ilist_lookcheck_loop
|
||||||
if *1list == 255 goto return_0
|
if *1list == 0 goto return_0
|
||||||
b = str_equals(list, ident)
|
b = str_equals(list, ident)
|
||||||
list = memchr(list, 0)
|
list = memchr(list, 0)
|
||||||
list += 9 ; skip null byte and value
|
list += 9 ; skip null byte and value
|
||||||
|
@ -101,7 +105,7 @@ function ident_list_lookup_check
|
||||||
function ident_list_print
|
function ident_list_print
|
||||||
argument list
|
argument list
|
||||||
:ilist_print_loop
|
:ilist_print_loop
|
||||||
if *1list == 255 goto ilist_print_loop_end
|
if *1list == 0 goto ilist_print_loop_end
|
||||||
puts(list)
|
puts(list)
|
||||||
putc(':)
|
putc(':)
|
||||||
putc(32)
|
putc(32)
|
||||||
|
|
11
05/main.b
11
05/main.b
|
@ -30,11 +30,9 @@ global types_bytes_used
|
||||||
global typedefs
|
global typedefs
|
||||||
; ident list of enum values
|
; ident list of enum values
|
||||||
global enumerators
|
global enumerators
|
||||||
; struct/union names
|
; struct/unions
|
||||||
; an ident list of pointers to struct data (see structures below)
|
; an ident list of pointers to struct data
|
||||||
global struct_names
|
; each struct data is an ident list of 64-bit values, (type << 32) | offset
|
||||||
; structs and unions
|
|
||||||
; each struct/union is an ident list of 64-bit values, (type << 32) | offset
|
|
||||||
; for unions, offset will always be 0.
|
; for unions, offset will always be 0.
|
||||||
global structures
|
global structures
|
||||||
global structures_bytes_used
|
global structures_bytes_used
|
||||||
|
@ -155,7 +153,7 @@ function main
|
||||||
|
|
||||||
typedefs = ident_list_create(100000)
|
typedefs = ident_list_create(100000)
|
||||||
enumerators = ident_list_create(4000000)
|
enumerators = ident_list_create(4000000)
|
||||||
struct_names = ident_list_create(4000000)
|
structures = ident_list_create(4000000)
|
||||||
|
|
||||||
dat_banned_objmacros = 255
|
dat_banned_objmacros = 255
|
||||||
dat_banned_fmacros = 255
|
dat_banned_fmacros = 255
|
||||||
|
@ -164,7 +162,6 @@ function main
|
||||||
*1file_list = 255
|
*1file_list = 255
|
||||||
object_macros = malloc(4000000)
|
object_macros = malloc(4000000)
|
||||||
function_macros = malloc(4000000)
|
function_macros = malloc(4000000)
|
||||||
structures = malloc(40000000)
|
|
||||||
|
|
||||||
types = malloc(16000000)
|
types = malloc(16000000)
|
||||||
types_init(types, &types_bytes_used)
|
types_init(types, &types_bytes_used)
|
||||||
|
|
17
05/main.c
17
05/main.c
|
@ -2,5 +2,18 @@
|
||||||
int i[41];
|
int i[41];
|
||||||
long double d;
|
long double d;
|
||||||
} (*x)(void);
|
} (*x)(void);
|
||||||
*/
|
|
||||||
typedef int *Foo[sizeof(unsigned short int)];
|
/* typedef enum X { */
|
||||||
|
/* R,S,T */
|
||||||
|
/* } *Foo[sizeof(unsigned long)]; */
|
||||||
|
/* typedef int A[T]; */
|
||||||
|
|
||||||
|
typedef struct A {
|
||||||
|
int x, y;
|
||||||
|
long double c;
|
||||||
|
unsigned long d;
|
||||||
|
char e[3];
|
||||||
|
char c[2];
|
||||||
|
char d;
|
||||||
|
long f;
|
||||||
|
} A;
|
||||||
|
|
173
05/parse.b
173
05/parse.b
|
@ -212,9 +212,6 @@ function type_get_base_end
|
||||||
token_skip_to_matching_rbrace(&token)
|
token_skip_to_matching_rbrace(&token)
|
||||||
token += 16
|
token += 16
|
||||||
goto skip_base_type_loop_end
|
goto skip_base_type_loop_end
|
||||||
:str_bad_type
|
|
||||||
string Bad type.
|
|
||||||
byte 0
|
|
||||||
|
|
||||||
|
|
||||||
; return the end of this type prefix
|
; return the end of this type prefix
|
||||||
|
@ -285,7 +282,10 @@ function type_get_suffix_end
|
||||||
|
|
||||||
return token
|
return token
|
||||||
:type_get_suffix_bad_type
|
:type_get_suffix_bad_type
|
||||||
token_error(prefix, .str_bad_type)
|
token_error(prefix, .str_bad_type_suffix)
|
||||||
|
:str_bad_type_suffix
|
||||||
|
string Bad type suffix.
|
||||||
|
byte 0
|
||||||
|
|
||||||
|
|
||||||
; writes to *(types + types_bytes_used), and updates types_bytes_used
|
; writes to *(types + types_bytes_used), and updates types_bytes_used
|
||||||
|
@ -397,7 +397,10 @@ function parse_type_declarators
|
||||||
:type_declarators_loop_end
|
:type_declarators_loop_end
|
||||||
return 0
|
return 0
|
||||||
:parse_typedecls_bad_type
|
:parse_typedecls_bad_type
|
||||||
token_error(prefix, .str_bad_type)
|
token_error(prefix, .str_bad_type_declarators)
|
||||||
|
:str_bad_type_declarators
|
||||||
|
string Bad type declarators.
|
||||||
|
byte 0
|
||||||
|
|
||||||
; writes to *(types + types_bytes_used), and updates types_bytes_used (no return value)
|
; writes to *(types + types_bytes_used), and updates types_bytes_used (no return value)
|
||||||
function parse_base_type
|
function parse_base_type
|
||||||
|
@ -407,7 +410,8 @@ function parse_base_type
|
||||||
local p
|
local p
|
||||||
local c
|
local c
|
||||||
local depth
|
local depth
|
||||||
local expr
|
local is_struct
|
||||||
|
is_struct = 0
|
||||||
|
|
||||||
out = types + types_bytes_used
|
out = types + types_bytes_used
|
||||||
|
|
||||||
|
@ -437,7 +441,6 @@ function parse_base_type
|
||||||
:base_type_normal_loop
|
:base_type_normal_loop
|
||||||
c = *1p
|
c = *1p
|
||||||
p += 16
|
p += 16
|
||||||
; yes, this allows for `int int x;` but whatever
|
|
||||||
if c == KEYWORD_CHAR goto base_type_flag_char
|
if c == KEYWORD_CHAR goto base_type_flag_char
|
||||||
if c == KEYWORD_SHORT goto base_type_flag_short
|
if c == KEYWORD_SHORT goto base_type_flag_short
|
||||||
if c == KEYWORD_INT goto base_type_flag_int
|
if c == KEYWORD_INT goto base_type_flag_int
|
||||||
|
@ -446,23 +449,40 @@ function parse_base_type
|
||||||
if c == KEYWORD_DOUBLE goto base_type_flag_double
|
if c == KEYWORD_DOUBLE goto base_type_flag_double
|
||||||
goto base_type_normal_loop_end
|
goto base_type_normal_loop_end
|
||||||
:base_type_flag_char
|
:base_type_flag_char
|
||||||
|
c = flags & PARSETYPE_FLAG_CHAR
|
||||||
|
if c != 0 goto repeated_base_type
|
||||||
flags |= PARSETYPE_FLAG_CHAR
|
flags |= PARSETYPE_FLAG_CHAR
|
||||||
goto base_type_normal_loop
|
goto base_type_normal_loop
|
||||||
:base_type_flag_short
|
:base_type_flag_short
|
||||||
|
c = flags & PARSETYPE_FLAG_SHORT
|
||||||
|
if c != 0 goto repeated_base_type
|
||||||
flags |= PARSETYPE_FLAG_SHORT
|
flags |= PARSETYPE_FLAG_SHORT
|
||||||
goto base_type_normal_loop
|
goto base_type_normal_loop
|
||||||
:base_type_flag_int
|
:base_type_flag_int
|
||||||
|
c = flags & PARSETYPE_FLAG_INT
|
||||||
|
if c != 0 goto repeated_base_type
|
||||||
flags |= PARSETYPE_FLAG_INT
|
flags |= PARSETYPE_FLAG_INT
|
||||||
goto base_type_normal_loop
|
goto base_type_normal_loop
|
||||||
:base_type_flag_long
|
:base_type_flag_long
|
||||||
|
c = flags & PARSETYPE_FLAG_LONG
|
||||||
|
if c != 0 goto repeated_base_type
|
||||||
flags |= PARSETYPE_FLAG_LONG
|
flags |= PARSETYPE_FLAG_LONG
|
||||||
goto base_type_normal_loop
|
goto base_type_normal_loop
|
||||||
:base_type_flag_unsigned
|
:base_type_flag_unsigned
|
||||||
|
c = flags & PARSETYPE_FLAG_UNSIGNED
|
||||||
|
if c != 0 goto repeated_base_type
|
||||||
flags |= PARSETYPE_FLAG_UNSIGNED
|
flags |= PARSETYPE_FLAG_UNSIGNED
|
||||||
goto base_type_normal_loop
|
goto base_type_normal_loop
|
||||||
:base_type_flag_double
|
:base_type_flag_double
|
||||||
|
c = flags & PARSETYPE_FLAG_DOUBLE
|
||||||
|
if c != 0 goto repeated_base_type
|
||||||
flags |= PARSETYPE_FLAG_DOUBLE
|
flags |= PARSETYPE_FLAG_DOUBLE
|
||||||
goto base_type_normal_loop
|
goto base_type_normal_loop
|
||||||
|
:repeated_base_type
|
||||||
|
token_error(p, .str_repeated_base_type)
|
||||||
|
:str_repeated_base_type
|
||||||
|
string Arithmetic type repeated (e.g. unsigned unsigned int).
|
||||||
|
byte 0
|
||||||
:base_type_normal_loop_end
|
:base_type_normal_loop_end
|
||||||
if flags == 8 goto base_type_int ; `int`
|
if flags == 8 goto base_type_int ; `int`
|
||||||
if flags == 1 goto base_type_uint ; `unsigned`
|
if flags == 1 goto base_type_uint ; `unsigned`
|
||||||
|
@ -524,13 +544,21 @@ function parse_base_type
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
:base_type_struct
|
:base_type_struct
|
||||||
|
is_struct = 1
|
||||||
|
; fallthrough
|
||||||
:base_type_union
|
:base_type_union
|
||||||
|
local struct_name
|
||||||
|
local struct
|
||||||
|
struct_name = .empty_string
|
||||||
p = base_type + 16
|
p = base_type + 16
|
||||||
if *1p != TOKEN_IDENTIFIER goto base_type_struct_definition
|
if *1p != TOKEN_IDENTIFIER goto base_type_have_name
|
||||||
p += 16
|
p += 8
|
||||||
|
struct_name = *8p
|
||||||
|
p += 8
|
||||||
|
:base_type_have_name
|
||||||
|
c = ident_list_lookup(structures, struct_name)
|
||||||
if *1p == SYMBOL_LBRACE goto base_type_struct_definition
|
if *1p == SYMBOL_LBRACE goto base_type_struct_definition
|
||||||
p -= 8
|
|
||||||
c = ident_list_lookup(struct_names, *8p)
|
|
||||||
if c == 0 goto base_type_incomplete_struct
|
if c == 0 goto base_type_incomplete_struct
|
||||||
; e.g. struct Foo x; where struct Foo has been defined
|
; e.g. struct Foo x; where struct Foo has been defined
|
||||||
*1out = TYPE_STRUCT
|
*1out = TYPE_STRUCT
|
||||||
|
@ -544,10 +572,99 @@ function parse_base_type
|
||||||
out += 1
|
out += 1
|
||||||
goto base_type_done
|
goto base_type_done
|
||||||
:base_type_struct_definition
|
:base_type_struct_definition
|
||||||
if *1p != SYMBOL_LBRACE goto bad_base_type
|
local member_base_type
|
||||||
byte 0xcc ; @TODO
|
local member_prefix
|
||||||
|
local member_prefix_end
|
||||||
|
local member_suffix
|
||||||
|
local member_suffix_end
|
||||||
|
local member_name
|
||||||
|
local member_type
|
||||||
|
local member_align
|
||||||
|
local member_size
|
||||||
|
|
||||||
|
if c != 0 goto struct_redefinition
|
||||||
|
struct = ident_list_create(8000) ; note: maximum "* 127 members in a single structure or union" C89 § 2.2.4.1
|
||||||
|
*1out = TYPE_STRUCT
|
||||||
|
out += 1
|
||||||
|
*8out = struct
|
||||||
|
out += 8
|
||||||
|
types_bytes_used = out - types
|
||||||
|
p += 16 ; skip opening {
|
||||||
|
|
||||||
|
local offset
|
||||||
|
offset = 0
|
||||||
|
|
||||||
|
ident_list_add(structures, struct_name, struct)
|
||||||
|
|
||||||
|
:struct_defn_loop
|
||||||
|
if *1p == SYMBOL_RBRACE goto struct_defn_loop_end
|
||||||
|
member_base_type = p
|
||||||
|
p = type_get_base_end(member_base_type)
|
||||||
|
:struct_defn_decl_loop ; handle each element of int x, y[5], *z;
|
||||||
|
member_prefix = p
|
||||||
|
member_prefix_end = type_get_prefix_end(member_prefix)
|
||||||
|
if *1member_prefix_end != TOKEN_IDENTIFIER goto member_no_identifier
|
||||||
|
member_name = member_prefix_end + 8
|
||||||
|
member_name = *8member_name
|
||||||
|
member_suffix = member_prefix_end + 16
|
||||||
|
member_suffix_end = type_get_suffix_end(member_prefix)
|
||||||
|
member_type = types_bytes_used
|
||||||
|
|
||||||
|
|
||||||
|
parse_type_declarators(member_prefix, member_prefix_end, member_suffix, member_suffix_end)
|
||||||
|
parse_base_type(member_base_type)
|
||||||
|
|
||||||
|
; make sure struct member is aligned
|
||||||
|
member_align = type_alignof(member_type)
|
||||||
|
; offset = ceil(offset / align) * align
|
||||||
|
offset += member_align - 1
|
||||||
|
offset /= member_align
|
||||||
|
offset *= member_align
|
||||||
|
|
||||||
|
if offset ] 0xffffffff goto struct_too_large
|
||||||
|
;putnln(offset)
|
||||||
|
; data = (type << 32) | offset
|
||||||
|
c = member_type < 32
|
||||||
|
c |= offset
|
||||||
|
ident_list_add(struct, member_name, c)
|
||||||
|
|
||||||
|
member_size = type_sizeof(member_type)
|
||||||
|
offset += member_size * is_struct ; keep offset as 0 if this is a union
|
||||||
|
p = member_suffix_end
|
||||||
|
if *1p == SYMBOL_SEMICOLON goto struct_defn_decl_loop_end
|
||||||
|
if *1p != SYMBOL_COMMA goto struct_bad_declaration
|
||||||
|
p += 16 ; skip comma
|
||||||
|
goto struct_defn_decl_loop
|
||||||
|
:struct_defn_decl_loop_end
|
||||||
|
p += 16 ; skip semicolon
|
||||||
|
goto struct_defn_loop
|
||||||
|
:struct_defn_loop_end
|
||||||
|
out = types + types_bytes_used
|
||||||
|
goto base_type_done
|
||||||
|
:struct_redefinition
|
||||||
|
token_error(p, .str_struct_redefinition)
|
||||||
|
:str_struct_redefinition
|
||||||
|
string struct redefinition.
|
||||||
|
byte 0
|
||||||
|
:struct_bad_declaration
|
||||||
|
token_error(p, .str_struct_bad_declaration)
|
||||||
|
:str_struct_bad_declaration
|
||||||
|
string Bad declaration in struct.
|
||||||
|
byte 0
|
||||||
|
:struct_too_large
|
||||||
|
token_error(p, .str_struct_too_large)
|
||||||
|
:str_struct_too_large
|
||||||
|
string struct too large (maximum is 4GB).
|
||||||
|
byte 0
|
||||||
|
:member_no_identifier
|
||||||
|
; e.g. struct { int; };
|
||||||
|
token_error(p, .str_member_no_identifier)
|
||||||
|
:str_member_no_identifier
|
||||||
|
string No identifier in struct member.
|
||||||
|
byte 0
|
||||||
:base_type_enum
|
:base_type_enum
|
||||||
local q
|
local q
|
||||||
|
local expr
|
||||||
|
|
||||||
*1out = TYPE_INT ; treat any enum as int
|
*1out = TYPE_INT ; treat any enum as int
|
||||||
out += 1
|
out += 1
|
||||||
|
@ -1320,6 +1437,36 @@ function type_sizeof
|
||||||
c = type_sizeof(p)
|
c = type_sizeof(p)
|
||||||
return n * c
|
return n * c
|
||||||
|
|
||||||
|
function type_alignof
|
||||||
|
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 alignof_array
|
||||||
|
fputs(2, .str_alignof_ni) ; @TODO
|
||||||
|
exit(1)
|
||||||
|
:str_alignof_ni
|
||||||
|
string type_alignof for this type not implemented.
|
||||||
|
byte 0
|
||||||
|
|
||||||
|
:alignof_array
|
||||||
|
p = type + 9 ; skip TYPE_ARRAY and size
|
||||||
|
return type_alignof(p)
|
||||||
|
|
||||||
; evaluate an expression which can be the size of an array, e.g.
|
; evaluate an expression which can be the size of an array, e.g.
|
||||||
; enum { A, B, C };
|
; enum { A, B, C };
|
||||||
; int x[A * sizeof(float) + 3 << 5];
|
; int x[A * sizeof(float) + 3 << 5];
|
||||||
|
|
|
@ -672,3 +672,10 @@ function print_tokens
|
||||||
:str_eof
|
:str_eof
|
||||||
string EOF
|
string EOF
|
||||||
byte 0
|
byte 0
|
||||||
|
|
||||||
|
function print_token
|
||||||
|
argument token
|
||||||
|
local p
|
||||||
|
p = token + 16
|
||||||
|
print_tokens(token, p)
|
||||||
|
return
|
||||||
|
|
14
05/util.b
14
05/util.b
|
@ -437,6 +437,11 @@ function putx64
|
||||||
argument n
|
argument n
|
||||||
fputx64(1, n)
|
fputx64(1, n)
|
||||||
return
|
return
|
||||||
|
function putx64ln
|
||||||
|
argument n
|
||||||
|
fputx64(1, n)
|
||||||
|
fputc(1, 10)
|
||||||
|
return
|
||||||
|
|
||||||
function fputx32
|
function fputx32
|
||||||
argument fd
|
argument fd
|
||||||
|
@ -456,6 +461,11 @@ function putx32
|
||||||
argument n
|
argument n
|
||||||
fputx32(1, n)
|
fputx32(1, n)
|
||||||
return
|
return
|
||||||
|
function putx32ln
|
||||||
|
argument n
|
||||||
|
fputx32(1, n)
|
||||||
|
fputc(1, 10)
|
||||||
|
return
|
||||||
|
|
||||||
function putn
|
function putn
|
||||||
argument n
|
argument n
|
||||||
|
@ -666,6 +676,10 @@ function leftmost_1bit
|
||||||
:str_leftmost1bit_0
|
:str_leftmost1bit_0
|
||||||
string 0 passed to leftmost_1bit.
|
string 0 passed to leftmost_1bit.
|
||||||
byte 0
|
byte 0
|
||||||
|
|
||||||
|
:empty_string
|
||||||
|
byte 0
|
||||||
|
|
||||||
:return_0
|
:return_0
|
||||||
return 0
|
return 0
|
||||||
:return_1
|
:return_1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue