diff --git a/control.hh b/control.hh index 2550bc1..ba8f2eb 100644 --- a/control.hh +++ b/control.hh @@ -36,6 +36,11 @@ enum E_OpType OP_FP_DIV , OP_FP_NEG , OP_FP_INV , + // + OP_INIT_PIPELINE , + OP_LOAD_PROGRAM , + // + OP_FULLSCREEN }; M_LSHIFT_OP( T_StringBuilder , E_OpType ); @@ -46,7 +51,7 @@ int32_t DeltaFPUStack( E_OpType op ) noexcept; struct T_Op { - static constexpr int MAX_ARGS = 4; + static constexpr int MAX_ARGS = 2; E_OpType op; T_SRDLocation location; diff --git a/opast.cc b/opast.cc index 567d71f..ddbf9a9 100644 --- a/opast.cc +++ b/opast.cc @@ -119,8 +119,9 @@ A_Node* opast::ASTVisitorBrowser( case A_Node::OP_CALL: { auto& n( (T_CallInstrNode&) node ); - if ( child < n.arguments( ) ) { - return &n.argument( child ); + const auto nArgs( n.arguments( ) ); + if ( child < nArgs ) { + return &n.argument( nArgs - child - 1 ); } break; } diff --git a/opcomp.cc b/opcomp.cc index 264eb18..06a84e2 100644 --- a/opcomp.cc +++ b/opcomp.cc @@ -65,9 +65,14 @@ struct T_CompilerImpl_ uint32_t args , uint32_t lvars , T_SRDLocation const& location ) noexcept; + bool processIdentifier( uint32_t funcIndex , T_IdentifierExprNode const& node ) noexcept; + bool processIdentifier( + uint32_t funcIndex , + T_String const& id , + T_SRDLocation const& location ) noexcept; void addInstruction( E_OpType op , @@ -300,11 +305,15 @@ bool T_CompilerImpl_::compileNode( { switch ( node.type( ) ) { + //- PROGRAM STRUCTURE ----------------------------------------------------------------- + case A_Node::ROOT: fprintf( stderr , "Internal error: root node found during compilation\n" ); std::abort( ); break; + case A_Node::ILIST: break; + case A_Node::DECL_FN: { T_FuncNode& fn( (T_FuncNode&) node ); @@ -321,6 +330,8 @@ bool T_CompilerImpl_::compileNode( break; } + //- GENERAL / FLOW CONTROL INSTRUCTIONS ----------------------------------------------- + case A_Node::OP_CALL: if ( exit ) { auto& call( (T_CallInstrNode&) node ); @@ -387,14 +398,12 @@ bool T_CompilerImpl_::compileNode( condJumps.addNew( ); } break; - case A_Node::TN_CONDITION: if ( exit ) { addInstruction( OP_PUSH , node.location( ) ); addInstruction( OP_FP_SSTORE_INT , 0 , node.location( ) ); } break; - case A_Node::TN_CASE: if ( exit ) { // Store a potential skip location @@ -406,9 +415,6 @@ bool T_CompilerImpl_::compileNode( const auto diff( cpos - ppos ); assert( diff > 1 ); output->ops.get( funcIndex , ppos ).args[ 1 ] = diff - 1; -#ifdef INVASIVE_TRACES - printf( "\tCOND JUMP UPDATED: %d\n" , diff - 1 ); -#endif } else { // If there is a previous skip location, insert the skip instruction if ( !condJumps.last( ).caseEnds.empty( ) ) { @@ -425,7 +431,6 @@ bool T_CompilerImpl_::compileNode( node.location( ) ); } break; - case A_Node::TN_DEFAULT: // If there is a previous skip location, insert the skip instruction // and update the previous conditional skip @@ -437,6 +442,44 @@ bool T_CompilerImpl_::compileNode( } break; + + //- ASSET DECLARATIONS ---------------------------------------------------------------- + + case A_Node::OP_PIPELINE: + if ( exit ) { + auto& pn( (T_PipelineInstrNode&) node ); + for ( auto i = 0u ; i < pn.size( ) ; i ++ ) { + processIdentifier( funcIndex , pn.program( i ) , + pn.pLocation( i ) ); + } + processIdentifier( funcIndex , pn.id( ) , pn.location( ) ); + addInstruction( OP_INIT_PIPELINE , pn.size( ) , pn.location( ) ); + sdMain -= pn.size( ); + } + break; + + case A_Node::OP_PROGRAM: + if ( exit ) { + auto& pn( (T_ProgramInstrNode&) node ); + processIdentifier( funcIndex , pn.id( ) , pn.idLocation( ) ); + if ( !output->progNames.contains( pn.path( ) ) ) { + output->progNames.add( pn.path( ) ); + } + addInstruction( OP_LOAD_PROGRAM , output->progNames.indexOf( pn.path( ) ) , + pn.location( ) ); + } + break; + + //- RENDERING ------------------------------------------------------------------------- + + case A_Node::OP_FULLSCREEN: + if ( exit ) { + addInstruction( OP_FULLSCREEN , node.location( ) ); + } + break; + + //- EXPRESSIONS - OPERATORS ----------------------------------------------------------- + case A_Node::EXPR_CMP_EQ: case A_Node::EXPR_CMP_NE: case A_Node::EXPR_CMP_GT: case A_Node::EXPR_CMP_GE: case A_Node::EXPR_CMP_LT: case A_Node::EXPR_CMP_LE: @@ -468,6 +511,8 @@ bool T_CompilerImpl_::compileNode( } break; + //- EXPRESSIONS - TERMINAL NODES ------------------------------------------------------ + case A_Node::EXPR_CONST: if ( !exit ) { T_OpValue value; @@ -484,6 +529,11 @@ bool T_CompilerImpl_::compileNode( dynamic_cast< T_IdentifierExprNode& >( node ) ); } break; + + case A_Node::EXPR_INPUT: + if ( !exit ) { + } + break; } return true; @@ -518,46 +568,54 @@ void T_CompilerImpl_::processFunction( bool T_CompilerImpl_::processIdentifier( const uint32_t funcIndex , T_IdentifierExprNode const& node ) noexcept +{ + return processIdentifier( funcIndex , node.id( ) , node.location( ) ); +} + +bool T_CompilerImpl_::processIdentifier( + uint32_t funcIndex , + T_String const& id , + T_SRDLocation const& location ) noexcept { auto& func{ input->root.function( funcIndex ) }; - if ( func.hasLocal( node.id( ) ) ) { - const E_DataType dt{ func.getLocalType( node.id( ) ) }; + if ( func.hasLocal( id ) ) { + const E_DataType dt{ func.getLocalType( id ) }; assert( dt != E_DataType::UNKNOWN ); uint32_t stackPos; - if ( func.isArgument( node.id( ) ) ) { + if ( func.isArgument( id ) ) { auto const& fn( (T_FuncNode&) func ); const auto nArgs( fn.arguments( ) ); - stackPos = nArgs - 1 - func.getLocalIndex( node.id( ) ); + stackPos = nArgs - 1 - func.getLocalIndex( id ); } else { - stackPos = func.getLocalIndex( node.id( ) ) + 1; + stackPos = func.getLocalIndex( id ) + 1; } assert( stackPos < sdMain ); const auto p( sdMain - ( stackPos + 1 ) ); if ( dt == E_DataType::VARIABLE ) { - addInstruction( OP_FP_SLOAD , p , node.location( ) ); + addInstruction( OP_FP_SLOAD , p , location ); return false; } - addInstruction( OP_SLOAD , p , node.location( ) ); - addInstruction( OP_PUSH , node.location( ) ); + addInstruction( OP_SLOAD , p , location ); + addInstruction( OP_PUSH , location ); return true; } - assert( input->types.contains( node.id( ) ) ); - const E_DataType dt{ *( input->types.get( node.id( ) ) ) }; + assert( input->types.contains( id ) ); + const E_DataType dt{ *( input->types.get( id ) ) }; assert( dt != E_DataType::UNKNOWN ); - assert( locations.contains( node.id( ) ) ); + assert( locations.contains( id ) ); if ( dt == E_DataType::VARIABLE || dt == E_DataType::BUILTIN ) { - addInstruction( OP_FP_LOAD , *locations.get( node.id( ) ) , - node.location( ) ); + addInstruction( OP_FP_LOAD , *locations.get( id ) , + location ); return false; } - addInstruction( OP_LOAD , *locations.get( node.id( ) ) , - node.location( ) ); - addInstruction( OP_PUSH , node.location( ) ); + addInstruction( OP_LOAD , *locations.get( id ) , + location ); + addInstruction( OP_PUSH , location ); return true; } diff --git a/ops.cc b/ops.cc index fbbf23a..c9eef3f 100644 --- a/ops.cc +++ b/ops.cc @@ -108,6 +108,11 @@ static T_KeyValueTable< E_OpType , T_OpInfo > OpInfoTable_{ ([]() { 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 } ); + // + infos.add( E_OpType::OP_INIT_PIPELINE , T_OpInfo{ "init-pipeline" , 1 , OpStackMain{ -1 } } ); + infos.add( E_OpType::OP_LOAD_PROGRAM , T_OpInfo{ "load-program" , 1 , OpStackMain{ -1 } } ); + // + infos.add( E_OpType::OP_FULLSCREEN , T_OpInfo{ "fullscreen" } ); return infos; })( ) };