/* 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;

/** \brief A wrapper over LLVM toolchain to generate and execute bytecode */
class LLVMLayer {
public:
  LLVMLayer(AST* rootAST);

  mutable llvm::LLVMContext llvmContext;
  llvm::IRBuilder<> irBuilder;
  AST *ast = 0;
  ExternLayer *layerExtern =0;
  std::unique_ptr<llvm::Module> module;
  std::unique_ptr<llvm::ExecutionEngine> jit;

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

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

class TypesHelper {
public:
  bool isArrayT(const Expanded<TypeAnnotation>& ty);
  bool isRecordT(const Expanded<TypeAnnotation>& ty);
  bool isPointerT(const Expanded<TypeAnnotation>& ty);
  bool isIntegerT(const Expanded<TypeAnnotation>& ty);
  llvm::IntegerType* getPreferredIntTy() const;
  std::vector<std::string> getRecordFields(const Expanded<TypeAnnotation>& t);

  TypesHelper(const LLVMLayer* llvmlayer): llvm(llvmlayer){}

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