//===-- TargetMachine.cpp - General Target Information ---------------------==//
//
// 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 file describes the general parts of a Target machine.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetMachine.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
using namespace llvm;

cl::opt<bool> llvm::NoKernelInfoEndLTO(
    "no-kernel-info-end-lto",
    cl::desc("remove the kernel-info pass at the end of the full LTO pipeline"),
    cl::init(false), cl::Hidden);

//---------------------------------------------------------------------------
// TargetMachine Class
//

static bool isExceptionModelSupportedByDefault(const Triple &TT,
                                               ExceptionHandling Model) {
  // Each model is valid only where its object format or architecture defines
  // it. DwarfCFI and SjLj are the generic unwinding schemes, valid on any
  // target that has exception handling by default.
  switch (Model) {
  case ExceptionHandling::DwarfCFI:
  case ExceptionHandling::SjLj:
    return TT.getDefaultExceptionHandling() != ExceptionHandling::None;
  case ExceptionHandling::WinEH:
    return TT.isOSBinFormatCOFF();
  case ExceptionHandling::ARM:
    return (TT.isARM() || TT.isThumb()) && TT.isOSBinFormatELF();
  case ExceptionHandling::AIX:
    return TT.isOSBinFormatXCOFF();
  case ExceptionHandling::ZOS:
    return TT.isOSBinFormatGOFF();
  case ExceptionHandling::Wasm:
  case ExceptionHandling::Emscripten:
    return TT.isWasm();
  case ExceptionHandling::None:
  case ExceptionHandling::Default:
    break;
  }

  llvm_unreachable("unexpected exception model");
}

TargetMachine::TargetMachine(const Target &T, StringRef DataLayoutString,
                             const Triple &TT, StringRef CPU, StringRef FS,
                             const TargetOptions &Options)
    : TheTarget(T), DL(DataLayoutString), TargetTriple(TT),
      TargetCPU(std::string(CPU)), TargetFS(std::string(FS)), AsmInfo(nullptr),
      MRI(nullptr), MII(nullptr), STI(nullptr), RequireStructuredCFG(false),
      O0WantsFastISel(false), EnableTiedFastRegAlloc(true),
      SupportsDefaultOutlining(false), SupportsDebugEntryValues(false),
      Options(Options) {
  for (ExceptionHandling Model :
       {ExceptionHandling::DwarfCFI, ExceptionHandling::SjLj,
        ExceptionHandling::ARM, ExceptionHandling::WinEH,
        ExceptionHandling::Wasm, ExceptionHandling::Emscripten,
        ExceptionHandling::AIX, ExceptionHandling::ZOS}) {
    setSupportsExceptionModel(Model,
                              isExceptionModelSupportedByDefault(TT, Model));
  }
}

TargetMachine::~TargetMachine() = default;

/// NOTE: There are targets that still do not support the debug entry values
/// production and that is being controlled with the SupportsDebugEntryValues.
/// In addition, SCE debugger does not have the feature implemented, so prefer
/// not to emit the debug entry values in that case.
/// The EnableDebugEntryValues can be used for the testing purposes.
bool TargetMachine::shouldEmitDebugEntryValues() const {
  return (SupportsDebugEntryValues &&
          Options.DebuggerTuning != DebuggerKind::SCE) ||
         Options.EnableDebugEntryValues;
}

Expected<std::unique_ptr<MCStreamer>>
TargetMachine::createMCStreamer(raw_pwrite_stream &Out,
                                raw_pwrite_stream *DwoOut,
                                CodeGenFileType FileType, MCContext &Ctx) {
  return nullptr;
}

bool TargetMachine::isLargeDataSize(uint64_t Size) const {
  if (getTargetTriple().getArch() != Triple::x86_64)
    return false;

  if (!getTargetTriple().isOSBinFormatELF())
    return getCodeModel() == CodeModel::Large;

  if (getCodeModel() == CodeModel::Medium || getCodeModel() == CodeModel::Large)
    return Size == 0 || Size > LargeDataThreshold;

  return false;
}

