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 );
|
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
|
||||||
|
|
56
opcomp.cc
56
opcomp.cc
|
@ -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
107
ops.cc
|
@ -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 ==========================================================*/
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue