summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShankar Easwaran <shankare@codeaurora.org>2013-10-29 05:12:14 +0000
committerShankar Easwaran <shankare@codeaurora.org>2013-10-29 05:12:14 +0000
commit2bc24928d36531aeea52c6563a125adb22c203bf (patch)
treeb7fd4a401d972e6c946bc2ba3309ca99924b2070
parent3aca58f135b593a66c4c5680a4ce3b97d6531bdf (diff)
downloadbcm5719-llvm-2bc24928d36531aeea52c6563a125adb22c203bf.tar.gz
bcm5719-llvm-2bc24928d36531aeea52c6563a125adb22c203bf.zip
[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
-rw-r--r--lld/include/lld/Core/LinkingContext.h2
-rw-r--r--lld/include/lld/Core/Pass.h6
-rw-r--r--lld/include/lld/Core/PassManager.h2
-rw-r--r--lld/include/lld/Core/Resolver.h11
-rw-r--r--lld/include/lld/Passes/LayoutPass.h2
-rw-r--r--lld/include/lld/Passes/RoundTripNativePass.h41
-rw-r--r--lld/include/lld/Passes/RoundTripYAMLPass.h41
-rw-r--r--lld/include/lld/ReaderWriter/CoreLinkingContext.h2
-rw-r--r--lld/include/lld/ReaderWriter/ELFLinkingContext.h2
-rw-r--r--lld/include/lld/ReaderWriter/MachOLinkingContext.h2
-rw-r--r--lld/include/lld/ReaderWriter/PECOFFLinkingContext.h2
-rw-r--r--lld/include/lld/ReaderWriter/Simple.h20
-rw-r--r--lld/lib/Core/LinkingContext.cpp2
-rw-r--r--lld/lib/Core/PassManager.cpp2
-rw-r--r--lld/lib/Core/Resolver.cpp2
-rw-r--r--lld/lib/Driver/Driver.cpp14
-rw-r--r--lld/lib/Passes/CMakeLists.txt4
-rw-r--r--lld/lib/Passes/GOTPass.cpp6
-rw-r--r--lld/lib/Passes/LayoutPass.cpp7
-rw-r--r--lld/lib/Passes/RoundTripNativePass.cpp44
-rw-r--r--lld/lib/Passes/RoundTripYAMLPass.cpp43
-rw-r--r--lld/lib/Passes/StubsPass.cpp6
-rw-r--r--lld/lib/ReaderWriter/CoreLinkingContext.cpp13
-rw-r--r--lld/lib/ReaderWriter/ELF/ArrayOrderPass.cpp4
-rw-r--r--lld/lib/ReaderWriter/ELF/ArrayOrderPass.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp8
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp16
-rw-r--r--lld/lib/ReaderWriter/ELF/PPC/PPCLinkingContext.cpp3
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp3
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp18
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp8
-rw-r--r--lld/lib/ReaderWriter/PECOFF/GroupedSectionsPass.h6
-rw-r--r--lld/lib/ReaderWriter/PECOFF/IdataPass.h8
-rw-r--r--lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp2
-rw-r--r--lld/test/elf/roundtrip.test9
37 files changed, 297 insertions, 70 deletions
diff --git a/lld/include/lld/Core/LinkingContext.h b/lld/include/lld/Core/LinkingContext.h
index 255e6595486..c617a22d6b2 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 147162a6674..6d4b6a5cc26 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 98a22512f26..2ed7a84db40 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 7ffd3523b50..bb19f14e250 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 39a9b49f208..bbd277f488f 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 00000000000..0d562ed58e1
--- /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 00000000000..772bc79455e
--- /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 9f6fcdd0574..3b74d3ab8fb 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 9a244300ccd..458ded2a0e0 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 c214ba72af6..6af1242c878 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 9fb39e1c1f6..c251cdcce04 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 c7d4bef3919..6baa4265a2b 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 9ae4f51da00..873d1d61c8b 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 238fb0a6b64..715a5fbda11 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 3a34cd3fe3f..3af0c5cba71 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 6f0f4ecdde6..1569d69384b 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 10759023a38..3cec05afec5 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 1bb6e4cee4a..b9a6f73e5b1 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 b00887d6fd4..77a484eaf0a 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 00000000000..f78ad7bb5cb
--- /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 00000000000..38012cd1308
--- /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 ef3870580cb..b75f2316bcb 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 ec8962bbce2..3b83d297e48 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 8a721367b9b..be9cd4b167d 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 8d40c44fc88..12cce561fbf 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 6d6f6a75794..827d73d2abe 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 ea3b9c3b513..90379503056 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 7c918877fc2..761471cb06a 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 24c38b1e9d0..02f6c21cc17 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 5b3a920547c..a5b27e656e5 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 c7ca812d1da..7877869bf36 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 a06b48746ba..3ce6b0873e3 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 69219e5b168..b79fd39a8bc 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 f8836061a07..e3186031b87 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 d13a718cb47..c3f7e976155 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 065a2c07166..252c91cc53a 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 00000000000..2bb25db563f
--- /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
+
OpenPOWER on IntegriCloud