bool TargetMachine::isLargeGlobalValue(const GlobalValue *GVal) const {
  if (getTargetTriple().getArch() != Triple::x86_64)
    return false;

  // Remaining logic below is ELF-specific. For other object file formats where
  // the large code model is mostly used for JIT compilation, just look at the
  // code model.
  if (!getTargetTriple().isOSBinFormatELF())
    return getCodeModel() == CodeModel::Large;

  auto *GO = GVal->getAliaseeObject();

  // Be conservative if we can't find an underlying GlobalObject.
  if (!GO)
    return true;

  auto *GV = dyn_cast<GlobalVariable>(GO);

  auto IsPrefix = [](StringRef Name, StringRef Prefix) {
    return Name.consume_front(Prefix) && (Name.empty() || Name[0] == '.');
  };

  // Functions/GlobalIFuncs are only large under the large code model.
  if (!GV) {
    // Handle explicit sections as we do for GlobalVariables with an explicit
    // section, see comments below.
    if (GO->hasSection()) {
      StringRef Name = GO->getSection();
      return IsPrefix(Name, ".ltext");
    }
    return getCodeModel() == CodeModel::Large;
  }

  if (GV->isThreadLocal())
    return false;

  // For x86-64, we treat an explicit GlobalVariable small code model to mean
  // that the global should be placed in a small section, and ditto for large.
  if (auto CM = GV->getCodeModel()) {
    if (*CM == CodeModel::Small)
      return false;
    if (*CM == CodeModel::Large)
      return true;
  }

  // Treat all globals in user-defined sections as small, except for the
  // standard large sections of .lbss, .ldata, .lrodata. This reduces the risk
  // of linking together small and large sections, resulting in small
  // references to large data sections. The code model attribute overrides this
  // above.
  if (GV->hasSection() || GV->hasImplicitSection()) {
    StringRef SectionName =
        TargetLoweringObjectFile::getCustomSectionName(GV, *this);
    if (!SectionName.empty()) {
      return IsPrefix(SectionName, ".lbss") ||
             IsPrefix(SectionName, ".ldata") ||
             IsPrefix(SectionName, ".lrodata");
    }
  }

  // Respect large data threshold for medium and large code models.
  if (getCodeModel() == CodeModel::Medium ||
      getCodeModel() == CodeModel::Large) {
    if (!GV->getValueType()->isSized())
      return true;
    // Linker defined start/stop symbols can point to arbitrary points in the
    // binary, so treat them as large.
    if (GV->isDeclaration() && (GV->getName() == "__ehdr_start" ||
                                GV->getName().starts_with("__start_") ||
                                GV->getName().starts_with("__stop_")))
      return true;
    // Linkers do not currently support PT_GNU_RELRO for SHF_X86_64_LARGE
    // sections; that would require the linker to emit more than one
    // PT_GNU_RELRO because large sections are discontiguous by design, and most
    // ELF dynamic loaders do not support that (bionic appears to support it but
    // glibc/musl/FreeBSD/NetBSD/OpenBSD appear not to). With current linkers
    // these sections will end up in .ldata which results in silently disabling
    // RELRO. If this ever gets supported by downstream components in the future
    // we could add an opt-in flag for moving these sections to .ldata.rel.ro
    // which would trigger the creation of a second PT_GNU_RELRO.
    if (!GV->isDeclarationForLinker() &&
        TargetLoweringObjectFile::getKindForGlobal(GV, *this)
            .isReadOnlyWithRel())
      return false;
    const DataLayout &DL = GV->getDataLayout();
    return isLargeDataSize(GV->getGlobalSize(DL));
  }

  return false;
}

bool TargetMachine::isPositionIndependent() const {
  return getRelocationModel() == Reloc::PIC_;
}

/// Returns the code generation relocation model. The choices are static, PIC,
/// and dynamic-no-pic.
Reloc::Model TargetMachine::getRelocationModel() const { return RM; }

uint64_t TargetMachine::getMaxCodeSize() const {
  switch (getCodeModel()) {
  case CodeModel::Tiny:
    return llvm::maxUIntN(10);
  case CodeModel::Small:
  case CodeModel::Kernel:
  case CodeModel::Medium:
    return llvm::maxUIntN(31);
  case CodeModel::Large:
    return llvm::maxUIntN(64);
  }
  llvm_unreachable("Unhandled CodeModel enum");
}

/// Get the IR-specified TLS model for Var.
static TLSModel::Model getSelectedTLSModel(const GlobalValue *GV) {
  switch (GV->getThreadLocalMode()) {
  case GlobalVariable::NotThreadLocal:
    llvm_unreachable("getSelectedTLSModel for non-TLS variable");
    break;
  case GlobalVariable::GeneralDynamicTLSModel:
    return TLSModel::GeneralDynamic;
  case GlobalVariable::LocalDynamicTLSModel:
    return TLSModel::LocalDynamic;
  case GlobalVariable::InitialExecTLSModel:
    return TLSModel::InitialExec;
  case GlobalVariable::LocalExecTLSModel:
    return TLSModel::LocalExec;
  }
  llvm_unreachable("invalid TLS model");
}

