#include "llvm/ExecutionEngine/Orc/ReOptimizeLayer.h"
#include "llvm/ExecutionEngine/Orc/LookupAndApply.h"
#include "llvm/ExecutionEngine/Orc/Mangling.h"
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"

using namespace llvm;
using namespace orc;

bool ReOptimizeLayer::ReOptMaterializationUnitState::tryStartReoptimize() {
  std::unique_lock<std::mutex> Lock(Mutex);
  if (Reoptimizing)
    return false;

  Reoptimizing = true;
  return true;
}

void ReOptimizeLayer::ReOptMaterializationUnitState::reoptimizeSucceeded() {
  std::unique_lock<std::mutex> Lock(Mutex);
  assert(Reoptimizing && "Tried to mark unstarted reoptimization as done");
  Reoptimizing = false;
  CurVersion++;
}

void ReOptimizeLayer::ReOptMaterializationUnitState::reoptimizeFailed() {
  std::unique_lock<std::mutex> Lock(Mutex);
  assert(Reoptimizing && "Tried to mark unstarted reoptimization as done");
  Reoptimizing = false;
}

static void orc_rt_lite_reoptimize_helper(
    shared::CWrapperFunctionBuffer (*JITDispatch)(void *Ctx, void *Tag,
                                                  const char *Data,
                                                  size_t Size),
    void *JITDispatchCtx, void *Tag, uint64_t MUID, uint32_t CurVersion) {
  // Serialize the arguments into a WrapperFunctionBuffer and call dispatch.
  using SPSArgs = shared::SPSArgList<uint64_t, uint32_t>;
  auto ArgBytes =
      shared::WrapperFunctionBuffer::allocate(SPSArgs::size(MUID, CurVersion));
  shared::SPSOutputBuffer OB(ArgBytes.data(), ArgBytes.size());
  if (!SPSArgs::serialize(OB, MUID, CurVersion)) {
    errs()
        << "Reoptimization error: could not serialize reoptimization arguments";
    abort();
  }
  shared::WrapperFunctionBuffer Buf{
      JITDispatch(JITDispatchCtx, Tag, ArgBytes.data(), ArgBytes.size())};

  if (const char *ErrMsg = Buf.getOutOfBandError()) {
    errs() << "Reoptimization error: " << ErrMsg << "\naborting.\n";
    abort();
  }
}

Error ReOptimizeLayer::addOrcRTLiteSupport(JITDylib &PlatformJD,
                                           const DataLayout &DL) {
  auto Ctx = std::make_unique<LLVMContext>();
  auto Mod = std::make_unique<Module>("orc-rt-lite-reoptimize.ll", *Ctx);
  Mod->setDataLayout(DL);

  IRBuilder<> Builder(*Ctx);

  // Create basic types portably
  Type *VoidTy = Type::getVoidTy(*Ctx);
  Type *Int8Ty = Type::getInt8Ty(*Ctx);
  Type *Int32Ty = Type::getInt32Ty(*Ctx);
  Type *Int64Ty = Type::getInt64Ty(*Ctx);
  Type *VoidPtrTy = PointerType::getUnqual(*Ctx);

  // Helper function type: void (void*, void*, void*, uint64_t, uint32_t)
  FunctionType *HelperFnTy = FunctionType::get(
      VoidTy, {VoidPtrTy, VoidPtrTy, VoidPtrTy, Int64Ty, Int32Ty}, false);

  // Define ReoptimizeTag with initializer = 0
  GlobalVariable *ReoptimizeTag = new GlobalVariable(
      *Mod, Int8Ty, false, GlobalValue::ExternalLinkage,
      ConstantInt::get(Int8Ty, 0), "__orc_rt_reoptimize_tag");

  // Define orc_rt_lite_reoptimize function: void (uint64_t, uint32_t)
  FunctionType *ReOptimizeFnTy =
      FunctionType::get(VoidTy, {Int64Ty, Int32Ty}, false);

  Function *ReOptimizeFn =
      Function::Create(ReOptimizeFnTy, Function::ExternalLinkage,
                       "__orc_rt_reoptimize", Mod.get());

  // Set parameter names
  auto ArgIt = ReOptimizeFn->arg_begin();
  Value *MUID = &*ArgIt++;
  MUID->setName("MUID");
  Value *CurVersion = &*ArgIt;
  CurVersion->setName("CurVersion");

  // Build function body
  BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", ReOptimizeFn);
  Builder.SetInsertPoint(Entry);

  ExecutorAddr JITDispatchSym, JITDispatchCtxSym;
  if (auto Err =
          lookupAndApply(ES.getBootstrapJITDylib(),
                         {recordAddr(rt::DispatchName, &JITDispatchSym),
                          recordAddr(rt::DispatchCtxName, &JITDispatchCtxSym)}))
    return Err;

  Type *IntPtrTy = DL.getIntPtrType(*Ctx);
  Constant *JITDispatchPtr = ConstantExpr::getIntToPtr(
      ConstantInt::get(IntPtrTy, JITDispatchSym.getValue()), VoidPtrTy);
  Constant *JITDispatchCtxPtr = ConstantExpr::getIntToPtr(
      ConstantInt::get(IntPtrTy, JITDispatchCtxSym.getValue()), VoidPtrTy);
  Constant *HelperFnAddr = ConstantExpr::getIntToPtr(
      ConstantInt::get(IntPtrTy, reinterpret_cast<uintptr_t>(
                                     &orc_rt_lite_reoptimize_helper)),
      PointerType::getUnqual(*Ctx));

  // Cast ReoptimizeTag to void*
  Value *ReoptimizeTagPtr = Builder.CreatePointerCast(ReoptimizeTag, VoidPtrTy);

  // Call the helper function
  Builder.CreateCall(
      HelperFnTy, HelperFnAddr,
      {JITDispatchPtr, JITDispatchCtxPtr, ReoptimizeTagPtr, MUID, CurVersion});

  // Return void
  Builder.CreateRetVoid();

  return BaseLayer.add(PlatformJD,
                       ThreadSafeModule(std::move(Mod), std::move(Ctx)));
}

