//===---------- speculation.cpp - Utilities for Speculation ----------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/Orc/Speculation.h"

#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Verifier.h"

namespace llvm {

namespace orc {

// ImplSymbolMap methods
void ImplSymbolMap::trackImpls(SymbolAliasMap ImplMaps, JITDylib *SrcJD) {
  assert(SrcJD && "Tracking on Null Source .impl dylib");
  std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
  for (auto &I : ImplMaps) {
    auto It = Maps.insert({I.first, {I.second.Aliasee, SrcJD}});
    // check rationale when independent dylibs have same symbol name?
    assert(It.second && "ImplSymbols are already tracked for this Symbol?");
    (void)(It);
  }
}

// Trigger Speculative Compiles.
void Speculator::speculateForEntryPoint(Speculator *Ptr, uint64_t StubId) {
  assert(Ptr && " Null Address Received in orc_speculate_for ");
  Ptr->speculateFor(ExecutorAddr(StubId));
}

Error Speculator::addSpeculationRuntime(JITDylib &JD,
                                        MangleAndInterner &Mangle) {
  ExecutorSymbolDef ThisPtr(ExecutorAddr::fromPtr(this),
                            JITSymbolFlags::Exported);
  ExecutorSymbolDef SpeculateForEntryPtr(
      ExecutorAddr::fromPtr(&speculateForEntryPoint), JITSymbolFlags::Exported);
  return JD.define(absoluteSymbols({
      {Mangle("__orc_speculator"), ThisPtr},                // Data Symbol
      {Mangle("__orc_speculate_for"), SpeculateForEntryPtr} // Callable Symbol
  }));
}

// If two modules, share the same LLVMContext, different threads must
// not access them concurrently without locking the associated LLVMContext
// this implementation follows this contract.
void IRSpeculationLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
                              ThreadSafeModule TSM) {

  assert(TSM && "Speculation Layer received Null Module ?");

  // Instrumentation of runtime calls, lock the Module
  TSM.withModuleDo([this, &R](Module &M) {
    auto &MContext = M.getContext();
    auto SpeculatorVTy = StructType::create(MContext, "Class.Speculator");
    auto RuntimeCallTy = FunctionType::get(
        Type::getVoidTy(MContext),
        {PointerType::getUnqual(MContext), Type::getInt64Ty(MContext)}, false);
    auto RuntimeCall =
        Function::Create(RuntimeCallTy, Function::LinkageTypes::ExternalLinkage,
                         "__orc_speculate_for", &M);
    auto SpeclAddr = new GlobalVariable(
        M, SpeculatorVTy, false, GlobalValue::LinkageTypes::ExternalLinkage,
        nullptr, "__orc_speculator");

    IRBuilder<> Mutator(MContext);

    // QueryAnalysis allowed to transform the IR source, one such example is
    // Simplify CFG helps the static branch prediction heuristics!
    for (auto &Fn : M.getFunctionList()) {
      if (!Fn.isDeclaration()) {

        auto IRNames = QueryAnalysis(Fn);
        // Instrument and register if Query has result
        if (IRNames) {

          // Emit globals for each function.
          auto LoadValueTy = Type::getInt8Ty(MContext);
          auto SpeculatorGuard = new GlobalVariable(
              M, LoadValueTy, false, GlobalValue::LinkageTypes::InternalLinkage,
              ConstantInt::get(LoadValueTy, 0),
              "__orc_speculate.guard.for." + Fn.getName());
          SpeculatorGuard->setAlignment(Align(1));
          SpeculatorGuard->setUnnamedAddr(GlobalValue::UnnamedAddr::Local);

          BasicBlock &ProgramEntry = Fn.getEntryBlock();
          // Create BasicBlocks before the program's entry basicblock
          BasicBlock *SpeculateBlock = BasicBlock::Create(
              MContext, "__orc_speculate.block", &Fn, &ProgramEntry);
          BasicBlock *SpeculateDecisionBlock = BasicBlock::Create(
              MContext, "__orc_speculate.decision.block", &Fn, SpeculateBlock);

          assert(SpeculateDecisionBlock == &Fn.getEntryBlock() &&
                 "SpeculateDecisionBlock not updated?");
          Mutator.SetInsertPoint(SpeculateDecisionBlock);

          auto LoadGuard =
              Mutator.CreateLoad(LoadValueTy, SpeculatorGuard, "guard.value");
          // if just loaded value equal to 0,return true.
          auto CanSpeculate =
              Mutator.CreateICmpEQ(LoadGuard, ConstantInt::get(LoadValueTy, 0),
                                   "compare.to.speculate");
          Mutator.CreateCondBr(CanSpeculate, SpeculateBlock, &ProgramEntry);

          Mutator.SetInsertPoint(SpeculateBlock);
          auto ImplAddrToUint =
              Mutator.CreatePtrToInt(&Fn, Type::getInt64Ty(MContext));
          Mutator.CreateCall(RuntimeCallTy, RuntimeCall,
                             {SpeclAddr, ImplAddrToUint});
          Mutator.CreateStore(ConstantInt::get(LoadValueTy, 1),
                              SpeculatorGuard);
          Mutator.CreateBr(&ProgramEntry);

          assert(Mutator.GetInsertBlock()->getParent() == &Fn &&
                 "IR builder association mismatch?");
          S.registerSymbols(internToJITSymbols(*IRNames),
                            &R->getTargetJITDylib());
        }
      }
    }
  });

  assert(!TSM.withModuleDo([](const Module &M) { return verifyModule(M); }) &&
         "Speculation Instrumentation breaks IR?");

  NextLayer.emit(std::move(R), std::move(TSM));
}

} // namespace orc
} // namespace llvm
