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<MutableFile> &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<MutableFile> &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<MutableFile> &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<void> runOnFile(MutableFile &); + ErrorOr<void> runOnFile(std::unique_ptr<MutableFile> &); 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<MutableFile> resultFile() { return std::move(_result); } private: @@ -117,7 +116,7 @@ private: std::set<const Atom *> _deadStripRoots; std::vector<const Atom *> _atomsWithUnresolvedReferences; llvm::DenseSet<const Atom *> _liveAtoms; - MergedFile _result; + std::unique_ptr<MergedFile> _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<MutableFile> &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 <map> +#include <vector> + +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<MutableFile> &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<std::unique_ptr<File> > _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 <map> +#include <vector> + +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<MutableFile> &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<std::unique_ptr<File> > _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<Reference::Kind> relocKindFromString(StringRef str) const; virtual ErrorOr<std::string> 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<lld::elf::TargetHandler<ELFT> &>(*_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<Reference::Kind> relocKindFromString(StringRef str) const; virtual ErrorOr<std::string> 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<std::unique_ptr<File> > &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<DefinedAtom> _definedAtoms; atom_collection_vector<UndefinedAtom> _undefinedAtoms; atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms; atom_collection_vector<AbsoluteAtom> _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<File &> 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<void> PassManager::runOnFile(MutableFile &mf) { +ErrorOr<void> PassManager::runOnFile(std::unique_ptr<MutableFile> &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<MutableFile> 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<Pass>(new RoundTripNativePass(context))); + pm.add(std::unique_ptr<Pass>(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<MutableFile> &mergedFile) { // Use map so all pointers to same symbol use same GOT entry. llvm::DenseMap<const Atom*, const DefinedAtom*> targetToGOT; // Scan all references in all atoms. - for(const DefinedAtom *atom : mergedFile.defined()) { + for (const 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<MutableFile> &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<MutableFile> &mergedFile) { + ScopedTask task(getDefaultDomain(), "RoundTripNativePass"); + std::unique_ptr<Writer> 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<llvm::MemoryBuffer> buff; + if (llvm::MemoryBuffer::getFileOrSTDIN(tmpNativeFile.str(), buff)) + return; + + std::unique_ptr<MemoryBuffer> 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<MutableFile> &mergedFile) { + ScopedTask task(getDefaultDomain(), "RoundTripYAMLPass"); + std::unique_ptr<Writer> 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<llvm::MemoryBuffer> buff; + if (llvm::MemoryBuffer::getFileOrSTDIN(tmpYAMLFile.str(), buff)) + return; + + std::unique_ptr<MemoryBuffer> 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<MutableFile> &mergedFile) { // Skip this pass if output format uses text relocations instead of stubs. if ( ! this->noTextRelocs() ) return; // Scan all references in all atoms. - for(const DefinedAtom *atom : mergedFile.defined()) { + for (const 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<DefinedAtom>(&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<Pass>((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<Pass>(new RoundTripYAMLPass(*this))); + pm.add(std::unique_ptr<Pass>(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<MutableFile> &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<MutableFile> &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<Pass>(new LayoutPass())); pm.add(std::unique_ptr<Pass>(new elf::ArrayOrderPass())); +#ifndef NDEBUG + pm.add(std::unique_ptr<Pass>(new RoundTripYAMLPass(*this))); + pm.add(std::unique_ptr<Pass>(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<Reference::Kind> relocKindFromString(StringRef str) const; virtual ErrorOr<std::string> 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<MutableFile> &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<Pass>(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<Reference::Kind> elf::PPCLinkingContext::relocKindFromString(StringRef str) const { int32_t ret = llvm::StringSwitch<int32_t>(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<TargetHandlerBase>( 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<MutableFile> &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<Pass>(new mach_o::GOTPass)); pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this))); pm.add(std::unique_ptr<Pass>(new LayoutPass())); +#ifndef NDEBUG + pm.add(std::unique_ptr<Pass>(new RoundTripYAMLPass(*this))); + pm.add(std::unique_ptr<Pass>(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<StringRef, std::vector<COFFDefinedAtom *>> sectionToHeadAtoms( - filterHeadAtoms(mergedFile)); + virtual void perform(std::unique_ptr<MutableFile> &mergedFile) { + std::map<StringRef, std::vector<COFFDefinedAtom *> > sectionToHeadAtoms( + filterHeadAtoms(*mergedFile)); std::vector<std::vector<COFFDefinedAtom *>> 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<MutableFile> &file) { + if (file->sharedLibrary().size() == 0) return; - Context context(file, _dummyFile); + Context context(*file, _dummyFile); map<StringRef, vector<COFFSharedLibraryAtom *> > sharedAtoms = - groupByLoadName(file); + groupByLoadName(*file); for (auto i : sharedAtoms) { StringRef loadName = i.first; vector<COFFSharedLibraryAtom *> &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<Pass>(new pecoff::GroupedSectionsPass())); pm.add(std::unique_ptr<Pass>(new pecoff::IdataPass(*this))); pm.add(std::unique_ptr<Pass>(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 +