#pragma once #include "sync.hh" #include "opast.hh" namespace ops { using namespace ebcl; enum E_OpType { OP_END , // OP_CALL , OP_RET , // OP_SKIP , OP_COND_SKIP , // OP_RES_STACK , OP_PUSH , OP_POP , // OP_LOAD , OP_SLOAD , // OP_FP_LOAD , OP_FP_STORE , OP_FP_SLOAD , OP_FP_SSTORE , OP_FP_SSTORE_INT , // OP_FP_CMP , OP_FP_ADD , OP_FP_SUB , OP_FP_MUL , OP_FP_DIV , OP_FP_NEG , OP_FP_INV , // OP_INIT_PIPELINE , OP_INIT_PROGRAM , OP_INIT_TEXTURE , // OP_FULLSCREEN , OP_CLEAR , // OP_UI_PENTER , OP_UI_PEXIT , }; 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 { static constexpr int MAX_ARGS = 2; E_OpType op; T_SRDLocation location; uint32_t args[ MAX_ARGS ]; T_Op( const E_OpType op , T_SRDLocation const& location , const uint32_t arg0 = 0 ) noexcept : op( op ) , location( location ) , args{ arg0 } { } T_Op( const E_OpType op , T_SRDLocation const& location , std::initializer_list< uint32_t > a ) noexcept : op( op ) , location( location ) { assert( a.size( ) <= MAX_ARGS ); auto it = a.begin( ); for ( auto i = 0u ; i < a.size( ) ; i ++ , ++it ) { args[ i ] = *it; } } }; M_LSHIFT_OP( T_StringBuilder , T_Op const& ); union T_OpValue { int32_t i; uint32_t u; float f; }; struct T_OpProgram { T_MultiArray< T_Op > ops; // All operations uint32_t init , // Index of initialisation function frame; // Index of frame rendering function T_Array< T_OpValue > constants; // Constants values uint32_t nVariables{ 0 }; // Amount of variables T_Array< T_String > inputs; // Input definitions uint32_t nPrograms{ 0 } , // Amount of programs nFramebuffers{ 0 } , // Amount of framebuffers nPipelines{ 0 } , // Amount of pipelines nSamplers{ 0 } , // Amount of samplers nTextures{ 0 }; // Amount of textures T_Array< T_String > progNames; // GLSL program files T_Array< T_String > uiStrings; // UI strings for profiling, etc. }; using P_OpProgram = T_OwnPtr< T_OpProgram >; struct T_OpContext { T_OpProgram& program; // The program uint32_t instrPtr; // Instruction pointer bool aborted; // Did the program fail? T_Array< T_OpValue > values; // VM data T_Array< T_OpValue > stack; // Main VM stack double x87stack[ 8 ]; // x87 FPU emulation stack int x87sp; // x87 FPU emulation stack pointer }; class X_OpFailure : public std::exception { public: X_OpFailure( ) = delete; DEF_COPY( X_OpFailure ); DEF_MOVE( X_OpFailure ); X_OpFailure( T_Op const& op , T_String error ) noexcept; T_Op const& op( ) const noexcept { return *op_; } T_String const& error( ) const noexcept { return error_; } char const* what( ) const noexcept override; private: T_Op const* op_; T_String error_; T_String fullMessage_; }; class T_Compiler : public A_PrivateImplementation { public: T_Compiler( ) noexcept; P_OpProgram compile( opast::T_ParserOutput const& input ) noexcept; }; } // namespace ops /*= FIXME OLD VERSION BELOW ====================================================*/ namespace cops { struct T_Program; struct T_Context { T_Program const* program; T_KeyValueTable< T_String , float > vars; T_Array< float > opStack; T_Context& store( T_String const& name , const float value ); }; class X_OpFailure : public std::exception { public: X_OpFailure( ) = delete; DEF_COPY( X_OpFailure ); DEF_MOVE( X_OpFailure ); X_OpFailure( T_String const& source , uint32_t line , T_String&& error ) noexcept; T_String const& source( ) const noexcept { return source_; } uint32_t line( ) const noexcept { return line_; } T_String const& error( ) const noexcept { return error_; } char const* what( ) const noexcept override; private: T_String source_; uint32_t line_; T_String error_; T_String fullMessage_; }; /*--------------------------------------------------------------------*/ enum E_Op { OP_LOAD_CONSTANT , OP_LOAD_VARIABLE , OP_LOAD_INPUT , OP_STORE_VARIABLE , // OP_ADD , OP_MUL , OP_NEG , OP_INV , // OP_DUP , OP_XCHG , // OP_SET_UNIFORM , OP_USE_PIPELINE , OP_USE_TEXTURE , OP_USE_FRAMEBUFFER , OP_SET_VIEWPORT , // OP_CLEAR , OP_FULLSCREEN , // OP_CALL }; struct T_Op { explicit T_Op( const E_Op op ); virtual ~T_Op( ) = 0; E_Op op( ) const noexcept { return op_; } virtual void execute( T_Context& ctx ) const = 0; T_String source{}; uint32_t line{0}; protected: X_OpFailure error( ebcl::T_StringBuilder& message ) const noexcept; X_OpFailure error( T_String const& message ) const noexcept; private: E_Op op_; }; using P_Op = T_OwnPtr< T_Op >; using T_Operations = T_Array< P_Op >; template< typename T > inline T_Operations& operator <<( T_Operations& ops , T&& item ) { ops.add( NewOwned< T >( std::move( item ) ) ); return ops; } void Execute( T_Operations const& operations , T_Context& context ); /*--------------------------------------------------------------------*/ struct T_Function { T_String name; uint32_t arguments; T_Operations operations; T_Function( T_String const& name , const uint32_t arguments ) : name( name ) , arguments( arguments ) { } DEF_COPY( T_Function ); DEF_MOVE( T_Function ); }; struct T_Program { T_ObjectTable< T_String , T_Function > functions; T_Operations main; T_Program( ) : functions( []( T_Function const& f ) -> T_String { return f.name; } ) { } T_Operations& function( T_String const& name , const uint32_t args ); void execute( T_Context& context ) { context.program = this; Execute( main , context ); } }; /*====================================================================*/ struct OPLoadConstant : public T_Op { explicit OPLoadConstant( const float constant ); void execute( T_Context& ctx ) const override; float constant; }; struct OPLoadVariable : public T_Op { explicit OPLoadVariable( T_String const& variable ); void execute( T_Context& ctx ) const override; T_String variable; }; struct OPLoadInput : public T_Op { explicit OPLoadInput( T_String const& input ); void execute( T_Context& ctx ) const override; T_String input; }; struct OPStoreVariable : public T_Op { explicit OPStoreVariable( T_String const& variable ); void execute( T_Context& ctx ) const override; T_String variable; }; /*--------------------------------------------------------------------*/ struct OPAdd : public T_Op { OPAdd( ) : T_Op( OP_ADD ) {} void execute( T_Context& ctx ) const override; }; struct OPMul : public T_Op { OPMul( ) : T_Op( OP_MUL ) {} void execute( T_Context& ctx ) const override; }; struct OPNeg : public T_Op { OPNeg( ) : T_Op( OP_NEG ) {} void execute( T_Context& ctx ) const override; }; struct OPInv : public T_Op { OPInv( ) : T_Op( OP_INV ) {} void execute( T_Context& ctx ) const override; }; /*--------------------------------------------------------------------*/ struct OPDup : public T_Op { explicit OPDup( uint32_t stackIndex = 0 ); void execute( T_Context& ctx ) const override; uint32_t stackIndex; }; struct OPXchg : public T_Op { explicit OPXchg( uint32_t stackIndex = 1 ); void execute( T_Context& ctx ) const override; uint32_t stackIndex; }; /*--------------------------------------------------------------------*/ struct OPSetUniform : public T_Op { OPSetUniform( const uint32_t count , const bool integer ); void execute( T_Context& ctx ) const override; uint32_t count; bool integer; }; struct OPUsePipeline : public T_Op { explicit OPUsePipeline( const uint32_t index ); void execute( T_Context& ctx ) const override; uint32_t pipeline; }; struct OPUseTexture : public T_Op { OPUseTexture( const uint32_t binding , const uint32_t texture , const uint32_t sampler = 0 ); void execute( T_Context& ctx ) const override; uint32_t binding; uint32_t texture; uint32_t sampler; }; struct OPUseFramebuffer : public T_Op { explicit OPUseFramebuffer( const uint32_t framebuffer ); void execute( T_Context& ctx ) const override; uint32_t framebuffer; }; struct OPSetViewport : public T_Op { OPSetViewport( ) : T_Op( OP_SET_VIEWPORT ) { } void execute( T_Context& ctx ) const override; }; /*--------------------------------------------------------------------*/ struct OPClear : public T_Op { OPClear( ) : T_Op( OP_CLEAR ) { } void execute( T_Context& ctx ) const override; }; struct OPFullscreen : public T_Op { OPFullscreen( ) : T_Op( OP_FULLSCREEN ) { } void execute( T_Context& ctx ) const override; }; /*--------------------------------------------------------------------*/ struct OPCall : public T_Op { explicit OPCall( T_String const& function ); void execute( T_Context& ctx ) const override; T_String function; }; } // namespace cops