diff options
Diffstat (limited to 'lld/lib/Passes')
| -rw-r--r-- | lld/lib/Passes/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | lld/lib/Passes/GOTPass.cpp | 107 | ||||
| -rw-r--r-- | lld/lib/Passes/StubsPass.cpp | 66 |
3 files changed, 0 insertions, 175 deletions
diff --git a/lld/lib/Passes/CMakeLists.txt b/lld/lib/Passes/CMakeLists.txt index 6f297fb24b5..0c0876b575d 100644 --- a/lld/lib/Passes/CMakeLists.txt +++ b/lld/lib/Passes/CMakeLists.txt @@ -1,6 +1,4 @@ add_lld_library(lldPasses - GOTPass.cpp - StubsPass.cpp LayoutPass.cpp RoundTripNativePass.cpp RoundTripYAMLPass.cpp diff --git a/lld/lib/Passes/GOTPass.cpp b/lld/lib/Passes/GOTPass.cpp deleted file mode 100644 index 4729ca1cb55..00000000000 --- a/lld/lib/Passes/GOTPass.cpp +++ /dev/null @@ -1,107 +0,0 @@ -//===- Passes/GOTPass.cpp - Adds GOT entries ------------------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This linker pass transforms all GOT kind references to real references. -/// That is, in assembly you can write something like: -/// movq foo@GOTPCREL(%rip), %rax -/// which means you want to load a pointer to "foo" out of the GOT (global -/// Offsets Table). In the object file, the Atom containing this instruction -/// has a Reference whose target is an Atom named "foo" and the Reference -/// kind is a GOT load. The linker needs to instantiate a pointer sized -/// GOT entry. This is done be creating a GOT Atom to represent that pointer -/// sized data in this pass, and altering the Atom graph so the Reference now -/// points to the GOT Atom entry (corresponding to "foo") and changing the -/// Reference Kind to reflect it is now pointing to a GOT entry (rather -/// then needing a GOT entry). -/// -/// There is one optimization the linker can do here. If the target of the GOT -/// is in the same linkage unit and does not need to be interposable, and -/// the GOT use is just a load (not some other operation), this pass can -/// transform that load into an LEA (add). This optimizes away one memory load -/// which at runtime that could stall the pipeline. This optimization only -/// works for architectures in which a (GOT) load instruction can be change to -/// an LEA instruction that is the same size. The method isGOTAccess() should -/// only return true for "canBypassGOT" if this optimization is supported. -/// -//===----------------------------------------------------------------------===// - -#include "lld/Core/DefinedAtom.h" -#include "lld/Core/File.h" -#include "lld/Core/LLVM.h" -#include "lld/Core/Pass.h" -#include "lld/Core/Reference.h" -#include "llvm/ADT/DenseMap.h" - -namespace lld { - -static bool shouldReplaceTargetWithGOTAtom(const Atom *target, - bool canBypassGOT) { - // Accesses to shared library symbols must go through GOT. - if (target->definition() == Atom::definitionSharedLibrary) - return true; - // Accesses to interposable symbols in same linkage unit must also go - // through GOT. - const DefinedAtom *defTarget = dyn_cast<DefinedAtom>(target); - if (defTarget != nullptr && - defTarget->interposable() != DefinedAtom::interposeNo) { - assert(defTarget->scope() != DefinedAtom::scopeTranslationUnit); - return true; - } - // Target does not require indirection. So, if instruction allows GOT to be - // by-passed, do that optimization and don't create GOT entry. - return !canBypassGOT; -} - -static const DefinedAtom * -findGOTAtom(const Atom *target, - llvm::DenseMap<const Atom *, const DefinedAtom *> &targetToGOT) { - auto pos = targetToGOT.find(target); - return (pos == targetToGOT.end()) ? nullptr : pos->second; -} - -void GOTPass::perform(std::unique_ptr<MutableFile> &mergedFile) { - // Use map so all pointers to same symbol use same GOT entry. - llvm::DenseMap<const Atom*, const DefinedAtom*> targetToGOT; - - // Scan all references in all atoms. - for (const DefinedAtom *atom : mergedFile->defined()) { - for (const Reference *ref : *atom) { - // Look at instructions accessing the GOT. - bool canBypassGOT; - if (!isGOTAccess(*ref, canBypassGOT)) - continue; - const Atom *target = ref->target(); - assert(target != nullptr); - - if (!shouldReplaceTargetWithGOTAtom(target, canBypassGOT)) { - // Update reference kind to reflect that target is a direct accesss. - updateReferenceToGOT(ref, false); - continue; - } - // Replace the target with a reference to a GOT entry. - const DefinedAtom *gotEntry = findGOTAtom(target, targetToGOT); - if (!gotEntry) { - gotEntry = makeGOTEntry(*target); - assert(gotEntry != nullptr); - assert(gotEntry->contentType() == DefinedAtom::typeGOT); - targetToGOT[target] = gotEntry; - } - const_cast<Reference *>(ref)->setTarget(gotEntry); - // Update reference kind to reflect that target is now a GOT entry. - updateReferenceToGOT(ref, true); - } - } - - // add all created GOT Atoms to master file - for (auto &it : targetToGOT) - mergedFile->addAtom(*it.second); -} - -} // end namesapce lld diff --git a/lld/lib/Passes/StubsPass.cpp b/lld/lib/Passes/StubsPass.cpp deleted file mode 100644 index e388949bc4d..00000000000 --- a/lld/lib/Passes/StubsPass.cpp +++ /dev/null @@ -1,66 +0,0 @@ -//===- Passes/StubsPass.cpp - Adds stubs ----------------------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This linker pass updates call-sites which have references to shared library -// atoms to instead have a reference to a stub (PLT entry) for the specified -// symbol. Each file format defines a subclass of StubsPass which implements -// the abstract methods for creating the file format specific StubAtoms. -// -//===----------------------------------------------------------------------===// - -#include "lld/Core/DefinedAtom.h" -#include "lld/Core/File.h" -#include "lld/Core/LLVM.h" -#include "lld/Core/Pass.h" -#include "lld/Core/Reference.h" -#include "llvm/ADT/DenseMap.h" - -namespace lld { - -void StubsPass::perform(std::unique_ptr<MutableFile> &mergedFile) { - // Skip this pass if output format uses text relocations instead of stubs. - if (!this->noTextRelocs()) - return; - - // Scan all references in all atoms. - for (const DefinedAtom *atom : mergedFile->defined()) { - for (const Reference *ref : *atom) { - // Look at call-sites. - if (!this->isCallSite(*ref)) - continue; - const Atom *target = ref->target(); - assert(target != nullptr); - if (target->definition() == Atom::definitionSharedLibrary) { - // Calls to shared libraries go through stubs. - replaceCalleeWithStub(target, ref); - continue; - } - const DefinedAtom *defTarget = dyn_cast<DefinedAtom>(target); - if (defTarget && defTarget->interposable() != DefinedAtom::interposeNo) { - // Calls to interposable functions in same linkage unit must also go - // through a stub. - assert(defTarget->scope() != DefinedAtom::scopeTranslationUnit); - replaceCalleeWithStub(target, ref); - } - } - } - // Add all created stubs and support Atoms. - this->addStubAtoms(*mergedFile); -} - -void StubsPass::replaceCalleeWithStub(const Atom *target, - const Reference *ref) { - // Make file-format specific stub and other support atoms. - const DefinedAtom *stub = this->getStub(*target); - assert(stub != nullptr); - // Switch call site to reference stub atom instead. - const_cast<Reference *>(ref)->setTarget(stub); -} - -} // end namespace lld |

