demotool/c-opopt.cc

172 lines
4 KiB
C++

#include "externals.hh"
#include "c-opopt.hh"
#include "c-sync.hh"
using namespace ebcl;
using namespace opast;
using namespace opopt;
// Macro to use either the specified visitor or a visitor created just for the
// occation
#define M_VISITOR_( E ) \
T_OwnPtr< T_Visitor< A_Node > > localVisitor_; \
if ( !(E) ) { \
localVisitor_ = NewOwned< T_Visitor< A_Node > >( ASTVisitorBrowser ); \
} \
T_Visitor< A_Node >& visitor{ (E) ? *(E) : *localVisitor_ }
/*= CONSTANT FOLDING =========================================================*/
namespace {
struct T_ConstantFolder_
{
// Input
T_Optional< std::pair< uint32_t , uint32_t > > fixedSize;
T_SyncCurves const* curves;
// Result
bool didFold{ false };
bool operator()( A_Node& node , bool exit ) noexcept;
private:
using F_ExprGet_ = std::function< A_ExpressionNode&( A_Node& ) >;
using F_ExprSet_ = std::function< void( A_Node& , P_ExpressionNode ) >;
void handleParentNode(
A_Node& node ,
F_ExprGet_ get ,
F_ExprSet_ set ) noexcept;
P_ExpressionNode checkExpression(
A_ExpressionNode const& node ) noexcept;
};
/*----------------------------------------------------------------------------*/
bool T_ConstantFolder_::operator()(
A_Node& node ,
const bool exit ) noexcept
{
if ( exit ) {
return true;
}
switch ( node.type( ) ) {
case A_Node::TN_ARG:
handleParentNode( node ,
[]( A_Node& n ) -> A_ExpressionNode& {
return ((T_ArgumentNode&)n).expression( );
} ,
[]( A_Node& n , P_ExpressionNode e ) {
((T_ArgumentNode&)n).expression( std::move( e ) );
} );
return false;
case A_Node::TN_CONDITION:
handleParentNode( node ,
[]( A_Node& n ) -> A_ExpressionNode& {
return ((T_CondInstrNode::T_Expression&)n).expression( );
} ,
[]( A_Node& n , P_ExpressionNode e ) {
((T_CondInstrNode::T_Expression&)n).expression( std::move( e ) );
} );
return false;
case A_Node::OP_SET:
handleParentNode( node ,
[]( A_Node& n ) -> A_ExpressionNode& {
return ((T_SetInstrNode&)n).expression( );
} ,
[]( A_Node& n , P_ExpressionNode e ) {
((T_SetInstrNode&)n).setExpression( std::move( e ) );
} );
return false;
default:
return true;
}
}
void T_ConstantFolder_::handleParentNode(
A_Node& node ,
F_ExprGet_ get ,
F_ExprSet_ set ) noexcept
{
auto r{ checkExpression( get( node ) ) };
if ( r ) {
set( node , std::move( r ) );
didFold = true;
}
}
/*----------------------------------------------------------------------------*/
P_ExpressionNode T_ConstantFolder_::checkExpression(
A_ExpressionNode const& node ) noexcept
{
#warning TODO optimize the fuck
// 1/ Replace inputs with value if no curve/constant curve
// Replace $width/$height with value if fixedSize
// 2/ Replace UnOp( Cnst ) with result
// Replace BinOp( Cnst , Cnst ) with result
// 3/ Try to find other optimisations, e.g. for Add( Cnst , Add( Cnst , Expr ) )
if ( node.type( ) == A_Node::EXPR_ID ) {
if ( !fixedSize ) {
return {};
}
T_IdentifierExprNode& n{ (T_IdentifierExprNode&) node };
if ( n.id( ) == "width" ) {
auto c{ NewOwned< T_ConstantExprNode >( n.parent( ) ,
double( fixedSize->first ) ) };
c->location( ) = n.location( );
return c;
}
if ( n.id( ) == "height" ) {
auto c{ NewOwned< T_ConstantExprNode >( n.parent( ) ,
float( fixedSize->second ) ) };
c->location( ) = n.location( );
return c;
}
return {};
}
return {};
}
} // namespace <anon>
bool opopt::FoldConstants(
T_RootNode& root ,
const T_Optional< std::pair< uint32_t , uint32_t > > fixedSize ,
T_SyncCurves const* curves ,
T_Visitor< A_Node >* const extVisitor ) noexcept
{
M_VISITOR_( extVisitor );
T_ConstantFolder_ folder;
folder.fixedSize = fixedSize;
folder.curves = curves;
visitor.visit( root , folder );
return folder.didFold;
}
/*= DEAD CODE REMOVAL ========================================================*/
bool opopt::RemoveDeadCode( opast::T_RootNode& root ,
ebcl::T_Visitor< opast::A_Node >* extVisitor ) noexcept
{
M_VISITOR_( extVisitor );
#warning blargh
return false;
}