llvm/lib/Target/TargetMachine.cpp
Rafael Espindola 94eb72df45 Bring back r323297.
It was reverted because it broke the grub build. The reason the grub
build broke is because grub does its own relocation processing and was
not handing R_386_PLT32. Since grub has no dynamic linker, the fix is
trivial: handle R_386_PLT32 exactly like R_386_PC32.

On the report it was noted that they are using
-fno-integrated-assembler. The upstream GAS (starting with
451875b4f976a527395e9303224c7881b65e12ed) will already be producing a
R_386_PLT32 anyway, so they have to update their code one way or the
other

Original message:

Don't assume a null GV is local for ELF and MachO.

This is already a simplification, and should help with avoiding a plt
reference when calling an intrinsic with -fno-plt.

With this change we return false for null GVs, so the caller only
needs to check the new metadata to decide if it should use foo@plt or
*foo@got.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@325514 91177308-0d34-0410-b5e6-96231b3b80d8
2018-02-19 16:02:38 +00:00

257 lines
9.6 KiB
C++

//===-- TargetMachine.cpp - General Target Information ---------------------==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the general parts of a Target machine.
//
//===----------------------------------------------------------------------===//
#include "llvm/Target/TargetMachine.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Mangler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/SectionKind.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(CPU),
TargetFS(FS), AsmInfo(nullptr), MRI(nullptr), MII(nullptr), STI(nullptr),
RequireStructuredCFG(false), DefaultOptions(Options), Options(Options) {
}
TargetMachine::~TargetMachine() {
delete AsmInfo;
delete MRI;
delete MII;
delete STI;
}
bool TargetMachine::isPositionIndependent() const {
return getRelocationModel() == Reloc::PIC_;
}
/// \brief Reset the target options based on the function's attributes.
// 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 { \
if (F.hasFnAttribute(Y)) \
Options.X = (F.getFnAttribute(Y).getValueAsString() == "true"); \
else \
Options.X = DefaultOptions.X; \
} 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(NoTrappingFPMath, "no-trapping-math");
StringRef Denormal =
F.getFnAttribute("denormal-fp-math").getValueAsString();
if (Denormal == "ieee")
Options.FPDenormalMode = FPDenormal::IEEE;
else if (Denormal == "preserve-sign")
Options.FPDenormalMode = FPDenormal::PreserveSign;
else if (Denormal == "positive-zero")
Options.FPDenormalMode = FPDenormal::PositiveZero;
else
Options.FPDenormalMode = DefaultOptions.FPDenormalMode;
}
/// Returns the code generation relocation model. The choices are static, PIC,
/// and dynamic-no-pic.
Reloc::Model TargetMachine::getRelocationModel() const { return RM; }
/// Returns the code model. The choices are small, kernel, medium, large, and
/// target default.
CodeModel::Model TargetMachine::getCodeModel() const { return CMModel; }
/// 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 {
// If the IR producer requested that this GV be treated as dso local, obey.
if (GV && GV->isDSOLocal())
return true;
// 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 pre-dso_local logic in here to improve the quality of the
// generated code:
Reloc::Model RM = getRelocationModel();
const Triple &TT = getTargetTriple();
// DLLImport explicitly marks the GV as external.
if (GV && GV->hasDLLImportStorageClass())
return false;
// Every other GV is local on COFF.
// Make an exception for windows OS in the triple: Some firmwares builds use
// *-win32-macho triples. This (accidentally?) produced windows relocations
// without GOT tables in older clang versions; Keep this behaviour.
if (TT.isOSBinFormatCOFF() || (TT.isOSWindows() && TT.isOSBinFormatMachO()))
return true;
// If GV is null we know that this is a call to an intrinsic. For ELF and
// MachO we don't need to assume those are local since the liker can trivially
// convert a call to a PLT to a direct call if the target (in the runtime
// library) turns out to be local.
if (!GV)
return false;
// Most PIC code sequences that assume that a symbol is local cannot
// produce a 0 if it turns out the symbol is undefined. While this
// is ABI and relocation depended, it seems worth it to handle it
// here.
if (isPositionIndependent() && GV->hasExternalWeakLinkage())
return false;
if (!GV->hasDefaultVisibility())
return true;
if (TT.isOSBinFormatMachO()) {
if (RM == Reloc::Static)
return true;
return GV->isStrongDefinitionForLinker();
}
assert(TT.isOSBinFormatELF());
assert(RM != Reloc::DynamicNoPIC);
bool IsExecutable =
RM == Reloc::Static || M.getPIELevel() != PIELevel::Default;
if (IsExecutable) {
// If the symbol is defined, it cannot be preempted.
if (!GV->isDeclarationForLinker())
return true;
// A symbol marked nonlazybind should not be accessed with a plt. If the
// symbol turns out to be external, the linker will convert a direct
// access to an access via the plt, so don't assume it is local.
const Function *F = dyn_cast<Function>(GV);
if (F && F->hasFnAttribute(Attribute::NonLazyBind))
return false;
bool IsTLS = GV->isThreadLocal();
bool IsAccessViaCopyRelocs =
Options.MCOptions.MCPIECopyRelocations && isa<GlobalVariable>(GV);
Triple::ArchType Arch = TT.getArch();
bool IsPPC =
Arch == Triple::ppc || Arch == Triple::ppc64 || Arch == Triple::ppc64le;
// Check if we can use copy relocations. PowerPC has no copy relocations.
if (!IsTLS && !IsPPC && (RM == Reloc::Static || IsAccessViaCopyRelocs))
return true;
}
// ELF supports preemption of other symbols.
return false;
}
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.
CodeGenOpt::Level TargetMachine::getOptLevel() const { return OptLevel; }
void TargetMachine::setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; }
TargetTransformInfo TargetMachine::getTargetTransformInfo(const Function &F) {
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();
SmallString<128> NameStr;
getNameWithPrefix(NameStr, GV, TLOF->getMangler());
return TLOF->getContext().getOrCreateSymbol(NameStr);
}
TargetIRAnalysis TargetMachine::getTargetIRAnalysis() {
// 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); });
}