diff --git a/c-opcomp.hh b/c-opcomp.hh index d833ee6..69ae2b6 100644 --- a/c-opcomp.hh +++ b/c-opcomp.hh @@ -7,6 +7,9 @@ /*= PARSER ===================================================================*/ +using F_OPGenLog = std::function< T_StringBuilder( ) >; +using F_OPLogger = std::function< void( F_OPGenLog , uint32_t ) >; + // Parser output. Consists in a root node as well as other details (table of // constants, data types, etc...) struct T_OpsParserOutput @@ -19,12 +22,22 @@ struct T_OpsParserOutput class T_OpsParser : public ebcl::A_PrivateImplementation { private: + F_OPLogger logger_{ []( auto , auto ) { } }; T_Array< ebcl::T_SRDError > errors_; T_OwnPtr< T_OpsParserOutput > output_; public: T_OpsParser( ) noexcept; + void setLogger( F_OPLogger logger ) + { + if ( logger ) { + logger_ = std::move( logger ); + } else { + logger_ = []( auto , auto ) { }; + } + } + bool parse( ebcl::T_SRDList const& input ) noexcept; T_Array< ebcl::T_SRDError > const& errors( ) const noexcept diff --git a/c-opopt.cc b/c-opopt.cc index e6cecb8..f030bbe 100644 --- a/c-opopt.cc +++ b/c-opopt.cc @@ -1,6 +1,5 @@ #include "externals.hh" -#include "c-opcomp.hh" #include "c-opopt.hh" #include "c-ops.hh" #include "c-sync.hh" @@ -134,8 +133,14 @@ template< std::function< void( T& , P_ExpressionNode ) > set ) noexcept { auto& node{ (T&) n }; - auto r{ checkExpression( get( node ) ) }; + auto& child{ get( node ) }; + auto r{ checkExpression( child ) }; if ( r ) { + oData.logger( [&]() { + T_StringBuilder sb; + sb << "substituting node at " << child.location( ); + return sb; + } , 2 ); r->location( ) = node.location( ); set( node , std::move( r ) ); didFold = true; @@ -230,11 +235,17 @@ P_ExpressionNode T_ConstantFolder_::doIdExpr( } if ( node.id( ) == "width" ) { + oData.logger( []{ + return T_StringBuilder{ "replacing $width with fixed width" }; + } , 2 ); return NewOwned< T_ConstantExprNode >( node.parent( ) , double( oData.fixedSize->first ) ); } if ( node.id( ) == "height" ) { + oData.logger( []{ + return T_StringBuilder{ "replacing $height with fixed height" }; + } , 2 ); return NewOwned< T_ConstantExprNode >( node.parent( ) , float( oData.fixedSize->second ) ); } @@ -363,10 +374,20 @@ bool opopt::FoldConstants( T_OptData& oData ) noexcept { T_ConstantFolder_ folder{ oData }; + oData.logger( []() { + return T_StringBuilder{ "constant folding pass" }; + } , 1 ); if ( oData.curves ) { oData.findInputDecls( program ); } - oData.visitor.visit( program.root , folder ); + oData.visitor.visit( program.root , [&]( auto& n , auto x ) { + return folder( n , x ); + } ); + oData.logger( [&]() { + return T_StringBuilder{ + folder.didFold ? "some constants were folded" + : "no constants were folded" }; + } , 1 ); return folder.didFold; } diff --git a/c-opopt.hh b/c-opopt.hh index d42863e..ccd749a 100644 --- a/c-opopt.hh +++ b/c-opopt.hh @@ -1,9 +1,9 @@ #pragma once #include "c-opast.hh" +#include "c-opcomp.hh" #include -struct T_OpsParserOutput; struct T_SyncCurves; namespace opopt { @@ -11,6 +11,9 @@ namespace opopt { // Persistent data for the various stages of the optimizer. struct T_OptData { + // Logger + F_OPLogger logger{ []( auto , auto ) {} }; + // List of errors generated by the optimizer T_Array< ebcl::T_SRDError > errors; @@ -19,7 +22,7 @@ struct T_OptData T_Optional< std::pair< uint32_t , uint32_t > > fixedSize; // The curves that will be bound to the inputs. - T_SyncCurves const* curves; + T_SyncCurves const* curves{ nullptr }; // A visitor to be used for the tree ebcl::T_Visitor< opast::A_Node > visitor{ opast::ASTVisitorBrowser }; diff --git a/c-opparser.cc b/c-opparser.cc index c5444ff..5255821 100644 --- a/c-opparser.cc +++ b/c-opparser.cc @@ -157,6 +157,7 @@ struct T_ParserImpl_ T_OwnPtr< T_OpsParserOutput >& output; T_Array< T_SRDError >& errors; + F_OPLogger& logger; T_MultiArray< uint32_t > calls; T_Array< T_InstrRestriction > callInfo; T_SRDParserConfig ovParserConfig; @@ -174,7 +175,8 @@ struct T_ParserImpl_ T_SyncOverrideVisitor ovVisitor; T_ParserImpl_( T_Array< T_SRDError >* errors , - T_OwnPtr< T_OpsParserOutput >* root ) noexcept; + T_OwnPtr< T_OpsParserOutput >* root , + F_OPLogger* logger ) noexcept; // --------------------------------------------------------------------- @@ -304,8 +306,9 @@ struct T_ParserImpl_ inline T_ParserImpl_::T_ParserImpl_( T_Array< T_SRDError >* const errors , - T_OwnPtr< T_OpsParserOutput >* const output ) noexcept - : output( *output ) , errors( *errors ) , + T_OwnPtr< T_OpsParserOutput >* const output , + F_OPLogger* logger ) noexcept + : output( *output ) , errors( *errors ) , logger( *logger ) , ovParserConfig( sov::GetParserConfig( ) ) , ovParser( ovParserConfig ) { } @@ -531,11 +534,11 @@ bool T_ParserImpl_::collectGlobalTypes( ) noexcept } assert( dt != E_DataType::UNKNOWN ); -#ifdef INVASIVE_TRACES - esb << "id " << id << " as " << dt << " at " << location << '\n' << '\0'; - printf( "%s" , esb.data( ) ); - esb.clear( ); -#endif + logger( [&]{ + T_StringBuilder sb; + sb << "id " << id << " as " << dt << " at " << location; + return sb; + } , 2 ); // When we find a set instruction, we need to check whether // it is affecting a local variable. If it is we'll just skip @@ -586,6 +589,8 @@ bool T_ParserImpl_::collectGlobalTypes( ) noexcept bool T_ParserImpl_::checkArgumentTypes( ) noexcept { + logger( []{ return T_StringBuilder{ "Checking argument types" }; } , 1 ); + // Find functions for which arguments types need to be resolved const auto nFunctions( output->root.nFunctions( ) ); bool argsResolved[ nFunctions ]; @@ -624,12 +629,12 @@ bool T_ParserImpl_::checkArgumentTypes( ) noexcept } ); } -#ifdef INVASIVE_TRACES - T_StringBuilder tracer; -#define TRACE( x ) do { tracer.clear( ) << x << '\0'; printf( "%s\n" , tracer.data( ) ); } while (0) -#else -#define TRACE( x ) -#endif +#define TRACE( x ) \ + logger( [&]{ \ + T_StringBuilder sb; \ + sb << x; \ + return sb; \ + } , 2 ) T_StringBuilder esb; bool changed = true; @@ -2039,7 +2044,8 @@ P_ExpressionNode T_ParserImpl_::parseUnaryOp( /*----------------------------------------------------------------------------*/ T_OpsParser::T_OpsParser( ) noexcept - : A_PrivateImplementation( new T_ParserImpl_( &errors_ , &output_ ) ) , + : A_PrivateImplementation( new T_ParserImpl_( + &errors_ , &output_ , &logger_ ) ) , errors_( 64 ) , output_{} {} diff --git a/m-builder.cc b/m-builder.cc index 444eb74..8aafae1 100644 --- a/m-builder.cc +++ b/m-builder.cc @@ -2,6 +2,7 @@ #include "c-opast.hh" #include "c-ops.hh" #include "c-opcomp.hh" +#include "c-opopt.hh" #include #include #include @@ -42,6 +43,16 @@ void WriteSRDError( int main( int argc , char** argv ) { + uint32_t logLevel{ 0 }; + const auto logger{ [=]( F_OPGenLog func , uint32_t level ) { + if ( level > logLevel ) { + return; + } + auto sb{ func( ) }; + sb << '\0'; + printf( "LOG{%d} %s\n" , level , sb.data( ) ); + } }; + // Open file const T_String inputName( argc >= 2 ? argv[ 1 ] : "demo.srd" ); T_File input( inputName , E_FileMode::READ_ONLY ); @@ -73,14 +84,10 @@ int main( int argc , char** argv ) return 2; } - // Parse the fuck + // Parse T_OpsParser parser; - if ( parser.parse( srdOut.list( ) ) ) { - printf( "Parser successful. Compiling...\n" ); - T_OpsCompiler compiler; - compiler.compile( *parser.result( ) ); - return 0; - } else { + parser.setLogger( logger ); + if ( !parser.parse( srdOut.list( ) ) ) { T_StringBuilder sb; for ( auto const& err : parser.errors( ) ) { WriteSRDError( sb , err ); @@ -89,4 +96,20 @@ int main( int argc , char** argv ) fprintf( stderr , "%s" , sb.data( ) ); return 3; } + auto parsed{ parser.result( ) }; + + // Optimize + opopt::T_OptData od; + od.logger = logger; + //od.fixedSize = std::make_pair( 1280u , 720u ); + bool doneStuff{ false }; + do { + doneStuff = opopt::FoldConstants( *parsed , od ); + doneStuff = opopt::RemoveDeadCode( *parsed , od ) || doneStuff; + } while ( doneStuff ); + + // Compile + T_OpsCompiler compiler; + compiler.compile( *parsed ); + return 0; }