From 2bc24928d36531aeea52c6563a125adb22c203bf Mon Sep 17 00:00:00 2001 From: Shankar Easwaran Date: Tue, 29 Oct 2013 05:12:14 +0000 Subject: [PATCH] [PassManager] add ReaderWriter{Native,YAML} to the Driver. Enable this for the following flavors a) core b) gnu c) darwin Its disabled for the flavor PECOFF. Convenient markers are added with FIXME comments in the Driver that would be removed and code removed from each flavor. llvm-svn: 193585 --- lld/include/lld/Core/LinkingContext.h | 2 +- lld/include/lld/Core/Pass.h | 6 +-- lld/include/lld/Core/PassManager.h | 2 +- lld/include/lld/Core/Resolver.h | 11 +++-- lld/include/lld/Passes/LayoutPass.h | 2 +- lld/include/lld/Passes/RoundTripNativePass.h | 41 +++++++++++++++++ lld/include/lld/Passes/RoundTripYAMLPass.h | 41 +++++++++++++++++ .../lld/ReaderWriter/CoreLinkingContext.h | 2 +- .../lld/ReaderWriter/ELFLinkingContext.h | 2 +- .../lld/ReaderWriter/MachOLinkingContext.h | 2 +- .../lld/ReaderWriter/PECOFFLinkingContext.h | 2 +- lld/include/lld/ReaderWriter/Simple.h | 20 ++++++++- lld/lib/Core/LinkingContext.cpp | 2 +- lld/lib/Core/PassManager.cpp | 2 +- lld/lib/Core/Resolver.cpp | 2 +- lld/lib/Driver/Driver.cpp | 14 +++++- lld/lib/Passes/CMakeLists.txt | 4 ++ lld/lib/Passes/GOTPass.cpp | 6 +-- lld/lib/Passes/LayoutPass.cpp | 7 ++- lld/lib/Passes/RoundTripNativePass.cpp | 44 +++++++++++++++++++ lld/lib/Passes/RoundTripYAMLPass.cpp | 43 ++++++++++++++++++ lld/lib/Passes/StubsPass.cpp | 6 +-- lld/lib/ReaderWriter/CoreLinkingContext.cpp | 13 ++++-- lld/lib/ReaderWriter/ELF/ArrayOrderPass.cpp | 4 +- lld/lib/ReaderWriter/ELF/ArrayOrderPass.h | 2 +- .../ReaderWriter/ELF/ELFLinkingContext.cpp | 8 +++- .../ELF/Hexagon/HexagonLinkingContext.h | 2 +- .../ELF/Hexagon/HexagonTargetHandler.cpp | 16 +++---- .../ELF/PPC/PPCLinkingContext.cpp | 3 +- .../ELF/X86_64/X86_64LinkingContext.cpp | 3 +- .../ELF/X86_64/X86_64LinkingContext.h | 2 +- .../ELF/X86_64/X86_64RelocationPass.cpp | 18 ++++---- .../MachO/MachOLinkingContext.cpp | 8 +++- .../ReaderWriter/PECOFF/GroupedSectionsPass.h | 6 +-- lld/lib/ReaderWriter/PECOFF/IdataPass.h | 8 ++-- .../PECOFF/PECOFFLinkingContext.cpp | 2 +- lld/test/elf/roundtrip.test | 9 ++++ 37 files changed, 297 insertions(+), 70 deletions(-) create mode 100644 lld/include/lld/Passes/RoundTripNativePass.h create mode 100644 lld/include/lld/Passes/RoundTripYAMLPass.h create mode 100644 lld/lib/Passes/RoundTripNativePass.cpp create mode 100644 lld/lib/Passes/RoundTripYAMLPass.cpp create mode 100644 lld/test/elf/roundtrip.test diff --git a/lld/include/lld/Core/LinkingContext.h b/lld/include/lld/Core/LinkingContext.h index 255e65954863..c617a22d6b26 100644 --- a/lld/include/lld/Core/LinkingContext.h +++ b/lld/include/lld/Core/LinkingContext.h @@ -293,7 +293,7 @@ public: /// This method is called by core linking to build the list of Passes to be /// run on the merged/linked graph of all input files. - virtual void addPasses(PassManager &pm) const; + virtual void addPasses(PassManager &pm); /// Calls through to the writeFile() method on the specified Writer. /// diff --git a/lld/include/lld/Core/Pass.h b/lld/include/lld/Core/Pass.h index 147162a66747..6d4b6a5cc268 100644 --- a/lld/include/lld/Core/Pass.h +++ b/lld/include/lld/Core/Pass.h @@ -36,7 +36,7 @@ public: virtual ~Pass() { } /// Do the actual work of the Pass. - virtual void perform(MutableFile &mergedFile) = 0; + virtual void perform(std::unique_ptr &mergedFile) = 0; protected: // Only subclassess can be instantiated. @@ -53,7 +53,7 @@ public: /// Scans all Atoms looking for call-site uses of SharedLibraryAtoms /// and transfroms the call-site to call a stub instead using the /// helper methods below. - virtual void perform(MutableFile &mergedFile); + virtual void perform(std::unique_ptr &mergedFile); /// If true, the pass should use stubs for references /// to shared library symbols. If false, the pass @@ -87,7 +87,7 @@ public: /// Scans all Atoms looking for pointer to SharedLibraryAtoms /// and transfroms them to a pointer to a GOT entry using the /// helper methods below. - virtual void perform(MutableFile &mergedFile); + virtual void perform(std::unique_ptr &mergedFile); /// If true, the pass will use GOT entries for references /// to shared library symbols. If false, the pass diff --git a/lld/include/lld/Core/PassManager.h b/lld/include/lld/Core/PassManager.h index 98a22512f262..2ed7a84db400 100644 --- a/lld/include/lld/Core/PassManager.h +++ b/lld/include/lld/Core/PassManager.h @@ -32,7 +32,7 @@ public: _passes.push_back(std::move(pass)); } - ErrorOr runOnFile(MutableFile &); + ErrorOr runOnFile(std::unique_ptr &); private: /// \brief Passes in the order they should run. diff --git a/lld/include/lld/Core/Resolver.h b/lld/include/lld/Core/Resolver.h index 7ffd3523b507..bb19f14e2507 100644 --- a/lld/include/lld/Core/Resolver.h +++ b/lld/include/lld/Core/Resolver.h @@ -37,8 +37,9 @@ public: }; Resolver(LinkingContext &context) - : _context(context), _symbolTable(context), _result(context), - _haveLLVMObjs(false), _addToFinalSection(false) {} + : _context(context), _symbolTable(context), + _result(new MergedFile(context)), _haveLLVMObjs(false), + _addToFinalSection(false) {} virtual ~Resolver() {} @@ -62,9 +63,7 @@ public: /// @brief do work of merging and resolving and return list bool resolve(); - MutableFile& resultFile() { - return _result; - } + std::unique_ptr resultFile() { return std::move(_result); } private: @@ -117,7 +116,7 @@ private: std::set _deadStripRoots; std::vector _atomsWithUnresolvedReferences; llvm::DenseSet _liveAtoms; - MergedFile _result; + std::unique_ptr _result; bool _haveLLVMObjs; bool _addToFinalSection; }; diff --git a/lld/include/lld/Passes/LayoutPass.h b/lld/include/lld/Passes/LayoutPass.h index 39a9b49f2085..bbd277f488f7 100644 --- a/lld/include/lld/Passes/LayoutPass.h +++ b/lld/include/lld/Passes/LayoutPass.h @@ -48,7 +48,7 @@ public: LayoutPass() : Pass(), _compareAtoms(*this) {} /// Sorts atoms in mergedFile by content type then by command line order. - virtual void perform(MutableFile &mergedFile); + virtual void perform(std::unique_ptr &mergedFile); virtual ~LayoutPass() {} diff --git a/lld/include/lld/Passes/RoundTripNativePass.h b/lld/include/lld/Passes/RoundTripNativePass.h new file mode 100644 index 000000000000..0d562ed58e1b --- /dev/null +++ b/lld/include/lld/Passes/RoundTripNativePass.h @@ -0,0 +1,41 @@ +//===--Passes/RoundTripNativePass.h - Write Native file/Read it back------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_PASSES_ROUND_TRIP_NATIVE_PASS_H +#define LLD_PASSES_ROUND_TRIP_NATIVE_PASS_H + +#include "lld/Core/File.h" +#include "lld/Core/LinkingContext.h" +#include "lld/Core/Pass.h" + +#include +#include + +namespace lld { +class RoundTripNativePass : public Pass { +public: + RoundTripNativePass(LinkingContext &context) : Pass(), _context(context) {} + + /// Writes to a native file and reads the atoms from the native file back. + /// Replaces mergedFile with the contents of the native File. + virtual void perform(std::unique_ptr &mergedFile); + + virtual ~RoundTripNativePass() {} + +private: + LinkingContext &_context; + // Keep the parsed file alive for the rest of the link. All atoms + // that are created by the RoundTripNativePass are owned by the + // nativeFile. + std::vector > _nativeFile; +}; + +} // namespace lld + +#endif // LLD_PASSES_ROUND_TRIP_NATIVE_PASS_H diff --git a/lld/include/lld/Passes/RoundTripYAMLPass.h b/lld/include/lld/Passes/RoundTripYAMLPass.h new file mode 100644 index 000000000000..772bc79455eb --- /dev/null +++ b/lld/include/lld/Passes/RoundTripYAMLPass.h @@ -0,0 +1,41 @@ +//===--Passes/RoundTripYAMLPass.h- Write YAML file/Read it back-----------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_PASSES_ROUND_TRIP_YAML_PASS_H +#define LLD_PASSES_ROUND_TRIP_YAML_PASS_H + +#include "lld/Core/File.h" +#include "lld/Core/LinkingContext.h" +#include "lld/Core/Pass.h" + +#include +#include + +namespace lld { +class RoundTripYAMLPass : public Pass { +public: + RoundTripYAMLPass(LinkingContext &context) : Pass(), _context(context) {} + + /// Writes to a YAML file and reads the atoms from the YAML file back. + /// Replaces the mergedFile with new contents. + virtual void perform(std::unique_ptr &mergedFile); + + virtual ~RoundTripYAMLPass() {} + +private: + LinkingContext &_context; + // Keep the parsed file alive for the rest of the link. All atoms + // that are created by the RoundTripYAMLPass are owned by the + // yamlFile. + std::vector > _yamlFile; +}; + +} // namespace lld + +#endif // LLD_PASSES_ROUND_TRIP_YAML_PASS_H diff --git a/lld/include/lld/ReaderWriter/CoreLinkingContext.h b/lld/include/lld/ReaderWriter/CoreLinkingContext.h index 9f6fcdd05745..3b74d3ab8fb1 100644 --- a/lld/include/lld/ReaderWriter/CoreLinkingContext.h +++ b/lld/include/lld/ReaderWriter/CoreLinkingContext.h @@ -23,7 +23,7 @@ public: CoreLinkingContext(); virtual bool validateImpl(raw_ostream &diagnostics); - virtual void addPasses(PassManager &pm) const; + virtual void addPasses(PassManager &pm); virtual ErrorOr relocKindFromString(StringRef str) const; virtual ErrorOr stringFromRelocKind(Reference::Kind kind) const; diff --git a/lld/include/lld/ReaderWriter/ELFLinkingContext.h b/lld/include/lld/ReaderWriter/ELFLinkingContext.h index 9a244300ccda..458ded2a0e06 100644 --- a/lld/include/lld/ReaderWriter/ELFLinkingContext.h +++ b/lld/include/lld/ReaderWriter/ELFLinkingContext.h @@ -130,7 +130,7 @@ public: return static_cast &>(*_targetHandler.get()); } - virtual void addPasses(PassManager &pm) const; + virtual void addPasses(PassManager &pm); void setTriple(llvm::Triple trip) { _triple = trip; } void setNoInhibitExec(bool v) { _noInhibitExec = v; } diff --git a/lld/include/lld/ReaderWriter/MachOLinkingContext.h b/lld/include/lld/ReaderWriter/MachOLinkingContext.h index c214ba72af62..6af1242c8786 100644 --- a/lld/include/lld/ReaderWriter/MachOLinkingContext.h +++ b/lld/include/lld/ReaderWriter/MachOLinkingContext.h @@ -27,7 +27,7 @@ public: MachOLinkingContext(); ~MachOLinkingContext(); - virtual void addPasses(PassManager &pm) const; + virtual void addPasses(PassManager &pm); virtual ErrorOr relocKindFromString(StringRef str) const; virtual ErrorOr stringFromRelocKind(Reference::Kind kind) const; virtual bool validateImpl(raw_ostream &diagnostics); diff --git a/lld/include/lld/ReaderWriter/PECOFFLinkingContext.h b/lld/include/lld/ReaderWriter/PECOFFLinkingContext.h index 9fb39e1c1f6e..c251cdcce043 100644 --- a/lld/include/lld/ReaderWriter/PECOFFLinkingContext.h +++ b/lld/include/lld/ReaderWriter/PECOFFLinkingContext.h @@ -65,7 +65,7 @@ public: virtual Writer &writer() const; virtual bool validateImpl(raw_ostream &diagnostics); - virtual void addPasses(PassManager &pm) const; + virtual void addPasses(PassManager &pm); virtual bool createImplicitFiles(std::vector > &result) const; diff --git a/lld/include/lld/ReaderWriter/Simple.h b/lld/include/lld/ReaderWriter/Simple.h index c7d4bef39191..6baa4265a2be 100644 --- a/lld/include/lld/ReaderWriter/Simple.h +++ b/lld/include/lld/ReaderWriter/Simple.h @@ -62,13 +62,31 @@ public: return make_range(_definedAtoms._atoms); } -private: +protected: atom_collection_vector _definedAtoms; atom_collection_vector _undefinedAtoms; atom_collection_vector _sharedLibraryAtoms; atom_collection_vector _absoluteAtoms; }; +class FileToMutable : public SimpleFile { +public: + explicit FileToMutable(const LinkingContext &context, File &file) + : SimpleFile(context, file.path()), _file(file) { + for (auto definedAtom : _file.defined()) + _definedAtoms._atoms.push_back(std::move(definedAtom)); + for (auto undefAtom : _file.undefined()) + _undefinedAtoms._atoms.push_back(std::move(undefAtom)); + for (auto shlibAtom : _file.sharedLibrary()) + _sharedLibraryAtoms._atoms.push_back(std::move(shlibAtom)); + for (auto absAtom : _file.absolute()) + _absoluteAtoms._atoms.push_back(std::move(absAtom)); + } + +private: + const File &_file; +}; + class SimpleReference : public Reference { public: SimpleReference(Reference::Kind k, uint64_t off, const Atom *t, diff --git a/lld/lib/Core/LinkingContext.cpp b/lld/lib/Core/LinkingContext.cpp index 9ae4f51da004..873d1d61c8be 100644 --- a/lld/lib/Core/LinkingContext.cpp +++ b/lld/lib/Core/LinkingContext.cpp @@ -108,6 +108,6 @@ ErrorOr LinkingContext::nextFile() { } } -void LinkingContext::addPasses(PassManager &pm) const {} +void LinkingContext::addPasses(PassManager &pm) {} } // end namespace lld diff --git a/lld/lib/Core/PassManager.cpp b/lld/lib/Core/PassManager.cpp index 238fb0a6b642..715a5fbda11e 100644 --- a/lld/lib/Core/PassManager.cpp +++ b/lld/lib/Core/PassManager.cpp @@ -15,7 +15,7 @@ #include "llvm/Support/ErrorOr.h" namespace lld { -ErrorOr PassManager::runOnFile(MutableFile &mf) { +ErrorOr PassManager::runOnFile(std::unique_ptr &mf) { for (auto &pass : _passes) { pass->perform(mf); } diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp index 3a34cd3fe3fd..3af0c5cba717 100644 --- a/lld/lib/Core/Resolver.cpp +++ b/lld/lib/Core/Resolver.cpp @@ -480,7 +480,7 @@ bool Resolver::resolve() { } this->removeCoalescedAwayAtoms(); this->linkTimeOptimize(); - this->_result.addAtoms(_atoms); + this->_result->addAtoms(_atoms); return true; } diff --git a/lld/lib/Driver/Driver.cpp b/lld/lib/Driver/Driver.cpp index 6f0f4ecdde60..1569d69384ba 100644 --- a/lld/lib/Driver/Driver.cpp +++ b/lld/lib/Driver/Driver.cpp @@ -16,6 +16,8 @@ #include "lld/Core/Resolver.h" #include "lld/ReaderWriter/Reader.h" #include "lld/ReaderWriter/Writer.h" +#include "lld/Passes/RoundTripNativePass.h" +#include "lld/Passes/RoundTripYAMLPass.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" @@ -105,19 +107,27 @@ bool Driver::link(LinkingContext &context, raw_ostream &diagnostics) { Resolver resolver(context); if (!resolver.resolve()) return false; - MutableFile &merged = resolver.resultFile(); + std::unique_ptr merged = resolver.resultFile(); resolveTask.end(); // Run passes on linked atoms. ScopedTask passTask(getDefaultDomain(), "Passes"); PassManager pm; context.addPasses(pm); + +// TODO: Replace the code with #ifndef NDEBUG after fixing the +// failures with pecoff +#ifdef FIXME + pm.add(std::unique_ptr(new RoundTripNativePass(context))); + pm.add(std::unique_ptr(new RoundTripYAMLPass(context))); +#endif + pm.runOnFile(merged); passTask.end(); // Give linked atoms to Writer to generate output file. ScopedTask writeTask(getDefaultDomain(), "Write"); - if (error_code ec = context.writeFile(merged)) { + if (error_code ec = context.writeFile(*merged)) { diagnostics << "Failed to write file '" << context.outputPath() << "': " << ec.message() << "\n"; return false; diff --git a/lld/lib/Passes/CMakeLists.txt b/lld/lib/Passes/CMakeLists.txt index 10759023a381..3cec05afec57 100644 --- a/lld/lib/Passes/CMakeLists.txt +++ b/lld/lib/Passes/CMakeLists.txt @@ -2,4 +2,8 @@ add_lld_library(lldPasses GOTPass.cpp StubsPass.cpp LayoutPass.cpp + RoundTripNativePass.cpp + RoundTripYAMLPass.cpp ) + +target_link_libraries(lldPasses lldReaderWriter) diff --git a/lld/lib/Passes/GOTPass.cpp b/lld/lib/Passes/GOTPass.cpp index 1bb6e4cee4ac..b9a6f73e5b13 100644 --- a/lld/lib/Passes/GOTPass.cpp +++ b/lld/lib/Passes/GOTPass.cpp @@ -67,12 +67,12 @@ findGOTAtom(const Atom *target, } } // end anonymous namespace -void GOTPass::perform(MutableFile &mergedFile) { +void GOTPass::perform(std::unique_ptr &mergedFile) { // Use map so all pointers to same symbol use same GOT entry. llvm::DenseMap targetToGOT; // Scan all references in all atoms. - for(const DefinedAtom *atom : mergedFile.defined()) { + for (const DefinedAtom *atom : mergedFile->defined()) { for (const Reference *ref : *atom) { // Look at instructions accessing the GOT. bool canBypassGOT; @@ -102,7 +102,7 @@ void GOTPass::perform(MutableFile &mergedFile) { // add all created GOT Atoms to master file for (auto &it : targetToGOT) { - mergedFile.addAtom(*it.second); + mergedFile->addAtom(*it.second); } } } diff --git a/lld/lib/Passes/LayoutPass.cpp b/lld/lib/Passes/LayoutPass.cpp index b00887d6fd4f..77a484eaf0a2 100644 --- a/lld/lib/Passes/LayoutPass.cpp +++ b/lld/lib/Passes/LayoutPass.cpp @@ -1,4 +1,4 @@ -//===- Passes/LayoutPass.cpp - Layout atoms -------------------------------===// +//===--Passes/LayoutPass.cpp - Layout atoms -------------------------------===// // // The LLVM Linker // @@ -6,7 +6,6 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// #define DEBUG_TYPE "LayoutPass" @@ -534,9 +533,9 @@ void LayoutPass::checkFollowonChain(MutableFile::DefinedAtomRange &range) { #endif // #ifndef NDEBUG /// Perform the actual pass -void LayoutPass::perform(MutableFile &mergedFile) { +void LayoutPass::perform(std::unique_ptr &mergedFile) { ScopedTask task(getDefaultDomain(), "LayoutPass"); - MutableFile::DefinedAtomRange atomRange = mergedFile.definedAtoms(); + MutableFile::DefinedAtomRange atomRange = mergedFile->definedAtoms(); // Build follow on tables buildFollowOnTable(atomRange); diff --git a/lld/lib/Passes/RoundTripNativePass.cpp b/lld/lib/Passes/RoundTripNativePass.cpp new file mode 100644 index 000000000000..f78ad7bb5cba --- /dev/null +++ b/lld/lib/Passes/RoundTripNativePass.cpp @@ -0,0 +1,44 @@ +//===--Passes/RoundTripNativePass.cpp - Write Native file/Read it back-----===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "RoundTripNativePass" + +#include "lld/Core/Instrumentation.h" +#include "lld/Passes/RoundTripNativePass.h" +#include "lld/ReaderWriter/Simple.h" +#include "lld/ReaderWriter/Writer.h" + +#include "llvm/Support/Path.h" + +using namespace lld; + +/// Perform the actual pass +void RoundTripNativePass::perform(std::unique_ptr &mergedFile) { + ScopedTask task(getDefaultDomain(), "RoundTripNativePass"); + std::unique_ptr nativeWriter = createWriterNative(_context); + SmallString<128> tmpNativeFile; + // Separate the directory from the filename + StringRef outFile = llvm::sys::path::filename(_context.outputPath()); + if (llvm::sys::fs::createTemporaryFile(outFile, "native", tmpNativeFile)) + return; + + // The file that is written would be kept around if there is a problem + // writing to the file or when reading atoms back from the file. + nativeWriter->writeFile(*mergedFile, tmpNativeFile.str()); + llvm::OwningPtr buff; + if (llvm::MemoryBuffer::getFileOrSTDIN(tmpNativeFile.str(), buff)) + return; + + std::unique_ptr mb(buff.take()); + _context.getNativeReader().parseFile(mb, _nativeFile); + + mergedFile.reset(new FileToMutable(_context, *_nativeFile[0].get())); + + llvm::sys::fs::remove(tmpNativeFile.str()); +} diff --git a/lld/lib/Passes/RoundTripYAMLPass.cpp b/lld/lib/Passes/RoundTripYAMLPass.cpp new file mode 100644 index 000000000000..38012cd13087 --- /dev/null +++ b/lld/lib/Passes/RoundTripYAMLPass.cpp @@ -0,0 +1,43 @@ +//===--Passes/RoundTripYAMLPass.cpp - Write YAML file/Read it back---------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "RoundTripYAMLPass" + +#include "lld/Core/Instrumentation.h" +#include "lld/Passes/RoundTripYAMLPass.h" +#include "lld/ReaderWriter/Simple.h" +#include "lld/ReaderWriter/Writer.h" + +#include "llvm/Support/Path.h" + +using namespace lld; + +/// Perform the actual pass +void RoundTripYAMLPass::perform(std::unique_ptr &mergedFile) { + ScopedTask task(getDefaultDomain(), "RoundTripYAMLPass"); + std::unique_ptr yamlWriter = createWriterYAML(_context); + SmallString<128> tmpYAMLFile; + // Separate the directory from the filename + StringRef outFile = llvm::sys::path::filename(_context.outputPath()); + if (llvm::sys::fs::createTemporaryFile(outFile, "yaml", tmpYAMLFile)) + return; + + // The file that is written would be kept around if there is a problem + // writing to the file or when reading atoms back from the file. + yamlWriter->writeFile(*mergedFile, tmpYAMLFile.str()); + llvm::OwningPtr buff; + if (llvm::MemoryBuffer::getFileOrSTDIN(tmpYAMLFile.str(), buff)) + return; + + std::unique_ptr mb(buff.take()); + _context.getYAMLReader().parseFile(mb, _yamlFile); + + mergedFile.reset(new FileToMutable(_context, *_yamlFile[0].get())); + + llvm::sys::fs::remove(tmpYAMLFile.str()); +} diff --git a/lld/lib/Passes/StubsPass.cpp b/lld/lib/Passes/StubsPass.cpp index ef3870580cb4..b75f2316bcbd 100644 --- a/lld/lib/Passes/StubsPass.cpp +++ b/lld/lib/Passes/StubsPass.cpp @@ -23,13 +23,13 @@ namespace lld { -void StubsPass::perform(MutableFile &mergedFile) { +void StubsPass::perform(std::unique_ptr &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 DefinedAtom *atom : mergedFile->defined()) { for (const Reference *ref : *atom) { // Look at call-sites. if (this->isCallSite(ref->kind()) ) { @@ -61,6 +61,6 @@ void StubsPass::perform(MutableFile &mergedFile) { } // Add all created stubs and support Atoms. - this->addStubAtoms(mergedFile); + this->addStubAtoms(*mergedFile); } } diff --git a/lld/lib/ReaderWriter/CoreLinkingContext.cpp b/lld/lib/ReaderWriter/CoreLinkingContext.cpp index ec8962bbce2c..3b83d297e48e 100644 --- a/lld/lib/ReaderWriter/CoreLinkingContext.cpp +++ b/lld/lib/ReaderWriter/CoreLinkingContext.cpp @@ -12,6 +12,9 @@ #include "lld/Core/Pass.h" #include "lld/Core/PassManager.h" #include "lld/Passes/LayoutPass.h" +#include "lld/Passes/RoundTripNativePass.h" +#include "lld/Passes/RoundTripYAMLPass.h" +#include "lld/ReaderWriter/Simple.h" #include "llvm/ADT/ArrayRef.h" @@ -149,10 +152,10 @@ private: uint32_t _ordinal; }; -class TestingPassFile : public MutableFile { +class TestingPassFile : public SimpleFile { public: TestingPassFile(const LinkingContext &ctx) - : MutableFile(ctx, "Testing pass") {} + : SimpleFile(ctx, "Testing pass") {} virtual void addAtom(const Atom &atom) { if (const DefinedAtom *defAtom = dyn_cast(&atom)) @@ -277,7 +280,7 @@ bool CoreLinkingContext::validateImpl(raw_ostream &) { return true; } -void CoreLinkingContext::addPasses(PassManager &pm) const { +void CoreLinkingContext::addPasses(PassManager &pm) { for (StringRef name : _passNames) { if (name.equals("layout")) pm.add(std::unique_ptr((new LayoutPass()))); @@ -288,6 +291,10 @@ void CoreLinkingContext::addPasses(PassManager &pm) const { else llvm_unreachable("bad pass name"); } +#ifndef NDEBUG + pm.add(std::unique_ptr(new RoundTripYAMLPass(*this))); + pm.add(std::unique_ptr(new RoundTripNativePass(*this))); +#endif } Writer &CoreLinkingContext::writer() const { return *_writer; } diff --git a/lld/lib/ReaderWriter/ELF/ArrayOrderPass.cpp b/lld/lib/ReaderWriter/ELF/ArrayOrderPass.cpp index 8a721367b9bb..be9cd4b167d9 100644 --- a/lld/lib/ReaderWriter/ELF/ArrayOrderPass.cpp +++ b/lld/lib/ReaderWriter/ELF/ArrayOrderPass.cpp @@ -13,8 +13,8 @@ namespace lld { namespace elf { -void ArrayOrderPass::perform(MutableFile &f) { - auto definedAtoms = f.definedAtoms(); +void ArrayOrderPass::perform(std::unique_ptr &f) { + auto definedAtoms = f->definedAtoms(); std::stable_sort(definedAtoms.begin(), definedAtoms.end(), [](const DefinedAtom *left, const DefinedAtom *right) { if (left->sectionChoice() != DefinedAtom::sectionCustomRequired || diff --git a/lld/lib/ReaderWriter/ELF/ArrayOrderPass.h b/lld/lib/ReaderWriter/ELF/ArrayOrderPass.h index 8d40c44fc88e..12cce561fbf8 100644 --- a/lld/lib/ReaderWriter/ELF/ArrayOrderPass.h +++ b/lld/lib/ReaderWriter/ELF/ArrayOrderPass.h @@ -18,7 +18,7 @@ namespace elf { class ArrayOrderPass : public Pass { public: ArrayOrderPass() : Pass() {} - virtual void perform(MutableFile &mergedFile) LLVM_OVERRIDE; + virtual void perform(std::unique_ptr &mergedFile) LLVM_OVERRIDE; }; } } diff --git a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp index 6d6f6a757942..827d73d2abe0 100644 --- a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp +++ b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp @@ -16,6 +16,8 @@ #include "lld/Core/Instrumentation.h" #include "lld/Passes/LayoutPass.h" +#include "lld/Passes/RoundTripNativePass.h" +#include "lld/Passes/RoundTripYAMLPass.h" #include "lld/ReaderWriter/ReaderLinkerScript.h" #include "llvm/ADT/Triple.h" @@ -52,10 +54,14 @@ bool ELFLinkingContext::isLittleEndian() const { return true; } -void ELFLinkingContext::addPasses(PassManager &pm) const { +void ELFLinkingContext::addPasses(PassManager &pm) { if (_runLayoutPass) pm.add(std::unique_ptr(new LayoutPass())); pm.add(std::unique_ptr(new elf::ArrayOrderPass())); +#ifndef NDEBUG + pm.add(std::unique_ptr(new RoundTripYAMLPass(*this))); + pm.add(std::unique_ptr(new RoundTripNativePass(*this))); +#endif } uint16_t ELFLinkingContext::getOutputMachine() const { diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h index ea3b9c3b5137..90379503056d 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h @@ -29,7 +29,7 @@ public: virtual ErrorOr relocKindFromString(StringRef str) const; virtual ErrorOr stringFromRelocKind(Reference::Kind kind) const; - virtual void addPasses(PassManager &) const; + virtual void addPasses(PassManager &); virtual bool isDynamicRelocation(const DefinedAtom &, const Reference &r) const { diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp index 7c918877fc27..761471cb06a6 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp @@ -157,9 +157,9 @@ public: /// /// After all references are handled, the atoms created during that are all /// added to mf. - virtual void perform(MutableFile &mf) { + virtual void perform(std::unique_ptr &mf) { // Process all references. - for (const auto &atom : mf.defined()) + for (const auto &atom : mf->defined()) for (const auto &ref : *atom) handleReference(*atom, *ref); @@ -167,23 +167,23 @@ public: uint64_t ordinal = 0; if (_PLT0) { _PLT0->setOrdinal(ordinal++); - mf.addAtom(*_PLT0); + mf->addAtom(*_PLT0); } for (auto &plt : _pltVector) { plt->setOrdinal(ordinal++); - mf.addAtom(*plt); + mf->addAtom(*plt); } if (_null) { _null->setOrdinal(ordinal++); - mf.addAtom(*_null); + mf->addAtom(*_null); } if (_got0) { _got0->setOrdinal(ordinal++); - mf.addAtom(*_got0); + mf->addAtom(*_got0); } for (auto &got : _gotVector) { got->setOrdinal(ordinal++); - mf.addAtom(*got); + mf->addAtom(*got); } } @@ -293,7 +293,7 @@ public: }; } // end anonymous namespace -void elf::HexagonLinkingContext::addPasses(PassManager &pm) const { +void elf::HexagonLinkingContext::addPasses(PassManager &pm) { if (isDynamic()) pm.add(std::unique_ptr(new DynamicGOTPLTPass(*this))); ELFLinkingContext::addPasses(pm); diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/PPC/PPCLinkingContext.cpp index 24c38b1e9d0f..02f6c21cc179 100644 --- a/lld/lib/ReaderWriter/ELF/PPC/PPCLinkingContext.cpp +++ b/lld/lib/ReaderWriter/ELF/PPC/PPCLinkingContext.cpp @@ -21,7 +21,7 @@ using namespace lld; ErrorOr elf::PPCLinkingContext::relocKindFromString(StringRef str) const { int32_t ret = llvm::StringSwitch(str) LLD_CASE(R_PPC_NONE) - LLD_CASE(R_PPC_ADDR32).Default(-1); + LLD_CASE(R_PPC_ADDR32) LLD_CASE(R_PPC_REL24).Default(-1); if (ret == -1) return make_error_code(YamlReaderError::illegal_value); @@ -39,6 +39,7 @@ elf::PPCLinkingContext::stringFromRelocKind(Reference::Kind kind) const { switch (kind) { LLD_CASE(R_PPC_NONE) LLD_CASE(R_PPC_ADDR32) + LLD_CASE(R_PPC_REL24) } return make_error_code(YamlReaderError::illegal_value); diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp index 5b3a920547c7..a5b27e656e50 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp @@ -90,8 +90,7 @@ private: } // end anon namespace - -void elf::X86_64LinkingContext::addPasses(PassManager &pm) const { +void elf::X86_64LinkingContext::addPasses(PassManager &pm) { auto pass = createX86_64RelocationPass(*this); if (pass) pm.add(std::move(pass)); diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h index c7ca812d1da1..7877869bf365 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h @@ -33,7 +33,7 @@ public: : ELFLinkingContext(triple, std::unique_ptr( new X86_64TargetHandler(*this))) {} - virtual void addPasses(PassManager &) const; + virtual void addPasses(PassManager &); virtual uint64_t getBaseAddress() const { if (_baseAddress == 0) diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp index a06b48746ba7..3ce6b0873e3b 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp @@ -217,10 +217,10 @@ public: /// /// After all references are handled, the atoms created during that are all /// added to mf. - virtual void perform(MutableFile &mf) { + virtual void perform(std::unique_ptr &mf) { ScopedTask task(getDefaultDomain(), "X86-64 GOT/PLT Pass"); // Process all references. - for (const auto &atom : mf.defined()) + for (const auto &atom : mf->defined()) for (const auto &ref : *atom) handleReference(*atom, *ref); @@ -228,29 +228,29 @@ public: uint64_t ordinal = 0; if (_PLT0) { _PLT0->setOrdinal(ordinal++); - mf.addAtom(*_PLT0); + mf->addAtom(*_PLT0); } for (auto &plt : _pltVector) { plt->setOrdinal(ordinal++); - mf.addAtom(*plt); + mf->addAtom(*plt); } if (_null) { _null->setOrdinal(ordinal++); - mf.addAtom(*_null); + mf->addAtom(*_null); } if (_PLT0) { _got0->setOrdinal(ordinal++); _got1->setOrdinal(ordinal++); - mf.addAtom(*_got0); - mf.addAtom(*_got1); + mf->addAtom(*_got0); + mf->addAtom(*_got1); } for (auto &got : _gotVector) { got->setOrdinal(ordinal++); - mf.addAtom(*got); + mf->addAtom(*got); } for (auto obj : _objectVector) { obj->setOrdinal(ordinal++); - mf.addAtom(*obj); + mf->addAtom(*obj); } } diff --git a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp index 69219e5b1684..b79fd39a8bcd 100644 --- a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp +++ b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp @@ -16,6 +16,8 @@ #include "lld/ReaderWriter/Reader.h" #include "lld/ReaderWriter/Writer.h" #include "lld/Passes/LayoutPass.h" +#include "lld/Passes/RoundTripNativePass.h" +#include "lld/Passes/RoundTripYAMLPass.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" @@ -235,10 +237,14 @@ bool MachOLinkingContext::setOS(OS os, StringRef minOSVersion) { return parsePackedVersion(minOSVersion, _osMinVersion); } -void MachOLinkingContext::addPasses(PassManager &pm) const { +void MachOLinkingContext::addPasses(PassManager &pm) { pm.add(std::unique_ptr(new mach_o::GOTPass)); pm.add(std::unique_ptr(new mach_o::StubsPass(*this))); pm.add(std::unique_ptr(new LayoutPass())); +#ifndef NDEBUG + pm.add(std::unique_ptr(new RoundTripYAMLPass(*this))); + pm.add(std::unique_ptr(new RoundTripNativePass(*this))); +#endif } Writer &MachOLinkingContext::writer() const { diff --git a/lld/lib/ReaderWriter/PECOFF/GroupedSectionsPass.h b/lld/lib/ReaderWriter/PECOFF/GroupedSectionsPass.h index f8836061a07e..e3186031b87c 100644 --- a/lld/lib/ReaderWriter/PECOFF/GroupedSectionsPass.h +++ b/lld/lib/ReaderWriter/PECOFF/GroupedSectionsPass.h @@ -60,9 +60,9 @@ class GroupedSectionsPass : public lld::Pass { public: GroupedSectionsPass() {} - virtual void perform(MutableFile &mergedFile) { - std::map> sectionToHeadAtoms( - filterHeadAtoms(mergedFile)); + virtual void perform(std::unique_ptr &mergedFile) { + std::map > sectionToHeadAtoms( + filterHeadAtoms(*mergedFile)); std::vector> groupedAtomsList( groupBySectionName(sectionToHeadAtoms)); for (auto &groupedAtoms : groupedAtomsList) diff --git a/lld/lib/ReaderWriter/PECOFF/IdataPass.h b/lld/lib/ReaderWriter/PECOFF/IdataPass.h index d13a718cb47b..c3f7e9761558 100644 --- a/lld/lib/ReaderWriter/PECOFF/IdataPass.h +++ b/lld/lib/ReaderWriter/PECOFF/IdataPass.h @@ -252,13 +252,13 @@ class IdataPass : public lld::Pass { public: IdataPass(const LinkingContext &ctx) : _dummyFile(ctx) {} - virtual void perform(MutableFile &file) { - if (file.sharedLibrary().size() == 0) + virtual void perform(std::unique_ptr &file) { + if (file->sharedLibrary().size() == 0) return; - Context context(file, _dummyFile); + Context context(*file, _dummyFile); map > sharedAtoms = - groupByLoadName(file); + groupByLoadName(*file); for (auto i : sharedAtoms) { StringRef loadName = i.first; vector &atoms = i.second; diff --git a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp index 065a2c071662..252c91cc53a5 100644 --- a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp +++ b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp @@ -204,7 +204,7 @@ PECOFFLinkingContext::stringFromRelocKind(Reference::Kind kind) const { return make_error_code(YamlReaderError::illegal_value); } -void PECOFFLinkingContext::addPasses(PassManager &pm) const { +void PECOFFLinkingContext::addPasses(PassManager &pm) { pm.add(std::unique_ptr(new pecoff::GroupedSectionsPass())); pm.add(std::unique_ptr(new pecoff::IdataPass(*this))); pm.add(std::unique_ptr(new LayoutPass())); diff --git a/lld/test/elf/roundtrip.test b/lld/test/elf/roundtrip.test new file mode 100644 index 000000000000..2bb25db563f5 --- /dev/null +++ b/lld/test/elf/roundtrip.test @@ -0,0 +1,9 @@ +# This tests the functionality of the RoundTrip Passes and verifies +# that the atoms belong to the native file after the passes finish + +RUN: lld -flavor gnu -target x86_64 %p/Inputs/foo.o.x86-64 --noinhibit-exec \ +RUN: --output-filetype=yaml -o %t1 +RUN: FileCheck %s < %t1 + +CHECK:path:{{.*}}.native +