Ops - Operator metadata
This commit is contained in:
parent
87b46284ab
commit
dd4c1ba7cd
4 changed files with 167 additions and 36 deletions
1
Makefile
1
Makefile
|
@ -29,6 +29,7 @@ COMMON = \
|
||||||
odbg.cc \
|
odbg.cc \
|
||||||
sync.cc \
|
sync.cc \
|
||||||
control.cc \
|
control.cc \
|
||||||
|
ops.cc \
|
||||||
opast.cc \
|
opast.cc \
|
||||||
opparser.cc \
|
opparser.cc \
|
||||||
opcomp.cc \
|
opcomp.cc \
|
||||||
|
|
|
@ -36,6 +36,10 @@ enum E_OpType
|
||||||
OP_FP_INV ,
|
OP_FP_INV ,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
M_LSHIFT_OP( T_StringBuilder , E_OpType );
|
||||||
|
uint32_t ArgumentsFor( E_OpType op ) noexcept;
|
||||||
|
|
||||||
|
|
||||||
struct T_Op
|
struct T_Op
|
||||||
{
|
{
|
||||||
E_OpType op;
|
E_OpType op;
|
||||||
|
@ -50,6 +54,8 @@ struct T_Op
|
||||||
arg0( arg0 ) , arg1( arg1 )
|
arg0( arg0 ) , arg1( arg1 )
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
M_LSHIFT_OP( T_StringBuilder , T_Op const& );
|
||||||
|
|
||||||
|
|
||||||
union T_OpValue
|
union T_OpValue
|
||||||
{
|
{
|
||||||
|
|
103
opcomp.cc
103
opcomp.cc
|
@ -47,9 +47,15 @@ struct T_CompilerImpl_
|
||||||
|
|
||||||
void addInstruction(
|
void addInstruction(
|
||||||
E_OpType op ,
|
E_OpType op ,
|
||||||
T_SRDLocation const& location ,
|
T_SRDLocation const& location ) noexcept;
|
||||||
uint32_t arg0 = 0 ,
|
void addInstruction(
|
||||||
uint32_t arg1 = 0 ) noexcept;
|
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 );
|
return compileNode( cfi , node , exit );
|
||||||
} );
|
} );
|
||||||
#ifdef INVASIVE_TRACES
|
#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 );
|
nInstr += output->ops.sizeOf( cfi );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -288,7 +305,7 @@ bool T_CompilerImpl_::compileNode(
|
||||||
auto& fcallee( (T_FuncNode&) callee );
|
auto& fcallee( (T_FuncNode&) callee );
|
||||||
const auto args( fcallee.arguments( ) );
|
const auto args( fcallee.arguments( ) );
|
||||||
assert( sdMain > args );
|
assert( sdMain > args );
|
||||||
addInstruction( OP_CALL , node.location( ) , fi );
|
addInstruction( OP_CALL , fi , node.location( ) );
|
||||||
sdMain -= args;
|
sdMain -= args;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -300,14 +317,14 @@ bool T_CompilerImpl_::compileNode(
|
||||||
(T_IdentifierExprNode&) n.expression( ) ) };
|
(T_IdentifierExprNode&) n.expression( ) ) };
|
||||||
if ( !main ) {
|
if ( !main ) {
|
||||||
addInstruction( OP_PUSH , node.location( ) );
|
addInstruction( OP_PUSH , node.location( ) );
|
||||||
addInstruction( OP_FP_SSTORE , node.location( ) , 0 );
|
addInstruction( OP_FP_SSTORE , 0 , node.location( ) );
|
||||||
sdMain ++;
|
sdMain ++;
|
||||||
sdFPU --;
|
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 , node.location( ) , 0 );
|
addInstruction( OP_FP_SSTORE , 0 , node.location( ) );
|
||||||
sdMain ++;
|
sdMain ++;
|
||||||
sdFPU --;
|
sdFPU --;
|
||||||
}
|
}
|
||||||
|
@ -321,11 +338,12 @@ bool T_CompilerImpl_::compileNode(
|
||||||
auto& func{ input->root.function( funcIndex ) };
|
auto& func{ input->root.function( funcIndex ) };
|
||||||
if ( func.hasLocal( id ) ) {
|
if ( func.hasLocal( id ) ) {
|
||||||
const auto pos( func.getLocalIndex( id ) + 1 );
|
const auto pos( func.getLocalIndex( id ) + 1 );
|
||||||
addInstruction( OP_FP_SSTORE , node.location( ) ,
|
addInstruction( OP_FP_SSTORE , sdMain - pos - 1 ,
|
||||||
sdMain - pos - 1 );
|
node.location( ) );
|
||||||
} else {
|
} else {
|
||||||
addInstruction( OP_FP_STORE , node.location( ) ,
|
addInstruction( OP_FP_STORE ,
|
||||||
*locations.get( ((T_SetInstrNode&)node).id( ) ) );
|
*locations.get( ((T_SetInstrNode&)node).id( ) ) ,
|
||||||
|
node.location( ) );
|
||||||
}
|
}
|
||||||
sdFPU --;
|
sdFPU --;
|
||||||
}
|
}
|
||||||
|
@ -334,7 +352,7 @@ bool T_CompilerImpl_::compileNode(
|
||||||
case A_Node::OP_COND:
|
case A_Node::OP_COND:
|
||||||
if ( exit ) {
|
if ( exit ) {
|
||||||
assert( sdMain > 0 );
|
assert( sdMain > 0 );
|
||||||
addInstruction( OP_POP , node.location( ) , 0 );
|
addInstruction( OP_POP , 0 , node.location( ) );
|
||||||
sdMain --;
|
sdMain --;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -342,7 +360,7 @@ bool T_CompilerImpl_::compileNode(
|
||||||
case A_Node::TN_CONDITION:
|
case A_Node::TN_CONDITION:
|
||||||
if ( exit ) {
|
if ( exit ) {
|
||||||
addInstruction( OP_PUSH , node.location( ) );
|
addInstruction( OP_PUSH , node.location( ) );
|
||||||
addInstruction( OP_FP_SSTORE_INT , node.location( ) , 0 );
|
addInstruction( OP_FP_SSTORE_INT , 0 , node.location( ) );
|
||||||
sdFPU --;
|
sdFPU --;
|
||||||
sdMain ++;
|
sdMain ++;
|
||||||
}
|
}
|
||||||
|
@ -360,8 +378,8 @@ bool T_CompilerImpl_::compileNode(
|
||||||
} else {
|
} else {
|
||||||
auto& c( (T_CondInstrNode::T_ValuedCase&) node );
|
auto& c( (T_CondInstrNode::T_ValuedCase&) node );
|
||||||
condJumps.add( output->ops.sizeOf( funcIndex ) );
|
condJumps.add( output->ops.sizeOf( funcIndex ) );
|
||||||
addInstruction( OP_COND_JUMP , node.location( ) ,
|
addInstruction( OP_COND_JUMP , 0 , c.value( ) ,
|
||||||
c.value( ) , 0 );
|
node.location( ) );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -371,7 +389,7 @@ bool T_CompilerImpl_::compileNode(
|
||||||
if ( exit ) {
|
if ( exit ) {
|
||||||
const uint32_t op( dynamic_cast< T_BinaryOperatorNode& >( node ).op( )
|
const uint32_t op( dynamic_cast< T_BinaryOperatorNode& >( node ).op( )
|
||||||
- T_BinaryOperatorNode::CMP_EQ );
|
- T_BinaryOperatorNode::CMP_EQ );
|
||||||
addInstruction( OP_FP_CMP , node.location( ) , op );
|
addInstruction( OP_FP_CMP , op , node.location( ) );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -408,8 +426,9 @@ bool T_CompilerImpl_::compileNode(
|
||||||
if ( !exit ) {
|
if ( !exit ) {
|
||||||
T_OpValue value;
|
T_OpValue value;
|
||||||
value.f = dynamic_cast< T_ConstantExprNode& >( node ).floatValue( );
|
value.f = dynamic_cast< T_ConstantExprNode& >( node ).floatValue( );
|
||||||
addInstruction( OP_FP_LOAD , node.location( ) ,
|
addInstruction( OP_FP_LOAD ,
|
||||||
constants.indexOf( value.u ) + 3 );
|
constants.indexOf( value.u ) + 3 ,
|
||||||
|
node.location( ) );
|
||||||
sdFPU ++;
|
sdFPU ++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -434,15 +453,15 @@ void T_CompilerImpl_::processFunction(
|
||||||
if ( exit ) {
|
if ( exit ) {
|
||||||
assert( sdMain == args + lvars + 1 );
|
assert( sdMain == args + lvars + 1 );
|
||||||
if ( lvars ) {
|
if ( lvars ) {
|
||||||
addInstruction( OP_POP , location , lvars - 1 );
|
addInstruction( OP_POP , lvars - 1 , location );
|
||||||
sdMain -= lvars;
|
sdMain -= lvars;
|
||||||
}
|
}
|
||||||
sdMain -= 1 + args;
|
sdMain -= 1 + args;
|
||||||
addInstruction( OP_RET , location , args );
|
addInstruction( OP_RET , args , location );
|
||||||
assert( sdMain == 0 );
|
assert( sdMain == 0 );
|
||||||
} else {
|
} else {
|
||||||
if ( lvars ) {
|
if ( lvars ) {
|
||||||
addInstruction( OP_RES_STACK , location , lvars - 1 );
|
addInstruction( OP_RES_STACK , lvars - 1 , location );
|
||||||
sdMain += lvars;
|
sdMain += lvars;
|
||||||
}
|
}
|
||||||
sdMain += 1 + args;
|
sdMain += 1 + args;
|
||||||
|
@ -472,12 +491,12 @@ 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 , node.location( ) , p );
|
addInstruction( OP_FP_SLOAD , p , node.location( ) );
|
||||||
sdFPU ++;
|
sdFPU ++;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
addInstruction( OP_SLOAD , node.location( ) , p );
|
addInstruction( OP_SLOAD , p , node.location( ) );
|
||||||
addInstruction( OP_PUSH , node.location( ) );
|
addInstruction( OP_PUSH , node.location( ) );
|
||||||
sdMain ++;
|
sdMain ++;
|
||||||
return true;
|
return true;
|
||||||
|
@ -488,14 +507,14 @@ bool T_CompilerImpl_::processIdentifier(
|
||||||
assert( dt != E_DataType::UNKNOWN );
|
assert( dt != E_DataType::UNKNOWN );
|
||||||
assert( locations.contains( node.id( ) ) );
|
assert( locations.contains( node.id( ) ) );
|
||||||
if ( dt == E_DataType::VARIABLE || dt == E_DataType::BUILTIN ) {
|
if ( dt == E_DataType::VARIABLE || dt == E_DataType::BUILTIN ) {
|
||||||
addInstruction( OP_FP_LOAD , node.location( ) ,
|
addInstruction( OP_FP_LOAD , *locations.get( node.id( ) ) ,
|
||||||
*locations.get( node.id( ) ) );
|
node.location( ) );
|
||||||
sdFPU ++;
|
sdFPU ++;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
addInstruction( OP_LOAD , node.location( ) ,
|
addInstruction( OP_LOAD , *locations.get( node.id( ) ) ,
|
||||||
*locations.get( node.id( ) ) );
|
node.location( ) );
|
||||||
addInstruction( OP_PUSH , node.location( ) );
|
addInstruction( OP_PUSH , node.location( ) );
|
||||||
sdMain ++;
|
sdMain ++;
|
||||||
return true;
|
return true;
|
||||||
|
@ -504,16 +523,28 @@ bool T_CompilerImpl_::processIdentifier(
|
||||||
|
|
||||||
void T_CompilerImpl_::addInstruction(
|
void T_CompilerImpl_::addInstruction(
|
||||||
const E_OpType op ,
|
const E_OpType op ,
|
||||||
T_SRDLocation const& location ,
|
T_SRDLocation const& location ) noexcept
|
||||||
const uint32_t arg0 ,
|
|
||||||
const uint32_t arg1 ) noexcept
|
|
||||||
{
|
{
|
||||||
#ifdef INVASIVE_TRACES
|
assert( ArgumentsFor( op ) == 0 );
|
||||||
T_StringBuilder tracer;
|
output->ops.addNew( op , location );
|
||||||
tracer << "\t+I( " << int( op ) << " ; " << arg0 << " ; "
|
}
|
||||||
<< arg1 << " ) @ " << location << '\n' << '\0';
|
|
||||||
printf( "%s" , tracer.data( ) );
|
void T_CompilerImpl_::addInstruction(
|
||||||
#endif
|
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 );
|
output->ops.addNew( op , location , arg0 , arg1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
93
ops.cc
Normal file
93
ops.cc
Normal file
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in a new issue