Goose  Artifact [0990ce7032]

Artifact 0990ce7032ab0bdfb94e39d3bde8f186e156aecfb616b106fcead12c91c9063c:

  • File bs/codegen/stack.h — part of check-in [9b8306c3af] at 2023-01-05 19:44:44 on branch trunk — Fixed passing tuple by value to functions, which involved properly handling type checking of constant tuples containing computed data and some codegen bugs (user: zlodo size: 2177)

#ifndef GOOSE_CODEGEN_STACK_H
#define GOOSE_CODEGEN_STACK_H

namespace goose::codegen
{
    class Stack
    {
        public:
            using Slot = variant< llvm::Value*, codegen::Address >;

            template< typename T = llvm::Value* >
            optional< T > pop( llvm::IRBuilder<>& builder )
            {
                if( m_stack.empty() )
                    return nullopt;

                auto result = m_stack.top();
                m_stack.pop();

                if constexpr( is_same_v< T, codegen::Address > )
                {
                    if( !holds_alternative< codegen::Address >( result ) )
                        return nullopt;
                    return get< codegen::Address >( result );
                }
                else if constexpr( is_same_v< T, llvm::Value* > )
                {
                    if( holds_alternative< codegen::Address >( result ) )
                        return AddressToGEP( builder, get< codegen::Address >( result ) );
                    else
                        return InsertLoadIfNeeded( builder, get< llvm::Value* >( result ) );
                }
                else if( holds_alternative< llvm::Value* >( result ) )
                    return llvm::dyn_cast_or_null< remove_pointer_t< T > >( InsertLoadIfNeeded( builder, get< llvm::Value* >( result ) ) );

                return nullopt;
            }

            optional< Slot > pop()
            {
                if( m_stack.empty() )
                    return nullopt;

                auto result = m_stack.top();
                m_stack.pop();
                return result;
            }

            template< typename T >
            void push( T&& v )
            {
                m_stack.push( forward< T >( v ) );
            }

        private:
            static llvm::Value* InsertLoadIfNeeded( llvm::IRBuilder<>& builder, llvm::Value* lv )
            {
                if( llvm::isa< llvm::AllocaInst >( lv ) )
                    return builder.CreateLoad( llvm::cast< llvm::AllocaInst >( lv )->getAllocatedType(), lv );
                return lv;
            }

            stack< Slot > m_stack;
    };
}

#endif