Goose  Artifact [6ae3991a5a]

Artifact 6ae3991a5a25605fc2a216dc04ee6a9a8264a7aa5751f553cdf0938ef95060a5:

  • File bs/codegen/module.h — part of check-in [bb17e9f3dd] at 2020-05-25 22:08:44 on branch trunk —
    • Added a "LowerConstantForRuntime" extension point, similar to LowerTypeForRunTime.
    • Added a way to represent Record constants.
    • Implemented LowerConstantForRunTime for tuples, which lowers them into a constant record.
    • Implemented codegen for constant records.
    • Implemented codegen for storing an aggregate constant.
    • Implemented a way (not exposed in the syntax for now) to create vararg function types, to be able to call vararg external functions such as printf.
    • Enabled the tuple runtime/compilation combined test which is now working.
    • Various bug fixes.
    (user: achavasse size: 5972)

#ifndef GOOSE_CODEGEN_MODULE_H
#define GOOSE_CODEGEN_MODULE_H

namespace llvm
{
    class TargetMachine;
}

namespace goose::codegen
{
    class Module
    {
        public:
            Module( const string& name );

            bool setupTarget();
            void dumpAsLlvmIr( const string& filename ) const;

            llvm::FunctionType* getOrCreateFuncType( const Context& c, const builtins::FuncType& ftype );

            llvm::Function* buildFuncProto( const Context& c, const builtins::Func& func, const string& name,
                llvm::Function::LinkageTypes linkageType );

            llvm::Function* getOrCreateFunc( const Context& c, const builtins::Func& func );
            llvm::Function* getOrCreateFunc( const Context& c, const builtins::Func& func, const string& name,
                llvm::Function::LinkageTypes linkageType );

            void runOptimizationPasses();
            bool emitToFile( const string& filename, llvm::CodeGenFileType type );

        private:
            struct Infos
            {
                Infos( const Context& c ) : context( c ) {}
                const Context& context;

                llvm::BasicBlock* allocaBasicBlock = nullptr;
                llvm::AllocaInst* lastEmittedAlloca = nullptr;

                using storage_type = llr::TempStorage< NullInit< llvm::Value* > >;
                ptr< storage_type > temporaries = make_shared< storage_type >();
            };

            llvm::Function* getCurrentFunction() const
            {
                return m_llvmBuilder.GetInsertBlock()->getParent();
            }

            llvm::BasicBlock* buildCFG( Infos& inf, llvm::Function* llvmFunc, const ptr< llr::CFG >& pCFG );
            llvm::BasicBlock* buildBasicBlock( Infos& inf, const ptr< llr::BasicBlock >& pBB );

            llvm::Value* buildValue( Infos& inf, const Value& val );
            llvm::Constant* buildConstant( Infos& inf, const Value& val );

            llvm::Value* buildInstruction( Infos& inf, const llr::Instruction& instr );
            llvm::Value* buildInstruction( Infos& inf, const llr::Call& call );
            llvm::Value* buildInstruction( Infos& inf, const llr::CreateTemporary& ct );
            llvm::Value* buildInstruction( Infos& inf, const llr::GetTemporary& gt );
            llvm::Value* buildInstruction( Infos& inf, const llr::AllocVar& av );
            llvm::Value* buildInstruction( Infos& inf, const llr::Load& load );
            llvm::Value* buildInstruction( Infos& inf, const llr::Store& store );
            llvm::Value* buildInstruction( Infos& inf, const llr::Phi& p );
            llvm::Value* buildInstruction( Infos& inf, const llr::LoadConstStr& lcs );

            llvm::Value* buildInstruction( Infos& inf, const llr::Not& uo );
            llvm::Value* buildInstruction( Infos& inf, const llr::And& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::Or& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::Xor& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::Shl& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::LShr& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::AShr& bo );

            llvm::Value* buildInstruction( Infos& inf, const llr::Add& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::Sub& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::Mul& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::UDiv& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::SDiv& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::URem& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::SRem& bo );

            llvm::Value* buildInstruction( Infos& inf, const llr::Eq& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::Neq& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::UGT& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::UGE& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::ULT& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::ULE& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::SGT& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::SGE& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::SLT& bo );
            llvm::Value* buildInstruction( Infos& inf, const llr::SLE& bo );

            llvm::Value* buildInstruction( Infos& inf, const llr::Assert& ass );
            llvm::Value* buildInstruction( Infos& inf, const llr::Placeholder& ph );

            bool buildTerminator( Infos& inf, const llr::Terminator& terminator );
            bool buildTerminator( Infos& inf, const llr::Ret& r );
            bool buildTerminator( Infos& inf, const llr::Branch& b );
            bool buildTerminator( Infos& inf, const llr::CondBranch& cb );

            template< typename T >
            bool buildTerminator( Infos& inf, const T& t )
            {
                return false;
            }

            llvm::Value* buildAddress( Infos& inf, const Address& addr );
            llvm::Value* buildAddress( Infos& inf, const BaseAddress& baseAddr );
            llvm::Value* buildAddress( Infos& inf, const TemporaryAddress& ta );
            llvm::Value* buildAddress( Infos& inf, const VarAddress& va );

            llvm::Value* buildAlloca( Infos& inf, llvm::Type* type );
            llvm::Value* createTemporary( Infos& inf, uint32_t index, llvm::Value* pValue ) const;

            llvm::Module m_llvmModule;
            llvm::DataLayout m_dataLayout;
            llvm::IRBuilder<> m_llvmBuilder;
            llvm::TargetMachine* m_targetMachine = nullptr;

            unordered_map< string, llvm::GlobalVariable* > m_strings;
            uint32_t m_nextAggregateID = 0;
    };
}

#endif