Goose  Artifact [2aeee4b7d8]

Artifact 2aeee4b7d80fcaa433954cfa1af369db8a91b17810e28e140e98ec3f39dc0ee1:

  • File bs/compile/compiler.cpp — part of check-in [238df77134] at 2019-11-19 00:04:49 on branch trunk — cfg: now that we got rid of this crazy system where CFGs could "call" other CFGs that weren't really functions, removed that clumsy cfg index that was needed to identify temporaries everywhere. (user: achavasse size: 3987)

#include "compiler.h"
#include "builtins/builtins.h"
#include "builtins/helpers.h"
#include "sema/sema.h"
#include "verify/verify.h"
#include "execute/execute.h"
#include "diagnostics/diagnostics.h"

#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/TargetSelect.h"

using namespace goose;
using namespace goose::util;
using namespace goose::ir;
using namespace goose::sema;
using namespace goose::diagnostics;

namespace goose::compile
{
    Compiler::Compiler( int argc, char** argv ) :
        m_pEnv( make_shared< sema::Env >() )
    {
        llvm::InitLLVM( argc, argv );

        string cmdArgs;
        for( size_t i = 1; i < static_cast< size_t >( argc ); ++i )
        {
            if( i > 1 )
                cmdArgs = cmdArgs + ' ';
            cmdArgs = cmdArgs + argv[i];
        }

        builtins::SetupBuiltins( *m_pEnv );

        builtins::RegisterBuiltinFunc< string() >( *m_pEnv, "Args"_sid,
            [cmdArgs]()
            {
                return cmdArgs;
            } );

        builtins::RegisterBuiltinFunc< void ( string ) >( *m_pEnv, "Print"_sid,
            []( const string& str )
            {
                cout << str;
            } );

        llvm::InitializeAllTargetInfos();
        llvm::InitializeAllTargets();
        llvm::InitializeAllTargetMCs();
        llvm::InitializeAllAsmParsers();
        llvm::InitializeAllAsmPrinters();
    }

    uint32_t Compiler::execute( const string& filename )
    {
        auto identity = sema::InjectDomainIntoIdentity( builtins::RootIdentity(), sema::DomainCompileTime() );

        auto result = LoadAndExecuteFile( m_pEnv, filename, identity, GetValueType< uint32_t >() );

        if( DiagnosticsManager::GetInstance().errorsWereEmitted() )
            return 0;

        if( !result )
            return 1;

        if( result->isPoison() )
            return 0;

        return *FromValue< uint32_t >( *result );
    }

    optional< Value > Compiler::LoadAndExecuteFile( const ptr< Env >& e, const string& filename, const Term& identity, optional< Term > returnType )
    {
        auto cfg = LoadAndParseFile( e, filename, identity, returnType );
        if( !cfg )
            return PoisonValue();

        if( !cfg->entryBB()->canBeExecuted() )
        {
            DiagnosticsManager::GetInstance().emitErrorMessage( 0,
                format( "{}: can not be executed.", filename ) );
            return PoisonValue();
        }

        execute::VM vm;
        return vm.execute( cfg->entryBB() );
    }

    ptr< llr::CFG > Compiler::LoadAndParseFile( const ptr< Env >& e, const string& filename, const Term& identity, optional< Term > returnType )
    {
        ifstream sourcefile( filename.c_str() );
        if( !sourcefile.good() )
        {
            DiagnosticsManager::GetInstance().emitErrorMessage( 0,
                format( "can't open '{}'.", filename ) );
            return nullptr;
        }

        sema::Context c( e, identity, returnType );
        DiagnosticsContext dc( 0, true );
        VerbosityContext vc( Verbosity::Normal, true );

        auto r = make_shared< parse::Resolver >(
            make_shared< lex::Lexer >( sourcefile, filename ), c );
        parse::Parser p( r );

        auto cfg = make_shared< llr::CFG >( 0 );
        cfg->createBB();
        p.setCFG( cfg );
        p.cfg()->setCurrentBB( cfg->entryBB() );

        p.parseSequence();

        if( cfg->isPoisoned() )
            return cfg;

        if( !r->eos() )
        {
            DiagnosticsManager::GetInstance().emitSyntaxErrorMessage(
                r->getCurrentLocation(), "syntax error." );
        }

        if( p.cfg()->currentBB() && !cfg->currentBB()->terminator() )
        {
            p.emitTerminator( llr::Ret() );

            if( returnType == GetValueType< void >() )
                p.emitTerminator( llr::Ret() );
        }

        verify::Func fv( cfg );
        if( !fv.verify() )
            return nullptr;

        return cfg;
    }
}