| //===-- 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/Support/CodeGen.h" | 
 | #include "llvm/Target/TargetLoweringObjectFile.h" | 
 | using namespace llvm; | 
 |  | 
 | cl::opt<bool> 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 | 
 | // | 
 |  | 
 | 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), Options(Options) {} | 
 |  | 
 | TargetMachine::~TargetMachine() = default; | 
 |  | 
 | Expected<std::unique_ptr<MCStreamer>> | 
 | TargetMachine::createMCStreamer(raw_pwrite_stream &Out, | 
 |                                 raw_pwrite_stream *DwoOut, | 
 |                                 CodeGenFileType FileType, MCContext &Ctx) { | 
 |   return nullptr; | 
 | } | 
 |  | 
 | 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 explicit 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()) { | 
 |     StringRef Name = GV->getSection(); | 
 |     return IsPrefix(Name, ".lbss") || IsPrefix(Name, ".ldata") || | 
 |            IsPrefix(Name, ".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; | 
 |     const DataLayout &DL = GV->getDataLayout(); | 
 |     uint64_t Size = DL.getTypeAllocSize(GV->getValueType()); | 
 |     return Size == 0 || Size > LargeDataThreshold; | 
 |   } | 
 |  | 
 |   return false; | 
 | } | 
 |  | 
 | bool TargetMachine::isPositionIndependent() const { | 
 |   return getRelocationModel() == Reloc::PIC_; | 
 | } | 
 |  | 
 | /// Reset the target options based on the function's attributes. | 
 | /// setFunctionAttributes should have made the raw attribute value consistent | 
 | /// with the command line flag if used. | 
 | // | 
 | // FIXME: This function needs to go away for a number of reasons: | 
 | // a) global state on the TargetMachine is terrible in general, | 
 | // b) these target options should be passed only on the function | 
 | //    and not on the TargetMachine (via TargetOptions) at all. | 
 | void TargetMachine::resetTargetOptions(const Function &F) const { | 
 | #define RESET_OPTION(X, Y)                                              \ | 
 |   do {                                                                  \ | 
 |     Options.X = F.getFnAttribute(Y).getValueAsBool();     \ | 
 |   } while (0) | 
 |  | 
 |   RESET_OPTION(UnsafeFPMath, "unsafe-fp-math"); | 
 |   RESET_OPTION(NoInfsFPMath, "no-infs-fp-math"); | 
 |   RESET_OPTION(NoNaNsFPMath, "no-nans-fp-math"); | 
 |   RESET_OPTION(NoSignedZerosFPMath, "no-signed-zeros-fp-math"); | 
 |   RESET_OPTION(ApproxFuncFPMath, "approx-func-fp-math"); | 
 | } | 
 |  | 
 | /// 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); }); | 
 | } | 
 |  | 
 | std::pair<int, int> TargetMachine::parseBinutilsVersion(StringRef Version) { | 
 |   if (Version == "none") | 
 |     return {INT_MAX, INT_MAX}; // Make binutilsIsAtLeast() return true. | 
 |   std::pair<int, int> Ret; | 
 |   if (!Version.consumeInteger(10, Ret.first) && Version.consume_front(".")) | 
 |     Version.consumeInteger(10, Ret.second); | 
 |   return Ret; | 
 | } |