[llvm-commits] [lld] r152269 - in /lld/trunk: ./ include/lld/Core/ include/lld/Platform/ lib/ lib/Core/ lib/Passes/ test/ tools/lld-core/
Nick Kledzik
kledzik at apple.com
Wed Mar 7 16:18:31 PST 2012
Author: kledzik
Date: Wed Mar 7 18:18:30 2012
New Revision: 152269
URL: http://llvm.org/viewvc/llvm-project?rev=152269&view=rev
Log:
Sources now require C++11 to build.
Add first linker pass (StubsPass) which looks for calls to shared library
symbols and replaces them with calls to a StubAtom. On ELF system, a "stub"
is a PLT entry. Added a simple test case.
Pass a Platform object to YAML reader and writer for converting fixup kinds
between names and values.
Change output of Resolver to be a File object instead of a vector of Atoms.
Thus, passes operate on a File instead of just Atoms.
Rework how to walk through a File's Atoms. Now iterator based instead of
a method that visits each atom.
Added:
lld/trunk/include/lld/Core/Pass.h
lld/trunk/lib/Passes/CMakeLists.txt
lld/trunk/lib/Passes/StubsPass.cpp
lld/trunk/test/pass-stubs-basic.objtxt
Modified:
lld/trunk/CMakeLists.txt
lld/trunk/include/lld/Core/Atom.h
lld/trunk/include/lld/Core/DefinedAtom.h
lld/trunk/include/lld/Core/File.h
lld/trunk/include/lld/Core/InputFiles.h
lld/trunk/include/lld/Core/Resolver.h
lld/trunk/include/lld/Core/YamlReader.h
lld/trunk/include/lld/Core/YamlWriter.h
lld/trunk/include/lld/Platform/Platform.h
lld/trunk/lib/CMakeLists.txt
lld/trunk/lib/Core/File.cpp
lld/trunk/lib/Core/NativeReader.cpp
lld/trunk/lib/Core/NativeWriter.cpp
lld/trunk/lib/Core/Resolver.cpp
lld/trunk/lib/Core/YamlKeyValues.cpp
lld/trunk/lib/Core/YamlReader.cpp
lld/trunk/lib/Core/YamlWriter.cpp
lld/trunk/tools/lld-core/CMakeLists.txt
lld/trunk/tools/lld-core/lld-core.cpp
Modified: lld/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/CMakeLists.txt?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/CMakeLists.txt (original)
+++ lld/trunk/CMakeLists.txt Wed Mar 7 18:18:30 2012
@@ -1,6 +1,8 @@
# If we are not building as a part of LLVM, build lld as a standalone project,
# using LLVM as an external library.
+
+
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
project(lld)
cmake_minimum_required(VERSION 2.8)
@@ -58,6 +60,20 @@
"`CMakeFiles'. Please delete them.")
endif()
+#
+# lld now requires C++11 to build
+#
+# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+include(CheckCXXCompilerFlag)
+check_cxx_compiler_flag("-std=c++11" SUPPORTS_CXX11_FLAG)
+if( SUPPORTS_CXX11_FLAG )
+ message(STATUS "Building with -std=c++11")
+ set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
+else( SUPPORTS_CXX11_FLAG )
+ message(WARNING "-std=c++11 not supported.")
+endif()
+
+
macro(add_lld_library name)
llvm_process_sources(srcs ${ARGN})
if (MSVC_IDE OR XCODE)
Modified: lld/trunk/include/lld/Core/Atom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Atom.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Atom.h (original)
+++ lld/trunk/include/lld/Core/Atom.h Wed Mar 7 18:18:30 2012
@@ -24,7 +24,7 @@
class SharedLibraryAtom;
class AbsoluteAtom;
- ///
+///
/// The linker has a Graph Theory model of linking. An object file is seen
/// as a set of Atoms with References to other Atoms. Each Atom is a node
/// and each Reference is an edge. An Atom can be a DefinedAtom which has
Modified: lld/trunk/include/lld/Core/DefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/DefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/DefinedAtom.h Wed Mar 7 18:18:30 2012
@@ -195,13 +195,6 @@
uint16_t modulus;
};
- /// for use iterating over this Atom's References
- class ReferenceHandler {
- public:
- virtual ~ReferenceHandler() {}
- virtual void doReference(const Reference &) = 0;
- };
-
/// ordinal - returns a value for the order of this Atom within its file.
/// This is used by the linker to order the layout of Atoms so that
/// the resulting image is stable and reproducible.
@@ -266,10 +259,43 @@
/// rawContent - returns a reference to the raw (unrelocated) bytes of
/// this Atom's content.
virtual llvm::ArrayRef<uint8_t> rawContent() const = 0;
+
+ /// This class abstracts iterating over the sequence of References
+ /// in an Atom. Concrete instances of DefinedAtom must implement
+ /// the derefIterator() and incrementIterator methods.
+ class reference_iterator {
+ public:
+ reference_iterator(const DefinedAtom& a, const void* it)
+ : _atom(a), _it(it) { }
- /// iterator over this Atom's References
- virtual void forEachReference(ReferenceHandler&) const = 0;
+ const Reference* operator*() const {
+ return _atom.derefIterator(_it);
+ }
+
+ const Reference* operator->() const {
+ return _atom.derefIterator(_it);
+ }
+
+ bool operator!=(const reference_iterator& other) const {
+ return (this->_it != other._it);
+ }
+
+ reference_iterator& operator++() {
+ _atom.incrementIterator(_it);
+ return *this;
+ }
+ private:
+ const DefinedAtom& _atom;
+ const void* _it;
+ };
+
+ /// Returns an iterator to the beginning of this Atom's References
+ virtual reference_iterator referencesBegin() const = 0;
+ /// Returns an iterator to the end of this Atom's References
+ virtual reference_iterator referencesEnd() const = 0;
+
+
protected:
/// DefinedAtom is an abstract base class.
/// Only subclasses can access constructor.
@@ -280,6 +306,15 @@
/// delete on an Atom. In fact, some File objects may bulk allocate
/// an array of Atoms, so they cannot be individually deleted by anyone.
virtual ~DefinedAtom() {}
+
+ /// Returns a pointer to the Reference object that the abstract
+ /// iterator "points" to.
+ virtual const Reference* derefIterator(const void* iter) const = 0;
+
+ /// Adjusts the abstract iterator to "point" to the next Reference object
+ /// for this Atom.
+ virtual void incrementIterator(const void*& iter) const = 0;
+
};
} // namespace lld
Modified: lld/trunk/include/lld/Core/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/File.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/File.h (original)
+++ lld/trunk/include/lld/Core/File.h Wed Mar 7 18:18:30 2012
@@ -1,4 +1,4 @@
-//===- Core/File.h - A Contaier of Atoms ----------------------------------===//
+//===- Core/File.h - A Container of Atoms ---------------------------------===//
//
// The LLVM Linker
//
@@ -10,6 +10,8 @@
#ifndef LLD_CORE_FILE_H_
#define LLD_CORE_FILE_H_
+#include <vector>
+
#include "llvm/ADT/StringRef.h"
#include "lld/Core/DefinedAtom.h"
@@ -19,31 +21,190 @@
namespace lld {
+
+///
+/// Every Atom is owned by some File. A common scenario is for a single
+/// object file (.o) to be parsed by some reader and produce a single
+/// File object that represents the content of that object file.
+///
+/// The File class has *begin() and *end() methods for use iterating through
+/// the Atoms in a File object.
+///
+/// The Atom objects in a File are owned by the File object. The Atom objects
+/// are destroyed when the File object is destroyed.
+///
class File {
public:
- File(llvm::StringRef p) : _path(p) {}
virtual ~File();
- class AtomHandler {
- public:
- virtual ~AtomHandler() {}
- virtual void doDefinedAtom(const class DefinedAtom &) = 0;
- virtual void doUndefinedAtom(const class UndefinedAtom &) = 0;
- virtual void doSharedLibraryAtom(const class SharedLibraryAtom &) = 0;
- virtual void doAbsoluteAtom(const class AbsoluteAtom &) = 0;
- virtual void doFile(const class File &) = 0;
- };
-
+ /// For error messages and debugging, this returns the path to the file
+ /// which was used to create this object (e.g. "/tmp/foo.o").
llvm::StringRef path() const {
return _path;
}
- virtual bool forEachAtom(AtomHandler &) const = 0;
- virtual bool justInTimeforEachAtom( llvm::StringRef name
- , AtomHandler &) const = 0;
+ /// Returns the path of the source file used to create the object
+ /// file which this (File) object represents. This information is usually
+ /// parsed out of the DWARF debug information. If the source file cannot
+ /// be ascertained, this method returns the empty string.
+ virtual llvm::StringRef translationUnitSource() const;
- virtual bool translationUnitSource(llvm::StringRef &path) const;
+protected:
+ template <typename T> class atom_iterator; // forward reference
+public:
+
+ /// For use interating over DefinedAtoms in this File.
+ typedef atom_iterator<DefinedAtom> defined_iterator;
+
+ /// For use interating over UndefinedAtoms in this File.
+ typedef atom_iterator<UndefinedAtom> undefined_iterator;
+
+ /// For use interating over SharedLibraryAtoms in this File.
+ typedef atom_iterator<SharedLibraryAtom> shared_library_iterator;
+
+ /// For use interating over AbsoluteAtoms in this File.
+ typedef atom_iterator<AbsoluteAtom> absolute_iterator;
+
+ /// Returns an iterator to the beginning of this File's DefinedAtoms
+ defined_iterator definedAtomsBegin() const {
+ return defined().begin();
+ }
+
+ /// Returns an iterator to the end of this File's DefinedAtoms
+ defined_iterator definedAtomsEnd() const {
+ return defined().end();
+ }
+
+ /// Returns an iterator to the beginning of this File's DefinedAtoms
+ undefined_iterator undefinedAtomsBegin() const {
+ return undefined().begin();
+ }
+
+ /// Returns an iterator to the end of this File's UndefinedAtoms
+ undefined_iterator undefinedAtomsEnd() const {
+ return undefined().end();
+ }
+
+ /// Returns an iterator to the beginning of this File's SharedLibraryAtoms
+ shared_library_iterator sharedLibraryAtomsBegin() const {
+ return sharedLibrary().begin();
+ }
+
+ /// Returns an iterator to the end of this File's SharedLibraryAtoms
+ shared_library_iterator sharedLibraryAtomsEnd() const {
+ return sharedLibrary().end();
+ }
+
+ /// Returns an iterator to the beginning of this File's AbsoluteAtoms
+ absolute_iterator absoluteAtomsBegin() const {
+ return absolute().begin();
+ }
+ /// Returns an iterator to the end of this File's AbsoluteAtoms
+ absolute_iterator absoluteAtomsEnd() const {
+ return absolute().end();
+ }
+
+ /// Note: this method is not const. All File objects instantiated by reading
+ /// an object file from disk are "const File*" objects and cannot be
+ /// modified. This method can only be used with temporay File objects
+ /// such as is seen by each Pass object when it runs.
+ /// This method is *not* safe to call while iterating through this File's
+ /// Atoms. A Pass should queue up any Atoms it want to add and then
+ /// call this method when no longer iterating over the File's Atoms.
+ virtual void addAtom(const Atom&) = 0;
+
+
+
+protected:
+ /// only subclasses of File can be instantiated
+ File(llvm::StringRef p) : _path(p) {}
+
+
+ /// Different object file readers may instantiate and manage atoms with
+ /// different data structures. This class is a collection abstraction.
+ /// Each concrete File instance must implement these atom_collection
+ /// methods to enable clients to interate the File's atoms.
+ template <typename T>
+ class atom_collection {
+ public:
+ virtual atom_iterator<T> begin() const = 0;
+ virtual atom_iterator<T> end() const = 0;
+ virtual const T* deref(const void* it) const = 0;
+ virtual void next(const void*& it) const = 0;
+ };
+
+
+ /// The class is the iterator type used to iterate through a File's Atoms.
+ /// This iterator delegates the work to the associated atom_collection object.
+ /// There are four kinds of Atoms, so this iterator is templated on
+ /// the four base Atom kinds.
+ template <typename T>
+ class atom_iterator {
+ public:
+ atom_iterator(const atom_collection<T>& c, const void* it)
+ : _collection(c), _it(it) { }
+
+ const T* operator*() const {
+ return _collection.deref(_it);
+ }
+
+ const T* operator->() const {
+ return _collection.deref(_it);
+ }
+
+ bool operator!=(const atom_iterator<T>& other) const {
+ return (this->_it != other._it);
+ }
+
+ atom_iterator<T>& operator++() {
+ _collection.next(_it);
+ return *this;
+ }
+ private:
+ const atom_collection<T>& _collection;
+ const void* _it;
+ };
+
+ /// Must be implemented to return the atom_collection object for
+ /// all DefinedAtoms in this File.
+ virtual const atom_collection<DefinedAtom>& defined() const = 0;
+
+ /// Must be implemented to return the atom_collection object for
+ /// all UndefinedAtomw in this File.
+ virtual const atom_collection<UndefinedAtom>& undefined() const = 0;
+
+ /// Must be implemented to return the atom_collection object for
+ /// all SharedLibraryAtoms in this File.
+ virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const = 0;
+
+ /// Must be implemented to return the atom_collection object for
+ /// all AbsoluteAtoms in this File.
+ virtual const atom_collection<AbsoluteAtom>& absolute() const = 0;
+
+ /// This is a convenience class for File subclasses which manage their
+ /// atoms as a simple std::vector<>.
+ template <typename T>
+ class atom_collection_vector : public atom_collection<T> {
+ public:
+ virtual atom_iterator<T> begin() const {
+ return atom_iterator<T>(*this, reinterpret_cast<const void*>(&_atoms[0]));
+ }
+ virtual atom_iterator<T> end() const{
+ return atom_iterator<T>(*this, reinterpret_cast<const void*>
+ (&_atoms[_atoms.size()]));
+ }
+ virtual const T* deref(const void* it) const {
+ return *reinterpret_cast<const T* const*>(it);
+ }
+ virtual void next(const void*& it) const {
+ const T * const * p = reinterpret_cast<const T * const *>(it);
+ ++p;
+ it = reinterpret_cast<const void*>(p);
+ }
+ std::vector<const T*> _atoms;
+ };
+
private:
llvm::StringRef _path;
Modified: lld/trunk/include/lld/Core/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputFiles.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/InputFiles.h (original)
+++ lld/trunk/include/lld/Core/InputFiles.h Wed Mar 7 18:18:30 2012
@@ -24,15 +24,26 @@
/// The searchLibraries() method is used to lazily search libraries.
class InputFiles {
public:
+ class Handler {
+ public:
+ virtual ~Handler() {}
+ virtual void doFile(const class File &) = 0;
+ virtual void doDefinedAtom(const class DefinedAtom &) = 0;
+ virtual void doUndefinedAtom(const class UndefinedAtom &) = 0;
+ virtual void doSharedLibraryAtom(const class SharedLibraryAtom &) = 0;
+ virtual void doAbsoluteAtom(const class AbsoluteAtom &) = 0;
+ };
+
+
/// @brief iterates all atoms in initial files
- virtual void forEachInitialAtom(File::AtomHandler &) const = 0;
+ virtual void forEachInitialAtom(Handler &) const = 0;
/// @brief searches libraries for name
virtual bool searchLibraries( llvm::StringRef name
, bool searchDylibs
, bool searchArchives
, bool dataSymbolOnly
- , File::AtomHandler &) const = 0;
+ , Handler &) const = 0;
};
} // namespace lld
Added: lld/trunk/include/lld/Core/Pass.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Pass.h?rev=152269&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/Pass.h (added)
+++ lld/trunk/include/lld/Core/Pass.h Wed Mar 7 18:18:30 2012
@@ -0,0 +1,65 @@
+//===------ Core/Pass.h - Base class for linker passes --------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_CORE_PASS_H_
+#define LLD_CORE_PASS_H_
+
+#include <vector>
+
+#include "lld/Core/Atom.h"
+#include "lld/Platform/Platform.h"
+
+namespace lld {
+
+
+///
+/// Once the core linking is done (which resolves references, coalesces atoms
+/// and produces a complete Atom graph), the linker runs a series of passes
+/// on the Atom graph. The graph is modeled as a File, which means the pass
+/// has access to all the atoms and to File level attributes. Each pass does
+/// a particular transformation to the Atom graph or to the File attributes.
+///
+/// This is the abstract base class for all passes. A Pass does its
+/// actual work in it perform() method. It can iterator over Atoms in the
+/// graph using the *begin()/*end() atom iterator of the File. It can add
+/// new Atoms to the graph using the File's addAtom() method.
+///
+///
+class Pass {
+public:
+ /// Do the actual work of the Pass.
+ virtual void perform() = 0;
+
+protected:
+ // Only subclassess can be instantiated.
+ Pass(File& f, Platform& p) : _file(f), _platform(p) {}
+
+
+ File& _file;
+ Platform& _platform;
+};
+
+
+///
+/// Pass for adding stubs (PLT entries) for calls to functions
+/// outside the linkage unit.
+///
+class StubsPass : public Pass {
+public:
+ StubsPass(File& f, Platform& p) : Pass(f, p) {}
+
+ /// Scans all Atoms looking for call-site uses of SharedLibraryAtoms
+ /// and transfroms the call-site to call a stub instead.
+ virtual void perform();
+};
+
+
+} // namespace lld
+
+#endif // LLD_CORE_PASS_H_
Modified: lld/trunk/include/lld/Core/Resolver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Resolver.h (original)
+++ lld/trunk/include/lld/Core/Resolver.h Wed Mar 7 18:18:30 2012
@@ -11,6 +11,7 @@
#define LLD_CORE_RESOLVER_H_
#include "lld/Core/File.h"
+#include "lld/Core/InputFiles.h"
#include "lld/Core/SymbolTable.h"
#include "llvm/ADT/DenseSet.h"
@@ -30,7 +31,7 @@
///
/// All platform specific resolving is done by delegating to the
/// Platform object specified.
-class Resolver : public File::AtomHandler {
+class Resolver : public InputFiles::Handler {
public:
Resolver(Platform &plat, const InputFiles &inputs)
: _platform(plat)
@@ -40,7 +41,7 @@
, _addToFinalSection(false)
, _completedInitialObjectFiles(false) {}
- // AtomHandler methods
+ // InputFiles::Handler methods
virtual void doDefinedAtom(const class DefinedAtom&);
virtual void doUndefinedAtom(const class UndefinedAtom&);
virtual void doSharedLibraryAtom(const class SharedLibraryAtom &);
@@ -48,7 +49,11 @@
virtual void doFile(const File&);
/// @brief do work of merging and resolving and return list
- std::vector<const Atom *> &resolve();
+ void resolve();
+
+ File& resultFile() {
+ return _result;
+ }
private:
struct WhyLiveBackChain {
@@ -73,31 +78,49 @@
void addAtoms(const std::vector<const DefinedAtom *>&);
- // helper to update targets for use with forEachReference()
- class MarkLiveReferences : public DefinedAtom::ReferenceHandler {
+ class MergedFile : public File {
public:
- MarkLiveReferences(Resolver& resolver, WhyLiveBackChain* chain)
- : _resolver(resolver), _chain(chain) { }
+ MergedFile() : File("<linker-internal>") { }
- virtual void doReference(const Reference& ref) {
- _resolver.markLive(*ref.target(), _chain);
- }
+
+
+ virtual const atom_collection<DefinedAtom>& defined() const {
+ return _definedAtoms;
+ }
+ virtual const atom_collection<UndefinedAtom>& undefined() const {
+ return _undefinedAtoms;
+ }
+ virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
+ return _sharedLibraryAtoms;
+ }
+ virtual const atom_collection<AbsoluteAtom>& absolute() const {
+ return _absoluteAtoms;
+ }
+
+ void addAtoms(std::vector<const Atom*>& atoms);
+
+ virtual void addAtom(const Atom& atom);
private:
- Resolver& _resolver;
- WhyLiveBackChain* _chain;
+ atom_collection_vector<DefinedAtom> _definedAtoms;
+ atom_collection_vector<UndefinedAtom> _undefinedAtoms;
+ atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
+ atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
};
-
- Platform &_platform;
- const InputFiles &_inputFiles;
- SymbolTable _symbolTable;
- std::vector<const Atom *> _atoms;
- std::set<const Atom *> _deadStripRoots;
- std::vector<const Atom *> _atomsWithUnresolvedReferences;
- llvm::DenseSet<const Atom *> _liveAtoms;
- bool _haveLLVMObjs;
- bool _addToFinalSection;
- bool _completedInitialObjectFiles;
+
+
+
+ Platform& _platform;
+ const InputFiles& _inputFiles;
+ SymbolTable _symbolTable;
+ std::vector<const Atom *> _atoms;
+ std::set<const Atom *> _deadStripRoots;
+ std::vector<const Atom *> _atomsWithUnresolvedReferences;
+ llvm::DenseSet<const Atom *> _liveAtoms;
+ MergedFile _result;
+ bool _haveLLVMObjs;
+ bool _addToFinalSection;
+ bool _completedInitialObjectFiles;
};
} // namespace lld
Modified: lld/trunk/include/lld/Core/YamlReader.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/YamlReader.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/YamlReader.h (original)
+++ lld/trunk/include/lld/Core/YamlReader.h Wed Mar 7 18:18:30 2012
@@ -10,8 +10,6 @@
#ifndef LLD_CORE_YAML_READER_H_
#define LLD_CORE_YAML_READER_H_
-#include "lld/Core/File.h"
-
#include "llvm/Support/system_error.h"
#include <vector>
@@ -19,19 +17,25 @@
namespace llvm { class MemoryBuffer; }
namespace lld {
+
+class Platform;
+class File;
+
namespace yaml {
/// parseObjectTextFileOrSTDIN - Open the specified YAML file (use stdin if
/// the path is "-") and parse into lld::File object(s) and append each to
/// the specified vector<File*>.
llvm::error_code parseObjectTextFileOrSTDIN(llvm::StringRef path
- , std::vector<File *>&);
+ , Platform&
+ , std::vector<const File *>&);
/// parseObjectText - Parse the specified YAML formatted MemoryBuffer
/// into lld::File object(s) and append each to the specified vector<File*>.
llvm::error_code parseObjectText(llvm::MemoryBuffer *mb
- , std::vector<File *>&);
+ , Platform&
+ , std::vector<const File *>&);
} // namespace yaml
} // namespace lld
Modified: lld/trunk/include/lld/Core/YamlWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/YamlWriter.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/YamlWriter.h (original)
+++ lld/trunk/include/lld/Core/YamlWriter.h Wed Mar 7 18:18:30 2012
@@ -10,15 +10,18 @@
#ifndef LLD_CORE_YAML_WRITER_H_
#define LLD_CORE_YAML_WRITER_H_
-#include "lld/Core/File.h"
#include "llvm/Support/raw_ostream.h"
namespace lld {
+
+class Platform;
+class File;
+
namespace yaml {
/// writeObjectText - writes the lld::File object as in YAML
/// format to the specified stream.
- void writeObjectText(const lld::File &, llvm::raw_ostream &);
+ void writeObjectText(const lld::File &, Platform &, llvm::raw_ostream &);
} // namespace yaml
} // namespace lld
Modified: lld/trunk/include/lld/Platform/Platform.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Platform/Platform.h?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/include/lld/Platform/Platform.h (original)
+++ lld/trunk/include/lld/Platform/Platform.h Wed Mar 7 18:18:30 2012
@@ -12,10 +12,13 @@
#include <vector>
+#include "lld/Core/Reference.h"
+
namespace lld {
class Atom;
class DefinedAtom;
+
/// The Platform class encapsulated plaform specific linking knowledge.
///
/// Much of what it does is driving by platform specific linker options.
@@ -98,6 +101,26 @@
/// @brief last chance for platform to tweak atoms
virtual void postResolveTweaks(std::vector<const Atom *>& all) = 0;
+
+ /// If the output being generated uses needs stubs for external calls
+ virtual bool outputUsesStubs() = 0;
+
+ /// Converts a reference kind string to a in-memory numeric value.
+ /// For use with parsing YAML encoded object files.
+ virtual Reference::Kind kindFromString(llvm::StringRef) = 0;
+
+ /// Converts an in-memory reference kind value to a string.
+ /// For use with writing YAML encoded object files.
+ virtual llvm::StringRef kindToString(Reference::Kind) = 0;
+
+ /// If Reference is a branch instruction that might need to be changed
+ /// to target a stub (PLT entry).
+ virtual bool isBranch(const Reference*) = 0;
+
+ /// Create a platform specific atom which contains a stub/PLT entry
+ /// targeting the specified shared library atom.
+ virtual const Atom* makeStub(const SharedLibraryAtom&, File&) = 0;
+
};
} // namespace lld
Modified: lld/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/CMakeLists.txt?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/CMakeLists.txt (original)
+++ lld/trunk/lib/CMakeLists.txt Wed Mar 7 18:18:30 2012
@@ -1 +1,2 @@
add_subdirectory(Core)
+add_subdirectory(Passes)
Modified: lld/trunk/lib/Core/File.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/File.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/File.cpp (original)
+++ lld/trunk/lib/Core/File.cpp Wed Mar 7 18:18:30 2012
@@ -13,8 +13,8 @@
File::~File() {}
-bool File::translationUnitSource(llvm::StringRef &path) const {
- return false;
+llvm::StringRef File::translationUnitSource() const {
+ return llvm::StringRef();
}
Modified: lld/trunk/lib/Core/NativeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeReader.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/NativeReader.cpp (original)
+++ lld/trunk/lib/Core/NativeReader.cpp Wed Mar 7 18:18:30 2012
@@ -92,9 +92,15 @@
}
virtual llvm::ArrayRef<uint8_t> rawContent() const;
-
- virtual void forEachReference(ReferenceHandler&) const;
-
+
+ virtual reference_iterator referencesBegin() const;
+
+ virtual reference_iterator referencesEnd() const;
+
+ virtual const Reference* derefIterator(const void*) const;
+
+ virtual void incrementIterator(const void*& it) const;
+
private:
const NativeAtomAttributesV1& attributes() const;
@@ -299,53 +305,29 @@
// the _definedAtoms array which was allocated to contain an array
// of Atom objects. The atoms have empty destructors, so it is ok
// to just delete the memory.
- delete _definedAtoms.arrayStart;
- delete _undefinedAtoms.arrayStart;
- delete _sharedLibraryAtoms.arrayStart;
- delete _absoluteAtoms.arrayStart;
+ delete _definedAtoms._arrayStart;
+ delete _undefinedAtoms._arrayStart;
+ delete _sharedLibraryAtoms._arrayStart;
+ delete _absoluteAtoms._arrayStart;
delete _references.arrayStart;
delete _targetsTable;
}
- // visits each atom in the file
- virtual bool forEachAtom(AtomHandler& handler) const {
- bool didSomething = false;
- for(const uint8_t* p=_definedAtoms.arrayStart; p != _definedAtoms.arrayEnd;
- p += _definedAtoms.elementSize) {
- const DefinedAtom* atom = reinterpret_cast<const DefinedAtom*>(p);
- handler.doDefinedAtom(*atom);
- didSomething = true;
- }
- for(const uint8_t* p=_undefinedAtoms.arrayStart;
- p != _undefinedAtoms.arrayEnd;
- p += _undefinedAtoms.elementSize) {
- const UndefinedAtom* atom = reinterpret_cast<const UndefinedAtom*>(p);
- handler.doUndefinedAtom(*atom);
- didSomething = true;
- }
- for(const uint8_t* p=_sharedLibraryAtoms.arrayStart;
- p != _sharedLibraryAtoms.arrayEnd;
- p += _sharedLibraryAtoms.elementSize) {
- const SharedLibraryAtom* atom
- = reinterpret_cast<const SharedLibraryAtom*>(p);
- handler.doSharedLibraryAtom(*atom);
- didSomething = true;
- }
- for(const uint8_t* p=_absoluteAtoms.arrayStart;
- p != _absoluteAtoms.arrayEnd;
- p += _absoluteAtoms.elementSize) {
- const AbsoluteAtom* atom
- = reinterpret_cast<const AbsoluteAtom*>(p);
- handler.doAbsoluteAtom(*atom);
- didSomething = true;
- }
- return didSomething;
- }
-
- // not used
- virtual bool justInTimeforEachAtom(llvm::StringRef name,
- AtomHandler &) const {
- return false;
+ virtual const atom_collection<DefinedAtom>& defined() const {
+ return _definedAtoms;
+ }
+ virtual const atom_collection<UndefinedAtom>& undefined() const {
+ return _undefinedAtoms;
+ }
+ virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
+ return _sharedLibraryAtoms;
+ }
+ virtual const atom_collection<AbsoluteAtom>& absolute() const {
+ return _absoluteAtoms;
+ }
+
+ virtual void addAtom(const Atom&) {
+ assert(0 && "cannot add atoms to native .o files");
}
private:
@@ -378,10 +360,10 @@
new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
++ivarData;
}
- this->_definedAtoms.arrayStart = atomsStart;
- this->_definedAtoms.arrayEnd = atomsEnd;
- this->_definedAtoms.elementSize = atomSize;
- this->_definedAtoms.elementCount = chunk->elementCount;
+ this->_definedAtoms._arrayStart = atomsStart;
+ this->_definedAtoms._arrayEnd = atomsEnd;
+ this->_definedAtoms._elementSize = atomSize;
+ this->_definedAtoms._elementCount = chunk->elementCount;
return make_error_code(native_reader_error::success);
}
@@ -416,10 +398,10 @@
new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
++ivarData;
}
- this->_undefinedAtoms.arrayStart = atomsStart;
- this->_undefinedAtoms.arrayEnd = atomsEnd;
- this->_undefinedAtoms.elementSize = atomSize;
- this->_undefinedAtoms.elementCount = chunk->elementCount;
+ this->_undefinedAtoms._arrayStart = atomsStart;
+ this->_undefinedAtoms._arrayEnd = atomsEnd;
+ this->_undefinedAtoms._elementSize = atomSize;
+ this->_undefinedAtoms._elementCount = chunk->elementCount;
return make_error_code(native_reader_error::success);
}
@@ -447,10 +429,10 @@
new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
++ivarData;
}
- this->_sharedLibraryAtoms.arrayStart = atomsStart;
- this->_sharedLibraryAtoms.arrayEnd = atomsEnd;
- this->_sharedLibraryAtoms.elementSize = atomSize;
- this->_sharedLibraryAtoms.elementCount = chunk->elementCount;
+ this->_sharedLibraryAtoms._arrayStart = atomsStart;
+ this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
+ this->_sharedLibraryAtoms._elementSize = atomSize;
+ this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
return make_error_code(native_reader_error::success);
}
@@ -478,10 +460,10 @@
new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
++ivarData;
}
- this->_absoluteAtoms.arrayStart = atomsStart;
- this->_absoluteAtoms.arrayEnd = atomsEnd;
- this->_absoluteAtoms.elementSize = atomSize;
- this->_absoluteAtoms.elementCount = chunk->elementCount;
+ this->_absoluteAtoms._arrayStart = atomsStart;
+ this->_absoluteAtoms._arrayEnd = atomsEnd;
+ this->_absoluteAtoms._elementSize = atomSize;
+ this->_absoluteAtoms._elementCount = chunk->elementCount;
return make_error_code(native_reader_error::success);
}
@@ -529,33 +511,33 @@
this->_targetsTable = new const Atom*[chunk->elementCount];
for (uint32_t i=0; i < chunk->elementCount; ++i) {
const uint32_t index = targetIndexes[i];
- if ( index < _definedAtoms.elementCount ) {
- const uint8_t* p = _definedAtoms.arrayStart
- + index * _definedAtoms.elementSize;
+ if ( index < _definedAtoms._elementCount ) {
+ const uint8_t* p = _definedAtoms._arrayStart
+ + index * _definedAtoms._elementSize;
this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
continue;
}
- const uint32_t undefIndex = index - _definedAtoms.elementCount;
- if ( undefIndex < _undefinedAtoms.elementCount ) {
- const uint8_t* p = _undefinedAtoms.arrayStart
- + undefIndex * _undefinedAtoms.elementSize;
+ const uint32_t undefIndex = index - _definedAtoms._elementCount;
+ if ( undefIndex < _undefinedAtoms._elementCount ) {
+ const uint8_t* p = _undefinedAtoms._arrayStart
+ + undefIndex * _undefinedAtoms._elementSize;
this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
continue;
}
- const uint32_t slIndex = index - _definedAtoms.elementCount
- - _undefinedAtoms.elementCount;
- if ( slIndex < _sharedLibraryAtoms.elementCount ) {
- const uint8_t* p = _sharedLibraryAtoms.arrayStart
- + slIndex * _sharedLibraryAtoms.elementSize;
+ const uint32_t slIndex = index - _definedAtoms._elementCount
+ - _undefinedAtoms._elementCount;
+ if ( slIndex < _sharedLibraryAtoms._elementCount ) {
+ const uint8_t* p = _sharedLibraryAtoms._arrayStart
+ + slIndex * _sharedLibraryAtoms._elementSize;
this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
continue;
}
- const uint32_t abIndex = index - _definedAtoms.elementCount
- - _undefinedAtoms.elementCount
- - _sharedLibraryAtoms.elementCount;
- if ( abIndex < _absoluteAtoms.elementCount ) {
- const uint8_t* p = _absoluteAtoms.arrayStart
- + slIndex * _absoluteAtoms.elementSize;
+ const uint32_t abIndex = index - _definedAtoms._elementCount
+ - _undefinedAtoms._elementCount
+ - _sharedLibraryAtoms._elementCount;
+ if ( abIndex < _absoluteAtoms._elementCount ) {
+ const uint8_t* p = _absoluteAtoms._arrayStart
+ + slIndex * _absoluteAtoms._elementSize;
this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
continue;
}
@@ -612,21 +594,13 @@
assert((result+size) <= _contentEnd);
return result;
}
-
- void forEachReference(DefinedAtom::ReferenceHandler& handler,
- uint32_t start, uint32_t count) const {
- assert(start < _references.elementCount);
- assert(start+count <= _references.elementCount);
- const uint8_t* arrStart = _references.arrayStart
- + start * _references.elementSize;
- const uint8_t* arrEnd = arrStart + count * _references.elementSize;
- for(const uint8_t* p=arrStart; p != arrEnd; p += _references.elementSize) {
- const NativeReferenceV1* ref
- = reinterpret_cast<const NativeReferenceV1*>(p);
- handler.doReference(*ref);
- }
- }
+ const Reference* referenceByIndex(uintptr_t index) const {
+ assert(index < _references.elementCount);
+ const uint8_t* p = _references.arrayStart + index * _references.elementSize;
+ return reinterpret_cast<const NativeReferenceV1*>(p);
+ }
+
const Atom* target(uint32_t index) const {
assert(index < _targetsTableCount);
return _targetsTable[index];
@@ -656,21 +630,52 @@
(_buffer->getBufferStart());
}
+ template <typename T>
+ class AtomArray : public File::atom_collection<T> {
+ public:
+ AtomArray() : _arrayStart(NULL), _arrayEnd(NULL),
+ _elementSize(0), _elementCount(0) { }
+
+ virtual atom_iterator<T> begin() const {
+ return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
+ }
+ virtual atom_iterator<T> end() const{
+ return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
+ }
+ virtual const T* deref(const void* it) const {
+ return reinterpret_cast<const T*>(it);
+ }
+ virtual void next(const void*& it) const {
+ const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
+ p += _elementSize;
+ it = reinterpret_cast<const void*>(p);
+ }
+ const uint8_t* _arrayStart;
+ const uint8_t* _arrayEnd;
+ uint32_t _elementSize;
+ uint32_t _elementCount;
+ };
+
struct IvarArray {
- IvarArray() : arrayStart(NULL), arrayEnd(NULL),
- elementSize(0), elementCount(0) { }
+ IvarArray() :
+ arrayStart(NULL),
+ arrayEnd(NULL),
+ elementSize(0),
+ elementCount(0) { }
+
const uint8_t* arrayStart;
const uint8_t* arrayEnd;
uint32_t elementSize;
uint32_t elementCount;
- };
+ };
+
llvm::OwningPtr<llvm::MemoryBuffer> _buffer;
const NativeFileHeader* _header;
- IvarArray _definedAtoms;
- IvarArray _undefinedAtoms;
- IvarArray _sharedLibraryAtoms;
- IvarArray _absoluteAtoms;
+ AtomArray<DefinedAtom> _definedAtoms;
+ AtomArray<UndefinedAtom> _undefinedAtoms;
+ AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
+ AtomArray<AbsoluteAtom> _absoluteAtoms;
const uint8_t* _attributes;
uint32_t _attributesMaxOffset;
IvarArray _references;
@@ -684,14 +689,14 @@
const uint8_t* _contentEnd;
};
-
+
inline const class File& NativeDefinedAtomV1::file() const {
return *_file;
}
inline uint64_t NativeDefinedAtomV1:: ordinal() const {
const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
- return p - _file->_definedAtoms.arrayStart;
+ return p - _file->_definedAtoms._arrayStart;
}
inline llvm::StringRef NativeDefinedAtomV1::name() const {
@@ -715,11 +720,27 @@
return _file->string(offset);
}
-inline void NativeDefinedAtomV1::forEachReference(ReferenceHandler& hnd) const {
- if ( _ivarData->referencesCount == 0 )
- return;
- _file->forEachReference(hnd, _ivarData->referencesStartIndex,
- _ivarData->referencesCount);
+DefinedAtom::reference_iterator NativeDefinedAtomV1::referencesBegin() const {
+ uintptr_t index = _ivarData->referencesStartIndex;
+ const void* it = reinterpret_cast<const void*>(index);
+ return reference_iterator(*this, it);
+}
+
+DefinedAtom::reference_iterator NativeDefinedAtomV1::referencesEnd() const {
+ uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
+ const void* it = reinterpret_cast<const void*>(index);
+ return reference_iterator(*this, it);
+}
+
+const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
+ uintptr_t index = reinterpret_cast<uintptr_t>(it);
+ return _file->referenceByIndex(index);
+}
+
+void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
+ uintptr_t index = reinterpret_cast<uintptr_t>(it);
+ ++index;
+ it = reinterpret_cast<const void*>(index);
}
inline const class File& NativeUndefinedAtomV1::file() const {
Modified: lld/trunk/lib/Core/NativeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeWriter.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/NativeWriter.cpp (original)
+++ lld/trunk/lib/Core/NativeWriter.cpp Wed Mar 7 18:18:30 2012
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include <vector>
-#include <map>
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ArrayRef.h"
@@ -26,15 +25,36 @@
///
/// Class for writing native object files.
///
-class NativeWriter : public File::AtomHandler,
- public DefinedAtom::ReferenceHandler {
+class NativeWriter {
public:
/// construct writer for an lld::File object
NativeWriter(const lld::File& file) : _file(file) {
// reserve first byte for unnamed atoms
_stringPool.push_back('\0');
// visit all atoms
- _file.forEachAtom(*this);
+ for(File::defined_iterator it=file.definedAtomsBegin(),
+ end=file.definedAtomsEnd();
+ it != end; ++it) {
+ this->addIVarsForDefinedAtom(**it);
+ }
+ for(File::undefined_iterator it=file.undefinedAtomsBegin(),
+ end=file.undefinedAtomsEnd();
+ it != end; ++it) {
+ this->addIVarsForUndefinedAtom(**it);
+ }
+ for(File::shared_library_iterator it=file.sharedLibraryAtomsBegin(),
+ end=file.sharedLibraryAtomsEnd();
+ it != end; ++it) {
+ this->addIVarsForSharedLibraryAtom(**it);
+ }
+ for(File::absolute_iterator it=file.absoluteAtomsBegin(),
+ end=file.absoluteAtomsEnd();
+ it != end; ++it) {
+ this->addIVarsForAbsoluteAtom(**it);
+ }
+
+
+
// construct file header based on atom information accumulated
makeHeader();
}
@@ -105,8 +125,7 @@
private:
- // visitor routine called by forEachAtom()
- virtual void doDefinedAtom(const DefinedAtom& atom) {
+ void addIVarsForDefinedAtom(const DefinedAtom& atom) {
_definedAtomIndex[&atom] = _definedAtomIvars.size();
NativeDefinedAtomIvarsV1 ivar;
unsigned refsCount;
@@ -119,8 +138,7 @@
_definedAtomIvars.push_back(ivar);
}
- // visitor routine called by forEachAtom()
- virtual void doUndefinedAtom(const UndefinedAtom& atom) {
+ void addIVarsForUndefinedAtom(const UndefinedAtom& atom) {
_undefinedAtomIndex[&atom] = _undefinedAtomIvars.size();
NativeUndefinedAtomIvarsV1 ivar;
ivar.nameOffset = getNameOffset(atom);
@@ -128,8 +146,7 @@
_undefinedAtomIvars.push_back(ivar);
}
- // visitor routine called by forEachAtom()
- virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) {
+ void addIVarsForSharedLibraryAtom(const SharedLibraryAtom& atom) {
_sharedLibraryAtomIndex[&atom] = _sharedLibraryAtomIvars.size();
NativeSharedLibraryAtomIvarsV1 ivar;
ivar.nameOffset = getNameOffset(atom);
@@ -138,8 +155,7 @@
_sharedLibraryAtomIvars.push_back(ivar);
}
- // visitor routine called by forEachAtom()
- virtual void doAbsoluteAtom(const AbsoluteAtom& atom) {
+ void addIVarsForAbsoluteAtom(const AbsoluteAtom& atom) {
_absoluteAtomIndex[&atom] = _absoluteAtomIvars.size();
NativeAbsoluteAtomIvarsV1 ivar;
ivar.nameOffset = getNameOffset(atom);
@@ -148,10 +164,6 @@
_absoluteAtomIvars.push_back(ivar);
}
- // visitor routine called by forEachAtom()
- virtual void doFile(const File &) {
- }
-
// fill out native file header and chunk directory
void makeHeader() {
const bool hasDefines = !_definedAtomIvars.empty();
@@ -304,6 +316,7 @@
return chunks[i];
}
assert(0 && "findChunk() signature not found");
+ static NativeChunk x; return x; // suppress warning
}
// append atom name to string pool and return offset
@@ -403,23 +416,23 @@
count = 0;
size_t startRefSize = _references.size();
uint32_t result = startRefSize;
- atom.forEachReference(*this);
+ for (auto it=atom.referencesBegin(), end=atom.referencesEnd();
+ it != end; ++it) {
+ const Reference* ref = *it;
+ NativeReferenceIvarsV1 nref;
+ nref.offsetInAtom = ref->offsetInAtom();
+ nref.kind = ref->kind();
+ nref.targetIndex = this->getTargetIndex(ref->target());
+ nref.addendIndex = this->getAddendIndex(ref->addend());
+ _references.push_back(nref);
+ }
count = _references.size() - startRefSize;
if ( count == 0 )
return 0;
else
return result;
}
-
- void doReference(const Reference& ref) {
- NativeReferenceIvarsV1 nref;
- nref.offsetInAtom = ref.offsetInAtom();
- nref.kind = ref.kind();
- nref.targetIndex = this->getTargetIndex(ref.target());
- nref.addendIndex = this->getAddendIndex(ref.addend());
- _references.push_back(nref);
- }
-
+
uint32_t getTargetIndex(const Atom* target) {
TargetToIndex::const_iterator pos = _targetsTableIndex.find(target);
if ( pos != _targetsTableIndex.end() ) {
Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Wed Mar 7 18:18:30 2012
@@ -217,29 +217,18 @@
}
}
-// helper to update targets for use with forEachReference()
-class ReferenceUpdater : public DefinedAtom::ReferenceHandler {
-public:
- ReferenceUpdater(SymbolTable& sym) : _symbolTable(sym) { }
-
- virtual void doReference(const Reference& ref) {
- const Atom* newTarget = _symbolTable.replacement(ref.target());
- (const_cast<Reference*>(&ref))->setTarget(newTarget);
- }
-
-private:
- SymbolTable& _symbolTable;
-};
-
// switch all references to undefined or coalesced away atoms
// to the new defined atom
void Resolver::updateReferences() {
- ReferenceUpdater updater(_symbolTable);
- for (std::vector<const Atom *>::iterator it = _atoms.begin();
- it != _atoms.end(); ++it) {
- if ( const DefinedAtom* defAtom = (*it)->definedAtom() ) {
- defAtom->forEachReference(updater);
+ for (auto ait = _atoms.begin(); ait != _atoms.end(); ++ait) {
+ if ( const DefinedAtom* defAtom = (*ait)->definedAtom() ) {
+ for (auto rit=defAtom->referencesBegin(), end=defAtom->referencesEnd();
+ rit != end; ++rit) {
+ const Reference* ref = *rit;
+ const Atom* newTarget = _symbolTable.replacement(ref->target());
+ (const_cast<Reference*>(ref))->setTarget(newTarget);
+ }
}
}
}
@@ -272,8 +261,11 @@
thisChain.previous = previous;
thisChain.referer = &atom;
if ( const DefinedAtom* defAtom = atom.definedAtom() ) {
- MarkLiveReferences markRefs(*this, &thisChain);
- defAtom->forEachReference(markRefs);
+ for (auto rit=defAtom->referencesBegin(), end=defAtom->referencesEnd();
+ rit != end; ++rit) {
+ const Reference* ref = *rit;
+ this->markLive(*ref->target(), &thisChain);
+ }
}
}
@@ -382,7 +374,7 @@
// FIX ME
}
-std::vector<const Atom *> &Resolver::resolve() {
+void Resolver::resolve() {
this->initializeState();
this->addInitialUndefines();
this->buildInitialAtomList();
@@ -394,7 +386,32 @@
this->checkDylibSymbolCollisions();
this->linkTimeOptimize();
this->tweakAtoms();
- return _atoms;
+ this->_result.addAtoms(_atoms);
}
+void Resolver::MergedFile::addAtom(const Atom& atom) {
+ if ( const DefinedAtom* defAtom = atom.definedAtom() ) {
+ _definedAtoms._atoms.push_back(defAtom);
+ }
+ else if ( const UndefinedAtom* undefAtom = atom.undefinedAtom() ) {
+ _undefinedAtoms._atoms.push_back(undefAtom);
+ }
+ else if ( const SharedLibraryAtom* slAtom = atom.sharedLibraryAtom() ) {
+ _sharedLibraryAtoms._atoms.push_back(slAtom);
+ }
+ else if ( const AbsoluteAtom* abAtom = atom.absoluteAtom() ) {
+ _absoluteAtoms._atoms.push_back(abAtom);
+ }
+ else {
+ assert(0 && "atom has unknown definition kind");
+ }
+}
+
+void Resolver::MergedFile::addAtoms(std::vector<const Atom*>& all) {
+ for(std::vector<const Atom*>::iterator it=all.begin(); it != all.end(); ++it) {
+ this->addAtom(**it);
+ }
+}
+
+
} // namespace lld
Modified: lld/trunk/lib/Core/YamlKeyValues.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.cpp (original)
+++ lld/trunk/lib/Core/YamlKeyValues.cpp Wed Mar 7 18:18:30 2012
@@ -137,6 +137,7 @@
static const ContentTypeMapping typeMappings[] = {
{ "unknown", DefinedAtom::typeUnknown },
{ "code", DefinedAtom::typeCode },
+ { "stub", DefinedAtom::typeStub },
{ "resolver", DefinedAtom::typeResolver },
{ "constant", DefinedAtom::typeConstant },
{ "c-string", DefinedAtom::typeCString },
Modified: lld/trunk/lib/Core/YamlReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlReader.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlReader.cpp (original)
+++ lld/trunk/lib/Core/YamlReader.cpp Wed Mar 7 18:18:30 2012
@@ -20,6 +20,8 @@
#include "lld/Core/File.h"
#include "lld/Core/Reference.h"
+#include "lld/Platform/Platform.h"
+
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ArrayRef.h"
@@ -297,10 +299,23 @@
: File("path")
, _lastRefIndex(0) {}
- virtual bool forEachAtom(File::AtomHandler &) const;
- virtual bool justInTimeforEachAtom(llvm::StringRef name,
- File::AtomHandler &) const;
+ virtual const atom_collection<DefinedAtom>& defined() const {
+ return _definedAtoms;
+ }
+ virtual const atom_collection<UndefinedAtom>& undefined() const {
+ return _undefinedAtoms;
+ }
+ virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
+ return _sharedLibraryAtoms;
+ }
+ virtual const atom_collection<AbsoluteAtom>& absolute() const {
+ return _absoluteAtoms;
+ }
+ virtual void addAtom(const Atom&) {
+ assert(0 && "cannot add atoms to YAML files");
+ }
+
void bindTargetReferences();
void addDefinedAtom(YAMLDefinedAtom* atom, const char* refName);
void addUndefinedAtom(UndefinedAtom* atom);
@@ -314,13 +329,13 @@
Atom* atom;
};
- std::vector<YAMLDefinedAtom*> _definedAtoms;
- std::vector<UndefinedAtom*> _undefinedAtoms;
- std::vector<SharedLibraryAtom*> _sharedLibraryAtoms;
- std::vector<AbsoluteAtom*> _absoluteAtoms;
- std::vector<YAMLReference> _references;
- std::vector<NameAtomPair> _nameToAtomMapping;
- unsigned int _lastRefIndex;
+ atom_collection_vector<DefinedAtom> _definedAtoms;
+ atom_collection_vector<UndefinedAtom> _undefinedAtoms;
+ atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
+ atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
+ std::vector<YAMLReference> _references;
+ std::vector<NameAtomPair> _nameToAtomMapping;
+ unsigned int _lastRefIndex;
};
@@ -434,14 +449,35 @@
return _ord;
}
-
- virtual void forEachReference(ReferenceHandler& handler) const {
- for (uint32_t i=_refStartIndex; i < _refEndIndex; ++i) {
- handler.doReference(_file._references[i]);
- }
+ DefinedAtom::reference_iterator referencesBegin() const {
+ uintptr_t index = _refStartIndex;
+ const void* it = reinterpret_cast<const void*>(index);
+ return reference_iterator(*this, it);
}
- void bindTargetReferences() {
+ DefinedAtom::reference_iterator referencesEnd() const {
+ uintptr_t index = _refEndIndex;
+ const void* it = reinterpret_cast<const void*>(index);
+ return reference_iterator(*this, it);
+ }
+
+ const Reference* derefIterator(const void* it) const {
+ uintptr_t index = reinterpret_cast<uintptr_t>(it);
+ assert(index >= _refStartIndex);
+ assert(index < _refEndIndex);
+ assert(index < _file._references.size());
+ return &_file._references[index];
+ }
+
+ void incrementIterator(const void*& it) const {
+ uintptr_t index = reinterpret_cast<uintptr_t>(it);
+ ++index;
+ it = reinterpret_cast<const void*>(index);
+ }
+
+
+
+ void bindTargetReferences() const {
for (unsigned int i=_refStartIndex; i < _refEndIndex; ++i) {
const char* targetName = _file._references[i]._targetName;
Atom* targetAtom = _file.findAtom(targetName);
@@ -559,40 +595,9 @@
-
-bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {
- handler.doFile(*this);
- for (std::vector<YAMLDefinedAtom *>::const_iterator it = _definedAtoms.begin();
- it != _definedAtoms.end(); ++it) {
- handler.doDefinedAtom(**it);
- }
- for (std::vector<UndefinedAtom *>::const_iterator it = _undefinedAtoms.begin();
- it != _undefinedAtoms.end(); ++it) {
- handler.doUndefinedAtom(**it);
- }
- for (std::vector<SharedLibraryAtom *>::const_iterator
- it = _sharedLibraryAtoms.begin();
- it != _sharedLibraryAtoms.end(); ++it) {
- handler.doSharedLibraryAtom(**it);
- }
- for (std::vector<AbsoluteAtom *>::const_iterator
- it = _absoluteAtoms.begin();
- it != _absoluteAtoms.end(); ++it) {
- handler.doAbsoluteAtom(**it);
- }
-
- return true;
-}
-
-bool YAMLFile::justInTimeforEachAtom(llvm::StringRef name,
- File::AtomHandler &handler) const {
- return false;
-}
-
void YAMLFile::bindTargetReferences() {
- for (std::vector<YAMLDefinedAtom *>::const_iterator
- it = _definedAtoms.begin(); it != _definedAtoms.end(); ++it) {
- YAMLDefinedAtom* atom = *it;
+ for (defined_iterator it = definedAtomsBegin(); it != definedAtomsEnd(); ++it) {
+ const YAMLDefinedAtom* atom = reinterpret_cast<const YAMLDefinedAtom*>(*it);
atom->bindTargetReferences();
}
}
@@ -607,31 +612,31 @@
}
void YAMLFile::addDefinedAtom(YAMLDefinedAtom* atom, const char* refName) {
- _definedAtoms.push_back(atom);
+ _definedAtoms._atoms.push_back(atom);
assert(refName != NULL);
_nameToAtomMapping.push_back(NameAtomPair(refName, atom));
}
void YAMLFile::addUndefinedAtom(UndefinedAtom* atom) {
- _undefinedAtoms.push_back(atom);
+ _undefinedAtoms._atoms.push_back(atom);
_nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
}
void YAMLFile::addSharedLibraryAtom(SharedLibraryAtom* atom) {
- _sharedLibraryAtoms.push_back(atom);
+ _sharedLibraryAtoms._atoms.push_back(atom);
_nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
}
void YAMLFile::addAbsoluteAtom(AbsoluteAtom* atom) {
- _absoluteAtoms.push_back(atom);
+ _absoluteAtoms._atoms.push_back(atom);
_nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
}
class YAMLAtomState {
public:
- YAMLAtomState();
-
+ YAMLAtomState(Platform& platform);
+
void setName(const char *n);
void setRefName(const char *n);
void setAlign2(const char *n);
@@ -642,6 +647,7 @@
void makeAtom(YAMLFile&);
+ Platform& _platform;
const char * _name;
const char * _refName;
const char * _sectionName;
@@ -666,8 +672,9 @@
};
-YAMLAtomState::YAMLAtomState()
- : _name(NULL)
+YAMLAtomState::YAMLAtomState(Platform& platform)
+ : _platform(platform)
+ , _name(NULL)
, _refName(NULL)
, _sectionName(NULL)
, _loadName(NULL)
@@ -764,15 +771,7 @@
void YAMLAtomState::setFixupKind(const char *s) {
- if (strcmp(s, "pcrel32") == 0)
- _ref._kind = 1;
- else if (strcmp(s, "call32") == 0)
- _ref._kind = 2;
- else {
- int k;
- llvm::StringRef(s).getAsInteger(10, k);
- _ref._kind = k;
- }
+ _ref._kind = _platform.kindFromString(llvm::StringRef(s));
}
void YAMLAtomState::setFixupTarget(const char *s) {
@@ -800,12 +799,13 @@
/// parseObjectText - Parse the specified YAML formatted MemoryBuffer
/// into lld::File object(s) and append each to the specified vector<File*>.
llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
- , std::vector<File *> &result) {
+ , Platform& platform
+ , std::vector<const File *> &result) {
std::vector<const YAML::Entry *> entries;
YAML::parse(mb, entries);
YAMLFile *file = NULL;
- YAMLAtomState atomState;
+ YAMLAtomState atomState(platform);
bool inAtoms = false;
bool inFixups = false;
int depthForAtoms = -1;
@@ -985,13 +985,14 @@
// Fill in vector<File*> from path to input text file.
//
llvm::error_code parseObjectTextFileOrSTDIN(llvm::StringRef path
- , std::vector<File*>& result) {
+ , Platform& platform
+ , std::vector<const File*>& result) {
llvm::OwningPtr<llvm::MemoryBuffer> mb;
llvm::error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb);
if ( ec )
return ec;
- return parseObjectText(mb.get(), result);
+ return parseObjectText(mb.get(), platform, result);
}
Modified: lld/trunk/lib/Core/YamlWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlWriter.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlWriter.cpp (original)
+++ lld/trunk/lib/Core/YamlWriter.cpp Wed Mar 7 18:18:30 2012
@@ -14,6 +14,8 @@
#include "lld/Core/File.h"
#include "lld/Core/Reference.h"
+#include "lld/Platform/Platform.h"
+
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringExtras.h"
@@ -41,44 +43,50 @@
/// In that case referencing the function by name is ambiguous, so a unique
/// ref-name is added.
///
-class RefNameBuilder : public File::AtomHandler,
- public DefinedAtom::ReferenceHandler {
+class RefNameBuilder {
public:
- RefNameBuilder() { }
-
- virtual void doReference(const Reference& ref) {
- // create refname for any unnamed reference target
- if ( ref.target()->name().empty() ) {
- char* buffer;
- asprintf(&buffer, "L%03d", _unnamedCounter++);
- _refNames[ref.target()] = buffer;
+ RefNameBuilder(const File& file)
+ : _collisionCount(0), _unnamedCounter(0) {
+ // visit all atoms
+ for(File::defined_iterator it=file.definedAtomsBegin(),
+ end=file.definedAtomsEnd();
+ it != end; ++it) {
+ const DefinedAtom* atom = *it;
+ // Build map of atoms names to detect duplicates
+ if ( ! atom->name().empty() )
+ buildDuplicateNameMap(*atom);
+
+ // Find references to unnamed atoms and create ref-names for them.
+ for (auto rit=atom->referencesBegin(), rend=atom->referencesEnd();
+ rit != rend; ++rit) {
+ const Reference* ref = *rit;
+ // create refname for any unnamed reference target
+ if ( ref->target()->name().empty() ) {
+ char* buffer;
+ asprintf(&buffer, "L%03d", _unnamedCounter++);
+ _refNames[ref->target()] = buffer;
+ }
+ }
+ }
+ for(File::undefined_iterator it=file.undefinedAtomsBegin(),
+ end=file.undefinedAtomsEnd();
+ it != end; ++it) {
+ buildDuplicateNameMap(**it);
+ }
+ for(File::shared_library_iterator it=file.sharedLibraryAtomsBegin(),
+ end=file.sharedLibraryAtomsEnd();
+ it != end; ++it) {
+ buildDuplicateNameMap(**it);
+ }
+ for(File::absolute_iterator it=file.absoluteAtomsBegin(),
+ end=file.absoluteAtomsEnd();
+ it != end; ++it) {
+ buildDuplicateNameMap(**it);
}
- }
- virtual void doFile(const File &) { }
-
- virtual void doDefinedAtom(const DefinedAtom& atom) {
- // Build map of atoms names to detect duplicates
- if ( ! atom.name().empty() )
- buildDuplicateNameMap(atom);
-
- // Find references to unnamed atoms and create ref-names for them.
- _unnamedCounter = 0;
- atom.forEachReference(*this);
- }
-
- virtual void doUndefinedAtom(const UndefinedAtom& atom) {
- buildDuplicateNameMap(atom);
- }
- virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) {
- buildDuplicateNameMap(atom);
- }
-
- virtual void doAbsoluteAtom(const AbsoluteAtom& atom) {
- buildDuplicateNameMap(atom);
}
-
+
void buildDuplicateNameMap(const Atom& atom) {
assert(!atom.name().empty());
NameToAtom::iterator pos = _nameMap.find(atom.name());
@@ -131,27 +139,55 @@
///
/// Helper class for writeObjectText() to write out atoms in yaml format.
///
-class AtomWriter : public File::AtomHandler,
- public DefinedAtom::ReferenceHandler {
+class AtomWriter {
public:
- AtomWriter(RefNameBuilder& rnb, llvm::raw_ostream &out)
- : _out(out), _rnb(rnb), _firstAtom(true) { }
+ AtomWriter(const File& file, Platform& platform, RefNameBuilder& rnb)
+ : _file(file), _platform(platform), _rnb(rnb), _firstAtom(true) { }
+
+
+ void write(llvm::raw_ostream& out) {
+ // write header
+ out << "---\n";
+
+ // visit all atoms
+ for(File::defined_iterator it=_file.definedAtomsBegin(),
+ end=_file.definedAtomsEnd();
+ it != end; ++it) {
+ writeDefinedAtom(**it, out);
+ }
+ for(File::undefined_iterator it=_file.undefinedAtomsBegin(),
+ end=_file.undefinedAtomsEnd();
+ it != end; ++it) {
+ writeUndefinedAtom(**it, out);
+ }
+ for(File::shared_library_iterator it=_file.sharedLibraryAtomsBegin(),
+ end=_file.sharedLibraryAtomsEnd();
+ it != end; ++it) {
+ writeSharedLibraryAtom(**it, out);
+ }
+ for(File::absolute_iterator it=_file.absoluteAtomsBegin(),
+ end=_file.absoluteAtomsEnd();
+ it != end; ++it) {
+ writeAbsoluteAtom(**it, out);
+ }
+
+ out << "...\n";
+ }
- virtual void doFile(const class File &) { _firstAtom = true; }
- virtual void doDefinedAtom(const class DefinedAtom &atom) {
+ void writeDefinedAtom(const DefinedAtom &atom, llvm::raw_ostream& out) {
if ( _firstAtom ) {
- _out << "atoms:\n";
+ out << "atoms:\n";
_firstAtom = false;
}
else {
// add blank line between atoms for readability
- _out << "\n";
+ out << "\n";
}
bool hasDash = false;
if ( !atom.name().empty() ) {
- _out << " - "
+ out << " - "
<< KeyValues::nameKeyword
<< ":"
<< spacePadding(KeyValues::nameKeyword)
@@ -161,7 +197,7 @@
}
if ( _rnb.hasRefName(&atom) ) {
- _out << (hasDash ? " " : " - ")
+ out << (hasDash ? " " : " - ")
<< KeyValues::refNameKeyword
<< ":"
<< spacePadding(KeyValues::refNameKeyword)
@@ -171,7 +207,7 @@
}
if ( atom.definition() != KeyValues::definitionDefault ) {
- _out << (hasDash ? " " : " - ")
+ out << (hasDash ? " " : " - ")
<< KeyValues::definitionKeyword
<< ":"
<< spacePadding(KeyValues::definitionKeyword)
@@ -181,7 +217,7 @@
}
if ( atom.scope() != KeyValues::scopeDefault ) {
- _out << (hasDash ? " " : " - ")
+ out << (hasDash ? " " : " - ")
<< KeyValues::scopeKeyword
<< ":"
<< spacePadding(KeyValues::scopeKeyword)
@@ -191,7 +227,7 @@
}
if ( atom.interposable() != KeyValues::interposableDefault ) {
- _out << " "
+ out << " "
<< KeyValues::interposableKeyword
<< ":"
<< spacePadding(KeyValues::interposableKeyword)
@@ -200,7 +236,7 @@
}
if ( atom.merge() != KeyValues::mergeDefault ) {
- _out << " "
+ out << " "
<< KeyValues::mergeKeyword
<< ":"
<< spacePadding(KeyValues::mergeKeyword)
@@ -209,7 +245,7 @@
}
if ( atom.contentType() != KeyValues::contentTypeDefault ) {
- _out << " "
+ out << " "
<< KeyValues::contentTypeKeyword
<< ":"
<< spacePadding(KeyValues::contentTypeKeyword)
@@ -218,7 +254,7 @@
}
if ( atom.deadStrip() != KeyValues::deadStripKindDefault ) {
- _out << " "
+ out << " "
<< KeyValues::deadStripKindKeyword
<< ":"
<< spacePadding(KeyValues::deadStripKindKeyword)
@@ -227,14 +263,14 @@
}
if ( atom.sectionChoice() != KeyValues::sectionChoiceDefault ) {
- _out << " "
+ out << " "
<< KeyValues::sectionChoiceKeyword
<< ":"
<< spacePadding(KeyValues::sectionChoiceKeyword)
<< KeyValues::sectionChoice(atom.sectionChoice())
<< "\n";
assert( ! atom.customSectionName().empty() );
- _out << " "
+ out << " "
<< KeyValues::sectionNameKeyword
<< ":"
<< spacePadding(KeyValues::sectionNameKeyword)
@@ -243,7 +279,7 @@
}
if ( atom.isThumb() != KeyValues::isThumbDefault ) {
- _out << " "
+ out << " "
<< KeyValues::isThumbKeyword
<< ":"
<< spacePadding(KeyValues::isThumbKeyword)
@@ -252,7 +288,7 @@
}
if ( atom.isAlias() != KeyValues::isAliasDefault ) {
- _out << " "
+ out << " "
<< KeyValues::isAliasKeyword
<< ":"
<< spacePadding(KeyValues::isAliasKeyword)
@@ -262,7 +298,7 @@
if ( (atom.contentType() != DefinedAtom::typeZeroFill)
&& (atom.size() != 0) ) {
- _out << " "
+ out << " "
<< KeyValues::contentKeyword
<< ":"
<< spacePadding(KeyValues::contentKeyword)
@@ -271,77 +307,77 @@
bool needComma = false;
for (unsigned int i=0; i < arr.size(); ++i) {
if ( needComma )
- _out << ", ";
- _out << hexdigit(arr[i] >> 4);
- _out << hexdigit(arr[i] & 0x0F);
+ out << ", ";
+ out << hexdigit(arr[i] >> 4);
+ out << hexdigit(arr[i] & 0x0F);
needComma = true;
}
- _out << " ]\n";
+ out << " ]\n";
}
- _wroteFirstFixup = false;
- atom.forEachReference(*this);
- }
-
- virtual void doReference(const Reference& ref) {
- if ( !_wroteFirstFixup ) {
- _out << " fixups:\n";
- _wroteFirstFixup = true;
- }
- _out << " - "
- << KeyValues::fixupsOffsetKeyword
- << ":"
- << spacePadding(KeyValues::fixupsOffsetKeyword)
- << ref.offsetInAtom()
- << "\n";
- _out << " "
- << KeyValues::fixupsKindKeyword
- << ":"
- << spacePadding(KeyValues::fixupsKindKeyword)
- << ref.kind()
- << "\n";
- const Atom* target = ref.target();
- if ( target != NULL ) {
- llvm::StringRef refName = target->name();
- if ( _rnb.hasRefName(target) )
- refName = _rnb.refName(target);
- assert(!refName.empty());
- _out << " "
- << KeyValues::fixupsTargetKeyword
- << ":"
- << spacePadding(KeyValues::fixupsTargetKeyword)
- << refName
- << "\n";
- }
- if ( ref.addend() != 0 ) {
- _out << " "
- << KeyValues::fixupsAddendKeyword
+ bool wroteFirstFixup = false;
+ for (auto it=atom.referencesBegin(), end=atom.referencesEnd();
+ it != end; ++it) {
+ const Reference* ref = *it;
+ if ( !wroteFirstFixup ) {
+ out << " fixups:\n";
+ wroteFirstFixup = true;
+ }
+ out << " - "
+ << KeyValues::fixupsOffsetKeyword
<< ":"
- << spacePadding(KeyValues::fixupsAddendKeyword)
- << ref.addend()
+ << spacePadding(KeyValues::fixupsOffsetKeyword)
+ << ref->offsetInAtom()
<< "\n";
+ out << " "
+ << KeyValues::fixupsKindKeyword
+ << ":"
+ << spacePadding(KeyValues::fixupsKindKeyword)
+ << _platform.kindToString(ref->kind())
+ << "\n";
+ const Atom* target = ref->target();
+ if ( target != NULL ) {
+ llvm::StringRef refName = target->name();
+ if ( _rnb.hasRefName(target) )
+ refName = _rnb.refName(target);
+ assert(!refName.empty());
+ out << " "
+ << KeyValues::fixupsTargetKeyword
+ << ":"
+ << spacePadding(KeyValues::fixupsTargetKeyword)
+ << refName
+ << "\n";
+ }
+ if ( ref->addend() != 0 ) {
+ out << " "
+ << KeyValues::fixupsAddendKeyword
+ << ":"
+ << spacePadding(KeyValues::fixupsAddendKeyword)
+ << ref->addend()
+ << "\n";
+ }
}
}
+
-
- virtual void doUndefinedAtom(const class UndefinedAtom &atom) {
+ void writeUndefinedAtom(const UndefinedAtom &atom, llvm::raw_ostream& out) {
if ( _firstAtom ) {
- _out << "atoms:\n";
+ out << "atoms:\n";
_firstAtom = false;
}
else {
// add blank line between atoms for readability
- _out << "\n";
+ out << "\n";
}
- _out << " - "
+ out << " - "
<< KeyValues::nameKeyword
<< ":"
<< spacePadding(KeyValues::nameKeyword)
<< atom.name()
<< "\n";
- _out << " "
+ out << " "
<< KeyValues::definitionKeyword
<< ":"
<< spacePadding(KeyValues::definitionKeyword)
@@ -349,7 +385,7 @@
<< "\n";
if ( atom.canBeNull() != KeyValues::canBeNullDefault ) {
- _out << " "
+ out << " "
<< KeyValues::canBeNullKeyword
<< ":"
<< spacePadding(KeyValues::canBeNullKeyword)
@@ -358,24 +394,24 @@
}
}
- virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) {
+ void writeSharedLibraryAtom(const SharedLibraryAtom& atom, llvm::raw_ostream& out) {
if ( _firstAtom ) {
- _out << "atoms:\n";
+ out << "atoms:\n";
_firstAtom = false;
}
else {
// add blank line between atoms for readability
- _out << "\n";
+ out << "\n";
}
- _out << " - "
+ out << " - "
<< KeyValues::nameKeyword
<< ":"
<< spacePadding(KeyValues::nameKeyword)
<< atom.name()
<< "\n";
- _out << " "
+ out << " "
<< KeyValues::definitionKeyword
<< ":"
<< spacePadding(KeyValues::definitionKeyword)
@@ -383,7 +419,7 @@
<< "\n";
if ( !atom.loadName().empty() ) {
- _out << " "
+ out << " "
<< KeyValues::loadNameKeyword
<< ":"
<< spacePadding(KeyValues::loadNameKeyword)
@@ -392,7 +428,7 @@
}
if ( atom.canBeNullAtRuntime() ) {
- _out << " "
+ out << " "
<< KeyValues::canBeNullKeyword
<< ":"
<< spacePadding(KeyValues::canBeNullKeyword)
@@ -401,37 +437,37 @@
}
}
- virtual void doAbsoluteAtom(const AbsoluteAtom& atom) {
+ void writeAbsoluteAtom(const AbsoluteAtom& atom, llvm::raw_ostream& out) {
if ( _firstAtom ) {
- _out << "atoms:\n";
+ out << "atoms:\n";
_firstAtom = false;
}
else {
// add blank line between atoms for readability
- _out << "\n";
+ out << "\n";
}
- _out << " - "
+ out << " - "
<< KeyValues::nameKeyword
<< ":"
<< spacePadding(KeyValues::nameKeyword)
<< atom.name()
<< "\n";
- _out << " "
+ out << " "
<< KeyValues::definitionKeyword
<< ":"
<< spacePadding(KeyValues::definitionKeyword)
<< KeyValues::definition(atom.definition())
<< "\n";
- _out << " "
+ out << " "
<< KeyValues::valueKeyword
<< ":"
<< spacePadding(KeyValues::valueKeyword)
<< "0x";
- _out.write_hex(atom.value());
- _out << "\n";
+ out.write_hex(atom.value());
+ out << "\n";
}
@@ -450,10 +486,10 @@
return 'A' + nibble - 0x0A;
}
- llvm::raw_ostream& _out;
- RefNameBuilder _rnb;
+ const File& _file;
+ Platform& _platform;
+ RefNameBuilder& _rnb;
bool _firstAtom;
- bool _wroteFirstFixup;
};
} // anonymous namespace
@@ -464,16 +500,14 @@
/// writeObjectText - writes the lld::File object as in YAML
/// format to the specified stream.
///
-void writeObjectText(const File &file, llvm::raw_ostream &out) {
+void writeObjectText(const File& file, Platform& platform,
+ llvm::raw_ostream &out) {
// Figure what ref-name labels are needed
- RefNameBuilder rnb;
- file.forEachAtom(rnb);
+ RefNameBuilder rnb(file);
// Write out all atoms
- AtomWriter h(rnb, out);
- out << "---\n";
- file.forEachAtom(h);
- out << "...\n";
+ AtomWriter writer(file, platform, rnb);
+ writer.write(out);
}
} // namespace yaml
Added: lld/trunk/lib/Passes/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Passes/CMakeLists.txt?rev=152269&view=auto
==============================================================================
--- lld/trunk/lib/Passes/CMakeLists.txt (added)
+++ lld/trunk/lib/Passes/CMakeLists.txt Wed Mar 7 18:18:30 2012
@@ -0,0 +1,3 @@
+add_lld_library(lldPasses
+ StubsPass.cpp
+ )
Added: lld/trunk/lib/Passes/StubsPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Passes/StubsPass.cpp?rev=152269&view=auto
==============================================================================
--- lld/trunk/lib/Passes/StubsPass.cpp (added)
+++ lld/trunk/lib/Passes/StubsPass.cpp Wed Mar 7 18:18:30 2012
@@ -0,0 +1,79 @@
+//===- 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 is
+//
+//
+//
+//
+
+
+#include "llvm/ADT/DenseMap.h"
+
+#include "lld/Core/Pass.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+#include "lld/Platform/Platform.h"
+
+
+namespace lld {
+
+void StubsPass::perform() {
+ // Skip this pass if output format does not need stubs.
+ if ( !_platform.outputUsesStubs() )
+ return;
+
+ // Use map so all call sites to same shlib symbol use same stub
+ llvm::DenseMap<const SharedLibraryAtom*, const Atom*> shlibToStub;
+
+ // Scan all references in all atoms.
+ for(auto ait=_file.definedAtomsBegin(), aend=_file.definedAtomsEnd();
+ ait != aend; ++ait) {
+ const DefinedAtom* atom = *ait;
+ for (auto rit=atom->referencesBegin(), rend=atom->referencesEnd();
+ rit != rend; ++rit) {
+ const Reference* ref = *rit;
+ const Atom* target = ref->target();
+ assert(target != NULL);
+ // If the target of this reference is in a shared library
+ if ( const SharedLibraryAtom* shlbTarget = target->sharedLibraryAtom() ) {
+ // and this is a call to that shared library symbol.
+ if ( _platform.isBranch(ref) ) {
+ const Atom* stub;
+ // Replace the target with a reference to a stub
+ auto pos = shlibToStub.find(shlbTarget);
+ if ( pos == shlibToStub.end() ) {
+ // This is no existing stub. Create a new one.
+ stub = _platform.makeStub(*shlbTarget, _file);
+ shlibToStub[shlbTarget] = stub;
+ }
+ else {
+ // Reuse and existing stub
+ stub = pos->second;
+ }
+ assert(stub != NULL);
+ // Switch call site in atom to refrence stub instead of shlib atom.
+ (const_cast<Reference*>(ref))->setTarget(stub);
+ }
+ }
+ }
+ }
+
+ // add all created stubs to file
+ for (auto it=shlibToStub.begin(), end=shlibToStub.end(); it != end; ++it) {
+ _file.addAtom(*it->second);
+ }
+
+
+}
+
+
+
+}
Added: lld/trunk/test/pass-stubs-basic.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pass-stubs-basic.objtxt?rev=152269&view=auto
==============================================================================
--- lld/trunk/test/pass-stubs-basic.objtxt (added)
+++ lld/trunk/test/pass-stubs-basic.objtxt Wed Mar 7 18:18:30 2012
@@ -0,0 +1,50 @@
+# RUN: lld-core %s -stubs_pass | FileCheck %s
+
+#
+# Test that stubs pass adds stubs and rebinds call sites to the stub
+#
+
+---
+atoms:
+ - name: foo
+ type: code
+ content: [ E8, 00, 00, 00, 00, E8, 00, 00, 00,
+ 00, 48 ,8B, 05, 00, 00, 00, 00 ]
+ fixups:
+ - offset: 1
+ kind: call32
+ target: malloc
+ - offset: 6
+ kind: call32
+ target: free
+ - offset: 13
+ kind: gotLoad32
+ target: malloc
+
+ - name: malloc
+ definition: shared-library
+ load-name: libc.so
+
+ - name: free
+ definition: shared-library
+ load-name: libc.so
+
+...
+
+# CHECK: name: foo
+# CHECK: fixups:
+# CHECK: kind: call32
+# CHECK: target: L
+# CHECK: kind: call32
+# CHECK: target: L
+# CHECK: kind: gotLoad32
+# CHECK: target: malloc
+# CHECK: name: L
+# CHECK: type: stub
+# CHECK: name: L
+# CHECK: type: stub
+# CHECK: name: malloc
+# CHECK: definition: shared-library
+# CHECK: name: free
+# CHECK: definition: shared-library
+# CHECK: ...
Modified: lld/trunk/tools/lld-core/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/CMakeLists.txt?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/CMakeLists.txt (original)
+++ lld/trunk/tools/lld-core/CMakeLists.txt Wed Mar 7 18:18:30 2012
@@ -1,5 +1,6 @@
set(LLVM_USED_LIBS
lldCore
+ lldPasses
)
set(LLVM_LINK_COMPONENTS
Modified: lld/trunk/tools/lld-core/lld-core.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/lld-core.cpp?rev=152269&r1=152268&r2=152269&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/lld-core.cpp (original)
+++ lld/trunk/tools/lld-core/lld-core.cpp Wed Mar 7 18:18:30 2012
@@ -11,6 +11,7 @@
#include "lld/Core/Atom.h"
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/Pass.h"
#include "lld/Core/Resolver.h"
#include "lld/Core/YamlReader.h"
#include "lld/Core/YamlWriter.h"
@@ -22,6 +23,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -49,15 +51,110 @@
}
namespace {
-class LdCore : public InputFiles, public Platform {
+
+
+//
+// Simple atoms created by the stubs pass.
+//
+class TestingStubAtom : public DefinedAtom {
public:
- LdCore(std::vector<File *> &f) : _files(f) { }
+ TestingStubAtom(const File& f, const SharedLibraryAtom& shlib) :
+ _file(f), _shlib(shlib) {
+ static uint32_t lastOrdinal = 0;
+ _ordinal = lastOrdinal++;
+ }
- // InputFiles interface
- virtual void forEachInitialAtom(File::AtomHandler &) const;
- virtual bool searchLibraries(llvm::StringRef name, bool searchDylibs,
- bool searchArchives, bool dataSymbolOnly,
- File::AtomHandler &) const;
+ virtual const File& file() const {
+ return _file;
+ }
+
+ virtual llvm::StringRef name() const {
+ return llvm::StringRef();
+ }
+
+ virtual uint64_t ordinal() const {
+ return _ordinal;
+ }
+
+ virtual uint64_t size() const {
+ return 0;
+ }
+
+ virtual Scope scope() const {
+ return DefinedAtom::scopeLinkageUnit;
+ }
+
+ virtual Interposable interposable() const {
+ return DefinedAtom::interposeNo;
+ }
+
+ virtual Merge merge() const {
+ return DefinedAtom::mergeNo;
+ }
+
+ virtual ContentType contentType() const {
+ return DefinedAtom::typeStub;
+ }
+
+ virtual Alignment alignment() const {
+ return Alignment(0,0);
+ }
+
+ virtual SectionChoice sectionChoice() const {
+ return DefinedAtom::sectionBasedOnContent;
+ }
+
+ virtual llvm::StringRef customSectionName() const {
+ return llvm::StringRef();
+ }
+ virtual DeadStripKind deadStrip() const {
+ return DefinedAtom::deadStripNormal;
+ }
+
+ virtual ContentPermissions permissions() const {
+ return DefinedAtom::permR_X;
+ }
+
+ virtual bool isThumb() const {
+ return false;
+ }
+
+ virtual bool isAlias() const {
+ return false;
+ }
+
+ virtual llvm::ArrayRef<uint8_t> rawContent() const {
+ return llvm::ArrayRef<uint8_t>();
+ }
+
+ virtual reference_iterator referencesBegin() const {
+ return reference_iterator(*this, NULL);
+ }
+
+ virtual reference_iterator referencesEnd() const {
+ return reference_iterator(*this, NULL);
+ }
+
+ virtual const Reference* derefIterator(const void* iter) const {
+ return NULL;
+ }
+
+ virtual void incrementIterator(const void*& iter) const {
+
+ }
+
+private:
+ const File& _file;
+ const SharedLibraryAtom& _shlib;
+ uint32_t _ordinal;
+};
+
+
+//
+// A simple platform for testing.
+//
+class TestingPlatform : public Platform {
+public:
virtual void initialize() { }
@@ -155,97 +252,163 @@
// last chance for platform to tweak atoms
virtual void postResolveTweaks(std::vector<const Atom *> &all) {}
-private:
- std::vector<File *> &_files;
-};
-}
+ virtual bool outputUsesStubs() { return true; };
+
+
+ struct KindMapping {
+ const char* string;
+ Reference::Kind value;
+ bool isBranch;
+ };
-void LdCore::forEachInitialAtom(File::AtomHandler &handler) const {
- for (std::vector<File *>::iterator it = _files.begin();
- it != _files.end(); ++it) {
- const File *file = *it;
- handler.doFile(*file);
- file->forEachAtom(handler);
+ static const KindMapping _s_kindMappings[];
+
+ virtual Reference::Kind kindFromString(llvm::StringRef kindName) {
+ for (const KindMapping* p = _s_kindMappings; p->string != NULL; ++p) {
+ if ( kindName.equals(p->string) )
+ return p->value;
+ }
+ int k;
+ kindName.getAsInteger(0, k);
+ return k;
+ }
+
+ virtual llvm::StringRef kindToString(Reference::Kind value) {
+ for (const KindMapping* p = _s_kindMappings; p->string != NULL; ++p) {
+ if ( value == p->value)
+ return p->string;
+ }
+ return llvm::StringRef("???");
}
-}
-bool LdCore::searchLibraries(llvm::StringRef name, bool searchDylibs,
- bool searchArchives, bool dataSymbolOnly,
- File::AtomHandler &) const {
- return false;
-}
-namespace {
-class MergedFile : public File {
+ virtual bool isBranch(const Reference* ref) {
+ Reference::Kind value = ref->kind();
+ for (const KindMapping* p = _s_kindMappings; p->string != NULL; ++p) {
+ if ( value == p->value )
+ return p->isBranch;
+ }
+ return false;
+ }
+
+ virtual const Atom* makeStub(const SharedLibraryAtom& shlibAtom, File& file) {
+ return new TestingStubAtom(file, shlibAtom);
+ }
+};
+
+
+//
+// Table of fixup kinds in YAML documents used for testing
+//
+const TestingPlatform::KindMapping TestingPlatform::_s_kindMappings[] = {
+ { "call32", 1, true },
+ { "pcrel32", 2, false },
+ { "gotLoad32", 3, false },
+ { NULL, 0, false }
+ };
+
+
+//
+// A simple input files wrapper for testing.
+//
+class TestingInputFiles : public InputFiles {
public:
- MergedFile(std::vector<const Atom *> &a)
- : File("path"), _atoms(a) { }
+ TestingInputFiles(std::vector<const File*>& f) : _files(f) { }
- virtual bool forEachAtom(File::AtomHandler &handler) const {
- handler.doFile(*this);
- // visit defined atoms
- for (std::vector<const Atom *>::iterator it = _atoms.begin();
- it != _atoms.end(); ++it) {
- const DefinedAtom* atom = (*it)->definedAtom();
- if ( atom )
- handler.doDefinedAtom(*atom);
- }
- // visit undefined atoms
- for (std::vector<const Atom *>::iterator it = _atoms.begin();
- it != _atoms.end(); ++it) {
- const UndefinedAtom* atom = (*it)->undefinedAtom();
- if ( atom )
- handler.doUndefinedAtom(*atom);
- }
- // visit shared library atoms
- for (std::vector<const Atom *>::iterator it = _atoms.begin();
- it != _atoms.end(); ++it) {
- const SharedLibraryAtom* atom = (*it)->sharedLibraryAtom();
- if ( atom )
- handler.doSharedLibraryAtom(*atom);
- }
- // visit absolute atoms
- for (std::vector<const Atom *>::iterator it = _atoms.begin();
- it != _atoms.end(); ++it) {
- const AbsoluteAtom* atom = (*it)->absoluteAtom();
- if ( atom )
- handler.doAbsoluteAtom(*atom);
+ // InputFiles interface
+ virtual void forEachInitialAtom(InputFiles::Handler& handler) const {
+ for (std::vector<const File *>::iterator fit = _files.begin();
+ fit != _files.end(); ++fit) {
+ const File* file = *fit;
+ handler.doFile(*file);
+ for(auto it=file->definedAtomsBegin(),end=file->definedAtomsEnd();
+ it != end; ++it) {
+ handler.doDefinedAtom(**it);
+ }
+ for(auto it=file->undefinedAtomsBegin(), end=file->undefinedAtomsEnd();
+ it != end; ++it) {
+ handler.doUndefinedAtom(**it);
+ }
+ for(auto it=file->sharedLibraryAtomsBegin(), end=file->sharedLibraryAtomsEnd();
+ it != end; ++it) {
+ handler.doSharedLibraryAtom(**it);
+ }
+ for(auto it=file->absoluteAtomsBegin(),end=file->absoluteAtomsEnd();
+ it != end; ++it) {
+ handler.doAbsoluteAtom(**it);
+ }
}
- return true;
}
- virtual bool justInTimeforEachAtom(llvm::StringRef name,
- File::AtomHandler &) const {
+ virtual bool searchLibraries(llvm::StringRef name, bool searchDylibs,
+ bool searchArchives, bool dataSymbolOnly,
+ InputFiles::Handler &) const {
return false;
}
+
private:
- std::vector<const Atom *> &_atoms;
+ std::vector<const File*>& _files;
};
-} //anonymous namespace
+}
+
+
+
-int main(int argc, const char *argv[]) {
+
+llvm::cl::opt<std::string>
+gInputFilePath(llvm::cl::Positional,
+ llvm::cl::desc("<input file>"),
+ llvm::cl::init("-"));
+
+llvm::cl::opt<std::string>
+gOutputFilePath("o",
+ llvm::cl::desc("Specify output filename"),
+ llvm::cl::value_desc("filename"));
+
+llvm::cl::opt<bool>
+gDoStubsPass("stubs_pass",
+ llvm::cl::desc("Run pass to create stub atoms"));
+
+
+int main(int argc, char *argv[]) {
// Print a stack trace if we signal out.
llvm::sys::PrintStackTraceOnErrorSignal();
llvm::PrettyStackTraceProgram X(argc, argv);
llvm::llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ // parse options
+ llvm::cl::ParseCommandLineOptions(argc, argv);
+
+ // create platform for testing
+ TestingPlatform testingPlatform;
+
// read input YAML doc into object file(s)
- std::vector<File *> files;
- if (error(yaml::parseObjectTextFileOrSTDIN(llvm::StringRef(argv[1]), files)))
+ std::vector<const File *> files;
+ if (error(yaml::parseObjectTextFileOrSTDIN(gInputFilePath,
+ testingPlatform, files))) {
return 1;
-
+ }
+
+ // create object to mange input files
+ TestingInputFiles inputFiles(files);
+
// merge all atom graphs
- LdCore core(files);
- Resolver resolver(core, core);
- std::vector<const Atom *> &mergedAtoms = resolver.resolve();
- MergedFile outFile(mergedAtoms);
+ Resolver resolver(testingPlatform, inputFiles);
+ resolver.resolve();
+ // run passes
+ if ( gDoStubsPass ) {
+ StubsPass addStubs(resolver.resultFile(), testingPlatform);
+ addStubs.perform();
+ }
+
// write new atom graph out as YAML doc
std::string errorInfo;
- llvm::raw_fd_ostream out("-", errorInfo);
-// yaml::writeObjectText(outFile, out);
+ const char* outPath = gOutputFilePath.empty() ? "-" : gOutputFilePath.c_str();
+ llvm::raw_fd_ostream out(outPath, errorInfo);
+// yaml::writeObjectText(resolver.resultFile(), out);
// make unique temp .o file to put generated object file
int fd;
@@ -254,7 +417,7 @@
llvm::raw_fd_ostream binaryOut(fd, /*shouldClose=*/true);
// write native file
- writeNativeObjectFile(outFile, binaryOut);
+ writeNativeObjectFile(resolver.resultFile(), binaryOut);
binaryOut.close(); // manually close so that file can be read next
// out << "native file: " << tempPath.str() << "\n";
@@ -265,7 +428,7 @@
return 1;
// write new atom graph out as YAML doc
- yaml::writeObjectText(*natFile, out);
+ yaml::writeObjectText(*natFile, testingPlatform, out);
// delete temp .o file
bool existed;
More information about the llvm-commits
mailing list