Optimizer - Var use finder refactored

This commit is contained in:
Emmanuel BENOîT 2017-12-04 07:03:54 +01:00
parent f1ec2cf18c
commit fa7fba0f98

View file

@ -356,6 +356,7 @@ void T_OptData::buildControlFlowGraph(
/*= T_OptData - USE/DEFINE CHAINS ============================================*/
namespace {
#warning Remove this later
#undef LL1
@ -363,6 +364,78 @@ void T_OptData::buildControlFlowGraph(
#define LL1 1
#define LL2 1
void BUDCAddUseRecord_(
A_Node& n ,
T_OptData& od ,
T_RootNode& root ) noexcept
{
// Find instruction and function index
auto& nId{ dynamic_cast< T_IdentifierExprNode& >( n ) };
A_FuncNode* func{ nullptr };
T_Optional< uint32_t > instrId;
A_Node* pn{ &nId };
while ( pn ) {
auto* const asInstr{ dynamic_cast< A_InstructionNode* >( pn ) };
func = dynamic_cast< A_FuncNode* >( pn );
if ( !instrId && asInstr ) {
instrId = od.indexOf( *asInstr );
} else if ( func ) {
break;
}
pn = &pn->parent( );
}
assert( func && instrId );
// Generate the identifier
const T_OptData::T_VarId varId{ [&]() {
auto const& n{ nId.id( ) };
if ( func->hasLocal( nId.id( ) ) ) {
return T_OptData::T_VarId{ n , func->name( ) ,
func->isArgument( nId.id( ) ) };
}
return T_OptData::T_VarId{ n };
} () };
// Access or create the record
auto* const varRec{ [&]() {
auto* const x{ od.varUDChains.get( varId ) };
if ( x ) {
return x;
}
od.varUDChains.add( T_OptData::T_VarUseDefine{ varId } );
return od.varUDChains.get( varId );
} () };
assert( varRec );
// Add use record
auto& useRec{ varRec->uses.addNew( ) };
useRec.node = *instrId;
useRec.fnIndex = root.functionIndex( func->name( ) );
od.logger( [&](){
T_StringBuilder sb;
sb << "use " << varId.name << " at " << nId.location( ) << " (";
if ( varId.type == T_OptData::E_UDVarType::GLOBAL ) {
sb << "global";
} else {
if ( varId.type == T_OptData::E_UDVarType::LOCAL ) {
sb << "local";
} else {
sb << "argument";
}
sb << " of " << varId.owner;
}
sb << ')';
return sb;
} , LL2 );
}
} // namespace <anon>
/*----------------------------------------------------------------------------*/
void T_OptData::buildUseDefineChains(
T_OpsParserOutput& program ) noexcept
{
@ -386,70 +459,10 @@ void T_OptData::buildUseDefineChains(
* looking at the call sites.
*/
visitor.visit( program.root , [&]( auto& n , const bool exit ) {
if ( n.type( ) != A_Node::EXPR_ID || exit ) {
return true;
if ( n.type( ) == A_Node::EXPR_ID && !exit ) {
BUDCAddUseRecord_( n , *this , program.root );
}
// Find instruction and function index
auto& nId{ dynamic_cast< T_IdentifierExprNode& >( n ) };
A_FuncNode* func{ nullptr };
T_Optional< uint32_t > instrId;
A_Node* pn{ &nId };
while ( pn ) {
auto* const asInstr{ dynamic_cast< A_InstructionNode* >( pn ) };
func = dynamic_cast< A_FuncNode* >( pn );
if ( !instrId && asInstr ) {
instrId = indexOf( *asInstr );
} else if ( func ) {
break;
}
pn = &pn->parent( );
}
assert( func && instrId );
// Generate the identifier
const T_VarId varId{ [&]() {
auto const& n{ nId.id( ) };
if ( func->hasLocal( nId.id( ) ) ) {
return T_VarId{ n , func->name( ) ,
func->isArgument( nId.id( ) ) };
}
return T_VarId{ n };
} () };
// Access or create the record
auto* const varRec{ [&]() {
auto* const x{ varUDChains.get( varId ) };
if ( x ) {
return x;
}
varUDChains.add( T_VarUseDefine{ varId } );
return varUDChains.get( varId );
} () };
assert( varRec );
// Add use record
auto& useRec{ varRec->uses.addNew( ) };
useRec.node = *instrId;
useRec.fnIndex = program.root.functionIndex( func->name( ) );
logger( [&](){
T_StringBuilder sb;
sb << "use " << varId.name << " at " << nId.location( ) << " (";
if ( varId.type == E_UDVarType::GLOBAL ) {
sb << "global";
} else {
if ( varId.type == E_UDVarType::LOCAL ) {
sb << "local";
} else {
sb << "argument";
}
sb << " of " << varId.owner;
}
sb << ')';
return sb;
} , LL2 );
return true;
} );
}