1f22ef01cSRoman Divacky //===-- TargetMachine.cpp - General Target Information ---------------------==//
2f22ef01cSRoman Divacky //
3f22ef01cSRoman Divacky //                     The LLVM Compiler Infrastructure
4f22ef01cSRoman Divacky //
5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source
6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details.
7f22ef01cSRoman Divacky //
8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
9f22ef01cSRoman Divacky //
10f22ef01cSRoman Divacky // This file describes the general parts of a Target machine.
11f22ef01cSRoman Divacky //
12f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
13f22ef01cSRoman Divacky 
14139f7f9bSDimitry Andric #include "llvm/Target/TargetMachine.h"
15ff0cc061SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
16139f7f9bSDimitry Andric #include "llvm/IR/Function.h"
17139f7f9bSDimitry Andric #include "llvm/IR/GlobalAlias.h"
18139f7f9bSDimitry Andric #include "llvm/IR/GlobalValue.h"
19139f7f9bSDimitry Andric #include "llvm/IR/GlobalVariable.h"
203ca95b02SDimitry Andric #include "llvm/IR/LegacyPassManager.h"
2191bc56edSDimitry Andric #include "llvm/IR/Mangler.h"
22f22ef01cSRoman Divacky #include "llvm/MC/MCAsmInfo.h"
2391bc56edSDimitry Andric #include "llvm/MC/MCContext.h"
24ff0cc061SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
2539d628a0SDimitry Andric #include "llvm/MC/MCSectionMachO.h"
2691bc56edSDimitry Andric #include "llvm/MC/MCTargetOptions.h"
2791bc56edSDimitry Andric #include "llvm/MC/SectionKind.h"
284ba319b5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h"
29f22ef01cSRoman Divacky using namespace llvm;
30f22ef01cSRoman Divacky 
31f22ef01cSRoman Divacky //---------------------------------------------------------------------------
32f22ef01cSRoman Divacky // TargetMachine Class
33f22ef01cSRoman Divacky //
34f22ef01cSRoman Divacky 
TargetMachine(const Target & T,StringRef DataLayoutString,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options)35ff0cc061SDimitry Andric TargetMachine::TargetMachine(const Target &T, StringRef DataLayoutString,
368f0fd8f6SDimitry Andric                              const Triple &TT, StringRef CPU, StringRef FS,
37dff0c46cSDimitry Andric                              const TargetOptions &Options)
38ff0cc061SDimitry Andric     : TheTarget(T), DL(DataLayoutString), TargetTriple(TT), TargetCPU(CPU),
393ca95b02SDimitry Andric       TargetFS(FS), AsmInfo(nullptr), MRI(nullptr), MII(nullptr), STI(nullptr),
40f1a29dd3SDimitry Andric       RequireStructuredCFG(false), DefaultOptions(Options), Options(Options) {
413ca95b02SDimitry Andric }
42f22ef01cSRoman Divacky 
43*b5893f02SDimitry Andric TargetMachine::~TargetMachine() = default;
44f22ef01cSRoman Divacky 
isPositionIndependent() const453ca95b02SDimitry Andric bool TargetMachine::isPositionIndependent() const {
463ca95b02SDimitry Andric   return getRelocationModel() == Reloc::PIC_;
473ca95b02SDimitry Andric }
483ca95b02SDimitry Andric 
494ba319b5SDimitry Andric /// Reset the target options based on the function's attributes.
50ff0cc061SDimitry Andric // FIXME: This function needs to go away for a number of reasons:
51ff0cc061SDimitry Andric // a) global state on the TargetMachine is terrible in general,
52f1a29dd3SDimitry Andric // b) these target options should be passed only on the function
53ff0cc061SDimitry Andric //    and not on the TargetMachine (via TargetOptions) at all.
resetTargetOptions(const Function & F) const5439d628a0SDimitry Andric void TargetMachine::resetTargetOptions(const Function &F) const {
55139f7f9bSDimitry Andric #define RESET_OPTION(X, Y)                                                     \
56139f7f9bSDimitry Andric   do {                                                                         \
5739d628a0SDimitry Andric     if (F.hasFnAttribute(Y))                                                   \
58ff0cc061SDimitry Andric       Options.X = (F.getFnAttribute(Y).getValueAsString() == "true");          \
59f1a29dd3SDimitry Andric     else                                                                       \
60f1a29dd3SDimitry Andric       Options.X = DefaultOptions.X;                                            \
61139f7f9bSDimitry Andric   } while (0)
62139f7f9bSDimitry Andric 
63139f7f9bSDimitry Andric   RESET_OPTION(UnsafeFPMath, "unsafe-fp-math");
64139f7f9bSDimitry Andric   RESET_OPTION(NoInfsFPMath, "no-infs-fp-math");
65139f7f9bSDimitry Andric   RESET_OPTION(NoNaNsFPMath, "no-nans-fp-math");
667a7e6055SDimitry Andric   RESET_OPTION(NoSignedZerosFPMath, "no-signed-zeros-fp-math");
67d88c1a5aSDimitry Andric   RESET_OPTION(NoTrappingFPMath, "no-trapping-math");
68d88c1a5aSDimitry Andric 
69d88c1a5aSDimitry Andric   StringRef Denormal =
70d88c1a5aSDimitry Andric     F.getFnAttribute("denormal-fp-math").getValueAsString();
71d88c1a5aSDimitry Andric   if (Denormal == "ieee")
72d88c1a5aSDimitry Andric     Options.FPDenormalMode = FPDenormal::IEEE;
73d88c1a5aSDimitry Andric   else if (Denormal == "preserve-sign")
74d88c1a5aSDimitry Andric     Options.FPDenormalMode = FPDenormal::PreserveSign;
75d88c1a5aSDimitry Andric   else if (Denormal == "positive-zero")
76d88c1a5aSDimitry Andric     Options.FPDenormalMode = FPDenormal::PositiveZero;
77f1a29dd3SDimitry Andric   else
78f1a29dd3SDimitry Andric     Options.FPDenormalMode = DefaultOptions.FPDenormalMode;
79139f7f9bSDimitry Andric }
80139f7f9bSDimitry Andric 
813ca95b02SDimitry Andric /// Returns the code generation relocation model. The choices are static, PIC,
823ca95b02SDimitry Andric /// and dynamic-no-pic.
getRelocationModel() const833ca95b02SDimitry Andric Reloc::Model TargetMachine::getRelocationModel() const { return RM; }
84f22ef01cSRoman Divacky 
853ca95b02SDimitry Andric /// Returns the code model. The choices are small, kernel, medium, large, and
863ca95b02SDimitry Andric /// target default.
getCodeModel() const873ca95b02SDimitry Andric CodeModel::Model TargetMachine::getCodeModel() const { return CMModel; }
88f22ef01cSRoman Divacky 
897ae0e2c9SDimitry Andric /// Get the IR-specified TLS model for Var.
getSelectedTLSModel(const GlobalValue * GV)9091bc56edSDimitry Andric static TLSModel::Model getSelectedTLSModel(const GlobalValue *GV) {
9191bc56edSDimitry Andric   switch (GV->getThreadLocalMode()) {
927ae0e2c9SDimitry Andric   case GlobalVariable::NotThreadLocal:
937ae0e2c9SDimitry Andric     llvm_unreachable("getSelectedTLSModel for non-TLS variable");
947ae0e2c9SDimitry Andric     break;
957ae0e2c9SDimitry Andric   case GlobalVariable::GeneralDynamicTLSModel:
967ae0e2c9SDimitry Andric     return TLSModel::GeneralDynamic;
977ae0e2c9SDimitry Andric   case GlobalVariable::LocalDynamicTLSModel:
987ae0e2c9SDimitry Andric     return TLSModel::LocalDynamic;
997ae0e2c9SDimitry Andric   case GlobalVariable::InitialExecTLSModel:
1007ae0e2c9SDimitry Andric     return TLSModel::InitialExec;
1017ae0e2c9SDimitry Andric   case GlobalVariable::LocalExecTLSModel:
1027ae0e2c9SDimitry Andric     return TLSModel::LocalExec;
1037ae0e2c9SDimitry Andric   }
1047ae0e2c9SDimitry Andric   llvm_unreachable("invalid TLS model");
1057ae0e2c9SDimitry Andric }
1067ae0e2c9SDimitry Andric 
shouldAssumeDSOLocal(const Module & M,const GlobalValue * GV) const1073ca95b02SDimitry Andric bool TargetMachine::shouldAssumeDSOLocal(const Module &M,
1083ca95b02SDimitry Andric                                          const GlobalValue *GV) const {
1092cab237bSDimitry Andric   // If the IR producer requested that this GV be treated as dso local, obey.
1102cab237bSDimitry Andric   if (GV && GV->isDSOLocal())
1112cab237bSDimitry Andric     return true;
1122cab237bSDimitry Andric 
1134ba319b5SDimitry Andric   // If we are not supossed to use a PLT, we cannot assume that intrinsics are
1144ba319b5SDimitry Andric   // local since the linker can convert some direct access to access via plt.
1154ba319b5SDimitry Andric   if (M.getRtLibUseGOT() && !GV)
1164ba319b5SDimitry Andric     return false;
1174ba319b5SDimitry Andric 
1184ba319b5SDimitry Andric   // According to the llvm language reference, we should be able to
1194ba319b5SDimitry Andric   // just return false in here if we have a GV, as we know it is
1204ba319b5SDimitry Andric   // dso_preemptable.  At this point in time, the various IR producers
1214ba319b5SDimitry Andric   // have not been transitioned to always produce a dso_local when it
1224ba319b5SDimitry Andric   // is possible to do so.
1234ba319b5SDimitry Andric   // In the case of intrinsics, GV is null and there is nowhere to put
1244ba319b5SDimitry Andric   // dso_local. Returning false for those will produce worse code in some
1254ba319b5SDimitry Andric   // architectures. For example, on x86 the caller has to set ebx before calling
1264ba319b5SDimitry Andric   // a plt.
1274ba319b5SDimitry Andric   // As a result we still have some logic in here to improve the quality of the
1284ba319b5SDimitry Andric   // generated code.
1294ba319b5SDimitry Andric   // FIXME: Add a module level metadata for whether intrinsics should be assumed
1304ba319b5SDimitry Andric   // local.
1312cab237bSDimitry Andric 
1323ca95b02SDimitry Andric   Reloc::Model RM = getRelocationModel();
1333ca95b02SDimitry Andric   const Triple &TT = getTargetTriple();
1343ca95b02SDimitry Andric 
1353ca95b02SDimitry Andric   // DLLImport explicitly marks the GV as external.
1363ca95b02SDimitry Andric   if (GV && GV->hasDLLImportStorageClass())
1373ca95b02SDimitry Andric     return false;
1383ca95b02SDimitry Andric 
139*b5893f02SDimitry Andric   // On MinGW, variables that haven't been declared with DLLImport may still
140*b5893f02SDimitry Andric   // end up automatically imported by the linker. To make this feasible,
141*b5893f02SDimitry Andric   // don't assume the variables to be DSO local unless we actually know
142*b5893f02SDimitry Andric   // that for sure. This only has to be done for variables; for functions
143*b5893f02SDimitry Andric   // the linker can insert thunks for calling functions from another DLL.
144*b5893f02SDimitry Andric   if (TT.isWindowsGNUEnvironment() && GV && GV->isDeclarationForLinker() &&
145*b5893f02SDimitry Andric       isa<GlobalVariable>(GV))
146*b5893f02SDimitry Andric     return false;
147*b5893f02SDimitry Andric 
148d88c1a5aSDimitry Andric   // Every other GV is local on COFF.
1494ba319b5SDimitry Andric   // Make an exception for windows OS in the triple: Some firmware builds use
150d88c1a5aSDimitry Andric   // *-win32-macho triples. This (accidentally?) produced windows relocations
151d88c1a5aSDimitry Andric   // without GOT tables in older clang versions; Keep this behaviour.
152d88c1a5aSDimitry Andric   if (TT.isOSBinFormatCOFF() || (TT.isOSWindows() && TT.isOSBinFormatMachO()))
1533ca95b02SDimitry Andric     return true;
1543ca95b02SDimitry Andric 
1552cab237bSDimitry Andric   // Most PIC code sequences that assume that a symbol is local cannot
1562cab237bSDimitry Andric   // produce a 0 if it turns out the symbol is undefined. While this
1572cab237bSDimitry Andric   // is ABI and relocation depended, it seems worth it to handle it
1582cab237bSDimitry Andric   // here.
1594ba319b5SDimitry Andric   if (GV && isPositionIndependent() && GV->hasExternalWeakLinkage())
1602cab237bSDimitry Andric     return false;
1612cab237bSDimitry Andric 
1624ba319b5SDimitry Andric   if (GV && !GV->hasDefaultVisibility())
1633ca95b02SDimitry Andric     return true;
1643ca95b02SDimitry Andric 
1653ca95b02SDimitry Andric   if (TT.isOSBinFormatMachO()) {
1663ca95b02SDimitry Andric     if (RM == Reloc::Static)
1673ca95b02SDimitry Andric       return true;
1683ca95b02SDimitry Andric     return GV && GV->isStrongDefinitionForLinker();
1693ca95b02SDimitry Andric   }
1703ca95b02SDimitry Andric 
1713ca95b02SDimitry Andric   assert(TT.isOSBinFormatELF());
1723ca95b02SDimitry Andric   assert(RM != Reloc::DynamicNoPIC);
1733ca95b02SDimitry Andric 
1743ca95b02SDimitry Andric   bool IsExecutable =
1753ca95b02SDimitry Andric       RM == Reloc::Static || M.getPIELevel() != PIELevel::Default;
1763ca95b02SDimitry Andric   if (IsExecutable) {
1773ca95b02SDimitry Andric     // If the symbol is defined, it cannot be preempted.
1783ca95b02SDimitry Andric     if (GV && !GV->isDeclarationForLinker())
1793ca95b02SDimitry Andric       return true;
1803ca95b02SDimitry Andric 
1812cab237bSDimitry Andric     // A symbol marked nonlazybind should not be accessed with a plt. If the
1822cab237bSDimitry Andric     // symbol turns out to be external, the linker will convert a direct
1832cab237bSDimitry Andric     // access to an access via the plt, so don't assume it is local.
1842cab237bSDimitry Andric     const Function *F = dyn_cast_or_null<Function>(GV);
1852cab237bSDimitry Andric     if (F && F->hasFnAttribute(Attribute::NonLazyBind))
1862cab237bSDimitry Andric       return false;
1872cab237bSDimitry Andric 
1883ca95b02SDimitry Andric     bool IsTLS = GV && GV->isThreadLocal();
189d88c1a5aSDimitry Andric     bool IsAccessViaCopyRelocs =
1904ba319b5SDimitry Andric         GV && Options.MCOptions.MCPIECopyRelocations && isa<GlobalVariable>(GV);
1917a7e6055SDimitry Andric     Triple::ArchType Arch = TT.getArch();
1927a7e6055SDimitry Andric     bool IsPPC =
1937a7e6055SDimitry Andric         Arch == Triple::ppc || Arch == Triple::ppc64 || Arch == Triple::ppc64le;
1947a7e6055SDimitry Andric     // Check if we can use copy relocations. PowerPC has no copy relocations.
1957a7e6055SDimitry Andric     if (!IsTLS && !IsPPC && (RM == Reloc::Static || IsAccessViaCopyRelocs))
1963ca95b02SDimitry Andric       return true;
1973ca95b02SDimitry Andric   }
1983ca95b02SDimitry Andric 
1993ca95b02SDimitry Andric   // ELF supports preemption of other symbols.
2003ca95b02SDimitry Andric   return false;
2013ca95b02SDimitry Andric }
2023ca95b02SDimitry Andric 
useEmulatedTLS() const2034ba319b5SDimitry Andric bool TargetMachine::useEmulatedTLS() const {
2044ba319b5SDimitry Andric   // Returns Options.EmulatedTLS if the -emulated-tls or -no-emulated-tls
2054ba319b5SDimitry Andric   // was specified explicitly; otherwise uses target triple to decide default.
2064ba319b5SDimitry Andric   if (Options.ExplicitEmulatedTLS)
2074ba319b5SDimitry Andric     return Options.EmulatedTLS;
2084ba319b5SDimitry Andric   return getTargetTriple().hasDefaultEmulatedTLS();
2094ba319b5SDimitry Andric }
2104ba319b5SDimitry Andric 
getTLSModel(const GlobalValue * GV) const211dff0c46cSDimitry Andric TLSModel::Model TargetMachine::getTLSModel(const GlobalValue *GV) const {
2123ca95b02SDimitry Andric   bool IsPIE = GV->getParent()->getPIELevel() != PIELevel::Default;
2133ca95b02SDimitry Andric   Reloc::Model RM = getRelocationModel();
2143ca95b02SDimitry Andric   bool IsSharedLibrary = RM == Reloc::PIC_ && !IsPIE;
2153ca95b02SDimitry Andric   bool IsLocal = shouldAssumeDSOLocal(*GV->getParent(), GV);
216dff0c46cSDimitry Andric 
2177ae0e2c9SDimitry Andric   TLSModel::Model Model;
2183ca95b02SDimitry Andric   if (IsSharedLibrary) {
2193ca95b02SDimitry Andric     if (IsLocal)
2207ae0e2c9SDimitry Andric       Model = TLSModel::LocalDynamic;
221dff0c46cSDimitry Andric     else
2227ae0e2c9SDimitry Andric       Model = TLSModel::GeneralDynamic;
223dff0c46cSDimitry Andric   } else {
2243ca95b02SDimitry Andric     if (IsLocal)
2257ae0e2c9SDimitry Andric       Model = TLSModel::LocalExec;
226dff0c46cSDimitry Andric     else
2277ae0e2c9SDimitry Andric       Model = TLSModel::InitialExec;
228dff0c46cSDimitry Andric   }
2297ae0e2c9SDimitry Andric 
2307ae0e2c9SDimitry Andric   // If the user specified a more specific model, use that.
23191bc56edSDimitry Andric   TLSModel::Model SelectedModel = getSelectedTLSModel(GV);
2327ae0e2c9SDimitry Andric   if (SelectedModel > Model)
2337ae0e2c9SDimitry Andric     return SelectedModel;
2347ae0e2c9SDimitry Andric 
2357ae0e2c9SDimitry Andric   return Model;
236dff0c46cSDimitry Andric }
237dff0c46cSDimitry Andric 
2383ca95b02SDimitry Andric /// Returns the optimization level: None, Less, Default, or Aggressive.
getOptLevel() const2393ca95b02SDimitry Andric CodeGenOpt::Level TargetMachine::getOptLevel() const { return OptLevel; }
240dff0c46cSDimitry Andric 
setOptLevel(CodeGenOpt::Level Level)2413ca95b02SDimitry Andric void TargetMachine::setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; }
242f785676fSDimitry Andric 
getTargetTransformInfo(const Function & F)243da09e106SDimitry Andric TargetTransformInfo TargetMachine::getTargetTransformInfo(const Function &F) {
244875ed548SDimitry Andric   return TargetTransformInfo(F.getParent()->getDataLayout());
24591bc56edSDimitry Andric }
24691bc56edSDimitry Andric 
getNameWithPrefix(SmallVectorImpl<char> & Name,const GlobalValue * GV,Mangler & Mang,bool MayAlwaysUsePrivate) const24791bc56edSDimitry Andric void TargetMachine::getNameWithPrefix(SmallVectorImpl<char> &Name,
24891bc56edSDimitry Andric                                       const GlobalValue *GV, Mangler &Mang,
24991bc56edSDimitry Andric                                       bool MayAlwaysUsePrivate) const {
25091bc56edSDimitry Andric   if (MayAlwaysUsePrivate || !GV->hasPrivateLinkage()) {
25191bc56edSDimitry Andric     // Simple case: If GV is not private, it is not important to find out if
25291bc56edSDimitry Andric     // private labels are legal in this case or not.
25391bc56edSDimitry Andric     Mang.getNameWithPrefix(Name, GV, false);
25491bc56edSDimitry Andric     return;
25591bc56edSDimitry Andric   }
256ff0cc061SDimitry Andric   const TargetLoweringObjectFile *TLOF = getObjFileLowering();
257d88c1a5aSDimitry Andric   TLOF->getNameWithPrefix(Name, GV, *this);
25891bc56edSDimitry Andric }
25991bc56edSDimitry Andric 
getSymbol(const GlobalValue * GV) const260d88c1a5aSDimitry Andric MCSymbol *TargetMachine::getSymbol(const GlobalValue *GV) const {
261ff0cc061SDimitry Andric   const TargetLoweringObjectFile *TLOF = getObjFileLowering();
262d88c1a5aSDimitry Andric   SmallString<128> NameStr;
263d88c1a5aSDimitry Andric   getNameWithPrefix(NameStr, GV, TLOF->getMangler());
264ff0cc061SDimitry Andric   return TLOF->getContext().getOrCreateSymbol(NameStr);
265f22ef01cSRoman Divacky }
266da09e106SDimitry Andric 
getTargetIRAnalysis()267da09e106SDimitry Andric TargetIRAnalysis TargetMachine::getTargetIRAnalysis() {
268da09e106SDimitry Andric   // Since Analysis can't depend on Target, use a std::function to invert the
269da09e106SDimitry Andric   // dependency.
270da09e106SDimitry Andric   return TargetIRAnalysis(
271da09e106SDimitry Andric       [this](const Function &F) { return this->getTargetTransformInfo(F); });
272da09e106SDimitry Andric }
273