MC: Introduce an ELF dwo object writer and teach llvm-mc about it.

Part of PR37466.

Differential Revision: https://reviews.llvm.org/D47051

llvm-svn: 332875
diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp
index d6df481..7b83c5e 100644
--- a/llvm/tools/llvm-mc/llvm-mc.cpp
+++ b/llvm/tools/llvm-mc/llvm-mc.cpp
@@ -45,9 +45,13 @@
 static cl::opt<std::string>
 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
 
-static cl::opt<std::string>
-OutputFilename("o", cl::desc("Output filename"),
-               cl::value_desc("filename"));
+static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
+                                           cl::value_desc("filename"),
+                                           cl::init("-"));
+
+static cl::opt<std::string> SplitDwarfFile("split-dwarf-file",
+                                           cl::desc("DWO output filename"),
+                                           cl::value_desc("filename"));
 
 static cl::opt<bool>
 ShowEncoding("show-encoding", cl::desc("Show instruction encodings"));
@@ -197,13 +201,9 @@
   return TheTarget;
 }
 
-static std::unique_ptr<ToolOutputFile> GetOutputStream() {
-  if (OutputFilename == "")
-    OutputFilename = "-";
-
+static std::unique_ptr<ToolOutputFile> GetOutputStream(StringRef Path) {
   std::error_code EC;
-  auto Out =
-      llvm::make_unique<ToolOutputFile>(OutputFilename, EC, sys::fs::F_None);
+  auto Out = llvm::make_unique<ToolOutputFile>(Path, EC, sys::fs::F_None);
   if (EC) {
     WithColor::error() << EC.message() << '\n';
     return nullptr;
@@ -411,10 +411,21 @@
     FeaturesStr = Features.getString();
   }
 
-  std::unique_ptr<ToolOutputFile> Out = GetOutputStream();
+  std::unique_ptr<ToolOutputFile> Out = GetOutputStream(OutputFilename);
   if (!Out)
     return 1;
 
+  std::unique_ptr<ToolOutputFile> DwoOut;
+  if (!SplitDwarfFile.empty()) {
+    if (FileType != OFT_ObjectFile) {
+      WithColor::error() << "dwo output only supported with object files\n";
+      return 1;
+    }
+    DwoOut = GetOutputStream(SplitDwarfFile);
+    if (!DwoOut)
+      return 1;
+  }
+
   std::unique_ptr<buffer_ostream> BOS;
   raw_pwrite_stream *OS = &Out->os();
   std::unique_ptr<MCStreamer> Str;
@@ -469,8 +480,10 @@
     MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions);
     Str.reset(TheTarget->createMCObjectStreamer(
         TheTriple, Ctx, std::unique_ptr<MCAsmBackend>(MAB),
-        MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(CE), *STI,
-        MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
+        DwoOut ? MAB->createDwoObjectWriter(*OS, DwoOut->os())
+               : MAB->createObjectWriter(*OS),
+        std::unique_ptr<MCCodeEmitter>(CE), *STI, MCOptions.MCRelaxAll,
+        MCOptions.MCIncrementalLinkerCompatible,
         /*DWARFMustBeAtTheEnd*/ false));
     if (NoExecStack)
       Str->InitSections(true);
@@ -503,6 +516,10 @@
                                     *Buffer, SrcMgr, Out->os());
 
   // Keep output if no errors.
-  if (Res == 0) Out->keep();
+  if (Res == 0) {
+    Out->keep();
+    if (DwoOut)
+      DwoOut->keep();
+  }
   return Res;
 }