Compiler - Metadata for operators' stack effects

This commit is contained in:
Emmanuel BENOîT 2017-11-12 18:38:31 +01:00
parent dd4c1ba7cd
commit bf1c4aa1b0
3 changed files with 120 additions and 45 deletions

View file

@ -38,6 +38,8 @@ enum E_OpType
M_LSHIFT_OP( T_StringBuilder , E_OpType ); M_LSHIFT_OP( T_StringBuilder , E_OpType );
uint32_t ArgumentsFor( E_OpType op ) noexcept; uint32_t ArgumentsFor( E_OpType op ) noexcept;
int32_t DeltaMainStack( E_OpType op ) noexcept;
int32_t DeltaFPUStack( E_OpType op ) noexcept;
struct T_Op struct T_Op

View file

@ -56,6 +56,8 @@ struct T_CompilerImpl_
E_OpType op , E_OpType op ,
uint32_t arg0 , uint32_t arg1 , uint32_t arg0 , uint32_t arg1 ,
T_SRDLocation const& location ) noexcept; T_SRDLocation const& location ) noexcept;
void applyStackEffects(
T_Op const& op ) noexcept;
}; };
@ -318,22 +320,17 @@ bool T_CompilerImpl_::compileNode(
if ( !main ) { if ( !main ) {
addInstruction( OP_PUSH , node.location( ) ); addInstruction( OP_PUSH , node.location( ) );
addInstruction( OP_FP_SSTORE , 0 , node.location( ) ); addInstruction( OP_FP_SSTORE , 0 , node.location( ) );
sdMain ++;
sdFPU --;
} }
return false; return false;
} else if ( exit && !n.isIdentifier( ) ) { } else if ( exit && !n.isIdentifier( ) ) {
addInstruction( OP_PUSH , node.location( ) ); addInstruction( OP_PUSH , node.location( ) );
addInstruction( OP_FP_SSTORE , 0 , node.location( ) ); addInstruction( OP_FP_SSTORE , 0 , node.location( ) );
sdMain ++;
sdFPU --;
} }
break; break;
} }
case A_Node::OP_SET: case A_Node::OP_SET:
if ( exit ) { if ( exit ) {
assert( sdFPU > 0 );
auto& id( ((T_SetInstrNode&)node).id( ) ); auto& id( ((T_SetInstrNode&)node).id( ) );
auto& func{ input->root.function( funcIndex ) }; auto& func{ input->root.function( funcIndex ) };
if ( func.hasLocal( id ) ) { if ( func.hasLocal( id ) ) {
@ -345,13 +342,11 @@ bool T_CompilerImpl_::compileNode(
*locations.get( ((T_SetInstrNode&)node).id( ) ) , *locations.get( ((T_SetInstrNode&)node).id( ) ) ,
node.location( ) ); node.location( ) );
} }
sdFPU --;
} }
break; break;
case A_Node::OP_COND: case A_Node::OP_COND:
if ( exit ) { if ( exit ) {
assert( sdMain > 0 );
addInstruction( OP_POP , 0 , node.location( ) ); addInstruction( OP_POP , 0 , node.location( ) );
sdMain --; sdMain --;
} }
@ -361,8 +356,6 @@ bool T_CompilerImpl_::compileNode(
if ( exit ) { if ( exit ) {
addInstruction( OP_PUSH , node.location( ) ); addInstruction( OP_PUSH , node.location( ) );
addInstruction( OP_FP_SSTORE_INT , 0 , node.location( ) ); addInstruction( OP_FP_SSTORE_INT , 0 , node.location( ) );
sdFPU --;
sdMain ++;
} }
break; break;
@ -395,30 +388,22 @@ bool T_CompilerImpl_::compileNode(
case A_Node::EXPR_ADD: case A_Node::EXPR_ADD:
if ( exit ) { if ( exit ) {
assert( sdFPU > 2 );
addInstruction( OP_FP_ADD , node.location( ) ); addInstruction( OP_FP_ADD , node.location( ) );
sdFPU --;
} }
break; break;
case A_Node::EXPR_SUB: case A_Node::EXPR_SUB:
if ( exit ) { if ( exit ) {
assert( sdFPU > 2 );
addInstruction( OP_FP_SUB , node.location( ) ); addInstruction( OP_FP_SUB , node.location( ) );
sdFPU --;
} }
break; break;
case A_Node::EXPR_MUL: case A_Node::EXPR_MUL:
if ( exit ) { if ( exit ) {
assert( sdFPU > 2 );
addInstruction( OP_FP_MUL , node.location( ) ); addInstruction( OP_FP_MUL , node.location( ) );
sdFPU --;
} }
break; break;
case A_Node::EXPR_DIV: case A_Node::EXPR_DIV:
if ( exit ) { if ( exit ) {
assert( sdFPU > 2 );
addInstruction( OP_FP_DIV , node.location( ) ); addInstruction( OP_FP_DIV , node.location( ) );
sdFPU --;
} }
break; break;
@ -429,7 +414,6 @@ bool T_CompilerImpl_::compileNode(
addInstruction( OP_FP_LOAD , addInstruction( OP_FP_LOAD ,
constants.indexOf( value.u ) + 3 , constants.indexOf( value.u ) + 3 ,
node.location( ) ); node.location( ) );
sdFPU ++;
} }
break; break;
@ -456,7 +440,7 @@ void T_CompilerImpl_::processFunction(
addInstruction( OP_POP , lvars - 1 , location ); addInstruction( OP_POP , lvars - 1 , location );
sdMain -= lvars; sdMain -= lvars;
} }
sdMain -= 1 + args; sdMain -= args;
addInstruction( OP_RET , args , location ); addInstruction( OP_RET , args , location );
assert( sdMain == 0 ); assert( sdMain == 0 );
} else { } else {
@ -492,13 +476,11 @@ bool T_CompilerImpl_::processIdentifier(
const auto p( sdMain - ( stackPos + 1 ) ); const auto p( sdMain - ( stackPos + 1 ) );
if ( dt == E_DataType::VARIABLE ) { if ( dt == E_DataType::VARIABLE ) {
addInstruction( OP_FP_SLOAD , p , node.location( ) ); addInstruction( OP_FP_SLOAD , p , node.location( ) );
sdFPU ++;
return false; return false;
} }
addInstruction( OP_SLOAD , p , node.location( ) ); addInstruction( OP_SLOAD , p , node.location( ) );
addInstruction( OP_PUSH , node.location( ) ); addInstruction( OP_PUSH , node.location( ) );
sdMain ++;
return true; return true;
} }
@ -509,14 +491,12 @@ bool T_CompilerImpl_::processIdentifier(
if ( dt == E_DataType::VARIABLE || dt == E_DataType::BUILTIN ) { if ( dt == E_DataType::VARIABLE || dt == E_DataType::BUILTIN ) {
addInstruction( OP_FP_LOAD , *locations.get( node.id( ) ) , addInstruction( OP_FP_LOAD , *locations.get( node.id( ) ) ,
node.location( ) ); node.location( ) );
sdFPU ++;
return false; return false;
} }
addInstruction( OP_LOAD , *locations.get( node.id( ) ) , addInstruction( OP_LOAD , *locations.get( node.id( ) ) ,
node.location( ) ); node.location( ) );
addInstruction( OP_PUSH , node.location( ) ); addInstruction( OP_PUSH , node.location( ) );
sdMain ++;
return true; return true;
} }
@ -526,7 +506,7 @@ void T_CompilerImpl_::addInstruction(
T_SRDLocation const& location ) noexcept T_SRDLocation const& location ) noexcept
{ {
assert( ArgumentsFor( op ) == 0 ); assert( ArgumentsFor( op ) == 0 );
output->ops.addNew( op , location ); applyStackEffects( output->ops.addNew( op , location ) );
} }
void T_CompilerImpl_::addInstruction( void T_CompilerImpl_::addInstruction(
@ -535,7 +515,7 @@ void T_CompilerImpl_::addInstruction(
T_SRDLocation const& location ) noexcept T_SRDLocation const& location ) noexcept
{ {
assert( ArgumentsFor( op ) == 1 ); assert( ArgumentsFor( op ) == 1 );
output->ops.addNew( op , location , arg0 ); applyStackEffects( output->ops.addNew( op , location , arg0 ) );
} }
void T_CompilerImpl_::addInstruction( void T_CompilerImpl_::addInstruction(
@ -545,7 +525,31 @@ void T_CompilerImpl_::addInstruction(
T_SRDLocation const& location ) noexcept T_SRDLocation const& location ) noexcept
{ {
assert( ArgumentsFor( op ) == 2 ); assert( ArgumentsFor( op ) == 2 );
output->ops.addNew( op , location , arg0 , arg1 ); applyStackEffects( output->ops.addNew( op , location , arg0 , arg1 ) );
}
void T_CompilerImpl_::applyStackEffects(
T_Op const& op ) noexcept
{
const auto m( DeltaMainStack( op.op ) );
const auto f( DeltaFPUStack( op.op ) );
#ifdef INVASIVE_TRACES
T_StringBuilder sb;
sb << "applying stack effects for (" << op << ") - sdMain " << sdMain
<< " (" << m << ") sdFPU " << sdFPU << " (" << f << ")" << '\n' << '\0';
printf( "%s" , sb.data( ) );
#endif
if ( m ) {
assert( m > 0 || sdMain >= uint32_t( -m ) );
sdMain += m;
}
if ( f ) {
assert( f > 0 || sdFPU >= uint32_t( -m ) );
sdFPU += m;
}
} }
} }

