Port the error functions from ELF to COFF.
authorRafael Espindola <rafael.espindola@gmail.com>
Thu, 6 Aug 2015 14:58:50 +0000 (14:58 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Thu, 6 Aug 2015 14:58:50 +0000 (14:58 +0000)
This has a few advantages

* Less C++ code (about 300 lines less).
* Less machine code (about 14 KB of text on a linux x86_64 build).
* It is more debugger friendly. Just set a breakpoint on the exit function and
  you get the complete lld stack trace of when the error was found.
* It is a more robust API. The errors are handled early and we don't get a
  std::error_code hot potato being passed around.
* In most cases the error function in a better position to print diagnostics
  (it has more context).

llvm-svn: 244215

18 files changed:
lld/COFF/CMakeLists.txt
lld/COFF/Chunks.cpp
lld/COFF/Driver.cpp
lld/COFF/Driver.h
lld/COFF/DriverUtils.cpp
lld/COFF/Error.cpp [new file with mode: 0644]
lld/COFF/Error.h
lld/COFF/InputFiles.cpp
lld/COFF/InputFiles.h
lld/COFF/ModuleDef.cpp
lld/COFF/SymbolTable.cpp
lld/COFF/SymbolTable.h
lld/COFF/Symbols.cpp
lld/COFF/Symbols.h
lld/COFF/Writer.cpp
lld/COFF/Writer.h
lld/include/lld/Driver/Driver.h
lld/lib/Driver/UniversalDriver.cpp

index fe90454..2bfd93b 100644 (file)
@@ -7,6 +7,7 @@ add_llvm_library(lldCOFF
   DLL.cpp
   Driver.cpp
   DriverUtils.cpp
+  Error.cpp
   ICF.cpp
   InputFiles.cpp
   ModuleDef.cpp
index fe8b990..8533fa7 100644 (file)
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Chunks.h"
+#include "Error.h"
 #include "InputFiles.h"
 #include "Symbols.h"
 #include "llvm/Object/COFF.h"
@@ -60,7 +61,7 @@ void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym,
   case IMAGE_REL_AMD64_SECTION:  add16(Off, Sym->getSectionIndex()); break;
   case IMAGE_REL_AMD64_SECREL:   add32(Off, Sym->getSecrel()); break;
   default:
-    llvm::report_fatal_error("Unsupported relocation type");
+    error("Unsupported relocation type");
   }
 }
 
@@ -75,7 +76,7 @@ void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym,
   case IMAGE_REL_I386_SECTION:  add16(Off, Sym->getSectionIndex()); break;
   case IMAGE_REL_I386_SECREL:   add32(Off, Sym->getSecrel()); break;
   default:
-    llvm::report_fatal_error("Unsupported relocation type");
+    error("Unsupported relocation type");
   }
 }
 
@@ -119,7 +120,7 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym,
   case IMAGE_REL_ARM_BRANCH24T: applyBranch24T(Off, S - P - 4); break;
   case IMAGE_REL_ARM_BLX23T:    applyBranch24T(Off, S - P - 4); break;
   default:
-    llvm::report_fatal_error("Unsupported relocation type");
+    error("Unsupported relocation type");
   }
 }
 
index 088e536..d363230 100644 (file)
@@ -43,7 +43,7 @@ namespace coff {
 Configuration *Config;
 LinkerDriver *Driver;
 
-bool link(llvm::ArrayRef<const char *> Args) {
+void link(llvm::ArrayRef<const char *> Args) {
   auto C = make_unique<Configuration>();
   Config = C.get();
   auto D = make_unique<LinkerDriver>();
@@ -60,11 +60,10 @@ static std::string getOutputPath(StringRef Path) {
 
 // Opens a file. Path has to be resolved already.
 // Newly created memory buffers are owned by this driver.
-ErrorOr<MemoryBufferRef> LinkerDriver::openFile(StringRef Path) {
+MemoryBufferRef LinkerDriver::openFile(StringRef Path) {
   auto MBOrErr = MemoryBuffer::getFile(Path);
-  if (auto EC = MBOrErr.getError())
-    return EC;
-  std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get());
+  error(MBOrErr, Twine("Could not open ") + Path);
+  std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
   MemoryBufferRef MBRef = MB->getMemBufferRef();
   OwningMBs.push_back(std::move(MB)); // take ownership
   return MBRef;
@@ -84,46 +83,35 @@ static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB) {
 
 // Parses .drectve section contents and returns a list of files
 // specified by /defaultlib.
-std::error_code
-LinkerDriver::parseDirectives(StringRef S) {
-  auto ArgsOrErr = Parser.parse(S);
-  if (auto EC = ArgsOrErr.getError())
-    return EC;
-  llvm::opt::InputArgList Args = std::move(ArgsOrErr.get());
+void LinkerDriver::parseDirectives(StringRef S) {
+  llvm::opt::InputArgList Args = Parser.parse(S);
 
   for (auto *Arg : Args) {
     switch (Arg->getOption().getID()) {
     case OPT_alternatename:
-      if (auto EC = parseAlternateName(Arg->getValue()))
-        return EC;
+      parseAlternateName(Arg->getValue());
       break;
     case OPT_defaultlib:
       if (Optional<StringRef> Path = findLib(Arg->getValue())) {
-        ErrorOr<MemoryBufferRef> MBOrErr = openFile(*Path);
-        if (auto EC = MBOrErr.getError())
-          return EC;
-        Symtab.addFile(createFile(MBOrErr.get()));
+        MemoryBufferRef MB = openFile(*Path);
+        Symtab.addFile(createFile(MB));
       }
       break;
     case OPT_export: {
-      ErrorOr<Export> E = parseExport(Arg->getValue());
-      if (auto EC = E.getError())
-        return EC;
-      if (Config->Machine == I386 && E->ExtName.startswith("_"))
-        E->ExtName = E->ExtName.substr(1);
-      Config->Exports.push_back(E.get());
+      Export E = parseExport(Arg->getValue());
+      if (Config->Machine == I386 && E.ExtName.startswith("_"))
+        E.ExtName = E.ExtName.substr(1);
+      Config->Exports.push_back(E);
       break;
     }
     case OPT_failifmismatch:
-      if (auto EC = checkFailIfMismatch(Arg->getValue()))
-        return EC;
+      checkFailIfMismatch(Arg->getValue());
       break;
     case OPT_incl:
       addUndefined(Arg->getValue());
       break;
     case OPT_merge:
-      if (auto EC = parseMerge(Arg->getValue()))
-        return EC;
+      parseMerge(Arg->getValue());
       break;
     case OPT_nodefaultlib:
       Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()));
@@ -131,11 +119,9 @@ LinkerDriver::parseDirectives(StringRef S) {
     case OPT_throwingnew:
       break;
     default:
-      llvm::errs() << Arg->getSpelling() << " is not allowed in .drectve\n";
-      return make_error_code(LLDError::InvalidOption);
+      error(Twine(Arg->getSpelling()) + " is not allowed in .drectve");
     }
   }
-  return std::error_code();
 }
 
 // Find file from search paths. You can omit ".obj", this function takes
@@ -253,7 +239,7 @@ static uint64_t getDefaultImageBase() {
   return Config->DLL ? 0x10000000 : 0x400000;
 }
 
-bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
+void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
   // Needed for LTO.
   llvm::InitializeAllTargetInfos();
   llvm::InitializeAllTargets();
@@ -265,26 +251,20 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
   // If the first command line argument is "/lib", link.exe acts like lib.exe.
   // We call our own implementation of lib.exe that understands bitcode files.
   if (ArgsArr.size() > 1 && StringRef(ArgsArr[1]).equals_lower("/lib"))
-    return llvm::libDriverMain(ArgsArr.slice(1)) == 0;
+    if (llvm::libDriverMain(ArgsArr.slice(1)) != 0)
+      error("lib failed");
 
   // Parse command line options.
-  auto ArgsOrErr = Parser.parseLINK(ArgsArr.slice(1));
-  if (auto EC = ArgsOrErr.getError()) {
-    llvm::errs() << EC.message() << "\n";
-    return false;
-  }
-  llvm::opt::InputArgList Args = std::move(ArgsOrErr.get());
+  llvm::opt::InputArgList Args = Parser.parseLINK(ArgsArr.slice(1));
 
   // Handle /help
   if (Args.hasArg(OPT_help)) {
     printHelp(ArgsArr[0]);
-    return true;
+    return;
   }
 
-  if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end()) {
-    llvm::errs() << "no input files.\n";
-    return false;
-  }
+  if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end())
+    error("no input files.");
 
   // Construct search path list.
   SearchPaths.push_back("");
@@ -310,10 +290,8 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
 
   // Handle /noentry
   if (Args.hasArg(OPT_noentry)) {
-    if (!Args.hasArg(OPT_dll)) {
-      llvm::errs() << "/noentry must be specified with /dll\n";
-      return false;
-    }
+    if (!Args.hasArg(OPT_dll))
+      error("/noentry must be specified with /dll");
     Config->NoEntry = true;
   }
 
@@ -325,21 +303,15 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
 
   // Handle /fixed
   if (Args.hasArg(OPT_fixed)) {
-    if (Args.hasArg(OPT_dynamicbase)) {
-      llvm::errs() << "/fixed must not be specified with /dynamicbase\n";
-      return false;
-    }
+    if (Args.hasArg(OPT_dynamicbase))
+      error("/fixed must not be specified with /dynamicbase");
     Config->Relocatable = false;
     Config->DynamicBase = false;
   }
 
   // Handle /machine
-  if (auto *Arg = Args.getLastArg(OPT_machine)) {
-    ErrorOr<MachineTypes> MTOrErr = getMachineType(Arg->getValue());
-    if (MTOrErr.getError())
-      return false;
-    Config->Machine = MTOrErr.get();
-  }
+  if (auto *Arg = Args.getLastArg(OPT_machine))
+    Config->Machine = getMachineType(Arg->getValue());
 
   // Handle /nodefaultlib:<filename>
   for (auto *Arg : Args.filtered(OPT_nodefaultlib))
@@ -350,54 +322,30 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
     Config->NoDefaultLibAll = true;
 
   // Handle /base
-  if (auto *Arg = Args.getLastArg(OPT_base)) {
-    if (auto EC = parseNumbers(Arg->getValue(), &Config->ImageBase)) {
-      llvm::errs() << "/base: " << EC.message() << "\n";
-      return false;
-    }
-  }
+  if (auto *Arg = Args.getLastArg(OPT_base))
+    parseNumbers(Arg->getValue(), &Config->ImageBase);
 
   // Handle /stack
-  if (auto *Arg = Args.getLastArg(OPT_stack)) {
-    if (auto EC = parseNumbers(Arg->getValue(), &Config->StackReserve,
-                               &Config->StackCommit)) {
-      llvm::errs() << "/stack: " << EC.message() << "\n";
-      return false;
-    }
-  }
+  if (auto *Arg = Args.getLastArg(OPT_stack))
+    parseNumbers(Arg->getValue(), &Config->StackReserve, &Config->StackCommit);
 
   // Handle /heap
-  if (auto *Arg = Args.getLastArg(OPT_heap)) {
-    if (auto EC = parseNumbers(Arg->getValue(), &Config->HeapReserve,
-                               &Config->HeapCommit)) {
-      llvm::errs() << "/heap: " << EC.message() << "\n";
-      return false;
-    }
-  }
+  if (auto *Arg = Args.getLastArg(OPT_heap))
+    parseNumbers(Arg->getValue(), &Config->HeapReserve, &Config->HeapCommit);
 
   // Handle /version
-  if (auto *Arg = Args.getLastArg(OPT_version)) {
-    if (auto EC = parseVersion(Arg->getValue(), &Config->MajorImageVersion,
-                               &Config->MinorImageVersion)) {
-      llvm::errs() << "/version: " << EC.message() << "\n";
-      return false;
-    }
-  }
+  if (auto *Arg = Args.getLastArg(OPT_version))
+    parseVersion(Arg->getValue(), &Config->MajorImageVersion,
+                 &Config->MinorImageVersion);
 
   // Handle /subsystem
-  if (auto *Arg = Args.getLastArg(OPT_subsystem)) {
-    if (auto EC = parseSubsystem(Arg->getValue(), &Config->Subsystem,
-                                 &Config->MajorOSVersion,
-                                 &Config->MinorOSVersion)) {
-      llvm::errs() << "/subsystem: " << EC.message() << "\n";
-      return false;
-    }
-  }
+  if (auto *Arg = Args.getLastArg(OPT_subsystem))
+    parseSubsystem(Arg->getValue(), &Config->Subsystem, &Config->MajorOSVersion,
+                   &Config->MinorOSVersion);
 
   // Handle /alternatename
   for (auto *Arg : Args.filtered(OPT_alternatename))
-    if (parseAlternateName(Arg->getValue()))
-      return false;
+    parseAlternateName(Arg->getValue());
 
   // Handle /include
   for (auto *Arg : Args.filtered(OPT_incl))
@@ -421,36 +369,25 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
     if (S != "ref" && S != "icf" && S != "noicf" &&
         S != "lbr" && S != "nolbr" &&
         !StringRef(S).startswith("icf=")) {
-      llvm::errs() << "/opt: unknown option: " << S << "\n";
-      return false;
+      error(Twine("/opt: unknown option: ") + S);
     }
   }
 
   // Handle /failifmismatch
   for (auto *Arg : Args.filtered(OPT_failifmismatch))
-    if (checkFailIfMismatch(Arg->getValue()))
-      return false;
+    checkFailIfMismatch(Arg->getValue());
 
   // Handle /merge
   for (auto *Arg : Args.filtered(OPT_merge))
-    if (parseMerge(Arg->getValue()))
-      return false;
+    parseMerge(Arg->getValue());
 
   // Handle /manifest
-  if (auto *Arg = Args.getLastArg(OPT_manifest_colon)) {
-    if (auto EC = parseManifest(Arg->getValue())) {
-      llvm::errs() << "/manifest: " << EC.message() << "\n";
-      return false;
-    }
-  }
+  if (auto *Arg = Args.getLastArg(OPT_manifest_colon))
+    parseManifest(Arg->getValue());
 
   // Handle /manifestuac
-  if (auto *Arg = Args.getLastArg(OPT_manifestuac)) {
-    if (auto EC = parseManifestUAC(Arg->getValue())) {
-      llvm::errs() << "/manifestuac: " << EC.message() << "\n";
-      return false;
-    }
-  }
+  if (auto *Arg = Args.getLastArg(OPT_manifestuac))
+    parseManifestUAC(Arg->getValue());
 
   // Handle /manifestdependency
   if (auto *Arg = Args.getLastArg(OPT_manifestdependency))
@@ -482,21 +419,12 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
   for (auto *Arg : Args.filtered(OPT_defaultlib))
     if (Optional<StringRef> Path = findLib(Arg->getValue()))
       Paths.push_back(*Path);
-  for (StringRef Path : Paths) {
-    ErrorOr<MemoryBufferRef> MBOrErr = openFile(Path);
-    if (auto EC = MBOrErr.getError()) {
-      llvm::errs() << "cannot open " << Path << ": " << EC.message() << "\n";
-      return false;
-    }
-    MBs.push_back(MBOrErr.get());
-  }
+  for (StringRef Path : Paths)
+    MBs.push_back(openFile(Path));
 
   // Windows specific -- Create a resource file containing a manifest file.
   if (Config->Manifest == Configuration::Embed) {
-    auto MBOrErr = createManifestRes();
-    if (MBOrErr.getError())
-      return false;
-    std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get());
+    std::unique_ptr<MemoryBuffer> MB = createManifestRes();
     MBs.push_back(MB->getMemBufferRef());
     OwningMBs.push_back(std::move(MB)); // take ownership
   }
@@ -518,10 +446,7 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
   // doesn't read files that are specified by directive sections.
   for (MemoryBufferRef MB : MBs)
     Symtab.addFile(createFile(MB));
-  if (auto EC = Symtab.step()) {
-    llvm::errs() << EC.message() << "\n";
-    return false;
-  }
+  Symtab.step();
 
   // Determine machine type and check if all object files are
   // for the same CPU type. Note that this needs to be done before
@@ -534,12 +459,9 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
       Config->Machine = MT;
       continue;
     }
