mirror of
https://github.com/Ed94/gencpp.git
synced 2025-06-16 11:41:46 -07:00
Compare commits
8 Commits
Ed94-patch
...
v0.23-Alph
Author | SHA1 | Date | |
---|---|---|---|
6d551e95b9 | |||
a7cb7b0411 | |||
46e816d7ce | |||
28aa2c4dec | |||
d410590a86 | |||
e271fa39e4 | |||
08dcc3152f | |||
0829603262 |
@ -152,7 +152,7 @@ See the [scripts directory](scripts/).
|
|||||||
|
|
||||||
### Listing definitions in the Cuik Compiler
|
### Listing definitions in the Cuik Compiler
|
||||||
|
|
||||||
|
https://github.com/user-attachments/assets/2302240c-01f1-4e1b-a4b5-292eb3186648
|
||||||
|
|
||||||
### Unreal: Generating a UAttributeSet from a UDataTable
|
### Unreal: Generating a UAttributeSet from a UDataTable
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ enum Specifier : u32
|
|||||||
Spec_Ptr,
|
Spec_Ptr,
|
||||||
Spec_Ref,
|
Spec_Ref,
|
||||||
Spec_Register,
|
Spec_Register,
|
||||||
|
Spec_Restrict,
|
||||||
Spec_RValue,
|
Spec_RValue,
|
||||||
Spec_Static,
|
Spec_Static,
|
||||||
Spec_Thread_Local,
|
Spec_Thread_Local,
|
||||||
@ -56,6 +57,7 @@ inline Str spec_to_str( Specifier type )
|
|||||||
{ "*", sizeof( "*" ) - 1 },
|
{ "*", sizeof( "*" ) - 1 },
|
||||||
{ "&", sizeof( "&" ) - 1 },
|
{ "&", sizeof( "&" ) - 1 },
|
||||||
{ "register", sizeof( "register" ) - 1 },
|
{ "register", sizeof( "register" ) - 1 },
|
||||||
|
{ "restrict", sizeof( "restrict" ) - 1 },
|
||||||
{ "&&", sizeof( "&&" ) - 1 },
|
{ "&&", sizeof( "&&" ) - 1 },
|
||||||
{ "static", sizeof( "static" ) - 1 },
|
{ "static", sizeof( "static" ) - 1 },
|
||||||
{ "thread_local", sizeof( "thread_local" ) - 1 },
|
{ "thread_local", sizeof( "thread_local" ) - 1 },
|
||||||
|
@ -83,6 +83,7 @@ enum TokType : u32
|
|||||||
Tok_Spec_Mutable,
|
Tok_Spec_Mutable,
|
||||||
Tok_Spec_NeverInline,
|
Tok_Spec_NeverInline,
|
||||||
Tok_Spec_Override,
|
Tok_Spec_Override,
|
||||||
|
Tok_Spec_Restrict,
|
||||||
Tok_Spec_Static,
|
Tok_Spec_Static,
|
||||||
Tok_Spec_ThreadLocal,
|
Tok_Spec_ThreadLocal,
|
||||||
Tok_Spec_Volatile,
|
Tok_Spec_Volatile,
|
||||||
@ -188,6 +189,7 @@ inline Str toktype_to_str( TokType type )
|
|||||||
{ "mutable", sizeof( "mutable" ) - 1 },
|
{ "mutable", sizeof( "mutable" ) - 1 },
|
||||||
{ "neverinline", sizeof( "neverinline" ) - 1 },
|
{ "neverinline", sizeof( "neverinline" ) - 1 },
|
||||||
{ "override", sizeof( "override" ) - 1 },
|
{ "override", sizeof( "override" ) - 1 },
|
||||||
|
{ "restrict", sizeof( "restrict" ) - 1 },
|
||||||
{ "static", sizeof( "static" ) - 1 },
|
{ "static", sizeof( "static" ) - 1 },
|
||||||
{ "thread_local", sizeof( "thread_local" ) - 1 },
|
{ "thread_local", sizeof( "thread_local" ) - 1 },
|
||||||
{ "volatile", sizeof( "volatile" ) - 1 },
|
{ "volatile", sizeof( "volatile" ) - 1 },
|
||||||
|
@ -39,7 +39,7 @@ CodeConstructor parse_constructor( Str def )
|
|||||||
|
|
||||||
while ( left && tok_is_specifier(currtok) )
|
while ( left && tok_is_specifier(currtok) )
|
||||||
{
|
{
|
||||||
Specifier spec = str_to_specifier( tok_to_str(currtok) );
|
Specifier spec = str_to_specifier( currtok.Text );
|
||||||
|
|
||||||
b32 ignore_spec = false;
|
b32 ignore_spec = false;
|
||||||
|
|
||||||
|
@ -281,7 +281,7 @@ s32 lex_preprocessor_directive( LexContext* ctx )
|
|||||||
ctx->token.Text.Len++;
|
ctx->token.Text.Len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->token.Type = str_to_toktype( tok_to_str(ctx->token) );
|
ctx->token.Type = str_to_toktype( ctx->token.Text );
|
||||||
|
|
||||||
bool is_preprocessor = ctx->token.Type >= Tok_Preprocess_Define && ctx->token.Type <= Tok_Preprocess_Pragma;
|
bool is_preprocessor = ctx->token.Type >= Tok_Preprocess_Define && ctx->token.Type <= Tok_Preprocess_Pragma;
|
||||||
if ( ! is_preprocessor )
|
if ( ! is_preprocessor )
|
||||||
@ -488,7 +488,7 @@ void lex_found_token( LexContext* ctx )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TokType type = str_to_toktype( tok_to_str(ctx->token) );
|
TokType type = str_to_toktype( ctx->token.Text );
|
||||||
|
|
||||||
if (type <= Tok_Access_Public && type >= Tok_Access_Private ) {
|
if (type <= Tok_Access_Public && type >= Tok_Access_Private ) {
|
||||||
ctx->token.Flags |= TF_AccessSpecifier;
|
ctx->token.Flags |= TF_AccessSpecifier;
|
||||||
|
@ -533,7 +533,7 @@ Code parse_array_decl()
|
|||||||
|
|
||||||
untyped_tok.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)untyped_tok.Text.Ptr;
|
untyped_tok.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)untyped_tok.Text.Ptr;
|
||||||
|
|
||||||
Code array_expr = untyped_str( tok_to_str(untyped_tok) );
|
Code array_expr = untyped_str( untyped_tok.Text );
|
||||||
// [ <Content>
|
// [ <Content>
|
||||||
|
|
||||||
if ( left == 0 )
|
if ( left == 0 )
|
||||||
@ -737,7 +737,7 @@ Code parse_class_struct( TokType which, bool inplace_def )
|
|||||||
}
|
}
|
||||||
|
|
||||||
Token parent_tok = parse_identifier(nullptr);
|
Token parent_tok = parse_identifier(nullptr);
|
||||||
parent = def_type( tok_to_str(parent_tok) );
|
parent = def_type( parent_tok.Text );
|
||||||
// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Parent/Interface Name>
|
// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Parent/Interface Name>
|
||||||
|
|
||||||
while ( check(Tok_Comma) )
|
while ( check(Tok_Comma) )
|
||||||
@ -750,7 +750,7 @@ Code parse_class_struct( TokType which, bool inplace_def )
|
|||||||
}
|
}
|
||||||
Token interface_tok = parse_identifier(nullptr);
|
Token interface_tok = parse_identifier(nullptr);
|
||||||
|
|
||||||
array_append( interfaces, def_type( tok_to_str(interface_tok) ) );
|
array_append( interfaces, def_type( interface_tok.Text ) );
|
||||||
// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Name>, ...
|
// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Name>, ...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -773,10 +773,10 @@ Code parse_class_struct( TokType which, bool inplace_def )
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( which == Tok_Decl_Class )
|
if ( which == Tok_Decl_Class )
|
||||||
result = cast(Code, def_class( tok_to_str(name), def_assign( body, parent, access, attributes, interfaces, scast(s32, array_num(interfaces)), mflags ) ));
|
result = cast(Code, def_class( name.Text, def_assign( body, parent, access, attributes, interfaces, scast(s32, array_num(interfaces)), mflags ) ));
|
||||||
|
|
||||||
else
|
else
|
||||||
result = cast(Code, def_struct( tok_to_str(name), def_assign( body, (CodeTypename)parent, access, attributes, interfaces, scast(s32, array_num(interfaces)), mflags ) ));
|
result = cast(Code, def_struct( name.Text, def_assign( body, (CodeTypename)parent, access, attributes, interfaces, scast(s32, array_num(interfaces)), mflags ) ));
|
||||||
|
|
||||||
if ( inline_cmt )
|
if ( inline_cmt )
|
||||||
result->InlineCmt = cast(Code, inline_cmt);
|
result->InlineCmt = cast(Code, inline_cmt);
|
||||||
@ -994,7 +994,7 @@ CodeBody parse_class_struct_body( TokType which, Token name )
|
|||||||
|
|
||||||
while ( left && tok_is_specifier(currtok) )
|
while ( left && tok_is_specifier(currtok) )
|
||||||
{
|
{
|
||||||
Specifier spec = str_to_specifier( tok_to_str(currtok) );
|
Specifier spec = str_to_specifier( currtok.Text );
|
||||||
|
|
||||||
b32 ignore_spec = false;
|
b32 ignore_spec = false;
|
||||||
|
|
||||||
@ -1102,7 +1102,7 @@ CodeBody parse_class_struct_body( TokType which, Token name )
|
|||||||
untyped_tok.Text.Len = ( (sptr)currtok.Text.Ptr + currtok.Text.Len ) - (sptr)untyped_tok.Text.Ptr;
|
untyped_tok.Text.Len = ( (sptr)currtok.Text.Ptr + currtok.Text.Len ) - (sptr)untyped_tok.Text.Ptr;
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
}
|
}
|
||||||
member = untyped_str( tok_to_str(untyped_tok) );
|
member = untyped_str( untyped_tok.Text );
|
||||||
// Something unknown
|
// Something unknown
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1130,7 +1130,7 @@ CodeComment parse_comment()
|
|||||||
CodeComment
|
CodeComment
|
||||||
result = (CodeComment) make_code();
|
result = (CodeComment) make_code();
|
||||||
result->Type = CT_Comment;
|
result->Type = CT_Comment;
|
||||||
result->Content = cache_str( tok_to_str(currtok_noskip) );
|
result->Content = cache_str( currtok_noskip.Text );
|
||||||
// result->Token = currtok_noskip;
|
// result->Token = currtok_noskip;
|
||||||
eat( Tok_Comment );
|
eat( Tok_Comment );
|
||||||
|
|
||||||
@ -1171,13 +1171,13 @@ Code parse_complicated_definition( TokType which )
|
|||||||
}
|
}
|
||||||
|
|
||||||
Token tok = tokens.Arr[ idx - 1 ];
|
Token tok = tokens.Arr[ idx - 1 ];
|
||||||
if ( tok_is_specifier(tok) && spec_is_trailing( str_to_specifier( tok_to_str(tok))) )
|
if ( tok_is_specifier(tok) && spec_is_trailing( str_to_specifier( tok.Text)) )
|
||||||
{
|
{
|
||||||
// <which> <type_identifier>(...) <specifier> ...;
|
// <which> <type_identifier>(...) <specifier> ...;
|
||||||
|
|
||||||
s32 spec_idx = idx - 1;
|
s32 spec_idx = idx - 1;
|
||||||
Token spec = tokens.Arr[spec_idx];
|
Token spec = tokens.Arr[spec_idx];
|
||||||
while ( tok_is_specifier(spec) && spec_is_trailing( str_to_specifier( tok_to_str(spec))) )
|
while ( tok_is_specifier(spec) && spec_is_trailing( str_to_specifier( spec.Text)) )
|
||||||
{
|
{
|
||||||
-- spec_idx;
|
-- spec_idx;
|
||||||
spec = tokens.Arr[spec_idx];
|
spec = tokens.Arr[spec_idx];
|
||||||
@ -1207,9 +1207,19 @@ Code parse_complicated_definition( TokType which )
|
|||||||
if ( tok.Type == Tok_BraceCurly_Close )
|
if ( tok.Type == Tok_BraceCurly_Close )
|
||||||
{
|
{
|
||||||
// Its an inplace definition
|
// Its an inplace definition
|
||||||
// <which> <type_identifier> { ... } <identifier>;
|
// <which> <type_identifier ?> { ... } <identifier>;
|
||||||
ok_to_parse = true;
|
ok_to_parse = true;
|
||||||
is_inplace = true;
|
is_inplace = true;
|
||||||
|
|
||||||
|
CodeTypename type = cast(CodeTypename, parse_forward_or_definition(which, is_inplace));
|
||||||
|
|
||||||
|
// Should be a name right after the type.
|
||||||
|
Token name = parse_identifier(nullptr);
|
||||||
|
_ctx->parser.Scope->Name = name.Text;
|
||||||
|
|
||||||
|
CodeVar result = parse_variable_after_name(ModuleFlag_None, NullCode, NullCode, type, name.Text);
|
||||||
|
parser_pop(& _ctx->parser);
|
||||||
|
return (Code) result;
|
||||||
}
|
}
|
||||||
else if ( tok.Type == Tok_Identifier && tokens.Arr[ idx - 3 ].Type == which )
|
else if ( tok.Type == Tok_Identifier && tokens.Arr[ idx - 3 ].Type == which )
|
||||||
{
|
{
|
||||||
@ -1327,7 +1337,7 @@ Code parse_assignment_expression()
|
|||||||
}
|
}
|
||||||
|
|
||||||
expr_tok.Text.Len = ( ( sptr )currtok.Text.Ptr + currtok.Text.Len ) - ( sptr )expr_tok.Text.Ptr - 1;
|
expr_tok.Text.Len = ( ( sptr )currtok.Text.Ptr + currtok.Text.Len ) - ( sptr )expr_tok.Text.Ptr - 1;
|
||||||
expr = untyped_str( tok_to_str(expr_tok) );
|
expr = untyped_str( expr_tok.Text );
|
||||||
// = <Expression>
|
// = <Expression>
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
@ -1383,12 +1393,12 @@ CodeFn parse_function_after_name(
|
|||||||
{
|
{
|
||||||
if ( specifiers == nullptr )
|
if ( specifiers == nullptr )
|
||||||
{
|
{
|
||||||
specifiers = def_specifier( str_to_specifier( tok_to_str(currtok)) );
|
specifiers = def_specifier( str_to_specifier( currtok.Text) );
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
specifiers_append(specifiers, str_to_specifier( tok_to_str(currtok)) );
|
specifiers_append(specifiers, str_to_specifier( currtok.Text) );
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
}
|
}
|
||||||
// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers>
|
// <Attributes> <Specifiers> <ReturnType> <Name> ( <Paraemters> ) <Specifiers>
|
||||||
@ -1431,7 +1441,7 @@ CodeFn parse_function_after_name(
|
|||||||
}
|
}
|
||||||
|
|
||||||
StrBuilder
|
StrBuilder
|
||||||
name_stripped = strbuilder_make_str( _ctx->Allocator_Temp, tok_to_str(name) );
|
name_stripped = strbuilder_make_str( _ctx->Allocator_Temp, name.Text );
|
||||||
strbuilder_strip_space(name_stripped);
|
strbuilder_strip_space(name_stripped);
|
||||||
|
|
||||||
CodeFn
|
CodeFn
|
||||||
@ -1718,7 +1728,7 @@ CodeBody parse_global_nspace( CodeType which )
|
|||||||
|
|
||||||
while ( left && tok_is_specifier(currtok) )
|
while ( left && tok_is_specifier(currtok) )
|
||||||
{
|
{
|
||||||
Specifier spec = str_to_specifier( tok_to_str(currtok) );
|
Specifier spec = str_to_specifier( currtok.Text );
|
||||||
|
|
||||||
bool ignore_spec = false;
|
bool ignore_spec = false;
|
||||||
|
|
||||||
@ -2059,7 +2069,7 @@ CodeInclude parse_include()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ctx->parser.Scope->Name = currtok.Text;
|
_ctx->parser.Scope->Name = currtok.Text;
|
||||||
include->Content = cache_str( tok_to_str(currtok) );
|
include->Content = cache_str( currtok.Text );
|
||||||
eat( Tok_String );
|
eat( Tok_String );
|
||||||
// #include <Path> or "Path"
|
// #include <Path> or "Path"
|
||||||
|
|
||||||
@ -2384,12 +2394,12 @@ CodeOperator parse_operator_after_ret_type(
|
|||||||
{
|
{
|
||||||
if ( specifiers == nullptr )
|
if ( specifiers == nullptr )
|
||||||
{
|
{
|
||||||
specifiers = def_specifier( str_to_specifier( tok_to_str(currtok)) );
|
specifiers = def_specifier( str_to_specifier( currtok.Text) );
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
specifiers_append(specifiers, str_to_specifier( tok_to_str(currtok)) );
|
specifiers_append(specifiers, str_to_specifier( currtok.Text) );
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
}
|
}
|
||||||
// <ExportFlag> <Attributes> <Specifiers> <ReturnType> <Qualifier::...> operator <Op> ( <Parameters> ) <Specifiers>
|
// <ExportFlag> <Attributes> <Specifiers> <ReturnType> <Qualifier::...> operator <Op> ( <Parameters> ) <Specifiers>
|
||||||
@ -2419,7 +2429,7 @@ CodeOperator parse_operator_after_ret_type(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OpValidateResult check_result = operator__validate( op, params, ret_type, specifiers );
|
// OpValidateResult check_result = operator__validate( op, params, ret_type, specifiers );
|
||||||
CodeOperator result = def_operator( op, tok_to_str(nspace), def_assign( params, ret_type, body, specifiers, attributes, mflags ) );
|
CodeOperator result = def_operator( op, nspace.Text, def_assign( params, ret_type, body, specifiers, attributes, mflags ) );
|
||||||
|
|
||||||
if ( inline_cmt )
|
if ( inline_cmt )
|
||||||
result->InlineCmt = inline_cmt;
|
result->InlineCmt = inline_cmt;
|
||||||
@ -2537,7 +2547,7 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes
|
|||||||
return InvalidCode;
|
return InvalidCode;
|
||||||
}
|
}
|
||||||
// Dealing with a variable
|
// Dealing with a variable
|
||||||
result = cast(Code, parse_variable_after_name( ModuleFlag_None, attributes, specifiers, type, tok_to_str(name) ));
|
result = cast(Code, parse_variable_after_name( ModuleFlag_None, attributes, specifiers, type, name.Text ));
|
||||||
// <Attributes> <Specifiers> <ValueType> <Name> ...
|
// <Attributes> <Specifiers> <ValueType> <Name> ...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2595,7 +2605,7 @@ CodePragma parse_pragma()
|
|||||||
|
|
||||||
_ctx->parser.Scope->Name = currtok.Text;
|
_ctx->parser.Scope->Name = currtok.Text;
|
||||||
|
|
||||||
pragma->Content = cache_str( tok_to_str(currtok) );
|
pragma->Content = cache_str( currtok.Text );
|
||||||
eat( Tok_Preprocess_Content );
|
eat( Tok_Preprocess_Content );
|
||||||
// #pragma <Content>
|
// #pragma <Content>
|
||||||
|
|
||||||
@ -2729,7 +2739,7 @@ CodeParams parse_params( bool use_template_capture )
|
|||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
}
|
}
|
||||||
|
|
||||||
value = untyped_str( strbuilder_to_str(parser_strip_formatting( tok_to_str(value_tok), parser_strip_formatting_dont_preserve_newlines )) );
|
value = untyped_str( strbuilder_to_str(parser_strip_formatting( value_tok.Text, parser_strip_formatting_dont_preserve_newlines )) );
|
||||||
// ( <Macro> <ValueType> <Name> = <Expression>
|
// ( <Macro> <ValueType> <Name> = <Expression>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2740,7 +2750,7 @@ CodeParams parse_params( bool use_template_capture )
|
|||||||
result->Macro = macro;
|
result->Macro = macro;
|
||||||
|
|
||||||
if ( name.Text.Len > 0 )
|
if ( name.Text.Len > 0 )
|
||||||
result->Name = cache_str( tok_to_str(name) );
|
result->Name = cache_str( name.Text );
|
||||||
|
|
||||||
result->ValueType = type;
|
result->ValueType = type;
|
||||||
|
|
||||||
@ -2843,7 +2853,7 @@ CodeParams parse_params( bool use_template_capture )
|
|||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
}
|
}
|
||||||
|
|
||||||
value = untyped_str( strbuilder_to_str(parser_strip_formatting( tok_to_str(value_tok), parser_strip_formatting_dont_preserve_newlines )) );
|
value = untyped_str( strbuilder_to_str(parser_strip_formatting( value_tok.Text, parser_strip_formatting_dont_preserve_newlines )) );
|
||||||
// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> <PostNameMacro> = <Expression>
|
// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> <PostNameMacro> = <Expression>
|
||||||
}
|
}
|
||||||
// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> <PostNameMacro> = <Expression>, ..
|
// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> <PostNameMacro> = <Expression>, ..
|
||||||
@ -2855,7 +2865,7 @@ CodeParams parse_params( bool use_template_capture )
|
|||||||
param->Macro = macro;
|
param->Macro = macro;
|
||||||
|
|
||||||
if ( name.Text.Len > 0 )
|
if ( name.Text.Len > 0 )
|
||||||
param->Name = cache_str( tok_to_str(name) );
|
param->Name = cache_str( name.Text );
|
||||||
|
|
||||||
param->PostNameMacro = post_name_macro;
|
param->PostNameMacro = post_name_macro;
|
||||||
param->ValueType = cast(CodeTypename, type);
|
param->ValueType = cast(CodeTypename, type);
|
||||||
@ -2912,7 +2922,7 @@ CodePreprocessCond parse_preprocess_cond()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ctx->parser.Scope->Name = currtok.Text;
|
_ctx->parser.Scope->Name = currtok.Text;
|
||||||
cond->Content = cache_str( tok_to_str(currtok) );
|
cond->Content = cache_str( currtok.Text );
|
||||||
eat( Tok_Preprocess_Content );
|
eat( Tok_Preprocess_Content );
|
||||||
// #<Conditiona> <Content>
|
// #<Conditiona> <Content>
|
||||||
|
|
||||||
@ -3179,7 +3189,7 @@ CodeVar parse_variable_after_name(
|
|||||||
eat( Tok_BraceCurly_Close );
|
eat( Tok_BraceCurly_Close );
|
||||||
|
|
||||||
expr_tok.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)expr_tok.Text.Ptr;
|
expr_tok.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)expr_tok.Text.Ptr;
|
||||||
expr = untyped_str( tok_to_str(expr_tok) );
|
expr = untyped_str( expr_tok.Text );
|
||||||
// <Attributes> <Specifiers> <ValueType> <Name> = { <Expression> }
|
// <Attributes> <Specifiers> <ValueType> <Name> = { <Expression> }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3205,7 +3215,7 @@ CodeVar parse_variable_after_name(
|
|||||||
}
|
}
|
||||||
|
|
||||||
expr_token.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)expr_token.Text.Ptr;
|
expr_token.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)expr_token.Text.Ptr;
|
||||||
expr = untyped_str( tok_to_str(expr_token) );
|
expr = untyped_str( expr_token.Text );
|
||||||
eat( Tok_Paren_Close );
|
eat( Tok_Paren_Close );
|
||||||
// <Attributes> <Specifiers> <ValueType> <Name> ( <Expression> )
|
// <Attributes> <Specifiers> <ValueType> <Name> ( <Expression> )
|
||||||
}
|
}
|
||||||
@ -3228,7 +3238,7 @@ CodeVar parse_variable_after_name(
|
|||||||
}
|
}
|
||||||
|
|
||||||
expr_tok.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)expr_tok.Text.Ptr;
|
expr_tok.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)expr_tok.Text.Ptr;
|
||||||
bitfield_expr = untyped_str( tok_to_str(expr_tok) );
|
bitfield_expr = untyped_str( expr_tok.Text );
|
||||||
// <Attributes> <Specifiers> <ValueType> <Name> : <Expression>
|
// <Attributes> <Specifiers> <ValueType> <Name> : <Expression>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3309,7 +3319,7 @@ CodeVar parse_variable_declaration_list()
|
|||||||
|
|
||||||
while ( left && tok_is_specifier(currtok) )
|
while ( left && tok_is_specifier(currtok) )
|
||||||
{
|
{
|
||||||
Specifier spec = str_to_specifier( tok_to_str(currtok) );
|
Specifier spec = str_to_specifier( currtok.Text );
|
||||||
|
|
||||||
switch ( spec )
|
switch ( spec )
|
||||||
{
|
{
|
||||||
@ -3333,7 +3343,7 @@ CodeVar parse_variable_declaration_list()
|
|||||||
{
|
{
|
||||||
log_failure( "Error, invalid specifier '%S' proceeding comma\n"
|
log_failure( "Error, invalid specifier '%S' proceeding comma\n"
|
||||||
"(Parser will add and continue to specifiers, but will most likely fail to compile)\n%S"
|
"(Parser will add and continue to specifiers, but will most likely fail to compile)\n%S"
|
||||||
, tok_to_str(currtok), strbuilder_to_str( parser_to_strbuilder(_ctx->parser)) );
|
, currtok.Text, strbuilder_to_str( parser_to_strbuilder(_ctx->parser)) );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -3348,7 +3358,7 @@ CodeVar parse_variable_declaration_list()
|
|||||||
}
|
}
|
||||||
// , <Specifiers>
|
// , <Specifiers>
|
||||||
|
|
||||||
Str name = tok_to_str(currtok);
|
Str name = currtok.Text;
|
||||||
eat( Tok_Identifier );
|
eat( Tok_Identifier );
|
||||||
// , <Specifiers> <Name>
|
// , <Specifiers> <Name>
|
||||||
|
|
||||||
@ -3417,7 +3427,7 @@ CodeConstructor parser_parse_constructor( CodeSpecifiers specifiers )
|
|||||||
initializer_list_tok.Text.Len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )initializer_list_tok.Text.Ptr;
|
initializer_list_tok.Text.Len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )initializer_list_tok.Text.Ptr;
|
||||||
// <Name> ( <Parameters> ) : <InitializerList>
|
// <Name> ( <Parameters> ) : <InitializerList>
|
||||||
|
|
||||||
initializer_list = untyped_str( tok_to_str(initializer_list_tok) );
|
initializer_list = untyped_str( initializer_list_tok.Text );
|
||||||
|
|
||||||
// TODO(Ed): Constructors can have post-fix specifiers
|
// TODO(Ed): Constructors can have post-fix specifiers
|
||||||
|
|
||||||
@ -3446,7 +3456,7 @@ CodeConstructor parser_parse_constructor( CodeSpecifiers specifiers )
|
|||||||
|
|
||||||
CodeConstructor result = ( CodeConstructor )make_code();
|
CodeConstructor result = ( CodeConstructor )make_code();
|
||||||
|
|
||||||
result->Name = cache_str( tok_to_str(identifier));
|
result->Name = cache_str( identifier.Text );
|
||||||
|
|
||||||
result->Specs = specifiers;
|
result->Specs = specifiers;
|
||||||
|
|
||||||
@ -3492,7 +3502,7 @@ CodeDefine parser_parse_define()
|
|||||||
return InvalidCode;
|
return InvalidCode;
|
||||||
}
|
}
|
||||||
_ctx->parser.Scope->Name = currtok.Text;
|
_ctx->parser.Scope->Name = currtok.Text;
|
||||||
define->Name = cache_str( tok_to_str(currtok) );
|
define->Name = cache_str( currtok.Text );
|
||||||
eat( Tok_Identifier );
|
eat( Tok_Identifier );
|
||||||
// #define <Name>
|
// #define <Name>
|
||||||
|
|
||||||
@ -3550,7 +3560,7 @@ CodeDefine parser_parse_define()
|
|||||||
return define;
|
return define;
|
||||||
}
|
}
|
||||||
|
|
||||||
define->Body = untyped_str( strbuilder_to_str( parser_strip_formatting( tok_to_str(currtok), parser_strip_formatting_dont_preserve_newlines )) );
|
define->Body = untyped_str( strbuilder_to_str( parser_strip_formatting( currtok.Text, parser_strip_formatting_dont_preserve_newlines )) );
|
||||||
eat( Tok_Preprocess_Content );
|
eat( Tok_Preprocess_Content );
|
||||||
// #define <Name> ( <params> ) <Content>
|
// #define <Name> ( <params> ) <Content>
|
||||||
|
|
||||||
@ -3650,7 +3660,7 @@ CodeDestructor parser_parse_destructor( CodeSpecifiers specifiers )
|
|||||||
|
|
||||||
if ( tok_is_valid(prefix_identifier) ) {
|
if ( tok_is_valid(prefix_identifier) ) {
|
||||||
prefix_identifier.Text.Len += 1 + identifier.Text.Len;
|
prefix_identifier.Text.Len += 1 + identifier.Text.Len;
|
||||||
result->Name = cache_str( tok_to_str(prefix_identifier) );
|
result->Name = cache_str( prefix_identifier.Text );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( specifiers )
|
if ( specifiers )
|
||||||
@ -3726,7 +3736,7 @@ CodeEnum parser_parse_enum( bool inplace_def )
|
|||||||
else if ( currtok.Type == Tok_Preprocess_Macro_Expr )
|
else if ( currtok.Type == Tok_Preprocess_Macro_Expr )
|
||||||
{
|
{
|
||||||
// We'll support the enum_underlying macro
|
// We'll support the enum_underlying macro
|
||||||
if ( str_contains( tok_to_str(currtok), enum_underlying_macro.Name) )
|
if ( str_contains( currtok.Text, enum_underlying_macro.Name) )
|
||||||
{
|
{
|
||||||
use_macro_underlying = true;
|
use_macro_underlying = true;
|
||||||
underlying_macro = parse_simple_preprocess( Tok_Preprocess_Macro_Expr );
|
underlying_macro = parse_simple_preprocess( Tok_Preprocess_Macro_Expr );
|
||||||
@ -3761,7 +3771,7 @@ CodeEnum parser_parse_enum( bool inplace_def )
|
|||||||
switch ( currtok_noskip.Type )
|
switch ( currtok_noskip.Type )
|
||||||
{
|
{
|
||||||
case Tok_NewLine:
|
case Tok_NewLine:
|
||||||
member = untyped_str( tok_to_str(currtok_noskip) );
|
member = untyped_str( currtok_noskip.Text );
|
||||||
eat( Tok_NewLine );
|
eat( Tok_NewLine );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3854,7 +3864,7 @@ CodeEnum parser_parse_enum( bool inplace_def )
|
|||||||
Token prev = * lex_previous(_ctx->parser.Tokens, lex_dont_skip_formatting);
|
Token prev = * lex_previous(_ctx->parser.Tokens, lex_dont_skip_formatting);
|
||||||
entry.Text.Len = ( (sptr)prev.Text.Ptr + prev.Text.Len ) - (sptr)entry.Text.Ptr;
|
entry.Text.Len = ( (sptr)prev.Text.Ptr + prev.Text.Len ) - (sptr)entry.Text.Ptr;
|
||||||
|
|
||||||
member = untyped_str( tok_to_str(entry) );
|
member = untyped_str( entry.Text );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3898,7 +3908,7 @@ CodeEnum parser_parse_enum( bool inplace_def )
|
|||||||
result->Type = is_enum_class ? CT_Enum_Class_Fwd : CT_Enum_Fwd;
|
result->Type = is_enum_class ? CT_Enum_Class_Fwd : CT_Enum_Fwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
result->Name = cache_str( tok_to_str(name) );
|
result->Name = cache_str( name.Text );
|
||||||
|
|
||||||
if ( attributes )
|
if ( attributes )
|
||||||
result->Attributes = attributes;
|
result->Attributes = attributes;
|
||||||
@ -3950,7 +3960,7 @@ CodeExtern parser_parse_extern_link()
|
|||||||
CodeExtern
|
CodeExtern
|
||||||
result = (CodeExtern) make_code();
|
result = (CodeExtern) make_code();
|
||||||
result->Type = CT_Extern_Linkage;
|
result->Type = CT_Extern_Linkage;
|
||||||
result->Name = cache_str( tok_to_str(name) );
|
result->Name = cache_str( name.Text );
|
||||||
|
|
||||||
CodeBody entry = parser_parse_extern_link_body();
|
CodeBody entry = parser_parse_extern_link_body();
|
||||||
if ( cast(Code, entry) == Code_Invalid )
|
if ( cast(Code, entry) == Code_Invalid )
|
||||||
@ -3986,7 +3996,7 @@ CodeFriend parser_parse_friend()
|
|||||||
|
|
||||||
while ( left && tok_is_specifier(currtok) )
|
while ( left && tok_is_specifier(currtok) )
|
||||||
{
|
{
|
||||||
Specifier spec = str_to_specifier( tok_to_str(currtok) );
|
Specifier spec = str_to_specifier( currtok.Text );
|
||||||
|
|
||||||
switch ( spec )
|
switch ( spec )
|
||||||
{
|
{
|
||||||
@ -4104,7 +4114,7 @@ CodeFn parser_parse_function()
|
|||||||
|
|
||||||
while ( left && tok_is_specifier(currtok) )
|
while ( left && tok_is_specifier(currtok) )
|
||||||
{
|
{
|
||||||
Specifier spec = str_to_specifier( tok_to_str(currtok) );
|
Specifier spec = str_to_specifier( currtok.Text );
|
||||||
|
|
||||||
switch ( spec )
|
switch ( spec )
|
||||||
{
|
{
|
||||||
@ -4174,7 +4184,7 @@ CodeNS parser_parse_namespace()
|
|||||||
CodeNS
|
CodeNS
|
||||||
result = (CodeNS) make_code();
|
result = (CodeNS) make_code();
|
||||||
result->Type = CT_Namespace;
|
result->Type = CT_Namespace;
|
||||||
result->Name = cache_str( tok_to_str(name) );
|
result->Name = cache_str( name.Text );
|
||||||
|
|
||||||
result->Body = body;
|
result->Body = body;
|
||||||
|
|
||||||
@ -4205,7 +4215,7 @@ CodeOperator parser_parse_operator()
|
|||||||
|
|
||||||
while ( left && tok_is_specifier(currtok) )
|
while ( left && tok_is_specifier(currtok) )
|
||||||
{
|
{
|
||||||
Specifier spec = str_to_specifier( tok_to_str(currtok) );
|
Specifier spec = str_to_specifier( currtok.Text );
|
||||||
|
|
||||||
switch ( spec )
|
switch ( spec )
|
||||||
{
|
{
|
||||||
@ -4319,7 +4329,7 @@ CodeOpCast parser_parse_operator_cast( CodeSpecifiers specifiers )
|
|||||||
eat( Tok_BraceCurly_Close );
|
eat( Tok_BraceCurly_Close );
|
||||||
// <Specifiers> <Qualifier> :: ... operator <UnderlyingType>() <const> { <Body> }
|
// <Specifiers> <Qualifier> :: ... operator <UnderlyingType>() <const> { <Body> }
|
||||||
|
|
||||||
body = untyped_str( tok_to_str(body_str) );
|
body = untyped_str( body_str.Text );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -4335,7 +4345,7 @@ CodeOpCast parser_parse_operator_cast( CodeSpecifiers specifiers )
|
|||||||
CodeOpCast result = (CodeOpCast) make_code();
|
CodeOpCast result = (CodeOpCast) make_code();
|
||||||
|
|
||||||
if ( tok_is_valid(name) )
|
if ( tok_is_valid(name) )
|
||||||
result->Name = cache_str( tok_to_str(name) );
|
result->Name = cache_str( name.Text );
|
||||||
|
|
||||||
if (body) {
|
if (body) {
|
||||||
result->Type = CT_Operator_Cast;
|
result->Type = CT_Operator_Cast;
|
||||||
@ -4438,7 +4448,7 @@ CodeTemplate parser_parse_template()
|
|||||||
{
|
{
|
||||||
while ( left && tok_is_specifier(currtok) )
|
while ( left && tok_is_specifier(currtok) )
|
||||||
{
|
{
|
||||||
Specifier spec = str_to_specifier( tok_to_str(currtok) );
|
Specifier spec = str_to_specifier( currtok.Text );
|
||||||
|
|
||||||
switch ( spec )
|
switch ( spec )
|
||||||
{
|
{
|
||||||
@ -4568,10 +4578,10 @@ CodeTypename parser_parse_type( bool from_template, bool* typedef_is_function )
|
|||||||
// Prefix specifiers
|
// Prefix specifiers
|
||||||
while ( left && tok_is_specifier(currtok) )
|
while ( left && tok_is_specifier(currtok) )
|
||||||
{
|
{
|
||||||
Specifier spec = str_to_specifier( tok_to_str(currtok) );
|
Specifier spec = str_to_specifier( currtok.Text );
|
||||||
|
|
||||||
if ( spec != Spec_Const ) {
|
if ( spec != Spec_Const ) {
|
||||||
log_failure( "Error, invalid specifier used in type definition: %S\n%SB", tok_to_str(currtok), parser_to_strbuilder(_ctx->parser) );
|
log_failure( "Error, invalid specifier used in type definition: %S\n%SB", currtok.Text, parser_to_strbuilder(_ctx->parser) );
|
||||||
parser_pop(& _ctx->parser);
|
parser_pop(& _ctx->parser);
|
||||||
return InvalidCode;
|
return InvalidCode;
|
||||||
}
|
}
|
||||||
@ -4707,15 +4717,18 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
// Suffix specifiers for typename.
|
// Suffix specifiers for typename.
|
||||||
while ( left && tok_is_specifier(currtok) )
|
while ( left && tok_is_specifier(currtok) )
|
||||||
{
|
{
|
||||||
Specifier spec = str_to_specifier( tok_to_str(currtok) );
|
Specifier spec = str_to_specifier( currtok.Text );
|
||||||
|
|
||||||
if ( spec != Spec_Const && spec != Spec_Ptr && spec != Spec_Ref && spec != Spec_RValue )
|
switch (spec ) {
|
||||||
{
|
GEN_PARSER_TYPENAME_ALLOWED_SUFFIX_SPECIFIER_CASES:
|
||||||
log_failure( "Error, invalid specifier used in type definition: %S\n%SB", tok_to_str(currtok), parser_to_strbuilder(_ctx->parser) );
|
break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
log_failure( "Error, invalid specifier used in type definition: %S\n%SB", currtok.Text, parser_to_strbuilder(_ctx->parser) );
|
||||||
parser_pop(& _ctx->parser);
|
parser_pop(& _ctx->parser);
|
||||||
return InvalidCode;
|
return InvalidCode;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
specs_found[ NumSpecifiers ] = spec;
|
specs_found[ NumSpecifiers ] = spec;
|
||||||
NumSpecifiers++;
|
NumSpecifiers++;
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
@ -4793,7 +4806,7 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
// StrBuilder
|
// StrBuilder
|
||||||
// name_stripped = StrBuilder::make( FallbackAllocator, name );
|
// name_stripped = StrBuilder::make( FallbackAllocator, name );
|
||||||
// name_stripped.strip_space();
|
// name_stripped.strip_space();
|
||||||
return_type->Name = cache_str( tok_to_str(name) );
|
return_type->Name = cache_str( name.Text );
|
||||||
|
|
||||||
#ifdef GEN_USE_NEW_TYPENAME_PARSING
|
#ifdef GEN_USE_NEW_TYPENAME_PARSING
|
||||||
if ( specifiers )
|
if ( specifiers )
|
||||||
@ -4906,14 +4919,14 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
// Look for suffix specifiers for the function
|
// Look for suffix specifiers for the function
|
||||||
while ( left && tok_is_specifier(currtok) )
|
while ( left && tok_is_specifier(currtok) )
|
||||||
{
|
{
|
||||||
Specifier spec = str_to_specifier( tok_to_str(currtok) );
|
Specifier spec = str_to_specifier( currtok.Text );
|
||||||
|
|
||||||
if ( spec != Spec_Const
|
if ( spec != Spec_Const
|
||||||
// TODO : Add support for NoExcept, l-value, volatile, l-value, etc
|
// TODO : Add support for NoExcept, l-value, volatile, l-value, etc
|
||||||
// && spec != Spec_NoExcept
|
// && spec != Spec_NoExcept
|
||||||
&& spec != Spec_RValue )
|
&& spec != Spec_RValue )
|
||||||
{
|
{
|
||||||
log_failure( "Error, invalid specifier used in type definition: %S\n%S", tok_to_str(currtok), strbuilder_to_str( parser_to_strbuilder(_ctx->parser)) );
|
log_failure( "Error, invalid specifier used in type definition: %S\n%S", currtok.Text, strbuilder_to_str( parser_to_strbuilder(_ctx->parser)) );
|
||||||
parser_pop(& _ctx->parser);
|
parser_pop(& _ctx->parser);
|
||||||
return InvalidCode;
|
return InvalidCode;
|
||||||
}
|
}
|
||||||
@ -4947,7 +4960,7 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
// result->Token = _ctx->parser.Scope->Start;
|
// result->Token = _ctx->parser.Scope->Start;
|
||||||
|
|
||||||
// Need to wait until were using the new parsing method to do this.
|
// Need to wait until were using the new parsing method to do this.
|
||||||
StrBuilder name_stripped = parser_strip_formatting( tok_to_str(name), parser_strip_formatting_dont_preserve_newlines );
|
StrBuilder name_stripped = parser_strip_formatting( name.Text, parser_strip_formatting_dont_preserve_newlines );
|
||||||
|
|
||||||
// name_stripped.strip_space();
|
// name_stripped.strip_space();
|
||||||
|
|
||||||
@ -5206,7 +5219,7 @@ CodeTypedef parser_parse_typedef()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result->Name = cache_str( tok_to_str(name) );
|
result->Name = cache_str( name.Text );
|
||||||
result->IsFunction = false;
|
result->IsFunction = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5250,7 +5263,7 @@ CodeUnion parser_parse_union( bool inplace_def )
|
|||||||
Str name = { nullptr, 0 };
|
Str name = { nullptr, 0 };
|
||||||
if ( check( Tok_Identifier ) )
|
if ( check( Tok_Identifier ) )
|
||||||
{
|
{
|
||||||
name = tok_to_str(currtok);
|
name = currtok.Text;
|
||||||
_ctx->parser.Scope->Name = currtok.Text;
|
_ctx->parser.Scope->Name = currtok.Text;
|
||||||
eat( Tok_Identifier );
|
eat( Tok_Identifier );
|
||||||
}
|
}
|
||||||
@ -5441,7 +5454,7 @@ CodeUsing parser_parse_using()
|
|||||||
|
|
||||||
CodeUsing
|
CodeUsing
|
||||||
result = (CodeUsing) make_code();
|
result = (CodeUsing) make_code();
|
||||||
result->Name = cache_str( tok_to_str(name) );
|
result->Name = cache_str( name.Text );
|
||||||
result->ModuleFlags = mflags;
|
result->ModuleFlags = mflags;
|
||||||
|
|
||||||
if ( is_namespace)
|
if ( is_namespace)
|
||||||
@ -5492,7 +5505,7 @@ CodeVar parser_parse_variable()
|
|||||||
|
|
||||||
while ( left && tok_is_specifier(currtok) )
|
while ( left && tok_is_specifier(currtok) )
|
||||||
{
|
{
|
||||||
Specifier spec = str_to_specifier( tok_to_str(currtok) );
|
Specifier spec = str_to_specifier( currtok.Text );
|
||||||
switch ( spec )
|
switch ( spec )
|
||||||
{
|
{
|
||||||
GEN_PARSER_VARIABLE_ALLOWED_SPECIFIER_CASES:
|
GEN_PARSER_VARIABLE_ALLOWED_SPECIFIER_CASES:
|
||||||
@ -5518,13 +5531,6 @@ CodeVar parser_parse_variable()
|
|||||||
}
|
}
|
||||||
// <ModuleFlags> <Attributes> <Specifiers>
|
// <ModuleFlags> <Attributes> <Specifiers>
|
||||||
|
|
||||||
// Note(Ed): We're enforcing that using this codepath requires non-macro jank.
|
|
||||||
// Code macro_stmt = parse_macro_as_definiton(attributes, specifiers);
|
|
||||||
// if (macro_stmt) {
|
|
||||||
// parser_pop(& _ctx->parser);
|
|
||||||
// return macro_stmt;
|
|
||||||
// }
|
|
||||||
|
|
||||||
CodeTypename type = parser_parse_type(parser_not_from_template, nullptr);
|
CodeTypename type = parser_parse_type(parser_not_from_template, nullptr);
|
||||||
// <ModuleFlags> <Attributes> <Specifiers> <ValueType>
|
// <ModuleFlags> <Attributes> <Specifiers> <ValueType>
|
||||||
|
|
||||||
|
@ -97,9 +97,16 @@ case Spec_Global: \
|
|||||||
case Spec_Inline: \
|
case Spec_Inline: \
|
||||||
case Spec_Local_Persist: \
|
case Spec_Local_Persist: \
|
||||||
case Spec_Mutable: \
|
case Spec_Mutable: \
|
||||||
|
case Spec_Restrict: \
|
||||||
case Spec_Static: \
|
case Spec_Static: \
|
||||||
case Spec_Thread_Local: \
|
case Spec_Thread_Local: \
|
||||||
case Spec_Volatile
|
case Spec_Volatile
|
||||||
|
|
||||||
|
#define GEN_PARSER_TYPENAME_ALLOWED_SUFFIX_SPECIFIER_CASES \
|
||||||
|
case Spec_Const: \
|
||||||
|
case Spec_Ptr: \
|
||||||
|
case Spec_Restrict: \
|
||||||
|
case Spec_Ref: \
|
||||||
|
case Spec_RValue
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,11 +43,6 @@ AccessSpec tok_to_access_specifier(Token tok) {
|
|||||||
return scast(AccessSpec, tok.Type);
|
return scast(AccessSpec, tok.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
forceinline
|
|
||||||
Str tok_to_str(Token tok) {
|
|
||||||
return tok.Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
forceinline
|
forceinline
|
||||||
bool tok_is_valid( Token tok ) {
|
bool tok_is_valid( Token tok ) {
|
||||||
return tok.Text.Ptr && tok.Text.Len && tok.Type != Tok_Invalid;
|
return tok.Text.Ptr && tok.Text.Len && tok.Type != Tok_Invalid;
|
||||||
|
@ -14,6 +14,7 @@ NeverInline, neverinline
|
|||||||
Ptr, *
|
Ptr, *
|
||||||
Ref, &
|
Ref, &
|
||||||
Register, register
|
Register, register
|
||||||
|
Restrict, restrict
|
||||||
RValue, &&
|
RValue, &&
|
||||||
Static, static
|
Static, static
|
||||||
Thread_Local, thread_local
|
Thread_Local, thread_local
|
||||||
|
|
@ -72,6 +72,7 @@ Spec_LocalPersist, "local_persist"
|
|||||||
Spec_Mutable, "mutable"
|
Spec_Mutable, "mutable"
|
||||||
Spec_NeverInline, "neverinline"
|
Spec_NeverInline, "neverinline"
|
||||||
Spec_Override, "override"
|
Spec_Override, "override"
|
||||||
|
Spec_Restrict, "restrict"
|
||||||
Spec_Static, "static"
|
Spec_Static, "static"
|
||||||
Spec_ThreadLocal, "thread_local"
|
Spec_ThreadLocal, "thread_local"
|
||||||
Spec_Volatile, "volatile"
|
Spec_Volatile, "volatile"
|
||||||
|
|
@ -1101,7 +1101,8 @@ Anything that is in the qualifier capture of the function typename is treated as
|
|||||||
1. If its an in-place definition of a class, enum, struct, or union:
|
1. If its an in-place definition of a class, enum, struct, or union:
|
||||||
2. If its a decltype (Not supported yet but draft impl there)
|
2. If its a decltype (Not supported yet but draft impl there)
|
||||||
3. If its a compound native type expression (unsigned, char, short, long, int, float, dobule, etc )
|
3. If its a compound native type expression (unsigned, char, short, long, int, float, dobule, etc )
|
||||||
4. Ends up being a regular type alias of an identifier
|
4. If its a typename amcro
|
||||||
|
5. A regular type alias of an identifier
|
||||||
5. Parse specifiers (postfix)
|
5. Parse specifiers (postfix)
|
||||||
6. We need to now look ahead to see If we're dealing with a function typename
|
6. We need to now look ahead to see If we're dealing with a function typename
|
||||||
7. If wer're dealing with a function typename:
|
7. If wer're dealing with a function typename:
|
||||||
@ -1129,7 +1130,8 @@ Anything that is in the qualifier capture of the function typename is treated as
|
|||||||
1. If its an in-place definition of a class, enum, struct, or union:
|
1. If its an in-place definition of a class, enum, struct, or union:
|
||||||
2. If its a decltype (Not supported yet but draft impl there)
|
2. If its a decltype (Not supported yet but draft impl there)
|
||||||
3. If its a compound native type expression (unsigned, char, short, long, int, float, dobule, etc )
|
3. If its a compound native type expression (unsigned, char, short, long, int, float, dobule, etc )
|
||||||
4. Ends up being a regular type alias of an identifier
|
4. If its a typename amcro
|
||||||
|
5. A regular type alias of an identifier
|
||||||
4. Parse specifiers (postfix)
|
4. Parse specifiers (postfix)
|
||||||
1. If any specifiers are found populate specifiers code with them.
|
1. If any specifiers are found populate specifiers code with them.
|
||||||
5. We need to now look ahead to see If we're dealing with a function typename
|
5. We need to now look ahead to see If we're dealing with a function typename
|
||||||
@ -1190,7 +1192,7 @@ Anything that is in the qualifier capture of the function typename is treated as
|
|||||||
6. Decl_Union
|
6. Decl_Union
|
||||||
7. Preprocess_Define
|
7. Preprocess_Define
|
||||||
8. Preprocess_Conditional (if, ifdef, ifndef, elif, else, endif)
|
8. Preprocess_Conditional (if, ifdef, ifndef, elif, else, endif)
|
||||||
9. Preprocess_Macro
|
9. Preprocess_Macro (`MT_Statement` or `MT_Typename`)
|
||||||
10. Preprocess_Pragma
|
10. Preprocess_Pragma
|
||||||
11. Unsupported preprocess directive
|
11. Unsupported preprocess directive
|
||||||
12. Variable
|
12. Variable
|
||||||
|
Binary file not shown.
@ -420,6 +420,10 @@ word make_code, gen_make_code
|
|||||||
|
|
||||||
namespace set_allocator_, gen_set_allocator_
|
namespace set_allocator_, gen_set_allocator_
|
||||||
|
|
||||||
|
word register_macro, gen_register_macro
|
||||||
|
word register_macros, gen_register_macros
|
||||||
|
word register_macros_arr, gen_register_macros_arr
|
||||||
|
|
||||||
namespace Opts_, gen_Opts_
|
namespace Opts_, gen_Opts_
|
||||||
|
|
||||||
namespace def_, gen_def_
|
namespace def_, gen_def_
|
||||||
|
@ -106,3 +106,9 @@ case Spec_Mutable: \
|
|||||||
case Spec_Static: \
|
case Spec_Static: \
|
||||||
case Spec_Thread_Local: \
|
case Spec_Thread_Local: \
|
||||||
case Spec_Volatile
|
case Spec_Volatile
|
||||||
|
|
||||||
|
#define GEN_PARSER_TYPENAME_ALLOWED_SUFFIX_SPECIFIER_CASES \
|
||||||
|
case Spec_Const: \
|
||||||
|
case Spec_Ptr: \
|
||||||
|
case Spec_Ref: \
|
||||||
|
case Spec_RValue
|
||||||
|
@ -326,7 +326,7 @@ if ( $unreal )
|
|||||||
}
|
}
|
||||||
|
|
||||||
# C Library testing
|
# C Library testing
|
||||||
if ( $test -and $true )
|
if ( $test -and $false )
|
||||||
{
|
{
|
||||||
$path_test_c = join-path $path_test c_library
|
$path_test_c = join-path $path_test c_library
|
||||||
$path_build = join-path $path_test_c build
|
$path_build = join-path $path_test_c build
|
||||||
@ -368,7 +368,49 @@ if ( $test -and $true )
|
|||||||
Pop-Location
|
Pop-Location
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($test -and $true)
|
if ( $test -and $true )
|
||||||
|
{
|
||||||
|
$path_test_c = join-path $path_test c_library
|
||||||
|
$path_build = join-path $path_test_c build
|
||||||
|
$path_gen = join-path $path_test_c gen
|
||||||
|
if ( -not(Test-Path($path_build) )) {
|
||||||
|
New-Item -ItemType Directory -Path $path_build
|
||||||
|
}
|
||||||
|
if ( -not(Test-Path($path_gen) )) {
|
||||||
|
New-Item -ItemType Directory -Path $path_gen
|
||||||
|
}
|
||||||
|
|
||||||
|
$path_singleheader_include = join-path $path_c_library gen
|
||||||
|
$includes = @( $path_singleheader_include )
|
||||||
|
$unit = join-path $path_test_c "test_cuik.c"
|
||||||
|
$executable = join-path $path_build "test_cuik.exe"
|
||||||
|
|
||||||
|
$compiler_args = @()
|
||||||
|
$compiler_args += ( $flag_define + 'GEN_TIME' )
|
||||||
|
$compiler_args += $flag_all_c
|
||||||
|
$compiler_args += $flag_updated_cpp_macro
|
||||||
|
$compiler_args += $flag_c11
|
||||||
|
|
||||||
|
$linker_args = @(
|
||||||
|
$flag_link_win_subsystem_console
|
||||||
|
)
|
||||||
|
|
||||||
|
$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable
|
||||||
|
|
||||||
|
Push-Location $path_test_c
|
||||||
|
if ( Test-Path( $executable ) ) {
|
||||||
|
write-host "`nRunning c_library test"
|
||||||
|
$time_taken = Measure-Command { & $executable
|
||||||
|
| ForEach-Object {
|
||||||
|
write-host `t $_ -ForegroundColor Green
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write-host "`nc_library generator completed in $($time_taken.TotalMilliseconds) ms"
|
||||||
|
}
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($test -and $false)
|
||||||
{
|
{
|
||||||
$path_test_cpp = join-path $path_test cpp_library
|
$path_test_cpp = join-path $path_test cpp_library
|
||||||
$path_build = join-path $path_test_cpp build
|
$path_build = join-path $path_test_cpp build
|
||||||
|
21
test/c_library/Cuik/LICENSE.txt
Normal file
21
test/c_library/Cuik/LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Yasser Arguelles Snape
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
454
test/c_library/Cuik/tb/opt/passes.h
Normal file
454
test/c_library/Cuik/tb/opt/passes.h
Normal file
@ -0,0 +1,454 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../tb_internal.h"
|
||||||
|
#include <arena_array.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
INT_WIDEN_LIMIT = 3,
|
||||||
|
FAST_IDOM_LIMIT = 20
|
||||||
|
};
|
||||||
|
|
||||||
|
#if TB_PACKED_USERS
|
||||||
|
#define USERN(u) ((TB_Node*) ((u)->_n)) // node
|
||||||
|
#define USERI(u) ((int) ((u)->_slot)) // index
|
||||||
|
#else
|
||||||
|
#define USERN(u) ((u)->_n) // node
|
||||||
|
#define USERI(u) ((u)->_slot) // index
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FOR_USERS(u, n) for (TB_User *u = (n)->users, *_end_ = &u[(n)->user_count]; u != _end_; u++)
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Constant prop
|
||||||
|
////////////////////////////////
|
||||||
|
typedef struct {
|
||||||
|
int64_t min, max;
|
||||||
|
// for known bit analysis
|
||||||
|
uint64_t known_zeros, known_ones;
|
||||||
|
// we really don't wanna widen 18 quintillion times, it's never worth it
|
||||||
|
uint64_t widen;
|
||||||
|
} LatticeInt;
|
||||||
|
|
||||||
|
// Represents the fancier type system within the optimizer, it's
|
||||||
|
// all backed by my shitty understanding of lattice theory
|
||||||
|
struct Lattice {
|
||||||
|
enum {
|
||||||
|
LATTICE_BOT, // bot ^ x = bot
|
||||||
|
LATTICE_TOP, // top ^ x = x
|
||||||
|
|
||||||
|
LATTICE_INT,
|
||||||
|
LATTICE_TUPLE,
|
||||||
|
|
||||||
|
// float (each float type has it's own separate set of these btw):
|
||||||
|
//
|
||||||
|
// top
|
||||||
|
// / \
|
||||||
|
// / \
|
||||||
|
// / \
|
||||||
|
// / \
|
||||||
|
// /|\ /|\
|
||||||
|
// / | \ / | \
|
||||||
|
// N N N 0.0 1.5 ... # fltcon
|
||||||
|
// \ | / \ | /
|
||||||
|
// \|/ \|/
|
||||||
|
// nan ~nan
|
||||||
|
// \ /
|
||||||
|
// \ /
|
||||||
|
// \ /
|
||||||
|
// \ /
|
||||||
|
// flt
|
||||||
|
//
|
||||||
|
// N means NaN it's just too long to write in the diagram
|
||||||
|
LATTICE_FLT32, LATTICE_FLT64, // bottom types for floats
|
||||||
|
LATTICE_NAN32, LATTICE_NAN64,
|
||||||
|
LATTICE_XNAN32, LATTICE_XNAN64,
|
||||||
|
LATTICE_FLTCON32, LATTICE_FLTCON64, // _f32 and _f64
|
||||||
|
|
||||||
|
// pointers:
|
||||||
|
// anyptr
|
||||||
|
// / \
|
||||||
|
// / \
|
||||||
|
// / /|\
|
||||||
|
// | / | \
|
||||||
|
// null a b ... # ptrcon
|
||||||
|
// | \ | /
|
||||||
|
// \ ~null
|
||||||
|
// \ /
|
||||||
|
// allptr
|
||||||
|
LATTICE_ALLPTR,
|
||||||
|
LATTICE_ANYPTR,
|
||||||
|
LATTICE_NULL,
|
||||||
|
LATTICE_XNULL,
|
||||||
|
LATTICE_PTRCON,
|
||||||
|
|
||||||
|
// memory types
|
||||||
|
LATTICE_MEMORY,
|
||||||
|
|
||||||
|
// control tokens:
|
||||||
|
// top
|
||||||
|
// |
|
||||||
|
// dead
|
||||||
|
// |
|
||||||
|
// live
|
||||||
|
// |
|
||||||
|
// bot
|
||||||
|
LATTICE_LIVE,
|
||||||
|
LATTICE_DEAD,
|
||||||
|
} tag;
|
||||||
|
union {
|
||||||
|
size_t _elem_count; // LATTICE_TUPLE
|
||||||
|
LatticeInt _int; // LATTICE_INT
|
||||||
|
TB_Symbol* _ptr; // LATTICE_PTRCON
|
||||||
|
float _f32; // LATTICE_FLTCON32
|
||||||
|
double _f64; // LATTICE_FLTCON64
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
Lattice* elems[0];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Cool properties
|
||||||
|
////////////////////////////////
|
||||||
|
uint32_t cfg_flags(TB_Node* n);
|
||||||
|
bool cfg_is_region(TB_Node* n);
|
||||||
|
bool cfg_is_natural_loop(TB_Node* n);
|
||||||
|
bool cfg_is_branch(TB_Node* n);
|
||||||
|
bool cfg_is_fork(TB_Node* n);
|
||||||
|
bool cfg_is_terminator(TB_Node* n);
|
||||||
|
bool cfg_is_endpoint(TB_Node* n);
|
||||||
|
|
||||||
|
bool tb_node_is_safepoint(TB_Node* n);
|
||||||
|
bool tb_node_has_mem_out(TB_Node* n);
|
||||||
|
TB_Node* tb_node_mem_in(TB_Node* n);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// CFG
|
||||||
|
////////////////////////////////
|
||||||
|
typedef struct {
|
||||||
|
TB_Node *phi, *n;
|
||||||
|
int dst, src;
|
||||||
|
} PhiVal;
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Core optimizer
|
||||||
|
////////////////////////////////
|
||||||
|
typedef struct {
|
||||||
|
TB_Module* mod;
|
||||||
|
NL_HashSet visited;
|
||||||
|
|
||||||
|
size_t ws_cap;
|
||||||
|
size_t ws_cnt;
|
||||||
|
TB_Function** ws;
|
||||||
|
} IPOSolver;
|
||||||
|
|
||||||
|
static bool cant_signed_overflow(TB_Node* n) {
|
||||||
|
return TB_NODE_GET_EXTRA_T(n, TB_NodeBinopInt)->ab & TB_ARITHMATIC_NSW;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_proj(TB_Node* n) {
|
||||||
|
return n->type == TB_PROJ || n->type == TB_MACH_PROJ || n->type == TB_BRANCH_PROJ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t tb__mask(uint64_t bits) {
|
||||||
|
return ~UINT64_C(0) >> (64 - bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cfg_is_cproj(TB_Node* n) {
|
||||||
|
return is_proj(n) && n->dt.type == TB_TAG_CONTROL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cfg_is_mproj(TB_Node* n) {
|
||||||
|
return n->type == TB_PROJ && n->dt.type == TB_TAG_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// includes tuples which have control flow
|
||||||
|
static bool cfg_is_control(TB_Node* n) {
|
||||||
|
if (n->dt.type == TB_TAG_CONTROL) { return true; }
|
||||||
|
if (n->dt.type == TB_TAG_TUPLE) {
|
||||||
|
FOR_USERS(u, n) {
|
||||||
|
if (cfg_is_cproj(USERN(u))) { return true; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cfg_is_bb_entry(TB_Node* n) {
|
||||||
|
if (cfg_is_region(n)) {
|
||||||
|
return true;
|
||||||
|
} else if (cfg_is_cproj(n) && (n->inputs[0]->type == TB_ROOT || cfg_is_fork(n->inputs[0]))) {
|
||||||
|
// Start's control proj or a branch target
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns a BranchProj's falsey proj, if it's an if-like TB_BRANCH
|
||||||
|
static TB_NodeBranchProj* cfg_if_branch(TB_Node* n) {
|
||||||
|
size_t succ_count = 0;
|
||||||
|
if (n->type == TB_BRANCH || n->type == TB_AFFINE_LATCH) {
|
||||||
|
TB_NodeBranch* br = TB_NODE_GET_EXTRA(n);
|
||||||
|
succ_count = br->succ_count;
|
||||||
|
} else if (cfg_is_branch(n)) {
|
||||||
|
FOR_USERS(u, n) {
|
||||||
|
if (USERN(u)->type == TB_BRANCH_PROJ) { succ_count++; }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tb_todo();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (succ_count != 2) { return NULL; }
|
||||||
|
FOR_USERS(u, n) {
|
||||||
|
if (USERN(u)->type == TB_BRANCH_PROJ) {
|
||||||
|
TB_NodeBranchProj* proj = TB_NODE_GET_EXTRA(USERN(u));
|
||||||
|
if (proj->index == 1) { return proj; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// shouldn't be reached wtf?
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_mem_out_op(TB_Node* n) {
|
||||||
|
return n->dt.type == TB_TAG_MEMORY || (n->type >= TB_STORE && n->type <= TB_ATOMIC_CAS) || (n->type >= TB_CALL && n->type <= TB_TAILCALL) || n->type == TB_SPLITMEM || n->type == TB_MERGEMEM || n->type == TB_DEBUG_LOCATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_mem_end_op(TB_Node* n) {
|
||||||
|
return n->type == TB_RETURN || n->type == TB_TRAP || n->type == TB_UNREACHABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_mem_in_op(TB_Node* n) {
|
||||||
|
return is_mem_out_op(n) || n->type == TB_SAFEPOINT || n->type == TB_LOAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_mem_only_in_op(TB_Node* n) {
|
||||||
|
return n->type == TB_SAFEPOINT || n->type == TB_LOAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool single_use(TB_Node* n) {
|
||||||
|
return n->user_count == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TB_User* get_single_use(TB_Node* n) {
|
||||||
|
return n->user_count == 1 ? &n->users[0] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tb_node_is_pinned(TB_Node* n) {
|
||||||
|
if ((n->type >= TB_ROOT && n->type <= TB_SAFEPOINT) || is_proj(n) || cfg_is_control(n)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg_flags(n) & NODE_PINNED;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// CFG analysis
|
||||||
|
////////////////////////////////
|
||||||
|
// if we see a branch projection, it may either be a BB itself
|
||||||
|
// or if it enters a REGION directly, then that region is the BB.
|
||||||
|
static TB_Node* cfg_next_bb_after_cproj(TB_Node* proj) {
|
||||||
|
return proj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TB_User* proj_with_index(TB_Node* n, int i) {
|
||||||
|
FOR_USERS(u, n) if (is_proj(USERN(u))) {
|
||||||
|
TB_NodeProj* p = TB_NODE_GET_EXTRA(USERN(u));
|
||||||
|
if (p->index == i) { return u; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TB_User* cfg_next_user(TB_Node* n) {
|
||||||
|
FOR_USERS(u, n) {
|
||||||
|
if (cfg_is_control(USERN(u))) { return u; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cfg_has_phis(TB_Node* n) {
|
||||||
|
if (!cfg_is_region(n)) { return false; }
|
||||||
|
FOR_USERS(u, n) {
|
||||||
|
if (USERN(u)->type == TB_PHI) { return true; }
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cfg_is_unreachable(TB_Node* n) {
|
||||||
|
FOR_USERS(u, n) {
|
||||||
|
if (USERN(u)->type == TB_UNREACHABLE) { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TB_Node* cfg_next_control(TB_Node* n) {
|
||||||
|
FOR_USERS(u, n) {
|
||||||
|
if (cfg_is_control(USERN(u))) { return USERN(u); }
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TB_Node* cfg_get_pred(TB_CFG* cfg, TB_Node* n, int i) {
|
||||||
|
n = n->inputs[i];
|
||||||
|
for (;;) {
|
||||||
|
ptrdiff_t search = nl_map_get(cfg->node_to_block, n);
|
||||||
|
if (search >= 0 || n->type == TB_DEAD || cfg_is_region(n)) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = n->inputs[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static TB_BasicBlock* cfg_get_pred_bb(TB_CFG* cfg, TB_Node* n, int i) {
|
||||||
|
n = n->inputs[i];
|
||||||
|
for (;;) {
|
||||||
|
ptrdiff_t search = nl_map_get(cfg->node_to_block, n);
|
||||||
|
if (search >= 0) {
|
||||||
|
return cfg->node_to_block[search].v;
|
||||||
|
} else if (n->type == TB_DEAD || cfg_is_region(n)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = n->inputs[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// shorthand because we use it a lot
|
||||||
|
static TB_Node* idom(TB_CFG* cfg, TB_Node* n) {
|
||||||
|
TB_ASSERT(cfg->node_to_block == NULL);
|
||||||
|
ptrdiff_t search = nl_map_get(cfg->node_to_block, n);
|
||||||
|
if (search < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
TB_BasicBlock* dom = cfg->node_to_block[search].v->dom;
|
||||||
|
return dom ? dom->start : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dom_depth(TB_CFG* cfg, TB_Node* n) {
|
||||||
|
return nl_map_get_checked(cfg->node_to_block, n)->dom_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool slow_dommy2(TB_BasicBlock* expected_dom, TB_BasicBlock* bb) {
|
||||||
|
while (bb->dom_depth > expected_dom->dom_depth) {
|
||||||
|
bb = bb->dom;
|
||||||
|
}
|
||||||
|
return bb == expected_dom;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool slow_dommy(TB_CFG* cfg, TB_Node* expected_dom, TB_Node* bb) {
|
||||||
|
TB_BasicBlock* a = nl_map_get_checked(cfg->node_to_block, expected_dom);
|
||||||
|
TB_BasicBlock* b = nl_map_get_checked(cfg->node_to_block, bb);
|
||||||
|
return slow_dommy2(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Unordered SoN successor iterator
|
||||||
|
////////////////////////////////
|
||||||
|
#define FOR_SUCC(it, n) for (SuccIter it = succ_iter(n); succ_iter_next(&it);)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
TB_Node* n;
|
||||||
|
TB_Node* succ;
|
||||||
|
int index; // -1 if we're not walking CProjs
|
||||||
|
} SuccIter;
|
||||||
|
|
||||||
|
static SuccIter succ_iter(TB_Node* n) {
|
||||||
|
if (n->dt.type == TB_TAG_TUPLE) {
|
||||||
|
return (SuccIter){ n, NULL, 0 };
|
||||||
|
} else if (!cfg_is_endpoint(n)) {
|
||||||
|
return (SuccIter){ n, NULL, -1 };
|
||||||
|
} else {
|
||||||
|
return (SuccIter){ n, NULL, n->user_count };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool succ_iter_next(SuccIter* restrict it) {
|
||||||
|
TB_Node* n = it->n;
|
||||||
|
|
||||||
|
// not branching? ok pick single next control
|
||||||
|
if (it->index == -1) {
|
||||||
|
it->index = n->user_count; // terminate
|
||||||
|
it->succ = cfg_next_control(n);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we're in this loop, we know we're scanning for CProjs
|
||||||
|
while (it->index < n->user_count) {
|
||||||
|
TB_Node* un = USERN(&n->users[it->index++]);
|
||||||
|
if (cfg_is_cproj(un)) {
|
||||||
|
it->succ = un;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lovely properties
|
||||||
|
bool cfg_is_region(TB_Node* n);
|
||||||
|
bool cfg_is_natural_loop(TB_Node* n);
|
||||||
|
bool cfg_is_terminator(TB_Node* n);
|
||||||
|
bool cfg_is_endpoint(TB_Node* n);
|
||||||
|
|
||||||
|
// internal debugging mostly
|
||||||
|
void tb_print_dumb_node(Lattice** types, TB_Node* n);
|
||||||
|
|
||||||
|
// computes basic blocks but also dominators and loop nests if necessary.
|
||||||
|
TB_CFG tb_compute_cfg(TB_Function* f, TB_Worklist* ws, TB_Arena* tmp_arena, bool dominators);
|
||||||
|
void tb_free_cfg(TB_CFG* cfg);
|
||||||
|
|
||||||
|
// TB_Worklist API
|
||||||
|
void worklist_alloc(TB_Worklist* restrict ws, size_t initial_cap);
|
||||||
|
void worklist_free(TB_Worklist* restrict ws);
|
||||||
|
void worklist_clear(TB_Worklist* restrict ws);
|
||||||
|
void worklist_clear_visited(TB_Worklist* restrict ws);
|
||||||
|
bool worklist_test(TB_Worklist* restrict ws, TB_Node* n);
|
||||||
|
bool worklist_test_n_set(TB_Worklist* restrict ws, TB_Node* n);
|
||||||
|
void worklist_push(TB_Worklist* restrict ws, TB_Node* restrict n);
|
||||||
|
int worklist_count(TB_Worklist* ws);
|
||||||
|
TB_Node* worklist_pop(TB_Worklist* ws);
|
||||||
|
|
||||||
|
void subsume_node(TB_Function* f, TB_Node* n, TB_Node* new_n);
|
||||||
|
void subsume_node2(TB_Function* f, TB_Node* n, TB_Node* new_n);
|
||||||
|
void subsume_node_without_phis(TB_Function* f, TB_Node* n, TB_Node* new_n);
|
||||||
|
void tb__gvn_remove(TB_Function* f, TB_Node* n);
|
||||||
|
|
||||||
|
// Scheduler's cost model crap (talk about these in codegen_impl.h)
|
||||||
|
typedef int (*TB_GetLatency)(TB_Function* f, TB_Node* n, TB_Node* end);
|
||||||
|
typedef uint64_t (*TB_GetUnitMask)(TB_Function* f, TB_Node* n);
|
||||||
|
|
||||||
|
// Local scheduler
|
||||||
|
void tb_list_scheduler(TB_Function* f, TB_CFG* cfg, TB_Worklist* ws, DynArray(PhiVal*) phi_vals, TB_BasicBlock* bb, TB_GetLatency get_lat, TB_GetUnitMask get_unit_mask, int unit_count);
|
||||||
|
void tb_greedy_scheduler(TB_Function* f, TB_CFG* cfg, TB_Worklist* ws, DynArray(PhiVal*) phi_vals, TB_BasicBlock* bb);
|
||||||
|
void tb_dataflow(TB_Function* f, TB_Arena* arena, TB_CFG cfg);
|
||||||
|
|
||||||
|
// Global scheduler
|
||||||
|
void tb_clear_anti_deps(TB_Function* f, TB_Worklist* ws);
|
||||||
|
void tb_renumber_nodes(TB_Function* f, TB_Worklist* ws);
|
||||||
|
void tb_compact_nodes(TB_Function* f, TB_Worklist* ws);
|
||||||
|
void tb_global_schedule(TB_Function* f, TB_Worklist* ws, TB_CFG cfg, bool early_only, bool dataflow, TB_GetLatency get_lat);
|
||||||
|
void tb_compute_synthetic_loop_freq(TB_Function* f, TB_CFG* cfg);
|
||||||
|
|
||||||
|
// BB placement
|
||||||
|
int bb_placement_rpo(TB_Arena* arena, TB_CFG* cfg, int* dst_order);
|
||||||
|
int bb_placement_trace(TB_Arena* arena, TB_CFG* cfg, int* dst_order);
|
||||||
|
|
||||||
|
// makes arch-friendly IR
|
||||||
|
void tb_opt_legalize(TB_Function* f, TB_Arch arch);
|
||||||
|
int tb_opt_peeps(TB_Function* f);
|
||||||
|
int tb_opt_locals(TB_Function* f);
|
||||||
|
|
||||||
|
// Integrated IR debugger
|
||||||
|
void tb_integrated_dbg(TB_Function* f, TB_Node* n);
|
||||||
|
|
||||||
|
Lattice* latuni_get(TB_Function* f, TB_Node* n);
|
||||||
|
|
||||||
|
void tb__print_regmask(RegMask* mask);
|
||||||
|
|
48
test/c_library/test_cuik.c
Normal file
48
test/c_library/test_cuik.c
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#define GEN_IMPLEMENTATION
|
||||||
|
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||||
|
#include "gen_singleheader.h"
|
||||||
|
|
||||||
|
#define gen_iterator( Type, container, iter ) \
|
||||||
|
gen_begin_ ## Type(container); \
|
||||||
|
iter != gen_end_ ## Type(container); \
|
||||||
|
code = gen_next_ ## Type(container, iter)
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
gen_Context ctx = {0};
|
||||||
|
gen_init(& ctx);
|
||||||
|
|
||||||
|
gen_register_macros( args(
|
||||||
|
((gen_Macro){ txt("USERN"), MT_Expression, MF_Functional }),
|
||||||
|
((gen_Macro){ txt("USERI"), MT_Expression, MF_Functional }),
|
||||||
|
((gen_Macro){ txt("USERI"), MT_Expression, MF_Functional }),
|
||||||
|
((gen_Macro){ txt("FOR_USERS"), MT_Statement, MF_Functional }),
|
||||||
|
((gen_Macro){ txt("FOR_SUCC"), MT_Statement, MF_Functional })
|
||||||
|
));
|
||||||
|
|
||||||
|
gen_CodeBody h_passes = gen_parse_file("Cuik/tb/opt/passes.h");
|
||||||
|
for (gen_Code code = gen_iterator(CodeBody, h_passes, code)) switch (code->Type) {
|
||||||
|
case CT_Function_Fwd:
|
||||||
|
case CT_Function:
|
||||||
|
gen_log_fmt("%S:\t%S RETURN_TYPE: %S PARAMS:%S\n"
|
||||||
|
, gen_codetype_to_str(code->Type)
|
||||||
|
, code->Name
|
||||||
|
, gen_strbuilder_to_str( gen_typename_to_strbuilder((gen_CodeTypename) code->ReturnType))
|
||||||
|
, gen_strbuilder_to_str( gen_params_to_strbuilder( (gen_CodeParams) code->Params))
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CT_Variable:
|
||||||
|
gen_log_fmt("%S:\t%S Type:%S\n", gen_codetype_to_str(code->Type), code->Name, code->ValueType);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CT_Struct_Fwd:
|
||||||
|
case CT_Struct:
|
||||||
|
case CT_Typedef:
|
||||||
|
gen_log_fmt("%S: %S\n", gen_codetype_to_str(code->Type), code->Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_deinit(& ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
Reference in New Issue
Block a user