#include "llvm/ExecutionEngine/Orc/ReOptimizeLayer.h"
#include "llvm/ExecutionEngine/Orc/Mangling.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);

  // Create absolute address constants
  auto &JDI = PlatformJD.getExecutionSession()
                  .getExecutorProcessControl()
                  .getJITDispatchInfo();

  Type *IntPtrTy = DL.getIntPtrType(*Ctx);
  Constant *JITDispatchPtr = ConstantExpr::getIntToPtr(
      ConstantInt::get(IntPtrTy, JDI.JITDispatchFunction.getValue()),
      VoidPtrTy);
  Constant *JITDispatchCtxPtr = ConstantExpr::getIntToPtr(
      ConstantInt::get(IntPtrTy, JDI.JITDispatchContext.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);
}