-    if (Config->Machine != MT) {
-      llvm::errs() << File->getShortName() << ": machine type "
-                   << machineToStr(MT) << " conflicts with "
-                   << machineToStr(Config->Machine) << "\n";
-      return false;
-    }
+    if (Config->Machine != MT)
+      error(Twine(File->getShortName()) + ": machine type " + machineToStr(MT) +
+            " conflicts with " + machineToStr(Config->Machine));
   }
   if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
     llvm::errs() << "warning: /machine is not specified. x64 is assumed.\n";
@@ -548,10 +470,7 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
 
   // Windows specific -- Convert Windows resource files to a COFF file.
   if (!Resources.empty()) {
-    auto MBOrErr = convertResToCOFF(Resources);
-    if (MBOrErr.getError())
-      return false;
-    std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get());
+    std::unique_ptr<MemoryBuffer> MB = convertResToCOFF(Resources);
     Symtab.addFile(createFile(MB->getMemBufferRef()));
     OwningMBs.push_back(std::move(MB)); // take ownership
   }
@@ -575,10 +494,8 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
     // Windows specific -- If entry point name is not given, we need to
     // infer that from user-defined entry name.
     StringRef S = findDefaultEntry();
-    if (S.empty()) {
-      llvm::errs() << "entry point must be defined\n";
-      return false;
-    }
+    if (S.empty())
+      error("entry point must be defined");
     Config->Entry = addUndefined(S);
     if (Config->Verbose)
       llvm::outs() << "Entry name inferred: " << S << "\n";
@@ -586,24 +503,17 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
 
   // Handle /export
   for (auto *Arg : Args.filtered(OPT_export)) {
-    ErrorOr<Export> E = parseExport(Arg->getValue());
-    if (E.getError())
-      return false;
-    if (Config->Machine == I386 && !E->Name.startswith("_@?"))
-      E->Name = mangle(E->Name);
-    Config->Exports.push_back(E.get());
+    Export E = parseExport(Arg->getValue());
+    if (Config->Machine == I386 && !E.Name.startswith("_@?"))
+      E.Name = mangle(E.Name);
+    Config->Exports.push_back(E);
   }
 
   // Handle /def
   if (auto *Arg = Args.getLastArg(OPT_deffile)) {
-    ErrorOr<MemoryBufferRef> MBOrErr = openFile(Arg->getValue());
-    if (auto EC = MBOrErr.getError()) {
-      llvm::errs() << "/def: " << EC.message() << "\n";
-      return false;
-    }
+    MemoryBufferRef MB = openFile(Arg->getValue());
     // parseModuleDefs mutates Config object.
-    if (parseModuleDefs(MBOrErr.get(), &Alloc))
-      return false;
+    parseModuleDefs(MB, &Alloc);
   }
 
   // Handle /delayload
@@ -628,10 +538,7 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
   Config->LoadConfigUsed = mangle("_load_config_used");
 
   // Read as much files as we can from directives sections.
-  if (auto EC = Symtab.run()) {
-    llvm::errs() << EC.message() << "\n";
-    return false;
-  }
+  Symtab.run();
 
   // Resolve auxiliary symbols until we get a convergence.
   // (Trying to resolve a symbol may trigger a Lazy symbol to load a new file.
@@ -668,31 +575,22 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
 
     if (Symtab.queueEmpty())
       break;
-    if (auto EC = Symtab.run()) {
-      llvm::errs() << EC.message() << "\n";
-      return false;
-    }
+    Symtab.run();
   }
 
   // Do LTO by compiling bitcode input files to a native COFF file
   // then link that file.
-  if (auto EC = Symtab.addCombinedLTOObject()) {
-    llvm::errs() << EC.message() << "\n";
-    return false;
-  }
+  Symtab.addCombinedLTOObject();
 
   // Make sure we have resolved all symbols.
-  if (Symtab.reportRemainingUndefines(/*Resolve=*/true))
-    return false;
+  Symtab.reportRemainingUndefines(/*Resolve=*/true);
 
   // Windows specific -- if no /subsystem is given, we need to infer
   // that from entry point name.
   if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
     Config->Subsystem = inferSubsystem();
-    if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
-      llvm::errs() << "subsystem must be defined\n";
-      return false;
-    }
+    if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN)
+      error("subsystem must be defined");
   }
 
   // Handle /safeseh.
@@ -700,46 +598,36 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
     for (ObjectFile *File : Symtab.ObjectFiles) {
       if (File->SEHCompat)
         continue;
-      llvm::errs() << "/safeseh: " << File->getName()
-                   << " is not compatible with SEH\n";
-      return false;
+      error(Twine("/safeseh: ") + File->getName() +
+            " is not compatible with SEH");
     }
   }
 
   // Windows specific -- when we are creating a .dll file, we also
   // need to create a .lib file.
   if (!Config->Exports.empty()) {
-    if (fixupExports())
-      return false;
-    if (writeImportLibrary())
-      return false;
+    fixupExports();
+    writeImportLibrary();
     assignExportOrdinals();
   }
 
   // Windows specific -- Create a side-by-side manifest file.
   if (Config->Manifest == Configuration::SideBySide)
-    if (createSideBySideManifest())
-      return false;
+    createSideBySideManifest();
 
   // Create a dummy PDB file to satisfy build sytem rules.
   if (auto *Arg = Args.getLastArg(OPT_pdb))
     touchFile(Arg->getValue());
 
   // Write the result.
