[yaml2obj/ObjectYAML] - Cleanup the error reporting API, add custom errors handlers.
authorGeorge Rimar <grimar@accesssoftek.com>
Fri, 13 Sep 2019 16:00:16 +0000 (16:00 +0000)
committerGeorge Rimar <grimar@accesssoftek.com>
Fri, 13 Sep 2019 16:00:16 +0000 (16:00 +0000)
This is a continuation of the YAML library error reporting
refactoring/improvement and the idea by itself was mentioned
in the following thread:
https://reviews.llvm.org/D67182?id=218714#inline-603404

This performs a cleanup of all object emitters in the library.
It allows using the custom one provided by the caller.

One of the nice things is that each tool can now print its tool name,
e.g: "yaml2obj: error: <text>"

Also, the code became a bit simpler.

Differential revision: https://reviews.llvm.org/D67445

llvm-svn: 371865

21 files changed:
llvm/include/llvm/ObjectYAML/yaml2obj.h
llvm/lib/ObjectYAML/COFFEmitter.cpp
llvm/lib/ObjectYAML/ELFEmitter.cpp
llvm/lib/ObjectYAML/MachOEmitter.cpp
llvm/lib/ObjectYAML/MinidumpEmitter.cpp
llvm/lib/ObjectYAML/WasmEmitter.cpp
llvm/lib/ObjectYAML/yaml2obj.cpp
llvm/test/ObjectYAML/wasm/invalid_section_order.yaml
llvm/test/tools/yaml2obj/coff-invalid-alignment.test
llvm/test/tools/yaml2obj/dynsymtab-implicit-sections-size-content.yaml
llvm/test/tools/yaml2obj/empty-or-invalid-doc.yaml
llvm/test/tools/yaml2obj/invalid-docnum.test
llvm/test/tools/yaml2obj/invalid_output_file.test
llvm/test/tools/yaml2obj/missing_document_tag.yaml
llvm/test/tools/yaml2obj/multi-doc.test
llvm/test/tools/yaml2obj/reloc-sec-info.yaml
llvm/test/tools/yaml2obj/section-size-content.yaml
llvm/tools/llvm-ifs/llvm-ifs.cpp
llvm/tools/yaml2obj/yaml2obj.cpp
llvm/unittests/ObjectYAML/MinidumpYAMLTest.cpp
llvm/unittests/ObjectYAML/YAML2ObjTest.cpp

index 54c39ef055d549722ed653b963411eccc41e1c67..386551337d86283a51cf07c18f4de9cef12e88a2 100644 (file)
@@ -44,17 +44,22 @@ namespace yaml {
 class Input;
 struct YamlObjectFile;
 
-bool yaml2coff(COFFYAML::Object &Doc, raw_ostream &Out);
-bool yaml2elf(ELFYAML::Object &Doc, raw_ostream &Out);
-bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out);
-bool yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out);
-bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out);
+using ErrorHandler = llvm::function_ref<void(const Twine &Msg)>;
 
-Error convertYAML(Input &YIn, raw_ostream &Out, unsigned DocNum = 1);
+bool yaml2coff(COFFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH);
+bool yaml2elf(ELFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH);
+bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out, ErrorHandler EH);
+bool yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out,
+                   ErrorHandler EH);
+bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH);
+
+bool convertYAML(Input &YIn, raw_ostream &Out, ErrorHandler ErrHandler,
+                 unsigned DocNum = 1);
 
 /// Convenience function for tests.
-Expected<std::unique_ptr<object::ObjectFile>>
-yaml2ObjectFile(SmallVectorImpl<char> &Storage, StringRef Yaml);
+std::unique_ptr<object::ObjectFile>
+yaml2ObjectFile(SmallVectorImpl<char> &Storage, StringRef Yaml,
+                ErrorHandler ErrHandler);
 
 } // namespace yaml
 } // namespace llvm
