Goose  Artifact [1ce2271bb1]

Artifact 1ce2271bb129a9a599951fd58d6616d4bef233ccfec3098d81f68c602bdc3a70:

  • File bs/cir/call.cpp — part of check-in [55beba911a] at 2021-09-12 16:48:57 on branch trunk —
    • Started work on extensibility api
    • some code cleanup
    (user: achavasse size: 2377)

#include "cir/cir.h"
#include "builtins/builtins.h"

using namespace goose::builtins;

namespace goose::cir
{
    bool Call::canBeExecuted() const
    {
        if( !IsValueConstantOrExecutable( m_func ) )
            return false;

        if( IsExternalFunc( m_func ) )
            return false;

        bool argsCanBeExecuted = true;
        ForEachInVectorTerm( m_args, [&]( auto&& arg )
        {
            if( !IsValueConstantOrExecutable( *EIRToValue( arg ) ) )
            {
                argsCanBeExecuted = false;
                return false;
            }

            return true;
        } );

        if( !argsCanBeExecuted )
            return false;

        if( IsBuiltinFunc( m_func ) )
            return true;

        const auto* pFunc = GetFuncCIR( m_func );

        // If the func is passed as a value, we might not have been able to evaluate
        // it yet, so we assume it's going to be executable. If it isn't, we'll fail
        // at execution time, which isn't a big deal - we should be able to avoid trying
        // executing it in the first place in most cases.
        return !pFunc || pFunc->canBeExecuted();
    }

    bool Call::canBeEagerlyEvaluated() const
    {
        // Functions with void return type are assumed to have side effects
        // and therefore that they should never be eagerly evaluated.
        // It's not like they would need to be anyway.
        if( GetFuncRType( m_func ) == GetValueType< void >() )
            return false;

        if( IsNonEagerBuiltinFunc( m_func ) )
            return false;

        if( IsExternalFunc( m_func ) )
            return false;

        bool argsAreConstant = true;
        ForEachInVectorTerm( m_args, [&]( auto&& arg )
        {
            if( !CanValueBeEagerlyEvaluated( *EIRToValue( arg ) ) )
            {
                argsAreConstant = false;
                return false;
            }

            return true;
        } );

        if( !argsAreConstant )
            return false;

        if( IsEagerBuiltinFunc( m_func ) )
            return true;

        const auto* pFuncCIR = GetFuncCIR( m_func );

        if( !pFuncCIR )
            return false;

        return pFuncCIR->canBeExecuted();
    }

    ostream& operator<<( ostream& out, const Call& ins )
    {
        return out << "CALL(" << ins.m_func << ", " << ins.m_args << ')';
    }
}