//===- MCJITTestBase.h - Common base class for MCJIT Unit tests -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This class implements common functionality required by the MCJIT unit tests,
// as well as logic to skip tests on unsupported architectures and operating
// systems.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H
#define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H

#include "MCJITTestAPICommon.h"
#include "llvm/Config/config.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/CodeGen.h"

namespace llvm {

/// Helper class that can build very simple Modules
class TrivialModuleBuilder {
protected:
  LLVMContext Context;
  IRBuilder<> Builder;
  const Triple &BuilderTriple;

  TrivialModuleBuilder(const Triple &TT)
      : Builder(Context), BuilderTriple(TT) {}

  Module *createEmptyModule(StringRef Name = StringRef()) {
    Module * M = new Module(Name, Context);
    M->setTargetTriple(BuilderTriple);
    return M;
  }

  Function *startFunction(Module *M, FunctionType *FT, StringRef Name) {
    Function *Result =
        Function::Create(FT, GlobalValue::ExternalLinkage, Name, M);

    BasicBlock *BB = BasicBlock::Create(Context, Name, Result);
    Builder.SetInsertPoint(BB);

    return Result;
  }

  void endFunctionWithRet(Function *Func, Value *RetValue) {
    Builder.CreateRet(RetValue);
  }

  // Inserts a simple function that invokes Callee and takes the same arguments:
  //    int Caller(...) { return Callee(...); }
  Function *insertSimpleCallFunction(Module *M, Function *Callee) {
    Function *Result = startFunction(M, Callee->getFunctionType(), "caller");

    SmallVector<Value *, 1> CallArgs(llvm::make_pointer_range(Result->args()));

    Value *ReturnCode = Builder.CreateCall(Callee, CallArgs);
    Builder.CreateRet(ReturnCode);
    return Result;
  }

  // Inserts a function named 'main' that returns a uint32_t:
  //    int32_t main() { return X; }
  // where X is given by returnCode
  Function *insertMainFunction(Module *M, uint32_t returnCode) {
    Function *Result = startFunction(
        M, FunctionType::get(Type::getInt32Ty(Context), {}, false), "main");

    Value *ReturnVal = ConstantInt::get(Context, APInt(32, returnCode));
    endFunctionWithRet(Result, ReturnVal);

    return Result;
  }

  // Inserts a function
  //    int32_t add(int32_t a, int32_t b) { return a + b; }
  // in the current module and returns a pointer to it.
  Function *insertAddFunction(Module *M, StringRef Name = "add") {
    Function *Result = startFunction(
        M,
        FunctionType::get(
            Type::getInt32Ty(Context),
            {Type::getInt32Ty(Context), Type::getInt32Ty(Context)}, false),
        Name);

    Function::arg_iterator args = Result->arg_begin();
    Value *Arg1 = &*args;
    Value *Arg2 = &*++args;
    Value *AddResult = Builder.CreateAdd(Arg1, Arg2);

    endFunctionWithRet(Result, AddResult);

    return Result;
  }

  // Inserts a declaration to a function defined elsewhere
  Function *insertExternalReferenceToFunction(Module *M, FunctionType *FTy,
                                              StringRef Name) {
    Function *Result =
        Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M);
    return Result;
  }

  // Inserts an declaration to a function defined elsewhere
  Function *insertExternalReferenceToFunction(Module *M, Function *Func) {
    Function *Result = Function::Create(Func->getFunctionType(),
                                        GlobalValue::ExternalLinkage,
                                        Func->getName(), M);
    return Result;
  }

  // Inserts a global variable of type int32
  // FIXME: make this a template function to support any type
  GlobalVariable *insertGlobalInt32(Module *M,
                                    StringRef name,
                                    int32_t InitialValue) {
    Type *GlobalTy = Type::getInt32Ty(Context);
    Constant *IV = ConstantInt::get(Context, APInt(32, InitialValue));
    GlobalVariable *Global = new GlobalVariable(*M,
                                                GlobalTy,
                                                false,
                                                GlobalValue::ExternalLinkage,
                                                IV,
                                                name);
    return Global;
  }

