[ORC] Add a utility to support dumping JIT'd objects to disk for debugging.

Adds a DumpObjects utility that can be used to dump JIT'd objects to disk.
Instances of DebugObjects may be used by ObjectTransformLayer as no-op
transforms.

This patch also adds an ObjectTransformLayer to LLJIT and an example of how
to use this utility to dump JIT'd objects in LLJIT.
diff --git a/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp b/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp
new file mode 100644
index 0000000..4e573da
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp
@@ -0,0 +1,68 @@
+//===---------- DebugUtils.cpp - Utilities for debugging ORC JITs ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define DEBUG_TYPE "orc"
+
+namespace llvm {
+namespace orc {
+
+DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)
+    : DumpDir(std::move(DumpDir)),
+      IdentifierOverride(std::move(IdentifierOverride)) {
+
+  /// Discard any trailing separators.
+  while (!this->DumpDir.empty() &&
+         sys::path::is_separator(this->DumpDir.back()))
+    this->DumpDir.pop_back();
+}
+
+Expected<std::unique_ptr<MemoryBuffer>>
+DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {
+  size_t Idx = 1;
+
+  std::string DumpPathStem;
+  raw_string_ostream(DumpPathStem)
+      << DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);
+
+  std::string DumpPath = DumpPathStem + ".o";
+  while (sys::fs::exists(DumpPath)) {
+    DumpPath.clear();
+    raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";
+  }
+
+  LLVM_DEBUG({
+    dbgs() << "Dumping object buffer [ " << (void *)Obj->getBufferStart()
+           << " -- " << (void *)(Obj->getBufferEnd() - 1) << " ] to "
+           << DumpPath << "\n";
+  });
+
+  std::error_code EC;
+  raw_fd_ostream DumpStream(DumpPath, EC);
+  if (EC)
+    return errorCodeToError(EC);
+  DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());
+
+  return Obj;
+}
+
+StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {
+  if (!IdentifierOverride.empty())
+    return IdentifierOverride;
+  StringRef Identifier = B.getBufferIdentifier();
+  Identifier.consume_back(".o");
+  return Identifier;
+}
+
+} // End namespace orc.
+} // End namespace llvm.