diff --git a/Makefile b/Makefile index 7ad3754..7d549f7 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,7 @@ COMMON = \ odbg.cc \ sync.cc \ control.cc \ + ops.cc \ opast.cc \ opparser.cc \ opcomp.cc \ diff --git a/control.hh b/control.hh index 396200c..e41f008 100644 --- a/control.hh +++ b/control.hh @@ -36,6 +36,10 @@ enum E_OpType OP_FP_INV , }; +M_LSHIFT_OP( T_StringBuilder , E_OpType ); +uint32_t ArgumentsFor( E_OpType op ) noexcept; + + struct T_Op { E_OpType op; @@ -50,6 +54,8 @@ struct T_Op arg0( arg0 ) , arg1( arg1 ) { } }; +M_LSHIFT_OP( T_StringBuilder , T_Op const& ); + union T_OpValue { diff --git a/opcomp.cc b/opcomp.cc index 4405798..9362d3d 100644 --- a/opcomp.cc +++ b/opcomp.cc @@ -47,9 +47,15 @@ struct T_CompilerImpl_ void addInstruction( E_OpType op , - T_SRDLocation const& location , - uint32_t arg0 = 0 , - uint32_t arg1 = 0 ) noexcept; + T_SRDLocation const& location ) noexcept; + void addInstruction( + E_OpType op , + uint32_t arg0 , + T_SRDLocation const& location ) noexcept; + void addInstruction( + E_OpType op , + uint32_t arg0 , uint32_t arg1 , + T_SRDLocation const& location ) noexcept; }; @@ -91,7 +97,18 @@ P_OpProgram T_CompilerImpl_::compile( return compileNode( cfi , node , exit ); } ); #ifdef INVASIVE_TRACES - printf( "\t%d instructions generated\n" , output->ops.sizeOf( cfi ) ); + T_StringBuilder dump , temp; + for ( auto i = 0u ; i < output->ops.sizeOf( cfi ) ; i ++ ) { + temp << "(" << output->ops.get( cfi , i ) << ")"; + while ( temp.length( ) < 30 ) { + temp << ' '; + } + dump << "\t\t" << temp << "{ " << output->ops.get( cfi , i ).location << " }\n"; + temp.clear( ); + } + dump << '\t' << output->ops.sizeOf( cfi ) << " instructions\n" + << '\0'; + printf( "%s" , dump.data( ) ); nInstr += output->ops.sizeOf( cfi ); #endif } @@ -288,7 +305,7 @@ bool T_CompilerImpl_::compileNode( auto& fcallee( (T_FuncNode&) callee ); const auto args( fcallee.arguments( ) ); assert( sdMain > args ); - addInstruction( OP_CALL , node.location( ) , fi ); + addInstruction( OP_CALL , fi , node.location( ) ); sdMain -= args; } break; @@ -300,14 +317,14 @@ bool T_CompilerImpl_::compileNode( (T_IdentifierExprNode&) n.expression( ) ) }; if ( !main ) { addInstruction( OP_PUSH , node.location( ) ); - addInstruction( OP_FP_SSTORE , node.location( ) , 0 ); + 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 , node.location( ) , 0 ); + addInstruction( OP_FP_SSTORE , 0 , node.location( ) ); sdMain ++; sdFPU --; } @@ -321,11 +338,12 @@ bool T_CompilerImpl_::compileNode( auto& func{ input->root.function( funcIndex ) }; if ( func.hasLocal( id ) ) { const auto pos( func.getLocalIndex( id ) + 1 ); - addInstruction( OP_FP_SSTORE , node.location( ) , - sdMain - pos - 1 ); + addInstruction( OP_FP_SSTORE , sdMain - pos - 1 , + node.location( ) ); } else { - addInstruction( OP_FP_STORE , node.location( ) , - *locations.get( ((T_SetInstrNode&)node).id( ) ) ); + addInstruction( OP_FP_STORE , + *locations.get( ((T_SetInstrNode&)node).id( ) ) , + node.location( ) ); } sdFPU --; } @@ -334,7 +352,7 @@ bool T_CompilerImpl_::compileNode( case A_Node::OP_COND: if ( exit ) { assert( sdMain > 0 ); - addInstruction( OP_POP , node.location( ) , 0 ); + addInstruction( OP_POP , 0 , node.location( ) ); sdMain --; } break; @@ -342,7 +360,7 @@ bool T_CompilerImpl_::compileNode( case A_Node::TN_CONDITION: if ( exit ) { addInstruction( OP_PUSH , node.location( ) ); - addInstruction( OP_FP_SSTORE_INT , node.location( ) , 0 ); + addInstruction( OP_FP_SSTORE_INT , 0 , node.location( ) ); sdFPU --; sdMain ++; } @@ -360,8 +378,8 @@ bool T_CompilerImpl_::compileNode( } else { auto& c( (T_CondInstrNode::T_ValuedCase&) node ); condJumps.add( output->ops.sizeOf( funcIndex ) ); - addInstruction( OP_COND_JUMP , node.location( ) , - c.value( ) , 0 ); + addInstruction( OP_COND_JUMP , 0 , c.value( ) , + node.location( ) ); } break; @@ -371,7 +389,7 @@ bool T_CompilerImpl_::compileNode( if ( exit ) { const uint32_t op( dynamic_cast< T_BinaryOperatorNode& >( node ).op( ) - T_BinaryOperatorNode::CMP_EQ ); - addInstruction( OP_FP_CMP , node.location( ) , op ); + addInstruction( OP_FP_CMP , op , node.location( ) ); } break; @@ -408,8 +426,9 @@ bool T_CompilerImpl_::compileNode( if ( !exit ) { T_OpValue value; value.f = dynamic_cast< T_ConstantExprNode& >( node ).floatValue( ); - addInstruction( OP_FP_LOAD , node.location( ) , - constants.indexOf( value.u ) + 3 ); + addInstruction( OP_FP_LOAD , + constants.indexOf( value.u ) + 3 , + node.location( ) ); sdFPU ++; } break; @@ -434,15 +453,15 @@ void T_CompilerImpl_::processFunction( if ( exit ) { assert( sdMain == args + lvars + 1 ); if ( lvars ) { - addInstruction( OP_POP , location , lvars - 1 ); + addInstruction( OP_POP , lvars - 1 , location ); sdMain -= lvars; } sdMain -= 1 + args; - addInstruction( OP_RET , location , args ); + addInstruction( OP_RET , args , location ); assert( sdMain == 0 ); } else { if ( lvars ) { - addInstruction( OP_RES_STACK , location , lvars - 1 ); + addInstruction( OP_RES_STACK , lvars - 1 , location ); sdMain += lvars; } sdMain += 1 + args; @@ -472,12 +491,12 @@ bool T_CompilerImpl_::processIdentifier( const auto p( sdMain - ( stackPos + 1 ) ); if ( dt == E_DataType::VARIABLE ) { - addInstruction( OP_FP_SLOAD , node.location( ) , p ); + addInstruction( OP_FP_SLOAD , p , node.location( ) ); sdFPU ++; return false; } - addInstruction( OP_SLOAD , node.location( ) , p ); + addInstruction( OP_SLOAD , p , node.location( ) ); addInstruction( OP_PUSH , node.location( ) ); sdMain ++; return true; @@ -488,14 +507,14 @@ bool T_CompilerImpl_::processIdentifier( assert( dt != E_DataType::UNKNOWN ); assert( locations.contains( node.id( ) ) ); if ( dt == E_DataType::VARIABLE || dt == E_DataType::BUILTIN ) { - addInstruction( OP_FP_LOAD , node.location( ) , - *locations.get( node.id( ) ) ); + addInstruction( OP_FP_LOAD , *locations.get( node.id( ) ) , + node.location( ) ); sdFPU ++; return false; } - addInstruction( OP_LOAD , node.location( ) , - *locations.get( node.id( ) ) ); + addInstruction( OP_LOAD , *locations.get( node.id( ) ) , + node.location( ) ); addInstruction( OP_PUSH , node.location( ) ); sdMain ++; return true; @@ -504,16 +523,28 @@ bool T_CompilerImpl_::processIdentifier( void T_CompilerImpl_::addInstruction( const E_OpType op , - T_SRDLocation const& location , - const uint32_t arg0 , - const uint32_t arg1 ) noexcept + T_SRDLocation const& location ) noexcept { -#ifdef INVASIVE_TRACES - T_StringBuilder tracer; - tracer << "\t+I( " << int( op ) << " ; " << arg0 << " ; " - << arg1 << " ) @ " << location << '\n' << '\0'; - printf( "%s" , tracer.data( ) ); -#endif + assert( ArgumentsFor( op ) == 0 ); + output->ops.addNew( op , location ); +} + +void T_CompilerImpl_::addInstruction( + const E_OpType op , + const uint32_t arg0 , + T_SRDLocation const& location ) noexcept +{ + assert( ArgumentsFor( op ) == 1 ); + output->ops.addNew( op , location , arg0 ); +} + +void T_CompilerImpl_::addInstruction( + const E_OpType op , + const uint32_t arg0 , + const uint32_t arg1 , + T_SRDLocation const& location ) noexcept +{ + assert( ArgumentsFor( op ) == 2 ); output->ops.addNew( op , location , arg0 , arg1 ); } diff --git a/ops.cc b/ops.cc new file mode 100644 index 0000000..738bf5e --- /dev/null +++ b/ops.cc @@ -0,0 +1,93 @@ +#include "externals.hh" +#include "control.hh" +#include "globals.hh" +#include "sync.hh" + +using namespace ops; +using namespace ebcl; + + +/*= OPCODE INFORMATIONS ========================================================*/ + +namespace { + +struct T_OpInfo +{ + char const* name; + int nArgs; + + T_OpInfo( char const* name , + int nArgs = 0 ) + : name( name ) , nArgs( nArgs ) + { } +}; + +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_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_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_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" } ); + + return infos; +})( ) }; + +} // namespace + +uint32_t ops::ArgumentsFor( + const E_OpType op ) noexcept +{ + assert( OpInfoTable_.contains( op ) ); + return OpInfoTable_.get( op )->nArgs; +} + + +/*= STRING FORMATTING ==========================================================*/ + +T_StringBuilder& ops::operator<<( + T_StringBuilder& sb , + const E_OpType et ) +{ + assert( OpInfoTable_.contains( et ) ); + sb << OpInfoTable_.get( et )->name; + return sb; +} + +T_StringBuilder& ops::operator<<( + T_StringBuilder& sb , + T_Op const& op ) +{ + sb << op.op; + + const auto args{ OpInfoTable_.get( op.op )->nArgs }; + if ( args ) { + sb << ' ' << op.arg0; + if ( args == 2 ) { + sb << ' ' << op.arg1; + } + } + return sb; +}