Goose  Artifact [bff7b3796a]

Artifact bff7b3796af862b3c44852d582ba2a1160a3e184ecf3dbe05301b784dfad0579:

  • File bs/cir/helpers.h — part of check-in [8ffbc35112] at 2024-08-31 14:05:17 on branch cir-ssa-refactor — Refactor Instruction to be just a variant instead of a class containing a variant and a clownshoes bunch of constructors (user: achavasse size: 4005)

#ifndef GOOSE_CIR_HELPERS_H
#define GOOSE_CIR_HELPERS_H

namespace goose::cir
{
    extern bool IsValueConstantOrExecutable( const eir::Value& val );
    extern bool CanValueBeEagerlyEvaluated( const eir::Value& val );

    extern bool DoesInstrSeqHaveSideEffects( const InstrSeq& is );

    template< typename T >
    class TempStorage
    {
        public:
            TempStorage( size_t size = 0 ) :
                m_storage( size )
            {}

            template< typename TT >
            T& set( uint32_t index, TT&& x )
            {
                if( IsUid( index ) )
                {
                    auto [it,_] = m_uidStorage.emplace( index, forward< TT >( x ) );
                    return it->second;
                }

                if( index >= m_storage.size() )
                    m_storage.resize( index + 1 );
                m_storage[index] = forward< TT >( x );
                return m_storage[index];
            }

            const T* get( uint32_t index ) const
            {
                if( IsUid( index ) )
                {
                    auto it = m_uidStorage.find( index );
                    if( it == m_uidStorage.end() )
                        return nullptr;
                    return &it->second;
                }

                if( index < m_storage.size() )
                    return &m_storage[index];

                return nullptr;
            }

            T* get( uint32_t index )
            {
                if( IsUid( index ) )
                    return nullptr;

                if( index < m_storage.size() )
                    return &m_storage[index];

                return nullptr;
            }

        private:
            llvm::SmallVector< T, 16 > m_storage;
            unordered_map< uint32_t, T > m_uidStorage;
    };

    // We need to lower types before consuming them from the CIR. Ideally we'd do this while building the CIR
    // but as things are now it would involve enormous refactoring to store lowered types in a bunch of high level
    // objects, and all the code to round trip them to EIR would have to deal with them, while also making sure
    // they aren't actually participating in pattern matching.
    // A significant redesign will probably allow for an elegant solution, but that's for the rewrite.
    // In the mean time we use this ugly helper that lowers the type when reading it from the CIR, if not previously done.
    // Since it needs the context we have to store the current context as a static member. This will have to do for
    // the BS compiler...
    class LowerableType
    {
        public:
            template< typename T >
            LowerableType( T&& type ) :
                m_type( forward< T >( type ) )
            {}

            const auto& type() const { return m_type; }
            const eir::Term& get() const;

            auto operator<( const LowerableType& other ) const
            {
                return m_type < other.m_type;
            }

            auto operator==( const LowerableType& other ) const
            {
                return m_type == other.m_type;
            }

        private:
            eir::Term m_type;
            mutable optional< eir::Term > m_loweredType;
    };

    // Same as above for values
    class LowerableValue
    {
        public:
            template< typename T >
            LowerableValue( T&& val ) :
                m_val( forward< T >( val ) )
            {}

            const auto& val() const { return m_val; }
            const eir::Value& get() const;
            eir::Value& modify();

            auto operator<( const LowerableValue& other ) const
            {
                return m_val < other.m_val;
            }

            auto operator==( const LowerableValue& other ) const
            {
                return m_val == other.m_val;
            }

        private:
            eir::Value m_val;
            mutable optional< eir::Value > m_loweredVal;
    };
}

#endif