-  if (auto EC = writeResult(&Symtab)) {
-    llvm::errs() << EC.message() << "\n";
-    return false;
-  }
+  writeResult(&Symtab);
 
   // Create a symbol map file containing symbol VAs and their names
   // to help debugging.
   if (auto *Arg = Args.getLastArg(OPT_lldmap)) {
     std::error_code EC;
     llvm::raw_fd_ostream Out(Arg->getValue(), EC, OpenFlags::F_Text);
-    if (EC) {
-      llvm::errs() << EC.message() << "\n";
-      return false;
-    }
+    error(EC, "Could not create the symbol map");
     Symtab.printMap(Out);
   }
   // Call exit to avoid calling destructors.
index c54c6de..a39ce1d 100644 (file)
@@ -36,27 +36,24 @@ using llvm::Optional;
 class InputFile;
 
 // Entry point of the COFF linker.
-bool link(llvm::ArrayRef<const char *> Args);
+void link(llvm::ArrayRef<const char *> Args);
 
 class ArgParser {
 public:
   ArgParser() : Alloc(AllocAux) {}
   // Parses command line options.
-  ErrorOr<llvm::opt::InputArgList> parse(llvm::ArrayRef<const char *> Args);
+  llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> Args);
 
   // Concatenate LINK environment varirable and given arguments and parse them.
-  ErrorOr<llvm::opt::InputArgList> parseLINK(llvm::ArrayRef<const char *> Args);
+  llvm::opt::InputArgList parseLINK(llvm::ArrayRef<const char *> Args);
 
   // Tokenizes a given string and then parses as command line options.
-  ErrorOr<llvm::opt::InputArgList> parse(StringRef S) {
-    return parse(tokenize(S));
-  }
+  llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); }
 
 private:
   std::vector<const char *> tokenize(StringRef S);
 
-  ErrorOr<std::vector<const char *>>
-  replaceResponseFiles(std::vector<const char *>);
+  std::vector<const char *> replaceResponseFiles(std::vector<const char *>);
 
   llvm::BumpPtrAllocator AllocAux;
   llvm::BumpPtrStringSaver Alloc;
@@ -65,10 +62,10 @@ private:
 class LinkerDriver {
 public:
   LinkerDriver() : Alloc(AllocAux) {}
-  bool link(llvm::ArrayRef<const char *> Args);
+  void link(llvm::ArrayRef<const char *> Args);
 
   // Used by the resolver to parse .drectve section contents.
-  std::error_code parseDirectives(StringRef S);
+  void parseDirectives(StringRef S);
 
 private:
   llvm::BumpPtrAllocator AllocAux;
@@ -77,7 +74,7 @@ private:
   SymbolTable Symtab;
 
   // Opens a file. Path has to be resolved already.
-  ErrorOr<MemoryBufferRef> openFile(StringRef Path);
+  MemoryBufferRef openFile(StringRef Path);
 
   // Searches a file from search paths.
   Optional<StringRef> findFile(StringRef Filename);
@@ -110,57 +107,55 @@ private:
   std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
 };
 
-std::error_code parseModuleDefs(MemoryBufferRef MB,
-                                llvm::BumpPtrStringSaver *Alloc);
-std::error_code writeImportLibrary();
+void parseModuleDefs(MemoryBufferRef MB, llvm::BumpPtrStringSaver *Alloc);
+void writeImportLibrary();
 
 // Functions below this line are defined in DriverUtils.cpp.
 
 void printHelp(const char *Argv0);
 
 // For /machine option.
-ErrorOr<MachineTypes> getMachineType(StringRef Arg);
+MachineTypes getMachineType(StringRef Arg);
 StringRef machineToStr(MachineTypes MT);
 
 // Parses a string in the form of "<integer>[,<integer>]".
-std::error_code parseNumbers(StringRef Arg, uint64_t *Addr,
-                             uint64_t *Size = nullptr);
+void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size = nullptr);
 
 // Parses a string in the form of "<integer>[.<integer>]".
 // Minor's default value is 0.
-std::error_code parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor);
+void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor);
 
 // Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
-std::error_code parseSubsystem(StringRef Arg, WindowsSubsystem *Sys,
-                               uint32_t *Major, uint32_t *Minor);
+void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,
+                    uint32_t *Minor);
 
-std::error_code parseAlternateName(StringRef);
-std::error_code parseMerge(StringRef);
+void parseAlternateName(StringRef);
+void parseMerge(StringRef);
 
 // Parses a string in the form of "EMBED[,=<integer>]|NO".
-std::error_code parseManifest(StringRef Arg);
+void parseManifest(StringRef Arg);
 
 // Parses a string in the form of "level=<string>|uiAccess=<string>"
-std::error_code parseManifestUAC(StringRef Arg);
+void parseManifestUAC(StringRef Arg);
 
 // Create a resource file containing a manifest XML.
-ErrorOr<std::unique_ptr<MemoryBuffer>> createManifestRes();
-std::error_code createSideBySideManifest();
+std::unique_ptr<MemoryBuffer> createManifestRes();
+void createSideBySideManifest();
 
 // Used for dllexported symbols.
-ErrorOr<Export> parseExport(StringRef Arg);
-std::error_code fixupExports();
+Export parseExport(StringRef Arg);
+void fixupExports();
 void assignExportOrdinals();
 
 // Parses a string in the form of "key=value" and check
 // if value matches previous values for the key.
 // This feature used in the directive section to reject
 // incompatible objects.
-std::error_code checkFailIfMismatch(StringRef Arg);
+void checkFailIfMismatch(StringRef Arg);
 
 // Convert Windows resource files (.res files) to a .obj file
 // using cvtres.exe.
-ErrorOr<std::unique_ptr<MemoryBuffer>>
+std::unique_ptr<MemoryBuffer>
 convertResToCOFF(const std::vector<MemoryBufferRef> &MBs);
 
 void touchFile(StringRef Path);
index a21ceb6..1ec8363 100644 (file)
@@ -50,13 +50,9 @@ public:
   void add(Twine S)        { Args.push_back(Saver.save(S)); }
   void add(const char *S)  { Args.push_back(Saver.save(S)); }
 
-  std::error_code run() {
+  void run() {
     ErrorOr<std::string> ExeOrErr = llvm::sys::findProgramByName(Prog);
-    if (auto EC = ExeOrErr.getError()) {
-      llvm::errs() << "unable to find " << Prog << " in PATH: "
-                   << EC.message() << "\n";
-      return make_error_code(LLDError::InvalidOption);
-    }
+    error(ExeOrErr, Twine("unable to find ") + Prog + " in PATH: ");
     const char *Exe = Saver.save(ExeOrErr.get());
     Args.insert(Args.begin(), Exe);
     Args.push_back(nullptr);
@@ -64,10 +60,8 @@ public:
       for (const char *S : Args)
         if (S)
           llvm::errs() << S << " ";
-      llvm::errs() << "failed\n";
-      return make_error_code(LLDError::InvalidOption);
+      error("failed");
     }
-    return std::error_code();
   }
 
 private:
@@ -80,7 +74,7 @@ private:
 } // anonymous namespace
 
 // Returns /machine's value.
