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 );
uint32_t ArgumentsFor( E_OpType op ) noexcept;
int32_t DeltaMainStack( E_OpType op ) noexcept;
int32_t DeltaFPUStack( E_OpType op ) noexcept;
struct T_Op

View file

@ -56,6 +56,8 @@ struct T_CompilerImpl_
E_OpType op ,
uint32_t arg0 , uint32_t arg1 ,
T_SRDLocation const& location ) noexcept;
void applyStackEffects(
T_Op const& op ) noexcept;
};
@ -318,22 +320,17 @@ bool T_CompilerImpl_::compileNode(
if ( !main ) {
addInstruction( OP_PUSH , node.location( ) );
addInstruction( OP_FP_SSTORE , 0 , node.location( ) );
sdMain ++;
sdFPU --;
}
return false;
} else if ( exit && !n.isIdentifier( ) ) {
addInstruction( OP_PUSH , node.location( ) );
addInstruction( OP_FP_SSTORE , 0 , node.location( ) );
sdMain ++;
sdFPU --;
}
break;
}
case A_Node::OP_SET:
if ( exit ) {
assert( sdFPU > 0 );
auto& id( ((T_SetInstrNode&)node).id( ) );
auto& func{ input->root.function( funcIndex ) };
if ( func.hasLocal( id ) ) {
@ -345,13 +342,11 @@ bool T_CompilerImpl_::compileNode(
*locations.get( ((T_SetInstrNode&)node).id( ) ) ,
node.location( ) );
}
sdFPU --;
}
break;
case A_Node::OP_COND:
if ( exit ) {
assert( sdMain > 0 );
addInstruction( OP_POP , 0 , node.location( ) );
sdMain --;
}
@ -361,8 +356,6 @@ bool T_CompilerImpl_::compileNode(
if ( exit ) {
addInstruction( OP_PUSH , node.location( ) );
addInstruction( OP_FP_SSTORE_INT , 0 , node.location( ) );
sdFPU --;
sdMain ++;
}
break;
@ -395,30 +388,22 @@ bool T_CompilerImpl_::compileNode(
case A_Node::EXPR_ADD:
if ( exit ) {
assert( sdFPU > 2 );
addInstruction( OP_FP_ADD , node.location( ) );
sdFPU --;
}
break;
case A_Node::EXPR_SUB:
if ( exit ) {
assert( sdFPU > 2 );
addInstruction( OP_FP_SUB , node.location( ) );
sdFPU --;
}
break;
case A_Node::EXPR_MUL:
if ( exit ) {
assert( sdFPU > 2 );
addInstruction( OP_FP_MUL , node.location( ) );
sdFPU --;
}
break;
case A_Node::EXPR_DIV:
if ( exit ) {
assert( sdFPU > 2 );
addInstruction( OP_FP_DIV , node.location( ) );
sdFPU --;
}
break;
@ -429,7 +414,6 @@ bool T_CompilerImpl_::compileNode(
addInstruction( OP_FP_LOAD ,
constants.indexOf( value.u ) + 3 ,
node.location( ) );
sdFPU ++;
}
break;
@ -456,7 +440,7 @@ void T_CompilerImpl_::processFunction(
addInstruction( OP_POP , lvars - 1 , location );
sdMain -= lvars;
}
sdMain -= 1 + args;
sdMain -= args;
addInstruction( OP_RET , args , location );
assert( sdMain == 0 );
} else {
@ -492,13 +476,11 @@ bool T_CompilerImpl_::processIdentifier(
const auto p( sdMain - ( stackPos + 1 ) );
if ( dt == E_DataType::VARIABLE ) {
addInstruction( OP_FP_SLOAD , p , node.location( ) );
sdFPU ++;
return false;
}
addInstruction( OP_SLOAD , p , node.location( ) );
addInstruction( OP_PUSH , node.location( ) );
sdMain ++;
return true;
}
@ -509,14 +491,12 @@ bool T_CompilerImpl_::processIdentifier(
if ( dt == E_DataType::VARIABLE || dt == E_DataType::BUILTIN ) {
addInstruction( OP_FP_LOAD , *locations.get( node.id( ) ) ,
node.location( ) );
sdFPU ++;
return false;
}
addInstruction( OP_LOAD , *locations.get( node.id( ) ) ,
node.location( ) );
addInstruction( OP_PUSH , node.location( ) );
sdMain ++;
return true;
}
@ -526,7 +506,7 @@ void T_CompilerImpl_::addInstruction(
T_SRDLocation const& location ) noexcept
{
assert( ArgumentsFor( op ) == 0 );
output->ops.addNew( op , location );
applyStackEffects( output->ops.addNew( op , location ) );
}
void T_CompilerImpl_::addInstruction(
@ -535,7 +515,7 @@ void T_CompilerImpl_::addInstruction(
T_SRDLocation const& location ) noexcept
{
assert( ArgumentsFor( op ) == 1 );
output->ops.addNew( op , location , arg0 );
applyStackEffects( output->ops.addNew( op , location , arg0 ) );
}
void T_CompilerImpl_::addInstruction(
@ -545,7 +525,31 @@ void T_CompilerImpl_::addInstruction(
T_SRDLocation const& location ) noexcept
{
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
{
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 ,
int nArgs = 0 )
: name( name ) , nArgs( nArgs )
{ }
template< typename ... Mods >
constexpr T_OpInfo( char const* name ,
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_{ ([]() {
T_KeyValueTable< E_OpType , T_OpInfo > infos;
infos.add( E_OpType::OP_END , T_OpInfo{ "end" } );
//
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_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_LOAD , T_OpInfo{ "load" , 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_SLOAD , T_OpInfo{ "fp-load-stack" , 1 } );
infos.add( E_OpType::OP_FP_STORE , T_OpInfo{ "fp-store" , 1 } );
infos.add( E_OpType::OP_FP_SSTORE , T_OpInfo{ "fp-store-stack" , 1 } );
infos.add( E_OpType::OP_FP_SSTORE_INT , T_OpInfo{ "fp-store-stack-int" , 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 , OpStackFPU{ 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 , OpStackFPU{ -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_ADD , T_OpInfo{ "fp-add" } );
infos.add( E_OpType::OP_FP_SUB , T_OpInfo{ "fp-sub" } );
infos.add( E_OpType::OP_FP_MUL , T_OpInfo{ "fp-mul" } );
infos.add( E_OpType::OP_FP_DIV , T_OpInfo{ "fp-div" } );
infos.add( E_OpType::OP_FP_MUL , T_OpInfo{ "fp-neg" } );
infos.add( E_OpType::OP_FP_DIV , T_OpInfo{ "fp-inv" } );
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" , 0 , OpStackFPU{ -1 } } );
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" , 0 , OpStackFPU{ -1 } } );
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" , 0 } );
infos.add( E_OpType::OP_FP_DIV , T_OpInfo{ "fp-inv" , 0 } );
return infos;
})( ) };
@ -64,6 +119,20 @@ uint32_t ops::ArgumentsFor(
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 ==========================================================*/