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 \
|
control.cc \
|
||||||
opast.cc \
|
opast.cc \
|
||||||
opparser.cc \
|
opparser.cc \
|
||||||
|
opcomp.cc \
|
||||||
# END COMMON
|
# END COMMON
|
||||||
|
|
||||||
DEMO = \
|
DEMO = \
|
||||||
|
|
116
control.hh
116
control.hh
|
@ -1,9 +1,114 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#ifndef REAL_BUILD
|
#include "sync.hh"
|
||||||
# include "externals.hh"
|
#include "opast.hh"
|
||||||
#endif
|
|
||||||
|
|
||||||
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 {
|
namespace cops {
|
||||||
|
|
||||||
|
@ -13,9 +118,6 @@ namespace cops {
|
||||||
{
|
{
|
||||||
T_Program const* program;
|
T_Program const* program;
|
||||||
|
|
||||||
float const* time;
|
|
||||||
T_SyncData const* sync;
|
|
||||||
|
|
||||||
T_KeyValueTable< T_String , float > vars;
|
T_KeyValueTable< T_String , float > vars;
|
||||||
|
|
||||||
T_Array< float > opStack;
|
T_Array< float > opStack;
|
||||||
|
|
1
opast.hh
1
opast.hh
|
@ -1211,7 +1211,6 @@ struct T_ParserOutput
|
||||||
{
|
{
|
||||||
T_RootNode root;
|
T_RootNode root;
|
||||||
T_KeyValueTable< T_String , E_DataType > types;
|
T_KeyValueTable< T_String , E_DataType > types;
|
||||||
T_Set< float > constants{ UseTag< IndexBacked< > >( ) };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The actual parser
|
// 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 "externals.hh"
|
||||||
#include "opast.hh"
|
#include "opast.hh"
|
||||||
|
#include "control.hh"
|
||||||
#include <ebcl/Files.hh>
|
#include <ebcl/Files.hh>
|
||||||
#include <ebcl/SRDText.hh>
|
#include <ebcl/SRDText.hh>
|
||||||
#include <ebcl/Algorithms.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
|
} // namespace
|
||||||
|
@ -85,20 +75,10 @@ int main( int argc , char** argv )
|
||||||
// Parse the fuck
|
// Parse the fuck
|
||||||
T_Parser parser;
|
T_Parser parser;
|
||||||
if ( parser.parse( srdOut.list( ) ) ) {
|
if ( parser.parse( srdOut.list( ) ) ) {
|
||||||
printf( "Success - now running prototypes\n" );
|
printf( "Parser successful. Compiling...\n" );
|
||||||
T_Array< T_SRDError > errors{ parserPrototypes( parser.result( ) ) };
|
ops::T_Compiler compiler;
|
||||||
if ( errors.empty( ) ) {
|
compiler.compile( *parser.result( ) );
|
||||||
printf( "Success!\n" );
|
return 0;
|
||||||
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;
|
|
||||||
} else {
|
} else {
|
||||||
T_StringBuilder sb;
|
T_StringBuilder sb;
|
||||||
for ( auto const& err : parser.errors( ) ) {
|
for ( auto const& err : parser.errors( ) ) {
|
||||||
|
|
Loading…
Reference in a new issue