bool TargetMachine::shouldAssumeDSOLocal(const GlobalValue *GV) const {
  const Triple &TT = getTargetTriple();
  Reloc::Model RM = getRelocationModel();

  // According to the llvm language reference, we should be able to
  // just return false in here if we have a GV, as we know it is
  // dso_preemptable.  At this point in time, the various IR producers
  // have not been transitioned to always produce a dso_local when it
  // is possible to do so.
  //
  // As a result we still have some logic in here to improve the quality of the
  // generated code.
  if (!GV)
    return false;

  // If the IR producer requested that this GV be treated as dso local, obey.
  if (GV->isDSOLocal())
    return true;

  if (TT.isOSBinFormatCOFF()) {
    // DLLImport explicitly marks the GV as external.
    if (GV->hasDLLImportStorageClass())
      return false;

    // On MinGW, variables that haven't been declared with DLLImport may still
    // end up automatically imported by the linker. To make this feasible,
    // don't assume the variables to be DSO local unless we actually know
    // that for sure. This only has to be done for variables; for functions
    // the linker can insert thunks for calling functions from another DLL.
    if (TT.isOSCygMing() && GV->isDeclarationForLinker() &&
        isa<GlobalVariable>(GV))
      return false;

    // Don't mark 'extern_weak' symbols as DSO local. If these symbols remain
    // unresolved in the link, they can be resolved to zero, which is outside
    // the current DSO.
    if (GV->hasExternalWeakLinkage())
      return false;

    // Every other GV is local on COFF.
    return true;
  }

  if (TT.isOSBinFormatGOFF())
    return true;

  if (TT.isOSBinFormatMachO()) {
    if (RM == Reloc::Static)
      return true;
    return GV->isStrongDefinitionForLinker();
  }

  assert(TT.isOSBinFormatELF() || TT.isOSBinFormatWasm() ||
         TT.isOSBinFormatXCOFF());
  return false;
}

bool TargetMachine::useEmulatedTLS() const { return Options.EmulatedTLS; }
bool TargetMachine::useTLSDESC() const { return Options.EnableTLSDESC; }

TLSModel::Model TargetMachine::getTLSModel(const GlobalValue *GV) const {
  bool IsPIE = GV->getParent()->getPIELevel() != PIELevel::Default;
  Reloc::Model RM = getRelocationModel();
  bool IsSharedLibrary = RM == Reloc::PIC_ && !IsPIE;
  bool IsLocal = shouldAssumeDSOLocal(GV);

  TLSModel::Model Model;
  if (IsSharedLibrary) {
    if (IsLocal)
      Model = TLSModel::LocalDynamic;
    else
      Model = TLSModel::GeneralDynamic;
  } else {
    if (IsLocal)
      Model = TLSModel::LocalExec;
    else
      Model = TLSModel::InitialExec;
  }

  // If the user specified a more specific model, use that.
  TLSModel::Model SelectedModel = getSelectedTLSModel(GV);
  if (SelectedModel > Model)
    return SelectedModel;

  return Model;
}

TargetTransformInfo
TargetMachine::getTargetTransformInfo(const Function &F) const {
  return TargetTransformInfo(F.getDataLayout());
}

void TargetMachine::getNameWithPrefix(SmallVectorImpl<char> &Name,
                                      const GlobalValue *GV, Mangler &Mang,
                                      bool MayAlwaysUsePrivate) const {
  if (MayAlwaysUsePrivate || !GV->hasPrivateLinkage()) {
    // Simple case: If GV is not private, it is not important to find out if
    // private labels are legal in this case or not.
    Mang.getNameWithPrefix(Name, GV, false);
    return;
  }
  const TargetLoweringObjectFile *TLOF = getObjFileLowering();
  TLOF->getNameWithPrefix(Name, GV, *this);
}

MCSymbol *TargetMachine::getSymbol(const GlobalValue *GV) const {
  const TargetLoweringObjectFile *TLOF = getObjFileLowering();
  // XCOFF symbols could have special naming convention.
  if (MCSymbol *TargetSymbol = TLOF->getTargetSymbol(GV, *this))
    return TargetSymbol;

  SmallString<128> NameStr;
  getNameWithPrefix(NameStr, GV, TLOF->getMangler());
  return TLOF->getContext().getOrCreateSymbol(NameStr);
}

TargetIRAnalysis TargetMachine::getTargetIRAnalysis() const {
  // Since Analysis can't depend on Target, use a std::function to invert the
  // dependency.
  return TargetIRAnalysis(
      [this](const Function &F) { return this->getTargetTransformInfo(F); });
}

StringRef TargetMachine::getTargetABIName(const Module &M) const {
  if (const auto *MD = cast_or_null<MDString>(M.getModuleFlag("target-abi")))
    return MD->getString();
  return Options.MCOptions.getABIName();
}

void TargetMachine::verifyOptionsConsistency(const Module &M) const {
  // The "target-abi" module flag must agree with the -target-abi option.
  StringRef OptionABI = Options.MCOptions.getABIName();
  if (!OptionABI.empty()) {
    if (const auto *MD =
            cast_or_null<MDString>(M.getModuleFlag("target-abi"))) {
      if (OptionABI != MD->getString())
        M.getContext().emitError(
            "-target-abi option != target-abi module flag");
    }
  }
}

const MCSubtargetInfo &TargetMachine::getMCSubtargetInfo(StringRef CPU,
                                                         StringRef FS) {
  if (CPU.empty() && FS.empty())
    return *STI;
  SmallString<128> Key = CPU;
  Key += '/';
  Key += FS;
  auto &Entry = MCSubtargetMap[Key];
  if (!Entry)
    Entry.reset(getTarget().createMCSubtargetInfo(getTargetTriple(), CPU, FS));
  return *Entry;
}