  // Inserts a function
  //   int32_t recursive_add(int32_t num) {
  //     if (num == 0) {
  //       return num;
  //     } else {
  //       int32_t recursive_param = num - 1;
  //       return num + Helper(recursive_param);
  //     }
  //   }
  // NOTE: if Helper is left as the default parameter, Helper == recursive_add.
  Function *insertAccumulateFunction(Module *M,
                                     Function *Helper = nullptr,
                                     StringRef Name = "accumulate") {
    Function *Result =
        startFunction(M,
                      FunctionType::get(Type::getInt32Ty(Context),
                                        {Type::getInt32Ty(Context)}, false),
                      Name);
    if (!Helper)
      Helper = Result;

    BasicBlock *BaseCase = BasicBlock::Create(Context, "", Result);
    BasicBlock *RecursiveCase = BasicBlock::Create(Context, "", Result);

    // if (num == 0)
    Value *Param = &*Result->arg_begin();
    Value *Zero = ConstantInt::get(Context, APInt(32, 0));
    Builder.CreateCondBr(Builder.CreateICmpEQ(Param, Zero),
                         BaseCase, RecursiveCase);

    //   return num;
    Builder.SetInsertPoint(BaseCase);
    Builder.CreateRet(Param);

    //   int32_t recursive_param = num - 1;
    //   return Helper(recursive_param);
    Builder.SetInsertPoint(RecursiveCase);
    Value *One = ConstantInt::get(Context, APInt(32, 1));
    Value *RecursiveParam = Builder.CreateSub(Param, One);
    Value *RecursiveReturn = Builder.CreateCall(Helper, RecursiveParam);
    Value *Accumulator = Builder.CreateAdd(Param, RecursiveReturn);
    Builder.CreateRet(Accumulator);

    return Result;
  }

  // Populates Modules A and B:
  // Module A { Extern FB1, Function FA which calls FB1 },
  // Module B { Extern FA, Function FB1, Function FB2 which calls FA },
  void createCrossModuleRecursiveCase(std::unique_ptr<Module> &A, Function *&FA,
                                      std::unique_ptr<Module> &B,
                                      Function *&FB1, Function *&FB2) {
    // Define FB1 in B.
    B.reset(createEmptyModule("B"));
    FB1 = insertAccumulateFunction(B.get(), nullptr, "FB1");

    // Declare FB1 in A (as an external).
    A.reset(createEmptyModule("A"));
    Function *FB1Extern = insertExternalReferenceToFunction(A.get(), FB1);

    // Define FA in A (with a call to FB1).
    FA = insertAccumulateFunction(A.get(), FB1Extern, "FA");

    // Declare FA in B (as an external)
    Function *FAExtern = insertExternalReferenceToFunction(B.get(), FA);

    // Define FB2 in B (with a call to FA)
    FB2 = insertAccumulateFunction(B.get(), FAExtern, "FB2");
  }

  // Module A { Function FA },
  // Module B { Extern FA, Function FB which calls FA },
  // Module C { Extern FB, Function FC which calls FB },
  void
  createThreeModuleChainedCallsCase(std::unique_ptr<Module> &A, Function *&FA,
                                    std::unique_ptr<Module> &B, Function *&FB,
                                    std::unique_ptr<Module> &C, Function *&FC) {
    A.reset(createEmptyModule("A"));
    FA = insertAddFunction(A.get());

    B.reset(createEmptyModule("B"));
    Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA);
    FB = insertSimpleCallFunction(B.get(), FAExtern_in_B);