Error ReOptimizeLayer::registerRuntimeFunctions(JITDylib &PlatformJD) {
  ExecutionSession::JITDispatchHandlerAssociationMap WFs;
  using ReoptimizeSPSSig = shared::SPSError(uint64_t, uint32_t);
  WFs[Mangle("__orc_rt_reoptimize_tag")] =
      ES.wrapAsyncWithSPS<ReoptimizeSPSSig>(this,
                                            &ReOptimizeLayer::rt_reoptimize);
  return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
}

void ReOptimizeLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
                           ThreadSafeModule TSM) {
  auto &JD = R->getTargetJITDylib();

  bool HasNonCallable = false;
  for (auto &KV : R->getSymbols()) {
    auto &Flags = KV.second;
    if (!Flags.isCallable())
      HasNonCallable = true;
  }

  if (HasNonCallable) {
    BaseLayer.emit(std::move(R), std::move(TSM));
    return;
  }

  auto &MUState = createMaterializationUnitState(TSM);

  if (auto Err = R->withResourceKeyDo([&](ResourceKey Key) {
        registerMaterializationUnitResource(Key, MUState);
      })) {
    ES.reportError(std::move(Err));
    R->failMaterialization();
    return;
  }

  if (auto Err =
          ProfilerFunc(*this, MUState.getID(), MUState.getCurVersion(), TSM)) {
    ES.reportError(std::move(Err));
    R->failMaterialization();
    return;
  }

  auto InitialDests =
      emitMUImplSymbols(MUState, MUState.getCurVersion(), JD, std::move(TSM));
  if (!InitialDests) {
    ES.reportError(InitialDests.takeError());
    R->failMaterialization();
    return;
  }

  RSManager.emitRedirectableSymbols(std::move(R), std::move(*InitialDests));
}

Error ReOptimizeLayer::reoptimizeIfCallFrequent(ReOptimizeLayer &Parent,
                                                ReOptMaterializationUnitID MUID,
                                                unsigned CurVersion,
                                                ThreadSafeModule &TSM) {
  return TSM.withModuleDo([&](Module &M) -> Error {
    Type *I64Ty = Type::getInt64Ty(M.getContext());
    GlobalVariable *Counter = new GlobalVariable(
        M, I64Ty, false, GlobalValue::InternalLinkage,
        Constant::getNullValue(I64Ty), "__orc_reopt_counter");
    for (auto &F : M) {
      if (F.isDeclaration())
        continue;
      auto &BB = F.getEntryBlock();
      auto *IP = &*BB.getFirstInsertionPt();
      IRBuilder<> IRB(IP);
      Value *Threshold = ConstantInt::get(I64Ty, CallCountThreshold, true);
      Value *Cnt = IRB.CreateLoad(I64Ty, Counter);
      // Use EQ to prevent further reoptimize calls.
      Value *Cmp = IRB.CreateICmpEQ(Cnt, Threshold);
      Value *Added = IRB.CreateAdd(Cnt, ConstantInt::get(I64Ty, 1));
      (void)IRB.CreateStore(Added, Counter);
      Instruction *SplitTerminator = SplitBlockAndInsertIfThen(Cmp, IP, false);
      createReoptimizeCall(M, *SplitTerminator, MUID, CurVersion);
    }
    return Error::success();
  });
}

