/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 * 
 * llvmlayer.h
 *
 *      Author: pgess <v.melnychenko@xreate.org>
 */

#ifndef LLVMLAYER_H
#define LLVMLAYER_H

#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "utils.h"

namespace xreate {
    class AST;
    class ExternLayer;
    class TypeAnnotation;

    class LLVMLayer {
    public:
        LLVMLayer(AST* rootAST);

        AST *ast = 0;
        ExternLayer *layerExtern =0;
        llvm::Module *module = 0;
        llvm::ExecutionEngine* jit= 0;
        llvm::IRBuilder<> builder;

        void moveToGarbage(void *o);

        llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty) const;
        void print();
        void* getFunctionPointer(llvm::Function* function);

        void initJit();

        llvm::BasicBlock* initExceptionBlock(llvm::BasicBlock* block);
    private:
        void initExceptionsSupport();
        llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty, std::map<int, llvm::StructType*>& conjunctions) const;
        std::vector<void *> __garbage;
    };

    struct TypeUtils {
        bool isStruct(const Expanded<TypeAnnotation>& ty);
        bool isPointer(const Expanded<TypeAnnotation>& ty);
        std::vector<std::string> getStructFields(const Expanded<TypeAnnotation>& t);

        TypeUtils(LLVMLayer*llvmlayer)
            : llvm(llvmlayer){}

        private:
            LLVMLayer* llvm;
    };
}
#endif // LLVMLAYER_H