    C.reset(createEmptyModule("C"));
    Function *FBExtern_in_C = insertExternalReferenceToFunction(C.get(), FB);
    FC = insertSimpleCallFunction(C.get(), FBExtern_in_C);
  }

  // Module A { Function FA },
  // Populates Modules A and B:
  // Module B { Function FB }
  void createTwoModuleCase(std::unique_ptr<Module> &A, Function *&FA,
                           std::unique_ptr<Module> &B, Function *&FB) {
    A.reset(createEmptyModule("A"));
    FA = insertAddFunction(A.get());

    B.reset(createEmptyModule("B"));
    FB = insertAddFunction(B.get());
  }

  // Module A { Function FA },
  // Module B { Extern FA, Function FB which calls FA }
  void createTwoModuleExternCase(std::unique_ptr<Module> &A, Function *&FA,
                                 std::unique_ptr<Module> &B, Function *&FB) {
    A.reset(createEmptyModule("A"));
    FA = insertAddFunction(A.get());

    B.reset(createEmptyModule("B"));
    Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA);
    FB = insertSimpleCallFunction(B.get(), FAExtern_in_B);
  }

  // Module A { Function FA },
  // Module B { Extern FA, Function FB which calls FA },
  // Module C { Extern FB, Function FC which calls FA },
  void createThreeModuleCase(std::unique_ptr<Module> &A, Function *&FA,
                             std::unique_ptr<Module> &B, Function *&FB,
                             std::unique_ptr<Module> &C, Function *&FC) {
    A.reset(createEmptyModule("A"));
    FA = insertAddFunction(A.get());

    B.reset(createEmptyModule("B"));
    Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA);
    FB = insertSimpleCallFunction(B.get(), FAExtern_in_B);

    C.reset(createEmptyModule("C"));
    Function *FAExtern_in_C = insertExternalReferenceToFunction(C.get(), FA);
    FC = insertSimpleCallFunction(C.get(), FAExtern_in_C);
  }
};

class MCJITTestBase : public MCJITTestAPICommon, public TrivialModuleBuilder {
protected:
  MCJITTestBase()
      : TrivialModuleBuilder(HostTriple), OptLevel(CodeGenOptLevel::None),
        CodeModel(CodeModel::Small), MArch(""), MM(new SectionMemoryManager) {
    // The architectures below are known to be compatible with MCJIT as they
    // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
    // kept in sync.
    SupportedArchs.push_back(Triple::aarch64);
    SupportedArchs.push_back(Triple::arm);
    SupportedArchs.push_back(Triple::mips);
    SupportedArchs.push_back(Triple::mipsel);
    SupportedArchs.push_back(Triple::mips64);
    SupportedArchs.push_back(Triple::mips64el);
    SupportedArchs.push_back(Triple::x86);
    SupportedArchs.push_back(Triple::x86_64);

    // Some architectures have sub-architectures in which tests will fail, like
    // ARM. These two vectors will define if they do have sub-archs (to avoid
    // extra work for those who don't), and if so, if they are listed to work
    HasSubArchs.push_back(Triple::arm);
    SupportedSubArchs.push_back("armv6");
    SupportedSubArchs.push_back("armv7");

    UnsupportedEnvironments.push_back(Triple::Cygnus);
  }

  void createJIT(std::unique_ptr<Module> M) {

    // Due to the EngineBuilder constructor, it is required to have a Module
    // in order to construct an ExecutionEngine (i.e. MCJIT)
    assert(M != 0 && "a non-null Module must be provided to create MCJIT");

    EngineBuilder EB(std::move(M));
    std::string Error;
    TheJIT.reset(EB.setEngineKind(EngineKind::JIT)
                     .setMCJITMemoryManager(std::move(MM))
                     .setErrorStr(&Error)
                     .setOptLevel(CodeGenOptLevel::None)
                     .setMArch(MArch)
                     .setMCPU(sys::getHostCPUName())
                     //.setMAttrs(MAttrs)
                     .create());
    // At this point, we cannot modify the module any more.
    assert(TheJIT.get() != NULL && "error creating MCJIT with EngineBuilder");
  }

  CodeGenOptLevel OptLevel;
  CodeModel::Model CodeModel;
  StringRef MArch;
  SmallVector<std::string, 1> MAttrs;
  std::unique_ptr<ExecutionEngine> TheJIT;
  std::unique_ptr<RTDyldMemoryManager> MM;

  std::unique_ptr<Module> M;
};

} // namespace llvm

#endif // LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H
