| //===-- 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/MC/MCAsmInfo.h" |
| #include "llvm/MC/MCContext.h" |
| #include "llvm/MC/MCInstrInfo.h" |
| #include "llvm/MC/MCRegisterInfo.h" |
| #include "llvm/MC/MCSubtargetInfo.h" |
| #include "llvm/Support/CodeGen.h" |
| #include "llvm/Target/TargetLoweringObjectFile.h" |
| using namespace llvm; |
| |
| //--------------------------------------------------------------------------- |
| // 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; |
| |
| bool TargetMachine::isLargeData(const GlobalVariable *GV) const { |
| if (getTargetTriple().getArch() != Triple::x86_64 || GV->isThreadLocal()) |
| return false; |
| // Large data under the large code model still needs to be thought about, so |
| // restrict this to medium. |
| if (getCodeModel() != CodeModel::Medium) |
| return false; |
| const DataLayout &DL = GV->getParent()->getDataLayout(); |
| uint64_t Size = DL.getTypeSizeInBits(GV->getValueType()) / 8; |
| return Size == 0 || Size > LargeDataThreshold; |
| } |
| |
| 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 Module &M, |
| 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.isWindowsGNUEnvironment() && 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; } |
| |
| 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->getParent(), 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; |
| } |
| |
| /// Returns the optimization level: None, Less, Default, or Aggressive. |
| CodeGenOptLevel TargetMachine::getOptLevel() const { return OptLevel; } |
| |
| void TargetMachine::setOptLevel(CodeGenOptLevel Level) { OptLevel = Level; } |
| |
| TargetTransformInfo |
| TargetMachine::getTargetTransformInfo(const Function &F) const { |
| return TargetTransformInfo(F.getParent()->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; |
| } |