107
ops.cc
View file

@ -14,43 +14,98 @@ namespace {
struct T_OpInfo struct T_OpInfo
{ {
char const* name; char const* name;
int nArgs; uint32_t nArgs;
int32_t sdMain{ 0 };
int32_t sdFPU{ 0 };
uint32_t fpuReq{ 0 };
T_OpInfo( char const* name , template< typename ... Mods >
int nArgs = 0 ) constexpr T_OpInfo( char const* name ,
: name( name ) , nArgs( nArgs ) uint32_t nArgs ,
{ } Mods&&... mods );
constexpr T_OpInfo( char const* name );
}; };
template< typename ... Mods >
constexpr void ApplyMods_( T_OpInfo& op , Mods&&... mods );
template< >
constexpr void ApplyMods_( T_OpInfo& )
{ }
template< typename M0 , typename ... Mods >
constexpr void ApplyMods_(
T_OpInfo& op ,
M0&& mod ,
Mods&&... mods )
{
mod.applyTo( op );
ApplyMods_( op , std::forward< Mods >( mods ) ... );
}
template< typename ... Mods >
constexpr T_OpInfo::T_OpInfo(
char const* name ,
uint32_t nArgs ,
Mods&&... mods )
: name( name ) , nArgs( nArgs )
{
ApplyMods_( *this , std::forward< Mods >( mods ) ... );
}
constexpr T_OpInfo::T_OpInfo( char const* name )
: T_OpInfo( name , 0 )
{}
struct OpStackMain
{
int32_t value;
explicit constexpr OpStackMain( int32_t v ) : value( v ) { }
constexpr void applyTo( T_OpInfo& op )
{ op.sdMain = value; }
};
struct OpStackFPU
{
int32_t value;
explicit constexpr OpStackFPU( int32_t v ) : value( v ) { }
constexpr void applyTo( T_OpInfo& op )
{ op.sdFPU = value; }
};
static T_KeyValueTable< E_OpType , T_OpInfo > OpInfoTable_{ ([]() { static T_KeyValueTable< E_OpType , T_OpInfo > OpInfoTable_{ ([]() {
T_KeyValueTable< E_OpType , T_OpInfo > infos; T_KeyValueTable< E_OpType , T_OpInfo > infos;
infos.add( E_OpType::OP_END , T_OpInfo{ "end" } ); infos.add( E_OpType::OP_END , T_OpInfo{ "end" } );
// //
infos.add( E_OpType::OP_CALL , T_OpInfo{ "call" , 1 } ); infos.add( E_OpType::OP_CALL , T_OpInfo{ "call" , 1 } );
infos.add( E_OpType::OP_RET , T_OpInfo{ "ret" , 1 } ); infos.add( E_OpType::OP_RET , T_OpInfo{ "ret" , 1 , OpStackMain{ -1 } } );
infos.add( E_OpType::OP_COND_JUMP , T_OpInfo{ "cond-jump" , 2 } ); infos.add( E_OpType::OP_COND_JUMP , T_OpInfo{ "cond-jump" , 2 } );
// //
infos.add( E_OpType::OP_RES_STACK , T_OpInfo{ "res-stack" , 1 } ); infos.add( E_OpType::OP_RES_STACK , T_OpInfo{ "res-stack" , 1 } );
infos.add( E_OpType::OP_PUSH , T_OpInfo{ "push" } ); infos.add( E_OpType::OP_PUSH , T_OpInfo{ "push" , 0 , OpStackMain{ 1 } } );
infos.add( E_OpType::OP_POP , T_OpInfo{ "pop" , 1 } ); infos.add( E_OpType::OP_POP , T_OpInfo{ "pop" , 1 } );
// //
infos.add( E_OpType::OP_LOAD , T_OpInfo{ "load" , 1 } ); infos.add( E_OpType::OP_LOAD , T_OpInfo{ "load" , 1 } );
infos.add( E_OpType::OP_SLOAD , T_OpInfo{ "load-stack" , 1 } ); infos.add( E_OpType::OP_SLOAD , T_OpInfo{ "load-stack" , 1 } );
// //
infos.add( E_OpType::OP_FP_LOAD , T_OpInfo{ "fp-load" , 1 } ); infos.add( E_OpType::OP_FP_LOAD , T_OpInfo{ "fp-load" , 1 , OpStackFPU{ 1 } } );
infos.add( E_OpType::OP_FP_SLOAD , T_OpInfo{ "fp-load-stack" , 1 } ); infos.add( E_OpType::OP_FP_SLOAD , T_OpInfo{ "fp-load-stack" , 1 , OpStackFPU{ 1 } } );
infos.add( E_OpType::OP_FP_STORE , T_OpInfo{ "fp-store" , 1 } ); infos.add( E_OpType::OP_FP_STORE , T_OpInfo{ "fp-store" , 1 , OpStackFPU{ -1 } } );
infos.add( E_OpType::OP_FP_SSTORE , T_OpInfo{ "fp-store-stack" , 1 } ); infos.add( E_OpType::OP_FP_SSTORE , T_OpInfo{ "fp-store-stack" , 1 , OpStackFPU{ -1 } } );
infos.add( E_OpType::OP_FP_SSTORE_INT , T_OpInfo{ "fp-store-stack-int" , 1 } ); infos.add( E_OpType::OP_FP_SSTORE_INT , T_OpInfo{ "fp-store-stack-int" , 1 , OpStackFPU{ -1 } } );
// //
infos.add( E_OpType::OP_FP_CMP , T_OpInfo{ "fp-cmp" , 1 } ); infos.add( E_OpType::OP_FP_CMP , T_OpInfo{ "fp-cmp" , 1 , OpStackFPU{ -1 } } );
infos.add( E_OpType::OP_FP_ADD , T_OpInfo{ "fp-add" } ); infos.add( E_OpType::OP_FP_ADD , T_OpInfo{ "fp-add" , 0 , OpStackFPU{ -1 } } );
infos.add( E_OpType::OP_FP_SUB , T_OpInfo{ "fp-sub" } ); infos.add( E_OpType::OP_FP_SUB , T_OpInfo{ "fp-sub" , 0 , OpStackFPU{ -1 } } );
infos.add( E_OpType::OP_FP_MUL , T_OpInfo{ "fp-mul" } ); infos.add( E_OpType::OP_FP_MUL , T_OpInfo{ "fp-mul" , 0 , OpStackFPU{ -1 } } );
infos.add( E_OpType::OP_FP_DIV , T_OpInfo{ "fp-div" } ); infos.add( E_OpType::OP_FP_DIV , T_OpInfo{ "fp-div" , 0 , OpStackFPU{ -1 } } );
infos.add( E_OpType::OP_FP_MUL , T_OpInfo{ "fp-neg" } ); infos.add( E_OpType::OP_FP_MUL , T_OpInfo{ "fp-neg" , 0 } );
infos.add( E_OpType::OP_FP_DIV , T_OpInfo{ "fp-inv" } ); infos.add( E_OpType::OP_FP_DIV , T_OpInfo{ "fp-inv" , 0 } );
return infos; return infos;
})( ) }; })( ) };
@ -64,6 +119,20 @@ uint32_t ops::ArgumentsFor(
return OpInfoTable_.get( op )->nArgs; return OpInfoTable_.get( op )->nArgs;
} }
int32_t ops::DeltaMainStack(
const E_OpType op ) noexcept
{
assert( OpInfoTable_.contains( op ) );
return OpInfoTable_.get( op )->sdMain;
}
int32_t ops::DeltaFPUStack(
const E_OpType op ) noexcept
{
assert( OpInfoTable_.contains( op ) );
return OpInfoTable_.get( op )->sdFPU;
}
/*= STRING FORMATTING ==========================================================*/ /*= STRING FORMATTING ==========================================================*/