index daa4f6d83db6c0fc4997381afe7cc9c5fb05088e..efcdc51e16703be58185bdc197dc50c5afc963cc 100644 (file)
@@ -34,8 +34,8 @@ namespace {
 /// This parses a yaml stream that represents a COFF object file.
 /// See docs/yaml2obj for the yaml scheema.
 struct COFFParser {
-  COFFParser(COFFYAML::Object &Obj)
-      : Obj(Obj), SectionTableStart(0), SectionTableSize(0) {
+  COFFParser(COFFYAML::Object &Obj, yaml::ErrorHandler EH)
+      : Obj(Obj), SectionTableStart(0), SectionTableSize(0), ErrHandler(EH) {
     // A COFF string table always starts with a 4 byte size field. Offsets into
     // it include this size, so allocate it now.
     StringTable.append(4, char(0));
@@ -81,7 +81,7 @@ struct COFFParser {
         unsigned Index = getStringIndex(Name);
         std::string str = utostr(Index);
         if (str.size() > 7) {
-          errs() << "String table got too large\n";
+          ErrHandler("string table got too large");
           return false;
         }
         Sec.Header.Name[0] = '/';
@@ -90,11 +90,11 @@ struct COFFParser {
 
       if (Sec.Alignment) {
         if (Sec.Alignment > 8192) {
-          errs() << "Section alignment is too large\n";
+          ErrHandler("section alignment is too large");
           return false;
         }
         if (!isPowerOf2_32(Sec.Alignment)) {
-          errs() << "Section alignment is not a power of 2\n";
+          ErrHandler("section alignment is not a power of 2");
           return false;
         }
         Sec.Header.Characteristics |= (Log2_32(Sec.Alignment) + 1) << 20;
@@ -155,6 +155,8 @@ struct COFFParser {
   std::string StringTable;
   uint32_t SectionTableStart;
   uint32_t SectionTableSize;
+
+  yaml::ErrorHandler ErrHandler;
 };
 
 enum { DOSStubSize = 128 };
@@ -592,24 +594,25 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
 namespace llvm {
 namespace yaml {
 
-bool yaml2coff(llvm::COFFYAML::Object &Doc, raw_ostream &Out) {
-  COFFParser CP(Doc);
+bool yaml2coff(llvm::COFFYAML::Object &Doc, raw_ostream &Out,
+               ErrorHandler ErrHandler) {
+  COFFParser CP(Doc, ErrHandler);
   if (!CP.parse()) {
-    errs() << "yaml2obj: Failed to parse YAML file!\n";
+    ErrHandler("failed to parse YAML file");
     return false;
   }
 
   if (!layoutOptionalHeader(CP)) {
-    errs() << "yaml2obj: Failed to layout optional header for COFF file!\n";
+    ErrHandler("failed to layout optional header for COFF file");
     return false;
   }
 
   if (!layoutCOFF(CP)) {
-    errs() << "yaml2obj: Failed to layout COFF file!\n";
+    ErrHandler("failed to layout COFF file");
     return false;
   }
   if (!writeCOFF(CP, Out)) {
-    errs() << "yaml2obj: Failed to write COFF file!\n";
+    ErrHandler("failed to write COFF file");
     return false;
   }
   return true;
index 6c64754f49bea4f7cd0d385abd35b7abf3ffeb68..4584e3d73bd7610adb264b369003c60f8f67aef9 100644 (file)
@@ -115,12 +115,13 @@ template <class ELFT> class ELFState {
   ELFYAML::Object &Doc;
 
   bool HasError = false;
+  yaml::ErrorHandler ErrHandler;
+  void reportError(const Twine &Msg);
 
   std::vector<Elf_Sym> toELFSymbols(ArrayRef<ELFYAML::Symbol> Symbols,
                                     const StringTableBuilder &Strtab);
   unsigned toSectionIndex(StringRef S, StringRef LocSec, StringRef LocSym = "");
   unsigned toSymbolIndex(StringRef S, StringRef LocSec, bool IsDynamic);
-  void reportError(const Twine &Msg);
 
   void buildSectionIndex();
   void buildSymbolIndexes();
@@ -166,9 +167,11 @@ template <class ELFT> class ELFState {
   void writeSectionContent(Elf_Shdr &SHeader,
                            const ELFYAML::DynamicSection &Section,
                            ContiguousBlobAccumulator &CBA);
-  ELFState(ELFYAML::Object &D);
+  ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH);
+
 public:
-  static bool writeELF(raw_ostream &OS, ELFYAML::Object &Doc);
+  static bool writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
+                       yaml::ErrorHandler EH);
 };
 } // end anonymous namespace
 
@@ -182,7 +185,9 @@ template <class T> static void writeArrayData(raw_ostream &OS, ArrayRef<T> A) {
 
 template <class T> static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); }
 
-template <class ELFT> ELFState<ELFT>::ELFState(ELFYAML::Object &D) : Doc(D) {
+template <class ELFT>
+ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
+    : Doc(D), ErrHandler(EH) {
   StringSet<> DocSections;
   for (std::unique_ptr<ELFYAML::Section> &D : Doc.Sections)
     if (!D->Name.empty())
@@ -592,7 +597,7 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
 }
 
 template <class ELFT> void ELFState<ELFT>::reportError(const Twine &Msg) {
-  WithColor::error() << Msg << "\n";
+  ErrHandler(Msg);
   HasError = true;
 }
 
@@ -983,8 +988,9 @@ template <class ELFT> void ELFState<ELFT>::finalizeStrings() {
 }
 
 template <class ELFT>
-bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc) {
-  ELFState<ELFT> State(Doc);
+bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
+                              yaml::ErrorHandler EH) {
+  ELFState<ELFT> State(Doc, EH);
 
   // Finalize .strtab and .dynstr sections. We do that early because want to
   // finalize the string table builders before writing the content of the
@@ -1022,17 +1028,17 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc) {
 namespace llvm {
 namespace yaml {
 
-bool yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out) {
+bool yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
   bool IsLE = Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);
   bool Is64Bit = Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);
   if (Is64Bit) {
     if (IsLE)
-      return ELFState<object::ELF64LE>::writeELF(Out, Doc);
-    return ELFState<object::ELF64BE>::writeELF(Out, Doc);
+      return ELFState<object::ELF64LE>::writeELF(Out, Doc, EH);
+    return ELFState<object::ELF64BE>::writeELF(Out, Doc, EH);
   }
   if (IsLE)
-    return ELFState<object::ELF32LE>::writeELF(Out, Doc);
-  return ELFState<object::ELF32BE>::writeELF(Out, Doc);
+    return ELFState<object::ELF32LE>::writeELF(Out, Doc, EH);
+  return ELFState<object::ELF32BE>::writeELF(Out, Doc, EH);
 }
 
 } // namespace yaml
index 621b9b2617d85a43f8a331ebaab4bcff49560f40..b56f811ce67d50d068eb2cda9355a743dacff447 100644 (file)
@@ -15,7 +15,6 @@
 #include "llvm/ObjectYAML/DWARFEmitter.h"
 #include "llvm/ObjectYAML/ObjectYAML.h"
 #include "llvm/ObjectYAML/yaml2obj.h"
-#include "llvm/Support/Error.h"
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
@@ -34,24 +33,24 @@ public:
     memset(reinterpret_cast<void *>(&Header), 0, sizeof(MachO::mach_header_64));
   }
 
-  Error writeMachO(raw_ostream &OS);
+  void writeMachO(raw_ostream &OS);
 
 private:
-  Error writeHeader(raw_ostream &OS);
-  Error writeLoadCommands(raw_ostream &OS);
-  Error writeSectionData(raw_ostream &OS);
-  Error writeLinkEditData(raw_ostream &OS);
+  void writeHeader(raw_ostream &OS);
+  void writeLoadCommands(raw_ostream &OS);
+  void writeSectionData(raw_ostream &OS);
+  void writeLinkEditData(raw_ostream &OS);
 
   void writeBindOpcodes(raw_ostream &OS,
                         std::vector<MachOYAML::BindOpcode> &BindOpcodes);
   // LinkEdit writers
-  Error writeRebaseOpcodes(raw_ostream &OS);
-  Error writeBasicBindOpcodes(raw_ostream &OS);
-  Error writeWeakBindOpcodes(raw_ostream &OS);
-  Error writeLazyBindOpcodes(raw_ostream &OS);
-  Error writeNameList(raw_ostream &OS);
-  Error writeStringTable(raw_ostream &OS);
-  Error writeExportTrie(raw_ostream &OS);
+  void writeRebaseOpcodes(raw_ostream &OS);
+  void writeBasicBindOpcodes(raw_ostream &OS);
+  void writeWeakBindOpcodes(raw_ostream &OS);
+  void writeLazyBindOpcodes(raw_ostream &OS);
+  void writeNameList(raw_ostream &OS);
+  void writeStringTable(raw_ostream &OS);
+  void writeExportTrie(raw_ostream &OS);
 
   void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry);
   void ZeroToOffset(raw_ostream &OS, size_t offset);
@@ -63,18 +62,14 @@ private:
   MachO::mach_header_64 Header;
 };
 
-Error MachOWriter::writeMachO(raw_ostream &OS) {
+void MachOWriter::writeMachO(raw_ostream &OS) {
   fileStart = OS.tell();
-  if (auto Err = writeHeader(OS))
-    return Err;
-  if (auto Err = writeLoadCommands(OS))
-    return Err;
-  if (auto Err = writeSectionData(OS))
-    return Err;
-  return Error::success();
+  writeHeader(OS);
+  writeLoadCommands(OS);
+  writeSectionData(OS);
 }
 
-Error MachOWriter::writeHeader(raw_ostream &OS) {
+void MachOWriter::writeHeader(raw_ostream &OS) {
   Header.magic = Obj.Header.magic;
   Header.cputype = Obj.Header.cputype;
   Header.cpusubtype = Obj.Header.cpusubtype;
@@ -90,8 +85,6 @@ Error MachOWriter::writeHeader(raw_ostream &OS) {
   auto header_size =
       is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
   OS.write((const char *)&Header, header_size);
-
-  return Error::success();
 }
 
 template <typename SectionType>
@@ -212,7 +205,7 @@ void MachOWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
     ZeroFillBytes(OS, Offset - currOffset);
 }
 
-Error MachOWriter::writeLoadCommands(raw_ostream &OS) {
+void MachOWriter::writeLoadCommands(raw_ostream &OS) {
   for (auto &LC : Obj.LoadCommands) {
     size_t BytesWritten = 0;
     llvm::MachO::macho_load_command Data = LC.Data;
@@ -259,10 +252,9 @@ Error MachOWriter::writeLoadCommands(raw_ostream &OS) {
       ZeroFillBytes(OS, BytesRemaining);
     }
   }
-  return Error::success();
 }
 
-Error MachOWriter::writeSectionData(raw_ostream &OS) {
+void MachOWriter::writeSectionData(raw_ostream &OS) {
   bool FoundLinkEditSeg = false;
   for (auto &LC : Obj.LoadCommands) {
     switch (LC.Data.load_command_data.cmd) {
@@ -273,8 +265,7 @@ Error MachOWriter::writeSectionData(raw_ostream &OS) {
       if (0 ==
           strncmp(&LC.Data.segment_command_data.segname[0], "__LINKEDIT", 16)) {
         FoundLinkEditSeg = true;
-        if (auto Err = writeLinkEditData(OS))
-          return Err;
+        writeLinkEditData(OS);
       }
       for (auto &Sec : LC.Sections) {
         ZeroToOffset(OS, Sec.offset);
@@ -326,11 +317,8 @@ Error MachOWriter::writeSectionData(raw_ostream &OS) {
   }
   // Old PPC Object Files didn't have __LINKEDIT segments, the data was just
   // stuck at the end of the file.
-  if (!FoundLinkEditSeg) {
-    if (auto Err = writeLinkEditData(OS))
-      return Err;
-  }
-  return Error::success();
+  if (!FoundLinkEditSeg)
+    writeLinkEditData(OS);
 }
 
 void MachOWriter::writeBindOpcodes(
@@ -377,9 +365,8 @@ void MachOWriter::dumpExportEntry(raw_ostream &OS,
     dumpExportEntry(OS, EE);
 }
 
-Error MachOWriter::writeExportTrie(raw_ostream &OS) {
+void MachOWriter::writeExportTrie(raw_ostream &OS) {
   dumpExportEntry(OS, Obj.LinkEdit.ExportTrie);
-  return Error::success();
 }
 
 template <typename NListType>
@@ -397,8 +384,8 @@ void writeNListEntry(MachOYAML::NListEntry &NLE, raw_ostream &OS,
   OS.write(reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));
 }
 
-Error MachOWriter::writeLinkEditData(raw_ostream &OS) {
-  typedef Error (MachOWriter::*writeHandler)(raw_ostream &);
+void MachOWriter::writeLinkEditData(raw_ostream &OS) {
+  typedef void (MachOWriter::*writeHandler)(raw_ostream &);
   typedef std::pair<uint64_t, writeHandler> writeOperation;
   std::vector<writeOperation> WriteQueue;
 
@@ -435,57 +422,47 @@ Error MachOWriter::writeLinkEditData(raw_ostream &OS) {
 
   for (auto writeOp : WriteQueue) {
     ZeroToOffset(OS, writeOp.first);
-    if (auto Err = (this->*writeOp.second)(OS))
-      return Err;
+    (this->*writeOp.second)(OS);
   }
-
-  return Error::success();
 }
 
-Error MachOWriter::writeRebaseOpcodes(raw_ostream &OS) {
+void MachOWriter::writeRebaseOpcodes(raw_ostream &OS) {
   MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
 
   for (auto Opcode : LinkEdit.RebaseOpcodes) {
     uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
     OS.write(reinterpret_cast<char *>(&OpByte), 1);
-    for (auto Data : Opcode.ExtraData) {
+    for (auto Data : Opcode.ExtraData)
       encodeULEB128(Data, OS);
-    }
   }
-  return Error::success();
 }
 
-Error MachOWriter::writeBasicBindOpcodes(raw_ostream &OS) {
+void MachOWriter::writeBasicBindOpcodes(raw_ostream &OS) {
   writeBindOpcodes(OS, Obj.LinkEdit.BindOpcodes);
-  return Error::success();
 }
 
-Error MachOWriter::writeWeakBindOpcodes(raw_ostream &OS) {
+void MachOWriter::writeWeakBindOpcodes(raw_ostream &OS) {
   writeBindOpcodes(OS, Obj.LinkEdit.WeakBindOpcodes);
-  return Error::success();
 }
 
-Error MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) {
+void MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) {
   writeBindOpcodes(OS, Obj.LinkEdit.LazyBindOpcodes);
-  return Error::success();
 }
 
-Error MachOWriter::writeNameList(raw_ostream &OS) {
+void MachOWriter::writeNameList(raw_ostream &OS) {
   for (auto NLE : Obj.LinkEdit.NameList) {
     if (is64Bit)
       writeNListEntry<MachO::nlist_64>(NLE, OS, Obj.IsLittleEndian);
     else
       writeNListEntry<MachO::nlist>(NLE, OS, Obj.IsLittleEndian);
   }
-  return Error::success();
 }
 
-Error MachOWriter::writeStringTable(raw_ostream &OS) {
+void MachOWriter::writeStringTable(raw_ostream &OS) {
   for (auto Str : Obj.LinkEdit.StringTable) {
     OS.write(Str.data(), Str.size());
     OS.write('\0');
   }
-  return Error::success();
 }
 
 class UniversalWriter {
@@ -493,11 +470,11 @@ public:
   UniversalWriter(yaml::YamlObjectFile &ObjectFile)
       : ObjectFile(ObjectFile), fileStart(0) {}
 
-  Error writeMachO(raw_ostream &OS);
+  void writeMachO(raw_ostream &OS);
 
 private:
-  Error writeFatHeader(raw_ostream &OS);
-  Error writeFatArchs(raw_ostream &OS);
+  void writeFatHeader(raw_ostream &OS);
+  void writeFatArchs(raw_ostream &OS);
 
   void ZeroToOffset(raw_ostream &OS, size_t offset);
 
@@ -505,30 +482,30 @@ private:
   uint64_t fileStart;
 };
 
-Error UniversalWriter::writeMachO(raw_ostream &OS) {
+void UniversalWriter::writeMachO(raw_ostream &OS) {
   fileStart = OS.tell();
   if (ObjectFile.MachO) {
     MachOWriter Writer(*ObjectFile.MachO);
-    return Writer.writeMachO(OS);
+    Writer.writeMachO(OS);
+    return;
   }
-  if (auto Err = writeFatHeader(OS))
-    return Err;
-  if (auto Err = writeFatArchs(OS))
-    return Err;
+
+  writeFatHeader(OS);
+  writeFatArchs(OS);
+
   auto &FatFile = *ObjectFile.FatMachO;
   assert(FatFile.FatArchs.size() == FatFile.Slices.size());
   for (size_t i = 0; i < FatFile.Slices.size(); i++) {
     ZeroToOffset(OS, FatFile.FatArchs[i].offset);
     MachOWriter Writer(FatFile.Slices[i]);
-    if (auto Err = Writer.writeMachO(OS))
-      return Err;
+    Writer.writeMachO(OS);
+
     auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size;
     ZeroToOffset(OS, SliceEnd);
   }
-  return Error::success();
 }
 
-Error UniversalWriter::writeFatHeader(raw_ostream &OS) {
+void UniversalWriter::writeFatHeader(raw_ostream &OS) {
   auto &FatFile = *ObjectFile.FatMachO;
   MachO::fat_header header;
   header.magic = FatFile.Header.magic;
@@ -536,7 +513,6 @@ Error UniversalWriter::writeFatHeader(raw_ostream &OS) {
   if (sys::IsLittleEndianHost)
     swapStruct(header);
   OS.write(reinterpret_cast<const char *>(&header), sizeof(MachO::fat_header));
-  return Error::success();
 }
 
 template <typename FatArchType>
@@ -572,7 +548,7 @@ void writeFatArch<MachO::fat_arch_64>(MachOYAML::FatArch &Arch,
            sizeof(MachO::fat_arch_64));
 }
 
-Error UniversalWriter::writeFatArchs(raw_ostream &OS) {
+void UniversalWriter::writeFatArchs(raw_ostream &OS) {
   auto &FatFile = *ObjectFile.FatMachO;
   bool is64Bit = FatFile.Header.magic == MachO::FAT_MAGIC_64;
   for (auto Arch : FatFile.FatArchs) {
@@ -581,8 +557,6 @@ Error UniversalWriter::writeFatArchs(raw_ostream &OS) {
     else
       writeFatArch<MachO::fat_arch>(Arch, OS);
   }
-
-  return Error::success();
 }
 
 void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
@@ -596,12 +570,9 @@ void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
 namespace llvm {
 namespace yaml {
 
-bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out) {
+bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out, ErrorHandler /*EH*/) {
   UniversalWriter Writer(Doc);
-  if (auto Err = Writer.writeMachO(Out)) {
-    errs() << toString(std::move(Err));
-    return false;
-  }
+  Writer.writeMachO(Out);
   return true;
 }
 
index cc28f96a44ad4d58b09b3cd050c69c3ef5831215..31a839e524c305cf7b156956872c0f48ef7b395c 100644 (file)
@@ -198,7 +198,8 @@ static Directory layout(BlobAllocator &File, Stream &S) {
 namespace llvm {
 namespace yaml {
 
-bool yaml2minidump(MinidumpYAML::Object &Obj, raw_ostream &Out) {
+bool yaml2minidump(MinidumpYAML::Object &Obj, raw_ostream &Out,
+                   ErrorHandler /*EH*/) {
   BlobAllocator File;
   File.allocateObject(Obj.Header);
 
index 28d469ccb977f926d9547d38689df25b40fd4d53..e374764bf13962b21e276a41fa5760472c8a58ab 100644 (file)
@@ -25,39 +25,46 @@ namespace {
 /// See docs/yaml2obj for the yaml scheema.
 class WasmWriter {
 public:
-  WasmWriter(WasmYAML::Object &Obj) : Obj(Obj) {}
+  WasmWriter(WasmYAML::Object &Obj, yaml::ErrorHandler EH)
+      : Obj(Obj), ErrHandler(EH) {}
   bool writeWasm(raw_ostream &OS);
 
 private:
-  int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
-                        uint32_t SectionIndex);
-
-  int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::EventSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::DataCountSection &Section);
+  void writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
+                         uint32_t SectionIndex);
+
+  void writeInitExpr(raw_ostream &OS, const wasm::WasmInitExpr &InitExpr);
+
+  void writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::EventSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::DataCountSection &Section);
 
   // Custom section types
-  int writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
-  int writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
-  int writeSectionContent(raw_ostream &OS,
+  void writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
+  void writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
+  void writeSectionContent(raw_ostream &OS,
                           WasmYAML::TargetFeaturesSection &Section);
   WasmYAML::Object &Obj;
   uint32_t NumImportedFunctions = 0;
   uint32_t NumImportedGlobals = 0;
   uint32_t NumImportedEvents = 0;
+
+  bool HasError = false;
+  yaml::ErrorHandler ErrHandler;
+  void reportError(const Twine &Msg);
 };
 
 class SubSectionWriter {
@@ -115,7 +122,13 @@ static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
   return 0;
 }
 
-static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
+void WasmWriter::reportError(const Twine &Msg) {
+  ErrHandler(Msg);
+  HasError = true;
+}
+
+void WasmWriter::writeInitExpr(raw_ostream &OS,
+                               const wasm::WasmInitExpr &InitExpr) {
   writeUint8(OS, InitExpr.Opcode);
   switch (InitExpr.Opcode) {
   case wasm::WASM_OPCODE_I32_CONST:
@@ -134,29 +147,26 @@ static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
     encodeULEB128(InitExpr.Value.Global, OS);
     break;
   default:
-    errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n";
-    return 1;
+    reportError("unknown opcode in init_expr: " + Twine(InitExpr.Opcode));
+    return;
   }
   writeUint8(OS, wasm::WASM_OPCODE_END);
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::DylinkSection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::DylinkSection &Section) {
   writeStringRef(Section.Name, OS);
   encodeULEB128(Section.MemorySize, OS);
   encodeULEB128(Section.MemoryAlignment, OS);
   encodeULEB128(Section.TableSize, OS);
   encodeULEB128(Section.TableAlignment, OS);
   encodeULEB128(Section.Needed.size(), OS);
-  for (StringRef Needed : Section.Needed) {
+  for (StringRef Needed : Section.Needed)
     writeStringRef(Needed, OS);
-  }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::LinkingSection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::LinkingSection &Section) {
   writeStringRef(Section.Name, OS);
   encodeULEB128(Section.Version, OS);
 
@@ -240,12 +250,10 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
     }
     SubSection.done();
   }
-
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::NameSection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::NameSection &Section) {
   writeStringRef(Section.Name, OS);
   if (Section.FunctionNames.size()) {
     writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
@@ -260,16 +268,15 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
 
     SubSection.done();
   }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::ProducersSection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::ProducersSection &Section) {
   writeStringRef(Section.Name, OS);
   int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
                int(!Section.SDKs.empty());
   if (Fields == 0)
-    return 0;
+    return;
   encodeULEB128(Fields, OS);
   for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
                       std::make_pair(StringRef("processed-by"), &Section.Tools),
@@ -283,52 +290,44 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
       writeStringRef(Entry.Version, OS);
     }
   }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::TargetFeaturesSection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::TargetFeaturesSection &Section) {
   writeStringRef(Section.Name, OS);
   encodeULEB128(Section.Features.size(), OS);
   for (auto &E : Section.Features) {
     writeUint8(OS, E.Prefix);
     writeStringRef(E.Name, OS);
   }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::CustomSection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::CustomSection &Section) {
   if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
-    if (auto Err = writeSectionContent(OS, *S))
-      return Err;
+    writeSectionContent(OS, *S);
   } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
-    if (auto Err = writeSectionContent(OS, *S))
-      return Err;
+    writeSectionContent(OS, *S);
   } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
-    if (auto Err = writeSectionContent(OS, *S))
-      return Err;
+    writeSectionContent(OS, *S);
   } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
-    if (auto Err = writeSectionContent(OS, *S))
-      return Err;
+    writeSectionContent(OS, *S);
   } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
-    if (auto Err = writeSectionContent(OS, *S))
-      return Err;
+    writeSectionContent(OS, *S);
   } else {
     writeStringRef(Section.Name, OS);
     Section.Payload.writeAsBinary(OS);
   }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
+void WasmWriter::writeSectionContent(raw_ostream &OS,
                                     WasmYAML::TypeSection &Section) {
   encodeULEB128(Section.Signatures.size(), OS);
   uint32_t ExpectedIndex = 0;
   for (const WasmYAML::Signature &Sig : Section.Signatures) {
     if (Sig.Index != ExpectedIndex) {
-      errs() << "Unexpected type index: " << Sig.Index << "\n";
-      return 1;
+      reportError("unexpected type index: " + Twine(Sig.Index));
+      return;
     }
     ++ExpectedIndex;
     writeUint8(OS, Sig.Form);
@@ -342,10 +341,9 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
       writeUint8(OS, Sig.ReturnType);
     }
   }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
+void WasmWriter::writeSectionContent(raw_ostream &OS,
                                     WasmYAML::ImportSection &Section) {
   encodeULEB128(Section.Imports.size(), OS);
   for (const WasmYAML::Import &Import : Section.Imports) {
@@ -375,23 +373,20 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
       writeLimits(Import.TableImport.TableLimits, OS);
       break;
     default:
-      errs() << "Unknown import type: " << Import.Kind << "\n";
-      return 1;
+      reportError("unknown import type: " +Twine(Import.Kind));
+      return;
     }
   }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::FunctionSection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::FunctionSection &Section) {
   encodeULEB128(Section.FunctionTypes.size(), OS);
-  for (uint32_t FuncType : Section.FunctionTypes) {
+  for (uint32_t FuncType : Section.FunctionTypes)
     encodeULEB128(FuncType, OS);
-  }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
+void WasmWriter::writeSectionContent(raw_ostream &OS,
                                     WasmYAML::ExportSection &Section) {
   encodeULEB128(Section.Exports.size(), OS);
   for (const WasmYAML::Export &Export : Section.Exports) {
@@ -399,83 +394,74 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
     writeUint8(OS, Export.Kind);
     encodeULEB128(Export.Index, OS);
   }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::StartSection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::StartSection &Section) {
   encodeULEB128(Section.StartFunction, OS);
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::TableSection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::TableSection &Section) {
   encodeULEB128(Section.Tables.size(), OS);
   for (auto &Table : Section.Tables) {
     writeUint8(OS, Table.ElemType);
     writeLimits(Table.TableLimits, OS);
   }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::MemorySection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::MemorySection &Section) {
   encodeULEB128(Section.Memories.size(), OS);
-  for (const WasmYAML::Limits &Mem : Section.Memories) {
+  for (const WasmYAML::Limits &Mem : Section.Memories)
     writeLimits(Mem, OS);
-  }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::GlobalSection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::GlobalSection &Section) {
   encodeULEB128(Section.Globals.size(), OS);
   uint32_t ExpectedIndex = NumImportedGlobals;
   for (auto &Global : Section.Globals) {
     if (Global.Index != ExpectedIndex) {
-      errs() << "Unexpected global index: " << Global.Index << "\n";
-      return 1;
+      reportError("unexpected global index: " + Twine(Global.Index));
+      return;
     }
     ++ExpectedIndex;
     writeUint8(OS, Global.Type);
     writeUint8(OS, Global.Mutable);
-    writeInitExpr(Global.InitExpr, OS);
+    writeInitExpr(OS, Global.InitExpr);
   }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
+void WasmWriter::writeSectionContent(raw_ostream &OS,
                                     WasmYAML::EventSection &Section) {
   encodeULEB128(Section.Events.size(), OS);
   uint32_t ExpectedIndex = NumImportedEvents;
   for (auto &Event : Section.Events) {
     if (Event.Index != ExpectedIndex) {
-      errs() << "Unexpected event index: " << Event.Index << "\n";
-      return 1;
+      reportError("unexpected event index: " + Twine(Event.Index));
+      return;
     }
     ++ExpectedIndex;
     encodeULEB128(Event.Attribute, OS);
     encodeULEB128(Event.SigIndex, OS);
   }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::ElemSection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::ElemSection &Section) {
   encodeULEB128(Section.Segments.size(), OS);
   for (auto &Segment : Section.Segments) {
     encodeULEB128(Segment.TableIndex, OS);
-    writeInitExpr(Segment.Offset, OS);
+    writeInitExpr(OS, Segment.Offset);
 
     encodeULEB128(Segment.Functions.size(), OS);
-    for (auto &Function : Segment.Functions) {
+    for (auto &Function : Segment.Functions)
       encodeULEB128(Function, OS);
-    }
   }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
+void WasmWriter::writeSectionContent(raw_ostream &OS,
                                     WasmYAML::CodeSection &Section) {
   encodeULEB128(Section.Functions.size(), OS);
   uint32_t ExpectedIndex = NumImportedFunctions;
@@ -483,8 +469,8 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
     std::string OutString;
     raw_string_ostream StringStream(OutString);
     if (Func.Index != ExpectedIndex) {
-      errs() << "Unexpected function index: " << Func.Index << "\n";
-      return 1;
+      reportError("unexpected function index: " + Twine(Func.Index));
+      return;
     }
     ++ExpectedIndex;
 
@@ -501,31 +487,28 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
     encodeULEB128(OutString.size(), OS);
     OS << OutString;
   }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::DataSection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::DataSection &Section) {
   encodeULEB128(Section.Segments.size(), OS);
   for (auto &Segment : Section.Segments) {
     encodeULEB128(Segment.InitFlags, OS);
     if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
       encodeULEB128(Segment.MemoryIndex, OS);
     if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0)
-      writeInitExpr(Segment.Offset, OS);
+      writeInitExpr(OS, Segment.Offset);
     encodeULEB128(Segment.Content.binary_size(), OS);
     Segment.Content.writeAsBinary(OS);
   }
-  return 0;
 }
 
-int WasmWriter::writeSectionContent(raw_ostream &OS,
-                                    WasmYAML::DataCountSection &Section) {
+void WasmWriter::writeSectionContent(raw_ostream &OS,
+                                     WasmYAML::DataCountSection &Section) {
   encodeULEB128(Section.Count, OS);
-  return 0;
 }
 
-int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
+void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
                                   uint32_t SectionIndex) {
   switch (Sec.Type) {
   case wasm::WASM_SEC_CODE:
@@ -541,7 +524,6 @@ int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
   }
   default:
     llvm_unreachable("not yet implemented");
-    return 1;
   }
 
   encodeULEB128(SectionIndex, OS);
@@ -560,7 +542,6 @@ int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
       encodeULEB128(Reloc.Addend, OS);
     }
   }
-  return 0;
 }
 
 bool WasmWriter::writeWasm(raw_ostream &OS) {
@@ -575,58 +556,46 @@ bool WasmWriter::writeWasm(raw_ostream &OS) {
     if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
       SecName = S->Name;
     if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
-      errs() << "Out of order section type: " << Sec->Type << "\n";
+      reportError("out of order section type: " + Twine(Sec->Type));
       return false;
     }
     encodeULEB128(Sec->Type, OS);
     std::string OutString;
     raw_string_ostream StringStream(OutString);
-    if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get())) {
-      if (auto Err = writeSectionContent(StringStream, *S))
-        return Err;
-    } else {
-      errs() << "Unknown section type: " << Sec->Type << "\n";
+    if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))
+      writeSectionContent(StringStream, *S);
+    else
+      reportError("unknown section type: " + Twine(Sec->Type));
+
+    if (HasError)
       return false;
-    }
+
     StringStream.flush();
 
     // Write the section size followed by the content
@@ -658,8 +627,8 @@ bool WasmWriter::writeWasm(raw_ostream &OS) {
 namespace llvm {
 namespace yaml {
 
-bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out) {
-  WasmWriter Writer(Doc);
+bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
+  WasmWriter Writer(Doc, EH);
   return Writer.writeWasm(Out);
 }
 
index 8ca490bf9ca1cb414b3b5e9835b49a0f46bcc6d4..c18fa5cfdb5e788db988e28df474df2f6e15317e 100644 (file)
@@ -8,59 +8,69 @@
 
 #include "llvm/ObjectYAML/yaml2obj.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/ObjectYAML/ObjectYAML.h"
 #include "llvm/Support/Errc.h"
+#include "llvm/Support/WithColor.h"
 #include "llvm/Support/YAMLTraits.h"
 
 namespace llvm {
 namespace yaml {
 
-Error convertYAML(yaml::Input &YIn, raw_ostream &Out, unsigned DocNum) {
-  auto BoolToErr = [](bool Ret) -> Error {
-    if (!Ret)
-      return createStringError(errc::invalid_argument, "yaml2obj failed");
-    return Error::success();
-  };
-
+bool convertYAML(yaml::Input &YIn, raw_ostream &Out, ErrorHandler ErrHandler,
+                 unsigned DocNum) {
   unsigned CurDocNum = 0;
   do {
-    if (++CurDocNum == DocNum) {
-      yaml::YamlObjectFile Doc;
-      YIn >> Doc;
-      if (std::error_code EC = YIn.error())
-        return createStringError(EC, "Failed to parse YAML input!");
-      if (Doc.Elf)
-        return BoolToErr(yaml2elf(*Doc.Elf, Out));
-      if (Doc.Coff)
-        return BoolToErr(yaml2coff(*Doc.Coff, Out));
-      if (Doc.MachO || Doc.FatMachO)
-        return BoolToErr(yaml2macho(Doc, Out));
-      if (Doc.Minidump)
-        return BoolToErr(yaml2minidump(*Doc.Minidump, Out));
-      if (Doc.Wasm)
-        return BoolToErr(yaml2wasm(*Doc.Wasm, Out));
-      return createStringError(errc::invalid_argument,
-                               "Unknown document type!");
+    if (++CurDocNum != DocNum)
+      continue;
+
+    yaml::YamlObjectFile Doc;
+    YIn >> Doc;
+    if (std::error_code EC = YIn.error()) {
+      ErrHandler("failed to parse YAML input: " + EC.message());
+      return false;
     }
+
+    if (Doc.Elf)
+      return yaml2elf(*Doc.Elf, Out, ErrHandler);
+    if (Doc.Coff)
+      return yaml2coff(*Doc.Coff, Out, ErrHandler);
+    if (Doc.MachO || Doc.FatMachO)
+      return yaml2macho(Doc, Out, ErrHandler);
+    if (Doc.Minidump)
+      return yaml2minidump(*Doc.Minidump, Out, ErrHandler);
+    if (Doc.Wasm)
+      return yaml2wasm(*Doc.Wasm, Out, ErrHandler);
+
+    ErrHandler("unknown document type");
+    return false;
+
   } while (YIn.nextDocument());
 
-  return createStringError(errc::invalid_argument,
-                           "Cannot find the %u%s document", DocNum,
-                           getOrdinalSuffix(DocNum).data());
+  ErrHandler("cannot find the " + Twine(DocNum) +
+             getOrdinalSuffix(DocNum).data() + " document");
+  return false;
 }
 
-Expected<std::unique_ptr<object::ObjectFile>>
-yaml2ObjectFile(SmallVectorImpl<char> &Storage, StringRef Yaml) {
+std::unique_ptr<object::ObjectFile>
+yaml2ObjectFile(SmallVectorImpl<char> &Storage, StringRef Yaml,
+                ErrorHandler ErrHandler) {
   Storage.clear();
   raw_svector_ostream OS(Storage);
 
   yaml::Input YIn(Yaml);
-  if (Error E = convertYAML(YIn, OS))
-    return std::move(E);
+  if (!convertYAML(YIn, OS, ErrHandler))
+    return {};
+
+  Expected<std::unique_ptr<object::ObjectFile>> ObjOrErr =
+      object::ObjectFile::createObjectFile(
+          MemoryBufferRef(OS.str(), "YamlObject"));
+  if (ObjOrErr)
+    return std::move(*ObjOrErr);
 
-  return object::ObjectFile::createObjectFile(
-      MemoryBufferRef(OS.str(), "YamlObject"));
+  ErrHandler(toString(ObjOrErr.takeError()));
+  return {};
 }
 
 } // namespace yaml
index 52ad13619622ac1d5d58bd5f02fd7e685048b137..4e3581ec5ebe3298b5293b49a02cc8fc7be98a43 100644 (file)
@@ -14,7 +14,7 @@ Sections:
       - Index:           0
         Locals:          []
         Body:            0B
-  # CHECK: Out of order section type: 3
+  # CHECK: yaml2obj: error: out of order section type: 3
   - Type:            FUNCTION
     FunctionTypes:   [ 0 ]
 ...
index fd9e0b04f271fcdc6596b34f064b97d7169dcb90..3a3d8a84ad1ce5d81759348e033ef6553587ea20 100644 (file)
@@ -1,6 +1,6 @@
 # RUN: not yaml2obj %s 2>&1 | FileCheck %s
 
-## CHECK: Section alignment is too large
+## CHECK: error: section alignment is too large
 
 --- !COFF
 header:
index 948d3250556ef57596de1772fc580b8d9d4fc35c..bd3d162953492240376bd00f4e8653d86d143205 100644 (file)
@@ -31,8 +31,7 @@ DynamicSymbols:
 
 # RUN: not yaml2obj --docnum=2 %s 2>&1 | FileCheck %s --implicit-check-not=error --check-prefix=CASE2
 
-# CASE2: error: cannot specify both `Size` and `DynamicSymbols` for symbol table section '.dynsym'
-# CASE2: error: yaml2obj failed
+# CASE2: yaml2obj: error: cannot specify both `Size` and `DynamicSymbols` for symbol table section '.dynsym'
 
 --- !ELF
 FileHeader:
@@ -55,8 +54,7 @@ DynamicSymbols:
 
 # RUN: not yaml2obj --docnum=3 %s 2>&1 | FileCheck %s --implicit-check-not=error --check-prefix=CASE3
 
-# CASE3: error: cannot specify both `Content` and `DynamicSymbols` for symbol table section '.dynsym'
-# CASE3: error: yaml2obj failed
+# CASE3: yaml2obj: error: cannot specify both `Content` and `DynamicSymbols` for symbol table section '.dynsym'
 
 --- !ELF
 FileHeader:
index 9f451cab5a5ac9f7bdce278c1efce613293717b9..31a0973209f3636c512281516043e08c33a4d41a 100644 (file)
@@ -2,7 +2,7 @@
 # RUN: echo -n "" | not yaml2obj 2>&1 | FileCheck %s
 # RUN: echo " " | not yaml2obj 2>&1 | FileCheck %s
 # RUN: echo "  " | not yaml2obj 2>&1 | FileCheck %s
-# CHECK: error: Unknown document type!
+# CHECK: yaml2obj: error: unknown document type
 
 # RUN: echo -e -n "\xff" | not yaml2obj 2>&1 | FileCheck %s --check-prefix=INVALID
-# INVALID: error: Failed to parse YAML input!
+# INVALID: yaml2obj: error: failed to parse YAML input
index 0a533468eda5e0733865dab20e2d47ec089802ff..e25a033b63881bfffb6a42255c9d5696d86696fd 100644 (file)
@@ -2,10 +2,10 @@
 ## greater than the number of YAML inputs in the file.
 
 # RUN: not yaml2obj %s --docnum=3 2>&1 | FileCheck %s
-# CHECK: error: Cannot find the 3rd document
+# CHECK: yaml2obj: error: cannot find the 3rd document
 
 # RUN: not yaml2obj %s --docnum=76768677 2>&1 | FileCheck %s --check-prefix=TWO
-# TWO: error: Cannot find the 76768677th document
+# TWO: yaml2obj: error: cannot find the 76768677th document
 
 --- !ELF
 FileHeader:
index 3045a0b21f56f161d5dc8711606aa8f8c5027095..1124b49d18cc158fb8a1b1ede0c1f76eb784495b 100644 (file)
@@ -1,4 +1,4 @@
 # RUN: not yaml2obj -o %p/path/does/not/exist 2>&1 | FileCheck %s
 
 # Don't check the OS-dependent message "No such file or directory".
-# CHECK: yaml2obj: Error opening '{{.*}}/path/does/not/exist': {{.*}}
+# CHECK: yaml2obj: error: failed to open '{{.*}}/path/does/not/exist': {{.*}}
index 09cdc4bff6567b59e49d813ed02485b8cd5a3719..fd6c42114beec3177dac6d70ffc0dd6937bd458e 100644 (file)
@@ -6,4 +6,4 @@ DummyData:
 ...
 
 # CHECK: YAML:4:1: error: YAML Object File missing document type tag!
-# CHECK: error: Failed to parse YAML input!
+# CHECK: error: failed to parse YAML input
index 0b794e1006760e41c1a97b656797c2be24a8c003..327d625bfb37875b079bf0aa32fe66d90b8aa2df 100644 (file)
@@ -16,7 +16,7 @@
 # DOC2: Name: _sym2
 # DOC3: Name: _sym3
 # DOC4: Name: _sym4
-# DOC5: error: Cannot find the 5th document
+# DOC5: error: cannot find the 5th document
 
 --- !ELF
 FileHeader: !FileHeader
index c20536b47ddae3d97fc6f41e76a2221b925abe73..801fe02e05f2e43beb81842cf71da6b48f67ef30 100644 (file)
@@ -30,7 +30,6 @@ Sections:
 
 # ERR: error: unknown section referenced: '.unknown1' by YAML section '.foo'
 # ERR: error: unknown section referenced: '.unknown2' by YAML section '.bar'
-# ERR: error: yaml2obj failed
 
 --- !ELF
 FileHeader:
index bc7a1a05c59be502bdf882bbf7e19a55fb9c7f79..16b4b37dd42411483ae51c0667566454b84f7c4a 100644 (file)
@@ -175,4 +175,4 @@ Sections:
 # ERR2:      error: Section size must be greater than or equal to the content size
 # ERR2-NEXT: - Name: .data
 # ERR2-NEXT:   ^
-# ERR2-NEXT: error: Failed to parse YAML input!
+# ERR2-NEXT: error: failed to parse YAML input
index 1746357827572ced6dd7bafac1a073189e30b55d..9d6d8d9ec4c0483f6bf9e4f0a8c6b066b02c255a 100644 (file)
@@ -376,12 +376,10 @@ int writeElfStub(const llvm::Triple &T, const std::set<IFSSymbol> &Symbols,
   });
 
   yaml::Input YIn(YamlStr);
-  if (Error E = convertYAML(YIn, Out)) {
-    logAllUnhandledErrors(std::move(E), WithColor::error(errs(), "llvm-ifs"));
-    return 1;
-  }
-
-  return 0;
+  auto ErrHandler = [](const Twine &Msg) {
+    WithColor::error(errs(), "llvm-ifs") << Msg << "\n";
+  };
+  return convertYAML(YIn, Out, ErrHandler) ? 0 : 1;
 }
 
 int writeIfso(const IFSStub &Stub, bool IsWriteIfs, raw_ostream &Out) {
index 76e6663c095d293cd03299ce3921bba245c17c86..66e0da69881dfae967d0c2c3e78aa657d289a5c5 100644 (file)
@@ -38,11 +38,6 @@ DocNum("docnum", cl::init(1),
 static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
                                            cl::value_desc("filename"));
 
-LLVM_ATTRIBUTE_NORETURN static void error(Twine Message) {
-  errs() << Message << "\n";
-  exit(1);
-}
-
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
   cl::ParseCommandLineOptions(argc, argv);
@@ -50,11 +45,17 @@ int main(int argc, char **argv) {
   if (OutputFilename.empty())
     OutputFilename = "-";
 
+  auto ErrHandler = [](const Twine &Msg) {
+    WithColor::error(errs(), "yaml2obj") << Msg << "\n";
+  };
+
   std::error_code EC;
   std::unique_ptr<ToolOutputFile> Out(
       new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None));
-  if (EC)
-    error("yaml2obj: Error opening '" + OutputFilename + "': " + EC.message());
+  if (EC) {
+    ErrHandler("failed to open '" + OutputFilename + "': " + EC.message());
+    return 1;
+  }
 
   ErrorOr<std::unique_ptr<MemoryBuffer>> Buf =
       MemoryBuffer::getFileOrSTDIN(Input);
@@ -62,10 +63,8 @@ int main(int argc, char **argv) {
     return 1;
 
   yaml::Input YIn(Buf.get()->getBuffer());
-  if (Error E = convertYAML(YIn, Out->os(), DocNum)) {
-    logAllUnhandledErrors(std::move(E), WithColor::error(errs(), argv[0]));
+  if (!convertYAML(YIn, Out->os(), ErrHandler, DocNum))
     return 1;
-  }
 
   Out->keep();
   Out->os().flush();
index 6df9536e9d3bf4f17abb1f0ee9c6328074a5c026..576d8a09dfdbaca7a21a6acea3d4ace65f1e0f35 100644 (file)
@@ -20,8 +20,9 @@ toBinary(SmallVectorImpl<char> &Storage, StringRef Yaml) {
   Storage.clear();
   raw_svector_ostream OS(Storage);
   yaml::Input YIn(Yaml);
-  if (Error E = yaml::convertYAML(YIn, OS))
-    return std::move(E);
+  if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {}))
+    return createStringError(std::errc::invalid_argument,
+                             "unable to convert YAML");
 
   return object::MinidumpFile::create(MemoryBufferRef(OS.str(), "Binary"));
 }
index 0a383881687b646749ba41449dfa5fe0469b2ad6..8fafca4f908f80cc931d9ef26f47c7cff92aae86 100644 (file)
@@ -10,6 +10,7 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/YAMLTraits.h"
 #include "llvm/Testing/Support/Error.h"
 #include "gtest/gtest.h"
 
@@ -18,19 +19,63 @@ using namespace object;
 using namespace yaml;
 
 TEST(yaml2ObjectFile, ELF) {
+  bool ErrorReported = false;
+  auto ErrHandler = [&](const Twine &Msg) { ErrorReported = true; };
+
+  SmallString<0> Storage;
+  std::unique_ptr<ObjectFile> Obj = yaml2ObjectFile(Storage, R"(
+--- !ELF
+FileHeader:
+  Class:    ELFCLASS64
+  Data:     ELFDATA2LSB
+  Type:     ET_REL
+  Machine:  EM_X86_64)", ErrHandler);
+
+  ASSERT_FALSE(ErrorReported);
+  ASSERT_TRUE(Obj);
+  ASSERT_TRUE(Obj->isELF());
+  ASSERT_TRUE(Obj->isRelocatableObject());
+}
+
+TEST(yaml2ObjectFile, Errors) {
+  std::vector<std::string> Errors;
+  auto ErrHandler = [&](const Twine &Msg) {
+    Errors.push_back("ObjectYAML: " + Msg.str());
+  };
+
   SmallString<0> Storage;
-  Expected<std::unique_ptr<ObjectFile>> ErrOrObj = yaml2ObjectFile(Storage, R"(
+  StringRef Yaml = R"(
 --- !ELF
 FileHeader:
   Class:    ELFCLASS64
   Data:     ELFDATA2LSB
   Type:     ET_REL
-  Machine:  EM_X86_64)");
+  Machine:  EM_X86_64
+Symbols:
+  - Name: foo
+  - Name: foo
+  - Name: foo
+)";
+
+  // 1. Test yaml2ObjectFile().
+
+  std::unique_ptr<ObjectFile> Obj = yaml2ObjectFile(Storage, Yaml, ErrHandler);
+
+  ASSERT_FALSE(Obj);
+  ASSERT_TRUE(Errors.size() == 2);
+  ASSERT_TRUE(Errors[0] == "ObjectYAML: repeated symbol name: 'foo'");
+  ASSERT_TRUE(Errors[1] == Errors[0]);
 
-  ASSERT_THAT_EXPECTED(ErrOrObj, Succeeded());
+  // 2. Test convertYAML(). 
 
-  std::unique_ptr<ObjectFile> ObjFile = std::move(ErrOrObj.get());
+  Errors.clear();
+  Storage.clear();
+  raw_svector_ostream OS(Storage);
 
-  ASSERT_TRUE(ObjFile->isELF());
-  ASSERT_TRUE(ObjFile->isRelocatableObject());
+  yaml::Input YIn(Yaml);
+  bool Res = convertYAML(YIn, OS, ErrHandler);
+  ASSERT_FALSE(Res);
+  ASSERT_TRUE(Errors.size() == 2);
+  ASSERT_TRUE(Errors[0] == "ObjectYAML: repeated symbol name: 'foo'");
+  ASSERT_TRUE(Errors[1] == Errors[0]);
 }