Compiler - Started work
Committing as I need to make a few adjustments to the AST in order to simplify things.
This commit is contained in:
parent
8806cd81d2
commit
abb2c02d61
5 changed files with 307 additions and 33 deletions
1
Makefile
1
Makefile
|
@ -31,6 +31,7 @@ COMMON = \
|
|||
control.cc \
|
||||
opast.cc \
|
||||
opparser.cc \
|
||||
opcomp.cc \
|
||||
# END COMMON
|
||||
|
||||
DEMO = \
|
||||
|
|
116
control.hh
116
control.hh
|
@ -1,9 +1,114 @@
|
|||
#pragma once
|
||||
#ifndef REAL_BUILD
|
||||
# include "externals.hh"
|
||||
#endif
|
||||
#include "sync.hh"
|
||||
#include "opast.hh"
|
||||
|
||||
struct T_SyncData;
|
||||
namespace ops {
|
||||
|
||||
using namespace ebcl;
|
||||
|
||||
enum E_OpType
|
||||
{
|
||||
OP_END ,
|
||||
//
|
||||
OP_FP_LOAD ,
|
||||
//
|
||||
OP_FP_CMP ,
|
||||
};
|
||||
|
||||
struct T_Op
|
||||
{
|
||||
E_OpType op;
|
||||
T_SRDLocation location;
|
||||
uint32_t arg0 , arg1;
|
||||
|
||||
T_Op( const E_OpType op ,
|
||||
T_SRDLocation const& location ,
|
||||
const uint32_t arg0 = 0 ,
|
||||
const uint32_t arg1 = 0 ) noexcept
|
||||
: op( op ) , location( location ) ,
|
||||
arg0( arg0 ) , arg1( arg1 )
|
||||
{ }
|
||||
};
|
||||
|
||||
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 {
|
||||
|
||||
|
@ -13,9 +118,6 @@ namespace cops {
|
|||
{
|
||||
T_Program const* program;
|
||||
|
||||
float const* time;
|
||||
T_SyncData const* sync;
|
||||
|
||||
T_KeyValueTable< T_String , float > vars;
|
||||
|
||||
T_Array< float > opStack;
|
||||
|
|
1
opast.hh
1
opast.hh
|
@ -1211,7 +1211,6 @@ struct T_ParserOutput
|
|||
{
|
||||
T_RootNode root;
|
||||
T_KeyValueTable< T_String , E_DataType > types;
|
||||
T_Set< float > constants{ UseTag< IndexBacked< > >( ) };
|
||||
};
|
||||
|
||||
// The actual parser
|
||||
|
|
192
opcomp.cc
Normal file
192
opcomp.cc
Normal file
|
@ -0,0 +1,192 @@
|
|||
#include "externals.hh"
|
||||
#include "control.hh"
|
||||
#include <ebcl/Algorithms.hh>
|
||||
|
||||
#define INVASIVE_TRACES
|
||||
|
||||
using namespace ebcl;
|
||||
using namespace ops;
|
||||
using namespace opast;
|
||||
|
||||
namespace {
|
||||
|
||||
struct T_CompilerImpl_
|
||||
{
|
||||
T_Visitor< A_Node > astVisitor{ ASTVisitorBrowser };
|
||||
T_Set< uint32_t > constants{ UseTag< IndexBacked< > >( ) };
|
||||
|
||||
T_ParserOutput* input;
|
||||
P_OpProgram output;
|
||||
|
||||
uint32_t fiVariables , fiFramebuffers ,
|
||||
fiPipelines , fiPrograms ,
|
||||
fiSamplers , fiTextures;
|
||||
|
||||
P_OpProgram compile(
|
||||
T_ParserOutput const& input ) noexcept;
|
||||
|
||||
private:
|
||||
void gatherConstants( ) noexcept;
|
||||
void countAssets( ) noexcept;
|
||||
|
||||
bool compileNode( uint32_t funcIndex ,
|
||||
A_Node& node ,
|
||||
bool exit ) noexcept;
|
||||
};
|
||||
|
||||
|
||||
P_OpProgram T_CompilerImpl_::compile(
|
||||
T_ParserOutput const& in ) noexcept
|
||||
{
|
||||
input = const_cast< T_ParserOutput* >( &in );
|
||||
output = NewOwned< T_OpProgram >( );
|
||||
|
||||
// Gather all constants used in expressions, count resources
|
||||
gatherConstants( );
|
||||
countAssets( );
|
||||
|
||||
// Get function indices
|
||||
// FIXME ideally we should remap functions so that init is always 0
|
||||
// and frame is always 1
|
||||
output->init = input->root.functionIndex( "*init*" );
|
||||
output->frame = input->root.functionIndex( "*frame*" );
|
||||
#ifdef INVASIVE_TRACES
|
||||
printf( "function indices\n\t%d\tinit\n\t%d\tframe\n" ,
|
||||
output->init , output->frame );
|
||||
#endif
|
||||
|
||||
// Compile each function
|
||||
uint32_t cfi;
|
||||
for ( cfi = 0u ; cfi < input->root.nFunctions( ) ; cfi ++ ) {
|
||||
output->ops.next( );
|
||||
auto& func( input->root.function( cfi ) );
|
||||
#ifdef INVASIVE_TRACES
|
||||
printf( "compiling function %s\n" ,
|
||||
func.name( ).toOSString( ).data( ) );
|
||||
#endif
|
||||
astVisitor.visit( func ,
|
||||
[=]( A_Node& node , const bool exit ) -> bool {
|
||||
return compileNode( cfi , node , exit );
|
||||
} );
|
||||
}
|
||||
|
||||
return std::move( output );
|
||||
}
|
||||
|
||||
void T_CompilerImpl_::gatherConstants( ) noexcept
|
||||
{
|
||||
constants.clear( );
|
||||
astVisitor.visit( input->root , [&]( A_Node& node , const bool exit ) {
|
||||
if ( exit && node.type( ) == A_Node::EXPR_CONST ) {
|
||||
T_OpValue value;
|
||||
value.f = dynamic_cast< T_ConstantExprNode& >( node ).floatValue( );
|
||||
if ( value.f != 0 && value.f != 1 ) {
|
||||
constants.add( value.u );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} );
|
||||
|
||||
#ifdef INVASIVE_TRACES
|
||||
printf( "%d constants\n" , constants.size( ) );
|
||||
for ( auto i = 0u ; i < constants.size( ) ; i ++ ) {
|
||||
printf( " %08x" , constants[ i ] );
|
||||
if ( i % 4 == 3 ) {
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
if ( constants.size( ) % 4 ) {
|
||||
printf( "\n" );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void T_CompilerImpl_::countAssets( ) noexcept
|
||||
{
|
||||
auto const nt{ input->types.size( ) };
|
||||
for ( auto i = 0u ; i < nt ; i ++ ) {
|
||||
const auto t{ input->types.values( )[ i ] };
|
||||
switch ( t ) {
|
||||
case E_DataType::FRAMEBUFFER:
|
||||
output->nFramebuffers ++;
|
||||
break;
|
||||
case E_DataType::PIPELINE:
|
||||
output->nPipelines ++;
|
||||
break;
|
||||
case E_DataType::PROGRAM:
|
||||
output->nPrograms ++;
|
||||
break;
|
||||
case E_DataType::SAMPLER:
|
||||
output->nSamplers ++;
|
||||
break;
|
||||
case E_DataType::TEXTURE:
|
||||
output->nTextures ++;
|
||||
break;
|
||||
case E_DataType::VARIABLE:
|
||||
output->nVariables ++;
|
||||
break;
|
||||
|
||||
case E_DataType::INPUT:
|
||||
assert( !output->inputs.contains(
|
||||
input->types.keys( )[ i ] ) );
|
||||
output->inputs.add( input->types.keys( )[ i ] );
|
||||
break;
|
||||
|
||||
case E_DataType::BUILTIN:
|
||||
case E_DataType::UNKNOWN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fiVariables = 3 + constants.size( );
|
||||
fiFramebuffers = fiVariables + output->nVariables;
|
||||
fiPipelines = fiFramebuffers + output->nFramebuffers;
|
||||
fiPrograms = fiPipelines + output->nPipelines;
|
||||
fiSamplers = fiPrograms + output->nPrograms;
|
||||
fiTextures = fiSamplers + output->nSamplers;
|
||||
|
||||
#ifdef INVASIVE_TRACES
|
||||
printf( "assets\n\t%d framebuffers\n\t%d pipelines\n"
|
||||
"\t%d programs\n\t%d samplers\n\t%d textures\n"
|
||||
"\t%d variables\n\t%d inputs\n" ,
|
||||
output->nFramebuffers , output->nPipelines ,
|
||||
output->nPrograms , output->nSamplers ,
|
||||
output->nTextures , output->nVariables ,
|
||||
output->inputs.size( ) );
|
||||
printf( "table ranges\n\t0\t2\tBuilt-ins\n"
|
||||
"\t3\t%d\tConstants\n"
|
||||
"\t%d\t%d\tVariables\n"
|
||||
"\t%d\t%d\tFramebuffers\n"
|
||||
"\t%d\t%d\tPipelines\n"
|
||||
"\t%d\t%d\tPrograms\n"
|
||||
"\t%d\t%d\tSamplers\n"
|
||||
"\t%d\t%d\tTextures\n" ,
|
||||
fiVariables - 1 , fiVariables , fiFramebuffers - 1 , fiFramebuffers ,
|
||||
fiPipelines - 1 , fiPipelines , fiPrograms - 1 , fiPrograms ,
|
||||
fiSamplers - 1 , fiSamplers , fiTextures - 1 , fiTextures ,
|
||||
fiTextures + output->nTextures - 1 );
|
||||
#endif
|
||||
}
|
||||
|
||||
bool T_CompilerImpl_::compileNode(
|
||||
const uint32_t funcIndex ,
|
||||
A_Node& node ,
|
||||
const bool exit ) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*= T_Compiler =================================================================*/
|
||||
|
||||
T_Compiler::T_Compiler( ) noexcept
|
||||
: A_PrivateImplementation( new T_CompilerImpl_( ) )
|
||||
{ }
|
||||
|
||||
P_OpProgram T_Compiler::compile(
|
||||
T_ParserOutput const& input ) noexcept
|
||||
{
|
||||
return p< T_CompilerImpl_ >( ).compile( input );
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#include "externals.hh"
|
||||
#include "opast.hh"
|
||||
#include "control.hh"
|
||||
#include <ebcl/Files.hh>
|
||||
#include <ebcl/SRDText.hh>
|
||||
#include <ebcl/Algorithms.hh>
|
||||
|
@ -34,17 +35,6 @@ void WriteSRDError(
|
|||
}
|
||||
|
||||
|
||||
/*============================================================================*/
|
||||
|
||||
T_Array< T_SRDError > parserPrototypes(
|
||||
T_OwnPtr< T_ParserOutput > const& output )
|
||||
{
|
||||
T_Visitor< opast::A_Node > visitor{ ASTVisitorBrowser };
|
||||
T_Array< T_SRDError > errors;
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
/*============================================================================*/
|
||||
|
||||
} // namespace
|
||||
|
@ -85,20 +75,10 @@ int main( int argc , char** argv )
|
|||
// Parse the fuck
|
||||
T_Parser parser;
|
||||
if ( parser.parse( srdOut.list( ) ) ) {
|
||||
printf( "Success - now running prototypes\n" );
|
||||
T_Array< T_SRDError > errors{ parserPrototypes( parser.result( ) ) };
|
||||
if ( errors.empty( ) ) {
|
||||
printf( "Success!\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
T_StringBuilder sb;
|
||||
for ( auto const& err : errors ) {
|
||||
WriteSRDError( sb , err );
|
||||
}
|
||||
sb << "Parser prototypes failed\n" << '\0';
|
||||
fprintf( stderr , "%s" , sb.data( ) );
|
||||
return 4;
|
||||
printf( "Parser successful. Compiling...\n" );
|
||||
ops::T_Compiler compiler;
|
||||
compiler.compile( *parser.result( ) );
|
||||
return 0;
|
||||
} else {
|
||||
T_StringBuilder sb;
|
||||
for ( auto const& err : parser.errors( ) ) {
|
||||
|
|
Loading…
Reference in a new issue