Goose  Artifact [6991173180]

Artifact 6991173180a71859e39909a3dacbab671bd9898a2e6089c5c6f3f87c28d6a0d9:

  • File bs/compile/compiler.cpp — part of check-in [184c1add90] at 2024-09-15 21:15:04 on branch cir-ssa-refactor —
    • Fix index Values EIR encoding
    • Fix CFG printer
    (user: achavasse size: 6300)

#include "compiler.h"
#include "builtins/builtins.h"
#include "g0api/g0api.h"
#include "sema/sema.h"
// TODO_SSA reenable
// #include "verify/verify.h"
#include "execute/execute.h"
#include "diagnostics/diagnostics.h"

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

#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"

using namespace goose;
using namespace goose::util;
using namespace goose::eir;
using namespace goose::sema;
using namespace goose::diagnostics;
using namespace goose::builtins;

namespace goose::compile
{
    Compiler::Compiler( int argc, char** argv ) :
        m_pEnv( make_shared< sema::Env >() )
    {
        string cmdArgs;
        for( size_t i = 1; i < static_cast< size_t >( argc ); ++i )
        {
            if( i > 1 )
                cmdArgs = cmdArgs + ' ';
            cmdArgs = cmdArgs + argv[i];
        }

        SetupBuiltins( *m_pEnv );
        parse::SetupParsingBuiltins( *m_pEnv );
        g0api::SetupG0Api( *m_pEnv );

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

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

        llvm::InitializeNativeTarget();
        llvm::InitializeNativeTargetAsmPrinter();
    }

    uint32_t Compiler::execute( const string& filename )
    {
        auto locVarsIdentity = AppendToVectorTerm( builtins::RootG0Identity(), TSID( 0_locvars ) );
        m_pEnv->addVisibilityRule( builtins::RootG0Identity(), locVarsIdentity );
        auto result = LoadAndExecuteFile( m_pEnv, filename, locVarsIdentity,
            GetValueType< uint32_t >(), ToValue< uint32_t >( 1 ) );

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

        if( !result )
        {
            DiagnosticsManager::GetInstance().emitErrorMessage(
                0, format( "{}: could not be executed.", filename ) );
            return 1;
        }

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

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

    optional< Value > Compiler::LoadAndExecuteFile( const ptr< Env >& e, const string& filename,
        const Term& identity, const Term& returnType, optional< Value > defRetVal )
    {
        ProfileZoneScoped;
        ProfileZoneName( filename.c_str(), filename.size() );

        auto cfg = LoadAndParseFile( e, filename, identity, returnType, defRetVal );
        if( !cfg || cfg->isPoisoned() )
            return PoisonValue();

       // ofstream out( "gg.txt" );
        cout << *cfg;

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

        sema::Context c( e, identity, returnType );
        Context::DefaultContextGuard dfg( c );

        execute::VM vm;
        return vm.execute( *cfg );
    }

    ptr< cir::CFG > Compiler::LoadAndParseFile( const ptr< Env >& e, const string& filename,
        const Term& identity, const Term& returnType, optional< Value > defRetVal )
    {
        ProfileZoneScoped;
        ProfileZoneName( filename.c_str(), filename.size() );

        auto& dm = DiagnosticsManager::GetInstance();

        assert( returnType == GetValueType< void >() || defRetVal );

        ifstream sourcefile( filename.c_str() );
        if( !sourcefile.good() )
        {
            dm.emitErrorMessage( 0, format( "can't open '{}'.", filename ) );
            return nullptr;
        }

        sema::Context c( e, identity, returnType );
        Context::DefaultContextGuard dfg( c );

        DiagnosticsContext dc( 0, true );
        VerbosityContext vc( Verbosity::Normal, true );

        auto cfg = make_shared< cir::CFG >( 0 );
        cfg->createBB();
        cfg->setCurrentBB( cfg->entryBB() );

        auto cb = make_shared< CodeBuilder >( cfg );
        c.setBuilder( ToValue( TypeWrapper< ptr< CodeBuilder > >( cb ) ) );

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

        p.parseSequence();

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

        if( !r->eos() )
        {
            dm.emitSyntaxErrorMessage( r->currentLocation(), "syntax error." );
            return nullptr;
        }

        if( cfg->currentBB() && !cfg->currentBB()->terminator() )
        {
            p.flushValue();
            cb->destroyAllLiveValues( c );

            if( returnType == GetValueType< void >() )
                cfg->emitTerminator( r->currentLocation(), cir::RetVoid( r->currentLocation() ) );
            else if( !defRetVal )
            {
                dm.emitSyntaxErrorMessage( r->currentLocation(), "missing return statement." );
                return nullptr;
            }
            else
            {
                auto converted = ConvertValueToType( c, *defRetVal, returnType );
                if( holds_alternative< ValUnifyError >( converted ) )
                {
                    switch( get< ValUnifyError >( converted ) )
                    {
                        case ValUnifyError::NoSolution:
                            dm.emitErrorMessage(
                                defRetVal->locationId(), "default return value type mismatch." );
                            break;

                        case ValUnifyError::Ambiguous:
                            dm.emitErrorMessage( defRetVal->locationId(),
                                "ambiguous default return value conversion." );
                            break;
                    }

                    return nullptr;
                }

                cfg->currentBB()->append( get< Value >( converted ) );
                cfg->emitTerminator( r->currentLocation(), cir::Ret( r->currentLocation() ) );
            }
        }

        // TODO_SSA reenable or not
        // ReindexVars( cfg );

        // TODO_SSA reenable
        /*verify::Func fv( c, cfg, returnType );
        if( !fv.verify() )
            return nullptr;*/

        return cfg;
    }
} // namespace goose::compile