-ErrorOr<MachineTypes> getMachineType(StringRef S) {
+MachineTypes getMachineType(StringRef S) {
   MachineTypes MT = StringSwitch<MachineTypes>(S.lower())
                         .Case("x64", AMD64)
                         .Case("amd64", AMD64)
@@ -90,8 +84,7 @@ ErrorOr<MachineTypes> getMachineType(StringRef S) {
                         .Default(IMAGE_FILE_MACHINE_UNKNOWN);
   if (MT != IMAGE_FILE_MACHINE_UNKNOWN)
     return MT;
-  llvm::errs() << "unknown /machine argument: " << S << "\n";
-  return make_error_code(LLDError::InvalidOption);
+  error(Twine("unknown /machine argument: ") + S);
 }
 
 StringRef machineToStr(MachineTypes MT) {
@@ -108,40 +101,30 @@ StringRef machineToStr(MachineTypes MT) {
 }
 
 // Parses a string in the form of "<integer>[,<integer>]".
-std::error_code parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size) {
+void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size) {
   StringRef S1, S2;
   std::tie(S1, S2) = Arg.split(',');
-  if (S1.getAsInteger(0, *Addr)) {
-    llvm::errs() << "invalid number: " << S1 << "\n";
-    return make_error_code(LLDError::InvalidOption);
-  }
-  if (Size && !S2.empty() && S2.getAsInteger(0, *Size)) {
-    llvm::errs() << "invalid number: " << S2 << "\n";
-    return make_error_code(LLDError::InvalidOption);
-  }
-  return std::error_code();
+  if (S1.getAsInteger(0, *Addr))
+    error(Twine("invalid number: ") + S1);
+  if (Size && !S2.empty() && S2.getAsInteger(0, *Size))
+    error(Twine("invalid number: ") + S2);
 }
 
 // Parses a string in the form of "<integer>[.<integer>]".
 // If second number is not present, Minor is set to 0.
-std::error_code parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor) {
+void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor) {
   StringRef S1, S2;
   std::tie(S1, S2) = Arg.split('.');
-  if (S1.getAsInteger(0, *Major)) {
-    llvm::errs() << "invalid number: " << S1 << "\n";
-    return make_error_code(LLDError::InvalidOption);
-  }
+  if (S1.getAsInteger(0, *Major))
+    error(Twine("invalid number: ") + S1);
   *Minor = 0;
-  if (!S2.empty() && S2.getAsInteger(0, *Minor)) {
-    llvm::errs() << "invalid number: " << S2 << "\n";
-    return make_error_code(LLDError::InvalidOption);
-  }
-  return std::error_code();
+  if (!S2.empty() && S2.getAsInteger(0, *Minor))
+    error(Twine("invalid number: ") + S2);
 }
 
 // Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
-std::error_code parseSubsystem(StringRef Arg, WindowsSubsystem *Sys,
-                               uint32_t *Major, uint32_t *Minor) {
+void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,
+                    uint32_t *Minor) {
   StringRef SysStr, Ver;
   std::tie(SysStr, Ver) = Arg.split(',');
   *Sys = StringSwitch<WindowsSubsystem>(SysStr.lower())
@@ -155,43 +138,32 @@ std::error_code parseSubsystem(StringRef Arg, WindowsSubsystem *Sys,
     .Case("posix", IMAGE_SUBSYSTEM_POSIX_CUI)
     .Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI)
     .Default(IMAGE_SUBSYSTEM_UNKNOWN);
-  if (*Sys == IMAGE_SUBSYSTEM_UNKNOWN) {
-    llvm::errs() << "unknown subsystem: " << SysStr << "\n";
-    return make_error_code(LLDError::InvalidOption);
-  }
+  if (*Sys == IMAGE_SUBSYSTEM_UNKNOWN)
+    error(Twine("unknown subsystem: ") + SysStr);
   if (!Ver.empty())
-    if (auto EC = parseVersion(Ver, Major, Minor))
-      return EC;
-  return std::error_code();
+    parseVersion(Ver, Major, Minor);
 }
 
 // Parse a string of the form of "<from>=<to>".
 // Results are directly written to Config.
-std::error_code parseAlternateName(StringRef S) {
+void parseAlternateName(StringRef S) {
   StringRef From, To;
   std::tie(From, To) = S.split('=');
-  if (From.empty() || To.empty()) {
-    llvm::errs() << "/alternatename: invalid argument: " << S << "\n";
-    return make_error_code(LLDError::InvalidOption);
-  }
+  if (From.empty() || To.empty())
+    error(Twine("/alternatename: invalid argument: ") + S);
   auto It = Config->AlternateNames.find(From);
-  if (It != Config->AlternateNames.end() && It->second != To) {
-    llvm::errs() << "/alternatename: conflicts: " << S << "\n";
-    return make_error_code(LLDError::InvalidOption);
-  }
+  if (It != Config->AlternateNames.end() && It->second != To)
+    error(Twine("/alternatename: conflicts: ") + S);
   Config->AlternateNames.insert(It, std::make_pair(From, To));
-  return std::error_code();
 }
 
 // Parse a string of the form of "<from>=<to>".
 // Results are directly written to Config.
-std::error_code parseMerge(StringRef S) {
+void parseMerge(StringRef S) {
   StringRef From, To;
   std::tie(From, To) = S.split('=');
-  if (From.empty() || To.empty()) {
-    llvm::errs() << "/merge: invalid argument: " << S << "\n";
-    return make_error_code(LLDError::InvalidOption);
-  }
+  if (From.empty() || To.empty())
+    error(Twine("/merge: invalid argument: ") + S);
   auto Pair = Config->Merge.insert(std::make_pair(From, To));
   bool Inserted = Pair.second;
   if (!Inserted) {
@@ -200,41 +172,39 @@ std::error_code parseMerge(StringRef S) {
       llvm::errs() << "warning: " << S << ": already merged into "
                    << Existing << "\n";
   }
-  return std::error_code();
 }
 
 // Parses a string in the form of "EMBED[,=<integer>]|NO".
 // Results are directly written to Config.
-std::error_code parseManifest(StringRef Arg) {
+void parseManifest(StringRef Arg) {
   if (Arg.equals_lower("no")) {
     Config->Manifest = Configuration::No;
-    return std::error_code();
+    return;
   }
   if (!Arg.startswith_lower("embed"))
-    return make_error_code(LLDError::InvalidOption);
+    error(Twine("Invalid option ") + Arg);
   Config->Manifest = Configuration::Embed;
   Arg = Arg.substr(strlen("embed"));
   if (Arg.empty())
-    return std::error_code();
+    return;
   if (!Arg.startswith_lower(",id="))
-    return make_error_code(LLDError::InvalidOption);
+    error(Twine("Invalid option ") + Arg);
   Arg = Arg.substr(strlen(",id="));
   if (Arg.getAsInteger(0, Config->ManifestID))
-    return make_error_code(LLDError::InvalidOption);
-  return std::error_code();
+    error(Twine("Invalid option ") + Arg);
 }
 
 // Parses a string in the form of "level=<string>|uiAccess=<string>|NO".
 // Results are directly written to Config.
-std::error_code parseManifestUAC(StringRef Arg) {
+void parseManifestUAC(StringRef Arg) {
   if (Arg.equals_lower("no")) {
     Config->ManifestUAC = false;
-    return std::error_code();
+    return;
   }
   for (;;) {
     Arg = Arg.ltrim();
     if (Arg.empty())
-      return std::error_code();
+      return;
     if (Arg.startswith_lower("level=")) {
       Arg = Arg.substr(strlen("level="));
       std::tie(Config->ManifestLevel, Arg) = Arg.split(" ");
@@ -245,7 +215,7 @@ std::error_code parseManifestUAC(StringRef Arg) {
       std::tie(Config->ManifestUIAccess, Arg) = Arg.split(" ");
       continue;
     }
-    return make_error_code(LLDError::InvalidOption);
+    error(Twine("Invalid option ") + Arg);
   }
 }
 
@@ -301,22 +271,16 @@ static std::string createManifestXml() {
 }
 
 // Create a resource file containing a manifest XML.
-ErrorOr<std::unique_ptr<MemoryBuffer>> createManifestRes() {
+std::unique_ptr<MemoryBuffer> createManifestRes() {
   // Create a temporary file for the resource script file.
   SmallString<128> RCPath;
-  if (sys::fs::createTemporaryFile("tmp", "rc", RCPath)) {
-    llvm::errs() << "cannot create a temporary file\n";
-    return make_error_code(LLDError::InvalidOption);
-  }
+  std::error_code EC = sys::fs::createTemporaryFile("tmp", "rc", RCPath);
+  error(EC, "cannot create a temporary file");
   FileRemover RCRemover(RCPath);
 
   // Open the temporary file for writing.
-  std::error_code EC;
   llvm::raw_fd_ostream Out(RCPath, EC, sys::fs::F_Text);
-  if (EC) {
-    llvm::errs() << "failed to open " << RCPath << ": " << EC.message() << "\n";
-    return make_error_code(LLDError::InvalidOption);
-  }
+  error(EC, Twine("failed to open ") + RCPath);
 
   // Write resource script to the RC file.
   Out << "#define LANG_ENGLISH 9\n"
@@ -331,39 +295,34 @@ ErrorOr<std::unique_ptr<MemoryBuffer>> createManifestRes() {
 
   // Create output resource file.
   SmallString<128> ResPath;
-  if (sys::fs::createTemporaryFile("tmp", "res", ResPath)) {
-    llvm::errs() << "cannot create a temporary file\n";
-    return make_error_code(LLDError::InvalidOption);
-  }
+  EC = sys::fs::createTemporaryFile("tmp", "res", ResPath);
+  error(EC, "cannot create a temporary file");
 
   Executor E("rc.exe");
   E.add("/fo");
   E.add(ResPath.str());
   E.add("/nologo");
   E.add(RCPath.str());
-  if (auto EC = E.run())
-    return EC;
-  return MemoryBuffer::getFile(ResPath);
+  E.run();
+  ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = MemoryBuffer::getFile(ResPath);
+  error(Ret, Twine("Could not open ") + ResPath);
+  return std::move(*Ret);
 }
 
-std::error_code createSideBySideManifest() {
+void createSideBySideManifest() {
   std::string Path = Config->ManifestFile;
   if (Path == "")
     Path = (Twine(Config->OutputFile) + ".manifest").str();
   std::error_code EC;
   llvm::raw_fd_ostream Out(Path, EC, llvm::sys::fs::F_Text);
-  if (EC) {
-    llvm::errs() << EC.message() << "\n";
-    return EC;
-  }
+  error(EC, "failed to create manifest");
   Out << createManifestXml();
-  return std::error_code();
 }
 
 // Parse a string in the form of
 // "<name>[=<internalname>][,@ordinal[,NONAME]][,DATA][,PRIVATE]".
 // Used for parsing /export arguments.
-ErrorOr<Export> parseExport(StringRef Arg) {
+Export parseExport(StringRef Arg) {
   Export E;
   StringRef Rest;
   std::tie(E.Name, Rest) = Arg.split(",");
@@ -406,22 +365,19 @@ ErrorOr<Export> parseExport(StringRef Arg) {
   return E;
 
 err:
-  llvm::errs() << "invalid /export: " << Arg << "\n";
-  return make_error_code(LLDError::InvalidOption);
+  error(Twine("invalid /export: ") + Arg);
 }
 
 // Performs error checking on all /export arguments.
 // It also sets ordinals.
-std::error_code fixupExports() {
+void fixupExports() {
   // Symbol ordinals must be unique.
   std::set<uint16_t> Ords;
   for (Export &E : Config->Exports) {
     if (E.Ordinal == 0)
       continue;
-    if (!Ords.insert(E.Ordinal).second) {
-      llvm::errs() << "duplicate export ordinal: " << E.Name << "\n";
-      return make_error_code(LLDError::InvalidOption);
-    }
+    if (!Ords.insert(E.Ordinal).second)
+      error(Twine("duplicate export ordinal: ") + E.Name);
   }
 
   for (Export &E : Config->Exports) {
@@ -462,7 +418,6 @@ std::error_code fixupExports() {
             [](const Export &A, const Export &B) {
               return A.ExtDLLName < B.ExtDLLName;
             });
-  return std::error_code();
 }
 
 void assignExportOrdinals() {
@@ -477,31 +432,26 @@ void assignExportOrdinals() {
 
 // Parses a string in the form of "key=value" and check
 // if value matches previous values for the same key.
-std::error_code checkFailIfMismatch(StringRef Arg) {
+void checkFailIfMismatch(StringRef Arg) {
   StringRef K, V;
   std::tie(K, V) = Arg.split('=');
-  if (K.empty() || V.empty()) {
-    llvm::errs() << "/failifmismatch: invalid argument: " << Arg << "\n";
-    return make_error_code(LLDError::InvalidOption);
-  }
+  if (K.empty() || V.empty())
+    error(Twine("/failifmismatch: invalid argument: ") + Arg);
   StringRef Existing = Config->MustMatch[K];
-  if (!Existing.empty() && V != Existing) {
-    llvm::errs() << "/failifmismatch: mismatch detected: "
-                 << Existing << " and " << V << " for key " << K << "\n";
-    return make_error_code(LLDError::InvalidOption);
-  }
+  if (!Existing.empty() && V != Existing)
+    error(Twine("/failifmismatch: mismatch detected: ") + Existing + " and " +
+          V + " for key " + K);
   Config->MustMatch[K] = V;
-  return std::error_code();
 }
 
 // Convert Windows resource files (.res files) to a .obj file
 // using cvtres.exe.
-ErrorOr<std::unique_ptr<MemoryBuffer>>
+std::unique_ptr<MemoryBuffer>
 convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) {
   // Create an output file path.
   SmallString<128> Path;
   if (llvm::sys::fs::createTemporaryFile("resource", "obj", Path))
-    return make_error_code(LLDError::InvalidOption);
+    error("Could not create temporary file");
 
   // Execute cvtres.exe.
   Executor E("cvtres.exe");
@@ -511,9 +461,10 @@ convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) {
   E.add("/out:" + Path);
   for (MemoryBufferRef MB : MBs)
     E.add(MB.getBufferIdentifier());
-  if (auto EC = E.run())
-    return EC;
-  return MemoryBuffer::getFile(Path);
+  E.run();
+  ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = MemoryBuffer::getFile(Path);
+  error(Ret, Twine("Could not open ") + Path);
+  return std::move(*Ret);
 }
 
 static std::string writeToTempFile(StringRef Contents) {
@@ -551,7 +502,7 @@ static std::string createModuleDefinitionFile() {
 }
 
 // Creates a .def file and runs lib.exe on it to create an import library.
-std::error_code writeImportLibrary() {
+void writeImportLibrary() {
   std::string Contents = createModuleDefinitionFile();
   std::string Def = writeToTempFile(Contents);
   llvm::FileRemover TempFile(Def);
@@ -567,13 +518,13 @@ std::error_code writeImportLibrary() {
   } else {
     E.add("/out:" + Config->Implib);
   }
-  return E.run();
+  E.run();
 }
 
 void touchFile(StringRef Path) {
   int FD;
-  if (sys::fs::openFileForWrite(Path, FD, sys::fs::F_Append))
-    report_fatal_error("failed to create a file");
+  std::error_code EC = sys::fs::openFileForWrite(Path, FD, sys::fs::F_Append);
+  error(EC, "failed to create a file");
   sys::Process::SafelyCloseFileDescriptor(FD);
 }
 
@@ -601,16 +552,9 @@ public:
 };
 
 // Parses a given list of options.
-ErrorOr<llvm::opt::InputArgList>
-ArgParser::parse(ArrayRef<const char *> ArgsArr) {
+llvm::opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) {
   // First, replace respnose files (@<file>-style options).
-  auto ArgvOrErr = replaceResponseFiles(ArgsArr);
-  if (auto EC = ArgvOrErr.getError()) {
-    llvm::errs() << "error while reading response file: " << EC.message()
-                 << "\n";
-    return EC;
-  }
-  std::vector<const char *> Argv = std::move(ArgvOrErr.get());
+  std::vector<const char *> Argv = replaceResponseFiles(ArgsArr);
 
   // Make InputArgList from string vectors.
   COFFOptTable Table;
@@ -618,20 +562,16 @@ ArgParser::parse(ArrayRef<const char *> ArgsArr) {
   unsigned MissingCount;
   llvm::opt::InputArgList Args =
       Table.ParseArgs(Argv, MissingIndex, MissingCount);
-  if (MissingCount) {
-    llvm::errs() << "missing arg value for \""
-                 << Args.getArgString(MissingIndex) << "\", expected "
-                 << MissingCount
-                 << (MissingCount == 1 ? " argument.\n" : " arguments.\n");
-    return make_error_code(LLDError::InvalidOption);
-  }
+  if (MissingCount)
+    error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) +
+          "\", expected " + Twine(MissingCount) +
+          (MissingCount == 1 ? " argument." : " arguments."));
   for (auto *Arg : Args.filtered(OPT_UNKNOWN))
     llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n";
-  return std::move(Args);
+  return Args;
 }
 
-ErrorOr<llvm::opt::InputArgList>
-ArgParser::parseLINK(ArrayRef<const char *> Args) {
+llvm::opt::InputArgList ArgParser::parseLINK(ArrayRef<const char *> Args) {
   // Concatenate LINK env and given arguments and parse them.
   Optional<std::string> Env = Process::GetEnv("LINK");
   if (!Env)
@@ -650,7 +590,7 @@ std::vector<const char *> ArgParser::tokenize(StringRef S) {
 
 // Creates a new command line by replacing options starting with '@'
 // character. '@<filename>' is replaced by the file's contents.
-ErrorOr<std::vector<const char *>>
+std::vector<const char *>
 ArgParser::replaceResponseFiles(std::vector<const char *> Argv) {
   SmallVector<const char *, 256> Tokens(Argv.data(), Argv.data() + Argv.size());
   BumpPtrStringSaver Saver(AllocAux);
diff --git a/lld/COFF/Error.cpp b/lld/COFF/Error.cpp
new file mode 100644 (file)
index 0000000..255d9bb
--- /dev/null
@@ -0,0 +1,30 @@
+//===- Error.cpp ----------------------------------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Error.h"
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace lld {
+namespace coff {
+
+void error(const Twine &Msg) {
+  llvm::errs() << Msg << "\n";
+  exit(1);
+}
+
+void error(std::error_code EC, const Twine &Prefix) {
+  if (!EC)
+    return;
+  error(Prefix + ": " + EC.message());
+}
+
+} // namespace coff
+} // namespace lld
index 45c31b8..3ce67ee 100644 (file)
 #ifndef LLD_COFF_ERROR_H
 #define LLD_COFF_ERROR_H
 
-#include <string>
-#include <system_error>
-#include "llvm/Support/ErrorHandling.h"
+#include "lld/Core/LLVM.h"
 
 namespace lld {
 namespace coff {
 
-enum class LLDError {
-  InvalidOption = 1,
-  InvalidFile,
-  BrokenFile,
-  DuplicateSymbols,
-};
+LLVM_ATTRIBUTE_NORETURN void error(const Twine &Msg);
+void error(std::error_code EC, const Twine &Prefix);
 
-class LLDErrorCategory : public std::error_category {
-public:
-  const char *name() const LLVM_NOEXCEPT override { return "lld"; }
-
-  std::string message(int EV) const override {
-    switch (static_cast<LLDError>(EV)) {
-    case LLDError::InvalidOption:
-      return "Invalid option";
-    case LLDError::InvalidFile:
-      return "Invalid file";
-    case LLDError::BrokenFile:
-      return "Broken file";
-    case LLDError::DuplicateSymbols:
-      return "Duplicate symbols";
-    }
-    llvm_unreachable("unknown error");
-  }
-};
-
-inline std::error_code make_error_code(LLDError Err) {
-  static LLDErrorCategory C;
-  return std::error_code(static_cast<int>(Err), C);
+template <typename T> void error(const ErrorOr<T> &V, const Twine &Prefix) {
+  error(V.getError(), Prefix);
 }
 
 } // namespace coff
index 215271c..7db946d 100644 (file)
@@ -50,11 +50,10 @@ std::string InputFile::getShortName() {
   return StringRef(Res).lower();
 }
 
-std::error_code ArchiveFile::parse() {
+void ArchiveFile::parse() {
   // Parse a MemoryBufferRef as an archive file.
   auto ArchiveOrErr = Archive::create(MB);
-  if (auto EC = ArchiveOrErr.getError())
-    return EC;
+  error(ArchiveOrErr, "Failed to parse static library");
   File = std::move(ArchiveOrErr.get());
 
   // Allocate a buffer for Lazy objects.
@@ -77,63 +76,55 @@ std::error_code ArchiveFile::parse() {
   // are not read yet.
   for (const Archive::Child &Child : File->children())
     Seen[Child.getChildOffset()].clear();
-  return std::error_code();
 }
 
 // Returns a buffer pointing to a member file containing a given symbol.
 // This function is thread-safe.
-ErrorOr<MemoryBufferRef> ArchiveFile::getMember(const Archive::Symbol *Sym) {
+MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
   auto ItOrErr = Sym->getMember();
-  if (auto EC = ItOrErr.getError())
-    return EC;
+  error(ItOrErr,
+        Twine("Could not get the member for symbol ") + Sym->getName());
   Archive::child_iterator It = ItOrErr.get();
 
   // Return an empty buffer if we have already returned the same buffer.
   if (Seen[It->getChildOffset()].test_and_set())
     return MemoryBufferRef();
-  return It->getMemoryBufferRef();
+  ErrorOr<MemoryBufferRef> Ret = It->getMemoryBufferRef();
+  error(Ret, Twine("Could not get the buffer for the member defining symbol ") +
+                 Sym->getName());
+  return *Ret;
 }
 
-std::error_code ObjectFile::parse() {
+void ObjectFile::parse() {
   // Parse a memory buffer as a COFF file.
   auto BinOrErr = createBinary(MB);
-  if (auto EC = BinOrErr.getError())
-    return EC;
+  error(BinOrErr, "Failed to parse object file");
   std::unique_ptr<Binary> Bin = std::move(BinOrErr.get());
 
   if (auto *Obj = dyn_cast<COFFObjectFile>(Bin.get())) {
     Bin.release();
     COFFObj.reset(Obj);
   } else {
-    llvm::errs() << getName() << " is not a COFF file.\n";
-    return make_error_code(LLDError::InvalidFile);
+    error(Twine(getName()) + " is not a COFF file.");
   }
 
   // Read section and symbol tables.
-  if (auto EC = initializeChunks())
-    return EC;
-  if (auto EC = initializeSymbols())
-    return EC;
-  return initializeSEH();
+  initializeChunks();
+  initializeSymbols();
+  initializeSEH();
 }
 
-std::error_code ObjectFile::initializeChunks() {
+void ObjectFile::initializeChunks() {
   uint32_t NumSections = COFFObj->getNumberOfSections();
   Chunks.reserve(NumSections);
   SparseChunks.resize(NumSections + 1);
   for (uint32_t I = 1; I < NumSections + 1; ++I) {
     const coff_section *Sec;
     StringRef Name;
-    if (auto EC = COFFObj->getSection(I, Sec)) {
-      llvm::errs() << "getSection failed: " << Name << ": "
-                   << EC.message() << "\n";
-      return make_error_code(LLDError::BrokenFile);
-    }
-    if (auto EC = COFFObj->getSectionName(Sec, Name)) {
-      llvm::errs() << "getSectionName failed: " << Name << ": "
-                   << EC.message() << "\n";
-      return make_error_code(LLDError::BrokenFile);
-    }
+    std::error_code EC = COFFObj->getSection(I, Sec);
+    error(EC, Twine("getSection failed: ") + Name);
+    EC = COFFObj->getSectionName(Sec, Name);
+    error(EC, Twine("getSectionName failed: ") + Name);
     if (Name == ".sxdata") {
       SXData = Sec;
       continue;
@@ -157,10 +148,9 @@ std::error_code ObjectFile::initializeChunks() {
     Chunks.push_back(C);
     SparseChunks[I] = C;
   }
-  return std::error_code();
 }
 
-std::error_code ObjectFile::initializeSymbols() {
+void ObjectFile::initializeSymbols() {
   uint32_t NumSymbols = COFFObj->getNumberOfSymbols();
   SymbolBodies.reserve(NumSymbols);
   SparseSymbolBodies.resize(NumSymbols);
@@ -168,11 +158,8 @@ std::error_code ObjectFile::initializeSymbols() {
   for (uint32_t I = 0; I < NumSymbols; ++I) {
     // Get a COFFSymbolRef object.
     auto SymOrErr = COFFObj->getSymbol(I);
-    if (auto EC = SymOrErr.getError()) {
-      llvm::errs() << "broken object file: " << getName() << ": "
-                   << EC.message() << "\n";
-      return make_error_code(LLDError::BrokenFile);
-    }
+    error(SymOrErr, Twine("broken object file: ") + getName());
+
     COFFSymbolRef Sym = SymOrErr.get();
 
     const void *AuxP = nullptr;
@@ -195,7 +182,6 @@ std::error_code ObjectFile::initializeSymbols() {
     I += Sym.getNumberOfAuxSymbols();
     LastSectionNumber = Sym.getSectionNumber();
   }
-  return std::error_code();
 }
 
 Undefined *ObjectFile::createUndefined(COFFSymbolRef Sym) {
@@ -258,20 +244,17 @@ Defined *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP,
   return B;
 }
 
-std::error_code ObjectFile::initializeSEH() {
+void ObjectFile::initializeSEH() {
   if (!SEHCompat || !SXData)
-    return std::error_code();
+    return;
   ArrayRef<uint8_t> A;
   COFFObj->getSectionContents(SXData, A);
-  if (A.size() % 4 != 0) {
-    llvm::errs() << ".sxdata must be an array of symbol table indices\n";
-    return make_error_code(LLDError::BrokenFile);
-  }
+  if (A.size() % 4 != 0)
+    error(".sxdata must be an array of symbol table indices");
   auto *I = reinterpret_cast<const ulittle32_t *>(A.data());
   auto *E = reinterpret_cast<const ulittle32_t *>(A.data() + A.size());
   for (; I != E; ++I)
     SEHandlers.insert(SparseSymbolBodies[*I]);
-  return std::error_code();
 }
 
 MachineTypes ObjectFile::getMachineType() {
@@ -286,16 +269,14 @@ StringRef ltrim1(StringRef S, const char *Chars) {
   return S;
 }
 
-std::error_code ImportFile::parse() {
+void ImportFile::parse() {
   const char *Buf = MB.getBufferStart();
   const char *End = MB.getBufferEnd();
   const auto *Hdr = reinterpret_cast<const coff_import_header *>(Buf);
 
   // Check if the total size is valid.
-  if ((size_t)(End - Buf) != (sizeof(*Hdr) + Hdr->SizeOfData)) {
-    llvm::errs() << "broken import library\n";
-    return make_error_code(LLDError::BrokenFile);
-  }
+  if ((size_t)(End - Buf) != (sizeof(*Hdr) + Hdr->SizeOfData))
+    error("broken import library");
 
   // Read names and create an __imp_ symbol.
   StringRef Name = StringAlloc.save(StringRef(Buf + sizeof(*Hdr)));
@@ -327,18 +308,15 @@ std::error_code ImportFile::parse() {
     auto *B = new (Alloc) DefinedImportThunk(Name, ImpSym, Hdr->Machine);
     SymbolBodies.push_back(B);
   }
-  return std::error_code();
 }
 
-std::error_code BitcodeFile::parse() {
+void BitcodeFile::parse() {
   std::string Err;
   M.reset(LTOModule::createFromBuffer(MB.getBufferStart(),
                                       MB.getBufferSize(),
                                       llvm::TargetOptions(), Err));
-  if (!Err.empty()) {
-    llvm::errs() << Err << '\n';
-    return make_error_code(LLDError::BrokenFile);
-  }
+  if (!Err.empty())
+    error(Err);
 
   llvm::BumpPtrStringSaver Saver(Alloc);
   for (unsigned I = 0, E = M->getSymbolCount(); I != E; ++I) {
@@ -362,7 +340,6 @@ std::error_code BitcodeFile::parse() {
   }
 
   Directives = M->getLinkerOpts();
-  return std::error_code();
 }
 
 MachineTypes BitcodeFile::getMachineType() {
index 6f201d6..9e1bdf5 100644 (file)
@@ -52,7 +52,7 @@ public:
 
   // Reads a file (constructors don't do that). Returns an error if a
   // file is broken.
-  virtual std::error_code parse() = 0;
+  virtual void parse() = 0;
 
   // Returns the CPU type this file was compiled to.
   virtual MachineTypes getMachineType() { return IMAGE_FILE_MACHINE_UNKNOWN; }
@@ -90,12 +90,12 @@ class ArchiveFile : public InputFile {
 public:
   explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
   static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
-  std::error_code parse() override;
+  void parse() override;
 
   // Returns a memory buffer for a given symbol. An empty memory buffer
   // is returned if we have already returned the same memory buffer.
   // (So that we don't instantiate same members more than once.)
-  ErrorOr<MemoryBufferRef> getMember(const Archive::Symbol *Sym);
+  MemoryBufferRef getMember(const Archive::Symbol *Sym);
 
   std::vector<Lazy *> &getLazySymbols() { return LazySymbols; }
 
@@ -117,7 +117,7 @@ class ObjectFile : public InputFile {
 public:
   explicit ObjectFile(MemoryBufferRef M) : InputFile(ObjectKind, M) {}
   static bool classof(const InputFile *F) { return F->kind() == ObjectKind; }
-  std::error_code parse() override;
+  void parse() override;
   MachineTypes getMachineType() override;
   std::vector<Chunk *> &getChunks() { return Chunks; }
   std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
@@ -140,9 +140,9 @@ public:
   std::set<SymbolBody *> SEHandlers;
 
 private:
-  std::error_code initializeChunks();
-  std::error_code initializeSymbols();
-  std::error_code initializeSEH();
+  void initializeChunks();
+  void initializeSymbols();
+  void initializeSEH();
 
   Defined *createDefined(COFFSymbolRef Sym, const void *Aux, bool IsFirst);
   Undefined *createUndefined(COFFSymbolRef Sym);
@@ -184,7 +184,7 @@ public:
   std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
 
 private:
-  std::error_code parse() override;
+  void parse() override;
 
   std::vector<SymbolBody *> SymbolBodies;
   llvm::BumpPtrAllocator Alloc;
@@ -204,7 +204,7 @@ public:
   LTOModule *releaseModule() { return M.release(); }
 
 private:
-  std::error_code parse() override;
+  void parse() override;
 
   std::vector<SymbolBody *> SymbolBodies;
   llvm::BumpPtrAllocator Alloc;
index 84b8870..57d9f22 100644 (file)
@@ -111,12 +111,10 @@ class Parser {
 public:
   explicit Parser(StringRef S, BumpPtrStringSaver *A) : Lex(S), Alloc(A) {}
 
-  std::error_code parse() {
+  void parse() {
     do {
-      if (auto EC = parseOne())
-        return EC;
+      parseOne();
     } while (Tok.K != Eof);
-    return std::error_code();
   }
 
 private:
@@ -129,80 +127,64 @@ private:
     Stack.pop_back();
   }
 
-  std::error_code readAsInt(uint64_t *I) {
+  void readAsInt(uint64_t *I) {
     read();
-    if (Tok.K != Identifier || Tok.Value.getAsInteger(10, *I)) {
-      llvm::errs() << "integer expected\n";
-      return make_error_code(LLDError::InvalidOption);
-    }
-    return std::error_code();
+    if (Tok.K != Identifier || Tok.Value.getAsInteger(10, *I))
+      error("integer expected");
   }
 
-  std::error_code expect(Kind Expected, StringRef Msg) {
+  void expect(Kind Expected, StringRef Msg) {
     read();
-    if (Tok.K != Expected) {
-      llvm::errs() << Msg << "\n";
-      return make_error_code(LLDError::InvalidOption);
-    }
-    return std::error_code();
+    if (Tok.K != Expected)
+      error(Msg);
   }
 
   void unget() { Stack.push_back(Tok); }
 
-  std::error_code parseOne() {
+  void parseOne() {
     read();
     switch (Tok.K) {
     case Eof:
-      return std::error_code();
+      return;
     case KwExports:
       for (;;) {
         read();
         if (Tok.K != Identifier) {
           unget();
-          return std::error_code();
+          return;
         }
-        if (auto EC = parseExport())
-          return EC;
+        parseExport();
       }
     case KwHeapsize:
-      if (auto EC = parseNumbers(&Config->HeapReserve, &Config->HeapCommit))
-        return EC;
-      return std::error_code();
+      parseNumbers(&Config->HeapReserve, &Config->HeapCommit);
+      return;
     case KwLibrary:
-      if (auto EC = parseName(&Config->OutputFile, &Config->ImageBase))
-        return EC;
+      parseName(&Config->OutputFile, &Config->ImageBase);
       if (!StringRef(Config->OutputFile).endswith_lower(".dll"))
         Config->OutputFile += ".dll";
-      return std::error_code();
+      return;
     case KwStacksize:
-      if (auto EC = parseNumbers(&Config->StackReserve, &Config->StackCommit))
-        return EC;
-      return std::error_code();
+      parseNumbers(&Config->StackReserve, &Config->StackCommit);
+      return;
     case KwName:
-      if (auto EC = parseName(&Config->OutputFile, &Config->ImageBase))
-        return EC;
-      return std::error_code();
+      parseName(&Config->OutputFile, &Config->ImageBase);
+      return;
     case KwVersion:
-      if (auto EC = parseVersion(&Config->MajorImageVersion,
-                                 &Config->MinorImageVersion))
-        return EC;
-      return std::error_code();
+      parseVersion(&Config->MajorImageVersion, &Config->MinorImageVersion);
+      return;
     default:
-      llvm::errs() << "unknown directive: " << Tok.Value << "\n";
-      return make_error_code(LLDError::InvalidOption);
+      error(Twine("unknown directive: ") + Tok.Value);
     }
   }
 
-  std::error_code parseExport() {
+  void parseExport() {
     Export E;
     E.Name = Tok.Value;
     read();
     if (Tok.K == Equal) {
       read();
-      if (Tok.K != Identifier) {
-        llvm::errs() << "identifier expected, but got " << Tok.Value << "\n";
-        return make_error_code(LLDError::InvalidOption);
-      }
+      if (Tok.K != Identifier)
+        error(Twine("identifier expected, but got ") + Tok.Value);
       E.ExtName = E.Name;
       E.Name = Tok.Value;
     } else {
@@ -234,68 +216,55 @@ private:
       }
       unget();
       Config->Exports.push_back(E);
-      return std::error_code();
+      return;
     }
   }
 
   // HEAPSIZE/STACKSIZE reserve[,commit]
-  std::error_code parseNumbers(uint64_t *Reserve, uint64_t *Commit) {
-    if (auto EC = readAsInt(Reserve))
-      return EC;
+  void parseNumbers(uint64_t *Reserve, uint64_t *Commit) {
+    readAsInt(Reserve);
     read();
     if (Tok.K != Comma) {
       unget();
       Commit = 0;
-      return std::error_code();
+      return;
     }
-    if (auto EC = readAsInt(Commit))
-      return EC;
-    return std::error_code();
+    readAsInt(Commit);
   }
 
   // NAME outputPath [BASE=address]
-  std::error_code parseName(std::string *Out, uint64_t *Baseaddr) {
+  void parseName(std::string *Out, uint64_t *Baseaddr) {
     read();
     if (Tok.K == Identifier) {
       *Out = Tok.Value;
     } else {
       *Out = "";
       unget();
-      return std::error_code();
+      return;
     }
     read();
     if (Tok.K == KwBase) {
-      if (auto EC = expect(Equal, "'=' expected"))
-        return EC;
-      if (auto EC = readAsInt(Baseaddr))
-        return EC;
+      expect(Equal, "'=' expected");
+      readAsInt(Baseaddr);
     } else {
       unget();
       *Baseaddr = 0;
     }
-    return std::error_code();
   }
 
   // VERSION major[.minor]
-  std::error_code parseVersion(uint32_t *Major, uint32_t *Minor) {
+  void parseVersion(uint32_t *Major, uint32_t *Minor) {
     read();
-    if (Tok.K != Identifier) {
-      llvm::errs() << "identifier expected, but got " << Tok.Value << "\n";
-      return make_error_code(LLDError::InvalidOption);
-    }
+    if (Tok.K != Identifier)
+      error(Twine("identifier expected, but got ") + Tok.Value);
     StringRef V1, V2;
     std::tie(V1, V2) = Tok.Value.split('.');
-    if (V1.getAsInteger(10, *Major)) {
-      llvm::errs() << "integer expected, but got " << Tok.Value << "\n";
-      return make_error_code(LLDError::InvalidOption);
-    }
-    if (V2.empty()) {
+    if (V1.getAsInteger(10, *Major))
+      error(Twine("integer expected, but got ") + Tok.Value);
+    if (V2.empty())
       *Minor = 0;
-    } else if (V2.getAsInteger(10, *Minor)) {
-      llvm::errs() << "integer expected, but got " << Tok.Value << "\n";
-      return make_error_code(LLDError::InvalidOption);
-    }
-    return std::error_code();
+    else if (V2.getAsInteger(10, *Minor))
+      error(Twine("integer expected, but got ") + Tok.Value);
   }
 
   Lexer Lex;
@@ -306,8 +275,8 @@ private:
 
 } // anonymous namespace
 
-std::error_code parseModuleDefs(MemoryBufferRef MB, BumpPtrStringSaver *Alloc) {
-  return Parser(MB.getBuffer(), Alloc).parse();
+void parseModuleDefs(MemoryBufferRef MB, BumpPtrStringSaver *Alloc) {
+  Parser(MB.getBuffer(), Alloc).parse();
 }
 
 } // namespace coff
index b476f69..89c9784 100644 (file)
@@ -40,26 +40,21 @@ void SymbolTable::addFile(std::unique_ptr<InputFile> FileP) {
   }
 }
 
-std::error_code SymbolTable::step() {
+void SymbolTable::step() {
   if (queueEmpty())
-    return std::error_code();
-  if (auto EC = readObjects())
-    return EC;
-  if (auto EC = readArchives())
-    return EC;
-  return std::error_code();
+    return;
+  readObjects();
+  readArchives();
 }
 
-std::error_code SymbolTable::run() {
+void SymbolTable::run() {
   while (!queueEmpty())
-    if (auto EC = step())
-      return EC;
-  return std::error_code();
+    step();
 }
 
-std::error_code SymbolTable::readArchives() {
+void SymbolTable::readArchives() {
   if (ArchiveQueue.empty())
-    return std::error_code();
+    return;
 
   // Add lazy symbols to the symbol table. Lazy symbols that conflict
   // with existing undefined symbols are accumulated in LazySyms.
@@ -67,8 +62,7 @@ std::error_code SymbolTable::readArchives() {
   for (ArchiveFile *File : ArchiveQueue) {
     if (Config->Verbose)
       llvm::outs() << "Reading " << File->getShortName() << "\n";
-    if (auto EC = File->parse())
-      return EC;
+    File->parse();
     for (Lazy *Sym : File->getLazySymbols())
       addLazy(Sym, &LazySyms);
   }
@@ -77,14 +71,12 @@ std::error_code SymbolTable::readArchives() {
   // Add archive member files to ObjectQueue that should resolve
   // existing undefined symbols.
   for (Symbol *Sym : LazySyms)
-    if (auto EC = addMemberFile(cast<Lazy>(Sym->Body)))
-      return EC;
-  return std::error_code();
+    addMemberFile(cast<Lazy>(Sym->Body));
 }
 
-std::error_code SymbolTable::readObjects() {
+void SymbolTable::readObjects() {
   if (ObjectQueue.empty())
-    return std::error_code();
+    return;
 
   // Add defined and undefined symbols to the symbol table.
   std::vector<StringRef> Directives;
@@ -92,14 +84,12 @@ std::error_code SymbolTable::readObjects() {
     InputFile *File = ObjectQueue[I];
     if (Config->Verbose)
       llvm::outs() << "Reading " << File->getShortName() << "\n";
-    if (auto EC = File->parse())
-      return EC;
+    File->parse();
     // Adding symbols may add more files to ObjectQueue
     // (but not to ArchiveQueue).
     for (SymbolBody *Sym : File->getSymbols())
       if (Sym->isExternal())
-        if (auto EC = addSymbol(Sym))
-          return EC;
+        addSymbol(Sym);
     StringRef S = File->getDirectives();
     if (!S.empty()) {
       Directives.push_back(S);
@@ -113,16 +103,14 @@ std::error_code SymbolTable::readObjects() {
   // Parse directive sections. This may add files to
   // ArchiveQueue and ObjectQueue.
   for (StringRef S : Directives)
-    if (auto EC = Driver->parseDirectives(S))
-      return EC;
-  return std::error_code();
+    Driver->parseDirectives(S);
 }
 
 bool SymbolTable::queueEmpty() {
   return ArchiveQueue.empty() && ObjectQueue.empty();
 }
 
-bool SymbolTable::reportRemainingUndefines(bool Resolve) {
+void SymbolTable::reportRemainingUndefines(bool Resolve) {
   llvm::SmallPtrSet<SymbolBody *, 8> Undefs;
   for (auto &I : Symtab) {
     Symbol *Sym = I.second;
@@ -157,7 +145,7 @@ bool SymbolTable::reportRemainingUndefines(bool Resolve) {
     Undefs.insert(Sym->Body);
   }
   if (Undefs.empty())
-    return false;
+    return;
   for (Undefined *U : Config->GCRoot)
     if (Undefs.count(U->repl()))
       llvm::errs() << "<root>: undefined symbol: " << U->getName() << "\n";
@@ -167,7 +155,8 @@ bool SymbolTable::reportRemainingUndefines(bool Resolve) {
         if (Undefs.count(Sym->repl()))
           llvm::errs() << File->getShortName() << ": undefined symbol: "
                        << Sym->getName() << "\n";
-  return !Config->Force;
+  if (!Config->Force)
+    error("Link failed");
 }
 
 void SymbolTable::addLazy(Lazy *New, std::vector<Symbol *> *Accum) {
@@ -190,12 +179,12 @@ void SymbolTable::addLazy(Lazy *New, std::vector<Symbol *> *Accum) {
   }
 }
 
-std::error_code SymbolTable::addSymbol(SymbolBody *New) {
+void SymbolTable::addSymbol(SymbolBody *New) {
   // Find an existing symbol or create and insert a new one.
   assert(isa<Defined>(New) || isa<Undefined>(New));
   Symbol *Sym = insert(New);
   if (Sym->Body == New)
-    return std::error_code();
+    return;
 
   for (;;) {
     SymbolBody *Existing = Sym->Body;
@@ -207,25 +196,25 @@ std::error_code SymbolTable::addSymbol(SymbolBody *New) {
       // since they would be replaced with weak aliases if they remain
       // undefined.
       if (auto *U = dyn_cast<Undefined>(New))
-        if (!U->WeakAlias)
-          return addMemberFile(L);
+        if (!U->WeakAlias) {
+          addMemberFile(L);
+          return;
+        }
       if (!Sym->Body.compare_exchange_strong(Existing, New))
         continue;
-      return std::error_code();
+      return;
     }
 
     // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
     // equivalent (conflicting), or more preferable, respectively.
     int Comp = Existing->compare(New);
-    if (Comp == 0) {
-      llvm::errs() << "duplicate symbol: " << Existing->getDebugName()
-                   << " and " << New->getDebugName() << "\n";
-      return make_error_code(LLDError::DuplicateSymbols);
-    }
+    if (Comp == 0)
+      error(Twine("duplicate symbol: ") + Existing->getDebugName() + " and " +
+            New->getDebugName());
     if (Comp < 0)
       if (!Sym->Body.compare_exchange_strong(Existing, New))
         continue;
-    return std::error_code();
+    return;
   }
 }
 
@@ -241,21 +230,17 @@ Symbol *SymbolTable::insert(SymbolBody *New) {
 }
 
 // Reads an archive member file pointed by a given symbol.
-std::error_code SymbolTable::addMemberFile(Lazy *Body) {
-  auto FileOrErr = Body->getMember();
-  if (auto EC = FileOrErr.getError())
-    return EC;
-  std::unique_ptr<InputFile> File = std::move(FileOrErr.get());
+void SymbolTable::addMemberFile(Lazy *Body) {
+  std::unique_ptr<InputFile> File = Body->getMember();
 
   // getMember returns an empty buffer if the member was already
   // read from the library.
   if (!File)
-    return std::error_code();
+    return;
   if (Config->Verbose)
     llvm::outs() << "Loaded " << File->getShortName() << " for "
                  << Body->getName() << "\n";
   addFile(std::move(File));
-  return std::error_code();
 }
 
 std::vector<Chunk *> SymbolTable::getChunks() {
@@ -346,23 +331,19 @@ void SymbolTable::printMap(llvm::raw_ostream &OS) {
   }
 }
 
-std::error_code SymbolTable::addCombinedLTOObject() {
+void SymbolTable::addCombinedLTOObject() {
   if (BitcodeFiles.empty())
-    return std::error_code();
+    return;
 
   // Diagnose any undefined symbols early, but do not resolve weak externals,
   // as resolution breaks the invariant that each Symbol points to a unique
   // SymbolBody, which we rely on to replace DefinedBitcode symbols correctly.
-  if (reportRemainingUndefines(/*Resolve=*/false))
-    return make_error_code(LLDError::BrokenFile);
+  reportRemainingUndefines(/*Resolve=*/false);
 
   // Create an object file and add it to the symbol table by replacing any
   // DefinedBitcode symbols with the definitions in the object file.
   LTOCodeGenerator CG;
-  auto FileOrErr = createLTOObject(&CG);
-  if (auto EC = FileOrErr.getError())
-    return EC;
-  ObjectFile *Obj = FileOrErr.get();
+  ObjectFile *Obj = createLTOObject(&CG);
 
   for (SymbolBody *Body : Obj->getSymbols()) {
     if (!Body->isExternal())
@@ -379,34 +360,26 @@ std::error_code SymbolTable::addCombinedLTOObject() {
     if (auto *L = dyn_cast<Lazy>(Sym->Body)) {
       // We may see new references to runtime library symbols such as __chkstk
       // here. These symbols must be wholly defined in non-bitcode files.
-      if (auto EC = addMemberFile(L))
-        return EC;
+      addMemberFile(L);
       continue;
     }
     SymbolBody *Existing = Sym->Body;
     int Comp = Existing->compare(Body);
-    if (Comp == 0) {
-      llvm::errs() << "LTO: unexpected duplicate symbol: " << Name << "\n";
-      return make_error_code(LLDError::BrokenFile);
-    }
+    if (Comp == 0)
+      error(Twine("LTO: unexpected duplicate symbol: ") + Name);
     if (Comp < 0)
       Sym->Body = Body;
   }
 
   size_t NumBitcodeFiles = BitcodeFiles.size();
-  if (auto EC = run())
-    return EC;
-  if (BitcodeFiles.size() != NumBitcodeFiles) {
-    llvm::errs() << "LTO: late loaded symbol created new bitcode reference\n";
-    return make_error_code(LLDError::BrokenFile);
-  }
-
-  return std::error_code();
+  run();
+  if (BitcodeFiles.size() != NumBitcodeFiles)
+    error("LTO: late loaded symbol created new bitcode reference");
 }
 
 // Combine and compile bitcode files and then return the result
 // as a regular COFF object file.
-ErrorOr<ObjectFile *> SymbolTable::createLTOObject(LTOCodeGenerator *CG) {
+ObjectFile *SymbolTable::createLTOObject(LTOCodeGenerator *CG) {
   // All symbols referenced by non-bitcode objects must be preserved.
   for (ObjectFile *File : ObjectFiles)
     for (SymbolBody *Body : File->getSymbols())
@@ -433,15 +406,12 @@ ErrorOr<ObjectFile *> SymbolTable::createLTOObject(LTOCodeGenerator *CG) {
 
   std::string ErrMsg;
   LTOMB = CG->compile(false, false, false, ErrMsg); // take MB ownership
-  if (!LTOMB) {
-    llvm::errs() << ErrMsg << '\n';
-    return make_error_code(LLDError::BrokenFile);
-  }
+  if (!LTOMB)
+    error(ErrMsg);
   auto *Obj = new ObjectFile(LTOMB->getMemBufferRef());
   Files.emplace_back(Obj);
   ObjectFiles.push_back(Obj);
-  if (auto EC = Obj->parse())
-    return EC;
+  Obj->parse();
   return Obj;
 }
 
index b465e50..9949550 100644 (file)
@@ -43,13 +43,13 @@ class SymbolTable {
 public:
   void addFile(std::unique_ptr<InputFile> File);
   std::vector<std::unique_ptr<InputFile>> &getFiles() { return Files; }
-  std::error_code step();
-  std::error_code run();
+  void step();
+  void run();
   bool queueEmpty();
 
   // Print an error message on undefined symbols. If Resolve is true, try to
   // resolve any undefined symbols and update the symbol table accordingly.
-  bool reportRemainingUndefines(bool Resolve);
+  void reportRemainingUndefines(bool Resolve);
 
   // Returns a list of chunks of selected symbols.
   std::vector<Chunk *> getChunks();
@@ -71,7 +71,7 @@ public:
   // Build a COFF object representing the combined contents of BitcodeFiles
   // and add it to the symbol table. Called after all files are added and
   // before the writer writes results to a file.
-  std::error_code addCombinedLTOObject();
+  void addCombinedLTOObject();
 
   // The writer needs to handle DLL import libraries specially in
   // order to create the import descriptor table.
@@ -89,16 +89,16 @@ public:
   std::vector<Chunk *> LocalImportChunks;
 
 private:
-  std::error_code readArchives();
-  std::error_code readObjects();
+  void readArchives();
+  void readObjects();
 
-  std::error_code addSymbol(SymbolBody *New);
+  void addSymbol(SymbolBody *New);
   void addLazy(Lazy *New, std::vector<Symbol *> *Accum);
   Symbol *insert(SymbolBody *New);
   StringRef findByPrefix(StringRef Prefix);
 
-  std::error_code addMemberFile(Lazy *Body);
-  ErrorOr<ObjectFile *> createLTOObject(llvm::LTOCodeGenerator *CG);
+  void addMemberFile(Lazy *Body);
+  ObjectFile *createLTOObject(llvm::LTOCodeGenerator *CG);
 
   llvm::DenseMap<StringRef, Symbol *> Symtab;
 
index 5b234cf..c0324fd 100644 (file)
@@ -207,11 +207,8 @@ DefinedImportThunk::DefinedImportThunk(StringRef Name, DefinedImportData *S,
   }
 }
 
-ErrorOr<std::unique_ptr<InputFile>> Lazy::getMember() {
-  auto MBRefOrErr = File->getMember(&Sym);
-  if (auto EC = MBRefOrErr.getError())
-    return EC;
-  MemoryBufferRef MBRef = MBRefOrErr.get();
+std::unique_ptr<InputFile> Lazy::getMember() {
+  MemoryBufferRef MBRef = File->getMember(&Sym);
 
   // getMember returns an empty buffer if the member was already
   // read from the library.
@@ -223,17 +220,15 @@ ErrorOr<std::unique_ptr<InputFile>> Lazy::getMember() {
     return std::unique_ptr<InputFile>(new ImportFile(MBRef));
 
   std::unique_ptr<InputFile> Obj;
-  if (Magic == file_magic::coff_object) {
+  if (Magic == file_magic::coff_object)
     Obj.reset(new ObjectFile(MBRef));
-  } else if (Magic == file_magic::bitcode) {
+  else if (Magic == file_magic::bitcode)
     Obj.reset(new BitcodeFile(MBRef));
-  } else {
-    llvm::errs() << File->getName() << ": unknown file type\n";
-    return make_error_code(LLDError::InvalidFile);
-  }
+  else
+    error(Twine(File->getName()) + ": unknown file type");
 
   Obj->setParentName(File->getName());
-  return std::move(Obj);
+  return Obj;
 }
 
 Defined *Undefined::getWeakAlias() {
index eb9afd3..d23fe09 100644 (file)
@@ -270,7 +270,7 @@ public:
 
   // Returns an object file for this symbol, or a nullptr if the file
   // was already returned.
-  ErrorOr<std::unique_ptr<InputFile>> getMember();
+  std::unique_ptr<InputFile> getMember();
 
   int getFileIndex() { return File->Index; }
 
index c698aec..c7692bb 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "Config.h"
 #include "DLL.h"
+#include "Error.h"
 #include "InputFiles.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
@@ -46,7 +47,7 @@ namespace {
 class Writer {
 public:
   Writer(SymbolTable *T) : Symtab(T) {}
-  std::error_code run();
+  void run();
 
 private:
   void markLive();
@@ -58,7 +59,7 @@ private:
   void assignAddresses();
   void removeEmptySections();
   void createSymbolAndStringTable();
-  std::error_code openFile(StringRef OutputPath);
+  void openFile(StringRef OutputPath);
   template <typename PEHeaderTy> void writeHeader();
   void fixSafeSEHSymbols();
   void writeSections();
@@ -101,7 +102,7 @@ private:
 namespace lld {
 namespace coff {
 
-std::error_code writeResult(SymbolTable *T) { return Writer(T).run(); }
+void writeResult(SymbolTable *T) { Writer(T).run(); }
 
 // OutputSection represents a section in an output file. It's a
 // container of chunks. OutputSection and Chunk are 1:N relationship.
@@ -198,13 +199,13 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) {
 uint64_t Defined::getSecrel() {
   if (auto *D = dyn_cast<DefinedRegular>(this))
     return getRVA() - D->getChunk()->getOutputSection()->getRVA();
-  llvm::report_fatal_error("SECREL relocation points to a non-regular symbol");
+  error("SECREL relocation points to a non-regular symbol");
 }
 
 uint64_t Defined::getSectionIndex() {
   if (auto *D = dyn_cast<DefinedRegular>(this))
     return D->getChunk()->getOutputSection()->SectionIndex;
-  llvm::report_fatal_error("SECTION relocation points to a non-regular symbol");
+  error("SECTION relocation points to a non-regular symbol");
 }
 
 bool Defined::isExecutable() {
@@ -218,7 +219,7 @@ bool Defined::isExecutable() {
 } // namespace lld
 
 // The main function of the writer.
-std::error_code Writer::run() {
+void Writer::run() {
   markLive();
   dedupCOMDATs();
   createSections();
@@ -230,8 +231,7 @@ std::error_code Writer::run() {
   assignAddresses();
   removeEmptySections();
   createSymbolAndStringTable();
-  if (auto EC = openFile(Config->OutputFile))
-    return EC;
+  openFile(Config->OutputFile);
   if (Config->is64()) {
     writeHeader<pe32plus_header>();
   } else {
@@ -240,7 +240,7 @@ std::error_code Writer::run() {
   fixSafeSEHSymbols();
   writeSections();
   sortExceptionTable();
-  return Buffer->commit();
+  error(Buffer->commit(), "Failed to write the output file");
 }
 
 // Set live bit on for each reachable chunk. Unmarked (unreachable)
@@ -692,13 +692,10 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
   memcpy(Buf + 4, Strtab.data(), Strtab.size());
 }
 
-std::error_code Writer::openFile(StringRef Path) {
-  if (auto EC = FileOutputBuffer::create(Path, FileSize, Buffer,
-                                         FileOutputBuffer::F_executable)) {
-    llvm::errs() << "failed to open " << Path << ": " << EC.message() << "\n";
-    return EC;
-  }
-  return std::error_code();
+void Writer::openFile(StringRef Path) {
+  std::error_code EC = FileOutputBuffer::create(Path, FileSize, Buffer,
+                                                FileOutputBuffer::F_executable);
+  error(EC, Twine("failed to open ") + Path);
 }
 
 void Writer::fixSafeSEHSymbols() {
index 0a213e2..8fc2051 100644 (file)
@@ -18,7 +18,7 @@ namespace coff {
 class Chunk;
 class OutputSection;
 
-std::error_code writeResult(SymbolTable *T);
+void writeResult(SymbolTable *T);
 
 // Implemented in ICF.cpp.
 void doICF(const std::vector<Chunk *> &Chunks);
index ea2d8b4..c22622e 100644 (file)
@@ -143,7 +143,7 @@ private:
 
 /// Driver for Windows 'link.exe' command line options
 namespace coff {
-bool link(llvm::ArrayRef<const char *> args);
+void link(llvm::ArrayRef<const char *> args);
 }
 
 namespace elf2 {
index d74b0f3..6741c1c 100644 (file)
@@ -212,7 +212,8 @@ bool UniversalDriver::link(llvm::MutableArrayRef<const char *> args,
   case Flavor::win_link:
     return WinLinkDriver::linkPECOFF(args, diagnostics);
   case Flavor::win_link2:
-    return coff::link(args);
+    coff::link(args);
+    return true;
   case Flavor::core:
     return CoreDriver::link(args, diagnostics);
   case Flavor::invalid: