diff --git a/c-opast.cc b/c-opast.cc index 1e3bae8..d0c0fa1 100644 --- a/c-opast.cc +++ b/c-opast.cc @@ -474,7 +474,7 @@ void T_InstrListNode::replaceMultiple( children_.addNew( ); } const auto newSize{ children_.size( ) }; - const auto nMove{ oldSize + 1 - index }; + const auto nMove{ rep.size( ) > 1 ? ( oldSize - index ) : 0 }; for ( auto i = 1u ; i < nMove ; i ++ ) { children_[ newSize - i ] = std::move( children_[ oldSize - i ] ); @@ -486,6 +486,8 @@ void T_InstrListNode::replaceMultiple( rep.children_[ i ] ); children_[ index + i ]->setParent( *this ); } + + rep.children_.clear( ); } else { children_.remove( index ); } diff --git a/c-opast.hh b/c-opast.hh index 38ad3de..b038984 100644 --- a/c-opast.hh +++ b/c-opast.hh @@ -622,6 +622,9 @@ class T_SetInstrNode : public A_InstructionNode ebcl::T_SRDLocation const& idLocation( ) const noexcept { return idLocation_; } + void id( T_String const& nid ) noexcept + { id_ = nid; } + void setExpression( P_ExpressionNode expression ) noexcept { if ( children_.size( ) ) { @@ -707,6 +710,13 @@ class T_FramebufferInstrNode : public A_ResourceDefInstrNode T_ArgumentNode* lod( ) const noexcept { return (T_ArgumentNode*) ( children_.size( ) ? child( 0 ).get( ) : nullptr ); } + + void id( T_String const& nid , + ebcl::T_SRDLocation const& loc ) noexcept + { + id_ = nid; + location( ) = loc; + } }; private: @@ -802,6 +812,14 @@ class T_PipelineInstrNode : public A_ResourceDefInstrNode { return pids_[ index ]; } ebcl::T_SRDLocation const& pLocation( const uint32_t index ) const noexcept { return pidLocations_[ index ]; } + + void program( const uint32_t index , + T_String const& id , + ebcl::T_SRDLocation const& location ) noexcept + { + pids_[ index ] = id; + pidLocations_[ index ] = location; + } }; // Program loader instruction @@ -1119,6 +1137,9 @@ class T_UniformsInstrNode : public A_InstructionNode { return progId_; } ebcl::T_SRDLocation const& progIdLocation( ) const noexcept { return progIdLocation_; } + void progId( T_String const& id , + ebcl::T_SRDLocation const& location ) noexcept + { progId_ = id; progIdLocation_ = location; } uint32_t uloc( ) const noexcept { return uloc_; } @@ -1171,6 +1192,9 @@ class T_UseInstrNode : public A_InstructionNode { return id_; } ebcl::T_SRDLocation const& idLocation( ) const noexcept { return idLocation_; } + void id( T_String const& nid , + ebcl::T_SRDLocation const& location ) noexcept + { id_ = nid; idLocation_ = location; } }; // Texture/sampler use instructions @@ -1203,6 +1227,9 @@ class T_UseTextureInstrNode : public T_UseInstrNode { return samplerId_; } ebcl::T_SRDLocation const& samplerIdLocation( ) const noexcept { return samplerIdLocation_; } + void samplerId( T_String const& id , + ebcl::T_SRDLocation const& location ) noexcept + { samplerId_ = id; samplerIdLocation_ = location; } }; // Viewport instruction diff --git a/c-opopt.cc b/c-opopt.cc index e115f9c..4f14c47 100644 --- a/c-opopt.cc +++ b/c-opopt.cc @@ -1858,6 +1858,8 @@ bool opopt::InlineFunctions( T_String target; T_CallInstrNode* callInstrNode; uint32_t fnIndex; + uint32_t nArgs{ 0 }; + uint32_t nLocals{ 0 }; T_InlineFunction_( T_String target , @@ -1871,6 +1873,7 @@ bool opopt::InlineFunctions( struct T_InlineTarget_ { uint32_t count{ 1 }; uint32_t extraLocals{ 0 }; + T_AutoArray< T_String , 16 > elNames; }; // Find functions that can be inlined @@ -1970,11 +1973,12 @@ bool opopt::InlineFunctions( // Compute extra locals required const auto nInlines{ ordered.size( ) }; for ( auto i = 0u ; i < nInlines ; i ++ ) { - auto const& ifd{ inlineFunctions.values( )[ ordered[ i ] ] }; + auto& ifd{ inlineFunctions.values( )[ ordered[ i ] ] }; auto const& fn{ program.root.function( ifd.fnIndex ) }; uint32_t nLocals{ fn.locals( ) }; for ( auto j = 0u ; j < fn.locals( ) ; j ++ ) { if ( fn.isArgument( fn.getLocalName( j ) ) ) { + ifd.nArgs ++; nLocals --; } } @@ -1984,11 +1988,234 @@ bool opopt::InlineFunctions( nLocals += asTarget->extraLocals; } + ifd.nLocals = nLocals; + auto* target{ inlineTargets.get( ifd.target ) }; target->extraLocals = std::max( target->extraLocals , nLocals ); } - // Merge (bottom to top) + // Add extra locals + const auto nTargets{ inlineTargets.size( ) }; + T_StringBuilder idsb; + for ( auto i = 0u ; i < nTargets ; i ++ ) { + auto& itd{ inlineTargets.values( )[ i ] }; + auto& fn{ program.root.function( inlineTargets.keys( )[ i ] ) }; + for ( auto j = 0u , c = 0u ; c < itd.extraLocals ; j ++ ) { + idsb.clear( ) << "*inline*" << j; + T_String id{ idsb }; + if ( !fn.hasLocal( id ) ) { + fn.addLocalVariable( id , T_SRDLocation{} ); + fn.setLocalType( fn.locals( ) - 1 , + opast::E_DataType::VARIABLE ); + itd.elNames.add( std::move( id ) ); + c ++; + } + } + } - return false; + // Merge (bottom to top) + for ( auto i = 0u ; i < nInlines ; i ++ ) { + auto const& ifd{ inlineFunctions.values( )[ i ] }; + auto const& itd{ *inlineTargets.get( ifd.target ) }; + auto& src{ program.root.function( ifd.fnIndex ) }; + auto& call{ *ifd.callInstrNode }; + oData.logger( [&]() { + T_StringBuilder sb; + sb << "Inlining function " << src.name( ); + return sb; + } , 5 ); + + // Replace arguments and locals + oData.visitor.visit( src.instructions( ) , [&]( A_Node& node , const bool exit ) { + if ( !exit ) { + return true; + } + + switch ( node.type( ) ) { + + default: break; + + case A_Node::EXPR_ID: { + auto const& id{ (T_IdentifierExprNode&) node }; + if ( !src.hasLocal( id.id( ) ) ) { + break; + } + T_OwnPtr< A_Node > nv; + if ( src.isArgument( id.id( ) ) ) { + const auto argIndex{ src.getLocalIndex( id.id( ) ) }; + auto const& callArg{ call.argument( argIndex ) }; + auto const& caValue{ callArg.expression( ) }; + if ( caValue.type( ) == A_Node::EXPR_CONST ) { + nv = NewOwned< T_ConstantExprNode >( + node.parent( ) , + ( (T_ConstantExprNode&) caValue ).floatValue( ) ); + } else { + nv = NewOwned< T_IdentifierExprNode >( + node.parent( ) , + ( (T_IdentifierExprNode&) caValue ).id( ) ); + } + } else { + nv = NewOwned< T_IdentifierExprNode >( + node.parent( ) , + itd.elNames[ src.getLocalIndex( id.id( ) ) - ifd.nArgs ] ); + } + oData.logger( [&]() { + T_StringBuilder sb; + sb << "Replacing identifier " << id.id( ) + << " at " << id.location( ) + << " with "; + if ( nv->type( ) == A_Node::EXPR_ID ) { + sb << "identifier " << ((T_IdentifierExprNode&)*nv).id( ); + } else { + sb << "constant " << ((T_ConstantExprNode&)*nv).floatValue( ); + } + return sb; + } , 6 ); + node.parent( ).replace( node , nv ); + break; + } + + case A_Node::OP_UNIFORMS: { + auto& n{ (T_UniformsInstrNode&) node }; + if ( src.isArgument( n.progId( ) ) ) { + const auto argIndex{ src.getLocalIndex( n.progId( ) ) }; + auto const& callArg{ call.argument( argIndex ) }; + auto const& caValue{ callArg.expression( ) }; + assert( caValue.type( ) == A_Node::EXPR_ID ); + auto const& repId{ ( (T_IdentifierExprNode&) caValue ).id( ) }; + oData.logger( [&]() { + T_StringBuilder sb; + sb << "Replacing identifier " << n.progId( ) + << " at " << n.progIdLocation( ) + << " with identifier " << repId; + return sb; + } , 6 ); + n.progId( repId , caValue.location( ) ); + } + break; + } + + case A_Node::OP_USE_TEXTURE: { + auto& n{ (T_UseTextureInstrNode&) node }; + if ( src.isArgument( n.samplerId( ) ) ) { + const auto argIndex{ src.getLocalIndex( n.samplerId( ) ) }; + auto const& callArg{ call.argument( argIndex ) }; + auto const& caValue{ callArg.expression( ) }; + assert( caValue.type( ) == A_Node::EXPR_ID ); + auto const& repId{ ( (T_IdentifierExprNode&) caValue ).id( ) }; + oData.logger( [&]() { + T_StringBuilder sb; + sb << "Replacing identifier " << n.samplerId( ) + << " at " << n.samplerIdLocation( ) + << " with identifier " << repId; + return sb; + } , 6 ); + n.samplerId( repId , caValue.location( ) ); + } + } // fallthrough + case A_Node::OP_USE_PROGRAM: + case A_Node::OP_USE_PIPELINE: + case A_Node::OP_USE_FRAMEBUFFER: { + auto& n{ (T_UseInstrNode&) node }; + if ( src.isArgument( n.id( ) ) ) { + const auto argIndex{ src.getLocalIndex( n.id( ) ) }; + auto const& callArg{ call.argument( argIndex ) }; + auto const& caValue{ callArg.expression( ) }; + assert( caValue.type( ) == A_Node::EXPR_ID ); + auto const& repId{ ( (T_IdentifierExprNode&) caValue ).id( ) }; + oData.logger( [&]() { + T_StringBuilder sb; + sb << "Replacing identifier " << n.id( ) + << " at " << n.idLocation( ) + << " with identifier " << repId; + return sb; + } , 6 ); + n.id( repId , caValue.location( ) ); + } + break; + } + + case A_Node::OP_PIPELINE: { + auto& n{ (T_PipelineInstrNode&) node }; + const auto np{ n.size( ) }; + for ( auto i = 0u ; i < np ; i ++ ) { + if ( src.isArgument( n.program( i ) ) ) { + const auto argIndex{ src.getLocalIndex( n.program( i ) ) }; + auto const& callArg{ call.argument( argIndex ) }; + auto const& caValue{ callArg.expression( ) }; + assert( caValue.type( ) == A_Node::EXPR_ID ); + auto const& repId{ ( (T_IdentifierExprNode&) caValue ).id( ) }; + oData.logger( [&]() { + T_StringBuilder sb; + sb << "Replacing identifier " << n.program( i ) + << " at " << n.pLocation( i ) + << " with identifier " << repId; + return sb; + } , 6 ); + n.program( i , repId , caValue.location( ) ); + } + } + break; + } + + case A_Node::TN_FBATT: { + auto& n{ (T_FramebufferInstrNode::T_Attachment&) node }; + if ( src.isArgument( n.id( ) ) ) { + const auto argIndex{ src.getLocalIndex( n.id( ) ) }; + auto const& callArg{ call.argument( argIndex ) }; + auto const& caValue{ callArg.expression( ) }; + assert( caValue.type( ) == A_Node::EXPR_ID ); + auto const& repId{ ( (T_IdentifierExprNode&) caValue ).id( ) }; + oData.logger( [&]() { + T_StringBuilder sb; + sb << "Replacing identifier " << n.id( ) + << " at " << n.location( ) + << " with identifier " << repId; + return sb; + } , 6 ); + n.id( repId , caValue.location( ) ); + } + break; + } + + case A_Node::OP_SET: { + auto& n{ (T_SetInstrNode&) node }; + if ( !src.hasLocal( n.id( ) ) ) { + break; + } + auto const& nid{ + itd.elNames[ src.getLocalIndex( n.id( ) ) - ifd.nArgs ] + }; + oData.logger( [&]() { + T_StringBuilder sb; + sb << "Replacing identifier " << n.id( ) + << " at " << n.location( ) + << " with identifier " << nid; + return sb; + } , 6 ); + n.id( nid ); + break; + } + + } + + return true; + } ); + + ((T_InstrListNode&) call.parent( )).replaceMultiple( + call , &src.instructions( ) ); + } + + T_AutoArray< T_String , 32 > iffns; + iffns.ensureCapacity( nInlines ); + for ( auto i = 0u ; i < nInlines ; i ++ ) { + auto const& ifd{ inlineFunctions.values( )[ i ] }; + iffns.add( program.root.function( ifd.fnIndex ).name( ) ); + } + for ( auto i = 0u ; i < nInlines ; i ++ ) { + program.root.removeFunction( iffns[ i ] ); + } + + oData.state = {}; + return true; }