173 lines
4 KiB
C++
173 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;
|
||
|
}
|