Expected<SymbolMap>
ReOptimizeLayer::emitMUImplSymbols(ReOptMaterializationUnitState &MUState,
                                   uint32_t Version, JITDylib &JD,
                                   ThreadSafeModule TSM) {
  DenseMap<SymbolStringPtr, SymbolStringPtr> RenamedMap;
  cantFail(TSM.withModuleDo([&](Module &M) -> Error {
    MangleAndInterner Mangle(ES, M.getDataLayout());
    for (auto &F : M)
      if (!F.isDeclaration()) {
        std::string NewName =
            (F.getName() + ".__def__." + Twine(Version)).str();
        RenamedMap[Mangle(F.getName())] = Mangle(NewName);
        F.setName(NewName);
      }
    return Error::success();
  }));

  auto RT = JD.createResourceTracker();
  if (auto Err =
          JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
                        BaseLayer, *getManglingOptions(), std::move(TSM)),
                    RT))
    return Err;
  MUState.setResourceTracker(RT);

  SymbolLookupSet LookupSymbols;
  for (auto [K, V] : RenamedMap)
    LookupSymbols.add(V);

  auto ImplSymbols =
      ES.lookup({{&JD, JITDylibLookupFlags::MatchAllSymbols}}, LookupSymbols,
                LookupKind::Static, SymbolState::Resolved);
  if (auto Err = ImplSymbols.takeError())
    return Err;

  SymbolMap Result;
  for (auto [K, V] : RenamedMap)
    Result[K] = (*ImplSymbols)[V];

  return Result;
}

void ReOptimizeLayer::rt_reoptimize(SendErrorFn SendResult,
                                    ReOptMaterializationUnitID MUID,
                                    uint32_t CurVersion) {
  auto &MUState = getMaterializationUnitState(MUID);
  if (CurVersion < MUState.getCurVersion() || !MUState.tryStartReoptimize()) {
    SendResult(Error::success());
    return;
  }

  ThreadSafeModule TSM = cloneToNewContext(MUState.getThreadSafeModule());
  auto OldRT = MUState.getResourceTracker();
  auto &JD = OldRT->getJITDylib();

  if (auto Err = ReOptFunc(*this, MUID, CurVersion + 1, OldRT, TSM)) {
    ES.reportError(std::move(Err));
    MUState.reoptimizeFailed();
    SendResult(Error::success());
    return;
  }

  auto SymbolDests =
      emitMUImplSymbols(MUState, CurVersion + 1, JD, std::move(TSM));
  if (!SymbolDests) {
    ES.reportError(SymbolDests.takeError());
    MUState.reoptimizeFailed();
    SendResult(Error::success());
    return;
  }

  if (auto Err = RSManager.redirect(JD, std::move(*SymbolDests))) {
    ES.reportError(std::move(Err));
    MUState.reoptimizeFailed();
    SendResult(Error::success());
    return;
  }

  MUState.reoptimizeSucceeded();
  SendResult(Error::success());
}

void ReOptimizeLayer::createReoptimizeCall(Module &M, Instruction &IP,
                                           ReOptMaterializationUnitID MUID,
                                           uint32_t CurVersion) {
  Type *MUIDTy = IntegerType::get(M.getContext(), 64);
  Type *VersionTy = IntegerType::get(M.getContext(), 32);
  Function *ReoptimizeFunc = M.getFunction("__orc_rt_reoptimize");
  if (!ReoptimizeFunc) {
    std::vector<Type *> ArgTys = {MUIDTy, VersionTy};
    FunctionType *FuncTy =
        FunctionType::get(Type::getVoidTy(M.getContext()), ArgTys, false);
    ReoptimizeFunc = Function::Create(FuncTy, GlobalValue::ExternalLinkage,
                                      "__orc_rt_reoptimize", &M);
  }
  Constant *MUIDArg = ConstantInt::get(MUIDTy, MUID, false);
  Constant *CurVersionArg = ConstantInt::get(VersionTy, CurVersion, false);
  IRBuilder<> IRB(&IP);
  (void)IRB.CreateCall(ReoptimizeFunc, {MUIDArg, CurVersionArg});
}

ReOptimizeLayer::ReOptMaterializationUnitState &
ReOptimizeLayer::createMaterializationUnitState(const ThreadSafeModule &TSM) {
  std::unique_lock<std::mutex> Lock(Mutex);
  ReOptMaterializationUnitID MUID = NextID;
  MUStates.emplace(MUID,
                   ReOptMaterializationUnitState(MUID, cloneToNewContext(TSM)));
  ++NextID;
  return MUStates.at(MUID);
}

ReOptimizeLayer::ReOptMaterializationUnitState &
ReOptimizeLayer::getMaterializationUnitState(ReOptMaterializationUnitID MUID) {
  std::unique_lock<std::mutex> Lock(Mutex);
  return MUStates.at(MUID);
}

void ReOptimizeLayer::registerMaterializationUnitResource(
    ResourceKey Key, ReOptMaterializationUnitState &State) {
  std::unique_lock<std::mutex> Lock(Mutex);
  MUResources[Key].insert(State.getID());
}

Error ReOptimizeLayer::handleRemoveResources(JITDylib &JD, ResourceKey K) {
  std::unique_lock<std::mutex> Lock(Mutex);
  for (auto MUID : MUResources[K])
    MUStates.erase(MUID);

  MUResources.erase(K);
  return Error::success();
}

void ReOptimizeLayer::handleTransferResources(JITDylib &JD, ResourceKey DstK,
                                              ResourceKey SrcK) {
  std::unique_lock<std::mutex> Lock(Mutex);
  MUResources[DstK].insert_range(MUResources[SrcK]);
  MUResources.erase(SrcK);
}
