10b57cec5SDimitry Andric //===-- TargetMachine.cpp - General Target Information ---------------------==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file describes the general parts of a Target machine.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
140b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
150b57cec5SDimitry Andric #include "llvm/IR/Function.h"
160b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
170b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
180b57cec5SDimitry Andric #include "llvm/IR/Mangler.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
2281ad6265SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
2381ad6265SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
24fe013be4SDimitry Andric #include "llvm/Support/CodeGen.h"
250b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h"
260b57cec5SDimitry Andric using namespace llvm;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric //---------------------------------------------------------------------------
290b57cec5SDimitry Andric // TargetMachine Class
300b57cec5SDimitry Andric //
310b57cec5SDimitry Andric 
TargetMachine(const Target & T,StringRef DataLayoutString,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options)320b57cec5SDimitry Andric TargetMachine::TargetMachine(const Target &T, StringRef DataLayoutString,
330b57cec5SDimitry Andric                              const Triple &TT, StringRef CPU, StringRef FS,
340b57cec5SDimitry Andric                              const TargetOptions &Options)
355ffd83dbSDimitry Andric     : TheTarget(T), DL(DataLayoutString), TargetTriple(TT),
365ffd83dbSDimitry Andric       TargetCPU(std::string(CPU)), TargetFS(std::string(FS)), AsmInfo(nullptr),
375ffd83dbSDimitry Andric       MRI(nullptr), MII(nullptr), STI(nullptr), RequireStructuredCFG(false),
38c9157d92SDimitry Andric       O0WantsFastISel(false), Options(Options) {}
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric TargetMachine::~TargetMachine() = default;
410b57cec5SDimitry Andric 
isLargeGlobalValue(const GlobalValue * GVal) const42c9157d92SDimitry Andric bool TargetMachine::isLargeGlobalValue(const GlobalValue *GVal) const {
43fe013be4SDimitry Andric   if (getTargetTriple().getArch() != Triple::x86_64)
44fe013be4SDimitry Andric     return false;
45c9157d92SDimitry Andric 
46c9157d92SDimitry Andric   auto *GO = GVal->getAliaseeObject();
47c9157d92SDimitry Andric 
48c9157d92SDimitry Andric   // Be conservative if we can't find an underlying GlobalObject.
49c9157d92SDimitry Andric   if (!GO)
50fe013be4SDimitry Andric     return true;
51c9157d92SDimitry Andric 
52c9157d92SDimitry Andric   auto *GV = dyn_cast<GlobalVariable>(GO);
53c9157d92SDimitry Andric 
54c9157d92SDimitry Andric   // Functions/GlobalIFuncs are only large under the large code model.
55c9157d92SDimitry Andric   if (!GV)
56c9157d92SDimitry Andric     return getCodeModel() == CodeModel::Large;
57c9157d92SDimitry Andric 
58c9157d92SDimitry Andric   if (GV->isThreadLocal())
59c9157d92SDimitry Andric     return false;
60c9157d92SDimitry Andric 
61c9157d92SDimitry Andric   // For x86-64, we treat an explicit GlobalVariable small code model to mean
62c9157d92SDimitry Andric   // that the global should be placed in a small section, and ditto for large.
63c9157d92SDimitry Andric   if (auto CM = GV->getCodeModel()) {
64c9157d92SDimitry Andric     if (*CM == CodeModel::Small)
65c9157d92SDimitry Andric       return false;
66c9157d92SDimitry Andric     if (*CM == CodeModel::Large)
67c9157d92SDimitry Andric       return true;
68c9157d92SDimitry Andric   }
69c9157d92SDimitry Andric 
70*a58f00eaSDimitry Andric   // Treat all globals in explicit sections as small, except for the standard
71*a58f00eaSDimitry Andric   // large sections of .lbss, .ldata, .lrodata. This reduces the risk of linking
72*a58f00eaSDimitry Andric   // together small and large sections, resulting in small references to large
73*a58f00eaSDimitry Andric   // data sections. The code model attribute overrides this above.
74*a58f00eaSDimitry Andric   if (GV->hasSection()) {
75*a58f00eaSDimitry Andric     StringRef Name = GV->getSection();
76*a58f00eaSDimitry Andric     auto IsPrefix = [&](StringRef Prefix) {
77*a58f00eaSDimitry Andric       StringRef S = Name;
78*a58f00eaSDimitry Andric       return S.consume_front(Prefix) && (S.empty() || S[0] == '.');
79*a58f00eaSDimitry Andric     };
80*a58f00eaSDimitry Andric     return IsPrefix(".lbss") || IsPrefix(".ldata") || IsPrefix(".lrodata");
81*a58f00eaSDimitry Andric   }
82*a58f00eaSDimitry Andric 
83*a58f00eaSDimitry Andric   // Respect large data threshold for medium and large code models.
84c9157d92SDimitry Andric   if (getCodeModel() == CodeModel::Medium ||
85c9157d92SDimitry Andric       getCodeModel() == CodeModel::Large) {
86c9157d92SDimitry Andric     if (!GV->getValueType()->isSized())
87c9157d92SDimitry Andric       return true;
88c9157d92SDimitry Andric     const DataLayout &DL = GV->getParent()->getDataLayout();
89c9157d92SDimitry Andric     uint64_t Size = DL.getTypeSizeInBits(GV->getValueType()) / 8;
90c9157d92SDimitry Andric     return Size == 0 || Size > LargeDataThreshold;
91c9157d92SDimitry Andric   }
92c9157d92SDimitry Andric 
93c9157d92SDimitry Andric   return false;
94fe013be4SDimitry Andric }
95fe013be4SDimitry Andric 
isPositionIndependent() const960b57cec5SDimitry Andric bool TargetMachine::isPositionIndependent() const {
970b57cec5SDimitry Andric   return getRelocationModel() == Reloc::PIC_;
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric /// Reset the target options based on the function's attributes.
1015ffd83dbSDimitry Andric /// setFunctionAttributes should have made the raw attribute value consistent
1025ffd83dbSDimitry Andric /// with the command line flag if used.
1035ffd83dbSDimitry Andric //
1040b57cec5SDimitry Andric // FIXME: This function needs to go away for a number of reasons:
1050b57cec5SDimitry Andric // a) global state on the TargetMachine is terrible in general,
1060b57cec5SDimitry Andric // b) these target options should be passed only on the function
1070b57cec5SDimitry Andric //    and not on the TargetMachine (via TargetOptions) at all.
resetTargetOptions(const Function & F) const1080b57cec5SDimitry Andric void TargetMachine::resetTargetOptions(const Function &F) const {
1090b57cec5SDimitry Andric #define RESET_OPTION(X, Y)                                              \
1100b57cec5SDimitry Andric   do {                                                                  \
111fe6060f1SDimitry Andric     Options.X = F.getFnAttribute(Y).getValueAsBool();     \
1120b57cec5SDimitry Andric   } while (0)
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   RESET_OPTION(UnsafeFPMath, "unsafe-fp-math");
1150b57cec5SDimitry Andric   RESET_OPTION(NoInfsFPMath, "no-infs-fp-math");
1160b57cec5SDimitry Andric   RESET_OPTION(NoNaNsFPMath, "no-nans-fp-math");
1170b57cec5SDimitry Andric   RESET_OPTION(NoSignedZerosFPMath, "no-signed-zeros-fp-math");
11881ad6265SDimitry Andric   RESET_OPTION(ApproxFuncFPMath, "approx-func-fp-math");
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric /// Returns the code generation relocation model. The choices are static, PIC,
1220b57cec5SDimitry Andric /// and dynamic-no-pic.
getRelocationModel() const1230b57cec5SDimitry Andric Reloc::Model TargetMachine::getRelocationModel() const { return RM; }
1240b57cec5SDimitry Andric 
getMaxCodeSize() const125c9157d92SDimitry Andric uint64_t TargetMachine::getMaxCodeSize() const {
126c9157d92SDimitry Andric   switch (getCodeModel()) {
127c9157d92SDimitry Andric   case CodeModel::Tiny:
128c9157d92SDimitry Andric     return llvm::maxUIntN(10);
129c9157d92SDimitry Andric   case CodeModel::Small:
130c9157d92SDimitry Andric   case CodeModel::Kernel:
131c9157d92SDimitry Andric   case CodeModel::Medium:
132c9157d92SDimitry Andric     return llvm::maxUIntN(31);
133c9157d92SDimitry Andric   case CodeModel::Large:
134c9157d92SDimitry Andric     return llvm::maxUIntN(64);
135c9157d92SDimitry Andric   }
136c9157d92SDimitry Andric   llvm_unreachable("Unhandled CodeModel enum");
137c9157d92SDimitry Andric }
138c9157d92SDimitry Andric 
1390b57cec5SDimitry Andric /// Get the IR-specified TLS model for Var.
getSelectedTLSModel(const GlobalValue * GV)1400b57cec5SDimitry Andric static TLSModel::Model getSelectedTLSModel(const GlobalValue *GV) {
1410b57cec5SDimitry Andric   switch (GV->getThreadLocalMode()) {
1420b57cec5SDimitry Andric   case GlobalVariable::NotThreadLocal:
1430b57cec5SDimitry Andric     llvm_unreachable("getSelectedTLSModel for non-TLS variable");
1440b57cec5SDimitry Andric     break;
1450b57cec5SDimitry Andric   case GlobalVariable::GeneralDynamicTLSModel:
1460b57cec5SDimitry Andric     return TLSModel::GeneralDynamic;
1470b57cec5SDimitry Andric   case GlobalVariable::LocalDynamicTLSModel:
1480b57cec5SDimitry Andric     return TLSModel::LocalDynamic;
1490b57cec5SDimitry Andric   case GlobalVariable::InitialExecTLSModel:
1500b57cec5SDimitry Andric     return TLSModel::InitialExec;
1510b57cec5SDimitry Andric   case GlobalVariable::LocalExecTLSModel:
1520b57cec5SDimitry Andric     return TLSModel::LocalExec;
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric   llvm_unreachable("invalid TLS model");
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
shouldAssumeDSOLocal(const Module & M,const GlobalValue * GV) const1570b57cec5SDimitry Andric bool TargetMachine::shouldAssumeDSOLocal(const Module &M,
1580b57cec5SDimitry Andric                                          const GlobalValue *GV) const {
159e8d8bef9SDimitry Andric   const Triple &TT = getTargetTriple();
160e8d8bef9SDimitry Andric   Reloc::Model RM = getRelocationModel();
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   // According to the llvm language reference, we should be able to
1630b57cec5SDimitry Andric   // just return false in here if we have a GV, as we know it is
1640b57cec5SDimitry Andric   // dso_preemptable.  At this point in time, the various IR producers
1650b57cec5SDimitry Andric   // have not been transitioned to always produce a dso_local when it
1660b57cec5SDimitry Andric   // is possible to do so.
167e8d8bef9SDimitry Andric   //
1680b57cec5SDimitry Andric   // As a result we still have some logic in here to improve the quality of the
1690b57cec5SDimitry Andric   // generated code.
170e8d8bef9SDimitry Andric   if (!GV)
171349cc55cSDimitry Andric     return false;
1720b57cec5SDimitry Andric 
173e8d8bef9SDimitry Andric   // If the IR producer requested that this GV be treated as dso local, obey.
174e8d8bef9SDimitry Andric   if (GV->isDSOLocal())
175e8d8bef9SDimitry Andric     return true;
1760b57cec5SDimitry Andric 
177349cc55cSDimitry Andric   if (TT.isOSBinFormatCOFF()) {
1780b57cec5SDimitry Andric     // DLLImport explicitly marks the GV as external.
179e8d8bef9SDimitry Andric     if (GV->hasDLLImportStorageClass())
1800b57cec5SDimitry Andric       return false;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric     // On MinGW, variables that haven't been declared with DLLImport may still
1830b57cec5SDimitry Andric     // end up automatically imported by the linker. To make this feasible,
1840b57cec5SDimitry Andric     // don't assume the variables to be DSO local unless we actually know
1850b57cec5SDimitry Andric     // that for sure. This only has to be done for variables; for functions
1860b57cec5SDimitry Andric     // the linker can insert thunks for calling functions from another DLL.
187349cc55cSDimitry Andric     if (TT.isWindowsGNUEnvironment() && GV->isDeclarationForLinker() &&
188349cc55cSDimitry Andric         isa<GlobalVariable>(GV))
1890b57cec5SDimitry Andric       return false;
1900b57cec5SDimitry Andric 
191349cc55cSDimitry Andric     // Don't mark 'extern_weak' symbols as DSO local. If these symbols remain
192349cc55cSDimitry Andric     // unresolved in the link, they can be resolved to zero, which is outside
193349cc55cSDimitry Andric     // the current DSO.
194349cc55cSDimitry Andric     if (GV->hasExternalWeakLinkage())
1950b57cec5SDimitry Andric       return false;
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric     // Every other GV is local on COFF.
198349cc55cSDimitry Andric     return true;
199349cc55cSDimitry Andric   }
200349cc55cSDimitry Andric 
201349cc55cSDimitry Andric   if (TT.isOSBinFormatGOFF())
2020b57cec5SDimitry Andric     return true;
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   if (TT.isOSBinFormatMachO()) {
2050b57cec5SDimitry Andric     if (RM == Reloc::Static)
2060b57cec5SDimitry Andric       return true;
207e8d8bef9SDimitry Andric     return GV->isStrongDefinitionForLinker();
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric 
210349cc55cSDimitry Andric   assert(TT.isOSBinFormatELF() || TT.isOSBinFormatWasm() ||
211349cc55cSDimitry Andric          TT.isOSBinFormatXCOFF());
2120b57cec5SDimitry Andric   return false;
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric 
useEmulatedTLS() const215fe013be4SDimitry Andric bool TargetMachine::useEmulatedTLS() const { return Options.EmulatedTLS; }
useTLSDESC() const216*a58f00eaSDimitry Andric bool TargetMachine::useTLSDESC() const { return Options.EnableTLSDESC; }
2170b57cec5SDimitry Andric 
getTLSModel(const GlobalValue * GV) const2180b57cec5SDimitry Andric TLSModel::Model TargetMachine::getTLSModel(const GlobalValue *GV) const {
2190b57cec5SDimitry Andric   bool IsPIE = GV->getParent()->getPIELevel() != PIELevel::Default;
2200b57cec5SDimitry Andric   Reloc::Model RM = getRelocationModel();
2210b57cec5SDimitry Andric   bool IsSharedLibrary = RM == Reloc::PIC_ && !IsPIE;
2220b57cec5SDimitry Andric   bool IsLocal = shouldAssumeDSOLocal(*GV->getParent(), GV);
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   TLSModel::Model Model;
2250b57cec5SDimitry Andric   if (IsSharedLibrary) {
2260b57cec5SDimitry Andric     if (IsLocal)
2270b57cec5SDimitry Andric       Model = TLSModel::LocalDynamic;
2280b57cec5SDimitry Andric     else
2290b57cec5SDimitry Andric       Model = TLSModel::GeneralDynamic;
2300b57cec5SDimitry Andric   } else {
2310b57cec5SDimitry Andric     if (IsLocal)
2320b57cec5SDimitry Andric       Model = TLSModel::LocalExec;
2330b57cec5SDimitry Andric     else
2340b57cec5SDimitry Andric       Model = TLSModel::InitialExec;
2350b57cec5SDimitry Andric   }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   // If the user specified a more specific model, use that.
2380b57cec5SDimitry Andric   TLSModel::Model SelectedModel = getSelectedTLSModel(GV);
2390b57cec5SDimitry Andric   if (SelectedModel > Model)
2400b57cec5SDimitry Andric     return SelectedModel;
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   return Model;
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric /// Returns the optimization level: None, Less, Default, or Aggressive.
getOptLevel() const246c9157d92SDimitry Andric CodeGenOptLevel TargetMachine::getOptLevel() const { return OptLevel; }
2470b57cec5SDimitry Andric 
setOptLevel(CodeGenOptLevel Level)248c9157d92SDimitry Andric void TargetMachine::setOptLevel(CodeGenOptLevel Level) { OptLevel = Level; }
2490b57cec5SDimitry Andric 
25081ad6265SDimitry Andric TargetTransformInfo
getTargetTransformInfo(const Function & F) const25181ad6265SDimitry Andric TargetMachine::getTargetTransformInfo(const Function &F) const {
2520b57cec5SDimitry Andric   return TargetTransformInfo(F.getParent()->getDataLayout());
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric 
getNameWithPrefix(SmallVectorImpl<char> & Name,const GlobalValue * GV,Mangler & Mang,bool MayAlwaysUsePrivate) const2550b57cec5SDimitry Andric void TargetMachine::getNameWithPrefix(SmallVectorImpl<char> &Name,
2560b57cec5SDimitry Andric                                       const GlobalValue *GV, Mangler &Mang,
2570b57cec5SDimitry Andric                                       bool MayAlwaysUsePrivate) const {
2580b57cec5SDimitry Andric   if (MayAlwaysUsePrivate || !GV->hasPrivateLinkage()) {
2590b57cec5SDimitry Andric     // Simple case: If GV is not private, it is not important to find out if
2600b57cec5SDimitry Andric     // private labels are legal in this case or not.
2610b57cec5SDimitry Andric     Mang.getNameWithPrefix(Name, GV, false);
2620b57cec5SDimitry Andric     return;
2630b57cec5SDimitry Andric   }
2640b57cec5SDimitry Andric   const TargetLoweringObjectFile *TLOF = getObjFileLowering();
2650b57cec5SDimitry Andric   TLOF->getNameWithPrefix(Name, GV, *this);
2660b57cec5SDimitry Andric }
2670b57cec5SDimitry Andric 
getSymbol(const GlobalValue * GV) const2680b57cec5SDimitry Andric MCSymbol *TargetMachine::getSymbol(const GlobalValue *GV) const {
2690b57cec5SDimitry Andric   const TargetLoweringObjectFile *TLOF = getObjFileLowering();
2705ffd83dbSDimitry Andric   // XCOFF symbols could have special naming convention.
2715ffd83dbSDimitry Andric   if (MCSymbol *TargetSymbol = TLOF->getTargetSymbol(GV, *this))
2725ffd83dbSDimitry Andric     return TargetSymbol;
2735ffd83dbSDimitry Andric 
2740b57cec5SDimitry Andric   SmallString<128> NameStr;
2750b57cec5SDimitry Andric   getNameWithPrefix(NameStr, GV, TLOF->getMangler());
2760b57cec5SDimitry Andric   return TLOF->getContext().getOrCreateSymbol(NameStr);
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
getTargetIRAnalysis() const27981ad6265SDimitry Andric TargetIRAnalysis TargetMachine::getTargetIRAnalysis() const {
2800b57cec5SDimitry Andric   // Since Analysis can't depend on Target, use a std::function to invert the
2810b57cec5SDimitry Andric   // dependency.
2820b57cec5SDimitry Andric   return TargetIRAnalysis(
2830b57cec5SDimitry Andric       [this](const Function &F) { return this->getTargetTransformInfo(F); });
2840b57cec5SDimitry Andric }
285e8d8bef9SDimitry Andric 
parseBinutilsVersion(StringRef Version)286e8d8bef9SDimitry Andric std::pair<int, int> TargetMachine::parseBinutilsVersion(StringRef Version) {
287e8d8bef9SDimitry Andric   if (Version == "none")
288e8d8bef9SDimitry Andric     return {INT_MAX, INT_MAX}; // Make binutilsIsAtLeast() return true.
289e8d8bef9SDimitry Andric   std::pair<int, int> Ret;
290e8d8bef9SDimitry Andric   if (!Version.consumeInteger(10, Ret.first) && Version.consume_front("."))
291e8d8bef9SDimitry Andric     Version.consumeInteger(10, Ret.second);
292e8d8bef9SDimitry Andric   return Ret;
293e8d8bef9SDimitry Andric }
294