diff --git a/Makefile b/Makefile index 344f32f..7ad3754 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,7 @@ COMMON = \ control.cc \ opast.cc \ opparser.cc \ + opcomp.cc \ # END COMMON DEMO = \ diff --git a/control.hh b/control.hh index e5a9272..9c9cf1a 100644 --- a/control.hh +++ b/control.hh @@ -1,9 +1,114 @@ #pragma once -#ifndef REAL_BUILD -# include "externals.hh" -#endif +#include "sync.hh" +#include "opast.hh" -struct T_SyncData; +namespace ops { + +using namespace ebcl; + +enum E_OpType +{ + OP_END , + // + OP_FP_LOAD , + // + OP_FP_CMP , +}; + +struct T_Op +{ + E_OpType op; + T_SRDLocation location; + uint32_t arg0 , arg1; + + T_Op( const E_OpType op , + T_SRDLocation const& location , + const uint32_t arg0 = 0 , + const uint32_t arg1 = 0 ) noexcept + : op( op ) , location( location ) , + arg0( arg0 ) , arg1( arg1 ) + { } +}; + +union T_OpValue +{ + int32_t i; + uint32_t u; + float f; +}; + +struct T_OpProgram +{ + T_MultiArray< T_Op > ops; // All operations + uint32_t init , // Index of initialisation function + frame; // Index of frame rendering function + + T_Array< T_OpValue > constants; // Constants values + uint32_t nVariables{ 0 }; // Amount of variables + + T_Array< T_String > inputs; // Input definitions + + uint32_t nPrograms{ 0 } , // Amount of programs + nFramebuffers{ 0 } , // Amount of framebuffers + nPipelines{ 0 } , // Amount of pipelines + nSamplers{ 0 } , // Amount of samplers + nTextures{ 0 }; // Amount of textures + T_Array< T_String > progNames; // GLSL program files + + T_Array< T_String > uiStrings; // UI strings for profiling, etc. +}; +using P_OpProgram = T_OwnPtr< T_OpProgram >; + +struct T_OpContext +{ + T_OpProgram& program; // The program + + uint32_t instrPtr; // Instruction pointer + bool aborted; // Did the program fail? + + T_Array< T_OpValue > values; // VM data + T_Array< T_OpValue > stack; // Main VM stack + + double x87stack[ 8 ]; // x87 FPU emulation stack + int x87sp; // x87 FPU emulation stack pointer +}; + +class X_OpFailure : public std::exception +{ + public: + X_OpFailure( ) = delete; + DEF_COPY( X_OpFailure ); + DEF_MOVE( X_OpFailure ); + + X_OpFailure( T_Op const& op , + T_String error ) noexcept; + + T_Op const& op( ) const noexcept + { return *op_; } + T_String const& error( ) const noexcept + { return error_; } + + char const* what( ) const noexcept override; + + private: + T_Op const* op_; + T_String error_; + T_String fullMessage_; +}; + +class T_Compiler : public A_PrivateImplementation +{ + public: + T_Compiler( ) noexcept; + + P_OpProgram compile( + opast::T_ParserOutput const& input ) noexcept; +}; + +} // namespace ops + + +/*= FIXME OLD VERSION BELOW ====================================================*/ namespace cops { @@ -13,9 +118,6 @@ namespace cops { { T_Program const* program; - float const* time; - T_SyncData const* sync; - T_KeyValueTable< T_String , float > vars; T_Array< float > opStack; diff --git a/opast.hh b/opast.hh index cb63035..4921f78 100644 --- a/opast.hh +++ b/opast.hh @@ -1211,7 +1211,6 @@ struct T_ParserOutput { T_RootNode root; T_KeyValueTable< T_String , E_DataType > types; - T_Set< float > constants{ UseTag< IndexBacked< > >( ) }; }; // The actual parser diff --git a/opcomp.cc b/opcomp.cc new file mode 100644 index 0000000..0d93df4 --- /dev/null +++ b/opcomp.cc @@ -0,0 +1,192 @@ +#include "externals.hh" +#include "control.hh" +#include + +#define INVASIVE_TRACES + +using namespace ebcl; +using namespace ops; +using namespace opast; + +namespace { + +struct T_CompilerImpl_ +{ + T_Visitor< A_Node > astVisitor{ ASTVisitorBrowser }; + T_Set< uint32_t > constants{ UseTag< IndexBacked< > >( ) }; + + T_ParserOutput* input; + P_OpProgram output; + + uint32_t fiVariables , fiFramebuffers , + fiPipelines , fiPrograms , + fiSamplers , fiTextures; + + P_OpProgram compile( + T_ParserOutput const& input ) noexcept; + + private: + void gatherConstants( ) noexcept; + void countAssets( ) noexcept; + + bool compileNode( uint32_t funcIndex , + A_Node& node , + bool exit ) noexcept; +}; + + +P_OpProgram T_CompilerImpl_::compile( + T_ParserOutput const& in ) noexcept +{ + input = const_cast< T_ParserOutput* >( &in ); + output = NewOwned< T_OpProgram >( ); + + // Gather all constants used in expressions, count resources + gatherConstants( ); + countAssets( ); + + // Get function indices + // FIXME ideally we should remap functions so that init is always 0 + // and frame is always 1 + output->init = input->root.functionIndex( "*init*" ); + output->frame = input->root.functionIndex( "*frame*" ); +#ifdef INVASIVE_TRACES + printf( "function indices\n\t%d\tinit\n\t%d\tframe\n" , + output->init , output->frame ); +#endif + + // Compile each function + uint32_t cfi; + for ( cfi = 0u ; cfi < input->root.nFunctions( ) ; cfi ++ ) { + output->ops.next( ); + auto& func( input->root.function( cfi ) ); +#ifdef INVASIVE_TRACES + printf( "compiling function %s\n" , + func.name( ).toOSString( ).data( ) ); +#endif + astVisitor.visit( func , + [=]( A_Node& node , const bool exit ) -> bool { + return compileNode( cfi , node , exit ); + } ); + } + + return std::move( output ); +} + +void T_CompilerImpl_::gatherConstants( ) noexcept +{ + constants.clear( ); + astVisitor.visit( input->root , [&]( A_Node& node , const bool exit ) { + if ( exit && node.type( ) == A_Node::EXPR_CONST ) { + T_OpValue value; + value.f = dynamic_cast< T_ConstantExprNode& >( node ).floatValue( ); + if ( value.f != 0 && value.f != 1 ) { + constants.add( value.u ); + } + } + return true; + } ); + +#ifdef INVASIVE_TRACES + printf( "%d constants\n" , constants.size( ) ); + for ( auto i = 0u ; i < constants.size( ) ; i ++ ) { + printf( " %08x" , constants[ i ] ); + if ( i % 4 == 3 ) { + printf( "\n" ); + } + } + if ( constants.size( ) % 4 ) { + printf( "\n" ); + } +#endif +} + +void T_CompilerImpl_::countAssets( ) noexcept +{ + auto const nt{ input->types.size( ) }; + for ( auto i = 0u ; i < nt ; i ++ ) { + const auto t{ input->types.values( )[ i ] }; + switch ( t ) { + case E_DataType::FRAMEBUFFER: + output->nFramebuffers ++; + break; + case E_DataType::PIPELINE: + output->nPipelines ++; + break; + case E_DataType::PROGRAM: + output->nPrograms ++; + break; + case E_DataType::SAMPLER: + output->nSamplers ++; + break; + case E_DataType::TEXTURE: + output->nTextures ++; + break; + case E_DataType::VARIABLE: + output->nVariables ++; + break; + + case E_DataType::INPUT: + assert( !output->inputs.contains( + input->types.keys( )[ i ] ) ); + output->inputs.add( input->types.keys( )[ i ] ); + break; + + case E_DataType::BUILTIN: + case E_DataType::UNKNOWN: + break; + } + } + + fiVariables = 3 + constants.size( ); + fiFramebuffers = fiVariables + output->nVariables; + fiPipelines = fiFramebuffers + output->nFramebuffers; + fiPrograms = fiPipelines + output->nPipelines; + fiSamplers = fiPrograms + output->nPrograms; + fiTextures = fiSamplers + output->nSamplers; + +#ifdef INVASIVE_TRACES + printf( "assets\n\t%d framebuffers\n\t%d pipelines\n" + "\t%d programs\n\t%d samplers\n\t%d textures\n" + "\t%d variables\n\t%d inputs\n" , + output->nFramebuffers , output->nPipelines , + output->nPrograms , output->nSamplers , + output->nTextures , output->nVariables , + output->inputs.size( ) ); + printf( "table ranges\n\t0\t2\tBuilt-ins\n" + "\t3\t%d\tConstants\n" + "\t%d\t%d\tVariables\n" + "\t%d\t%d\tFramebuffers\n" + "\t%d\t%d\tPipelines\n" + "\t%d\t%d\tPrograms\n" + "\t%d\t%d\tSamplers\n" + "\t%d\t%d\tTextures\n" , + fiVariables - 1 , fiVariables , fiFramebuffers - 1 , fiFramebuffers , + fiPipelines - 1 , fiPipelines , fiPrograms - 1 , fiPrograms , + fiSamplers - 1 , fiSamplers , fiTextures - 1 , fiTextures , + fiTextures + output->nTextures - 1 ); +#endif +} + +bool T_CompilerImpl_::compileNode( + const uint32_t funcIndex , + A_Node& node , + const bool exit ) noexcept +{ + return false; +} + +} + + +/*= T_Compiler =================================================================*/ + +T_Compiler::T_Compiler( ) noexcept + : A_PrivateImplementation( new T_CompilerImpl_( ) ) +{ } + +P_OpProgram T_Compiler::compile( + T_ParserOutput const& input ) noexcept +{ + return p< T_CompilerImpl_ >( ).compile( input ); +} diff --git a/parsercheck.cc b/parsercheck.cc index 5ee3fa6..6dffb9d 100644 --- a/parsercheck.cc +++ b/parsercheck.cc @@ -1,5 +1,6 @@ #include "externals.hh" #include "opast.hh" +#include "control.hh" #include #include #include @@ -34,17 +35,6 @@ void WriteSRDError( } -/*============================================================================*/ - -T_Array< T_SRDError > parserPrototypes( - T_OwnPtr< T_ParserOutput > const& output ) -{ - T_Visitor< opast::A_Node > visitor{ ASTVisitorBrowser }; - T_Array< T_SRDError > errors; - return errors; -} - - /*============================================================================*/ } // namespace @@ -85,20 +75,10 @@ int main( int argc , char** argv ) // Parse the fuck T_Parser parser; if ( parser.parse( srdOut.list( ) ) ) { - printf( "Success - now running prototypes\n" ); - T_Array< T_SRDError > errors{ parserPrototypes( parser.result( ) ) }; - if ( errors.empty( ) ) { - printf( "Success!\n" ); - return 0; - } - - T_StringBuilder sb; - for ( auto const& err : errors ) { - WriteSRDError( sb , err ); - } - sb << "Parser prototypes failed\n" << '\0'; - fprintf( stderr , "%s" , sb.data( ) ); - return 4; + printf( "Parser successful. Compiling...\n" ); + ops::T_Compiler compiler; + compiler.compile( *parser.result( ) ); + return 0; } else { T_StringBuilder sb; for ( auto const& err : parser.errors( ) ) {