Compiler - Metadata for operators' stack effects
This commit is contained in:
parent
dd4c1ba7cd
commit
bf1c4aa1b0
3 changed files with 120 additions and 45 deletions
|
@ -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
|
||||
|
|
56
opcomp.cc
56
opcomp.cc
|
@ -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
107
ops.cc
|
@ -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 ==========================================================*/
|
||||
|
||||
|
|
Loading…
Reference in a new issue