Make it possible to redirect not only errs() but also outs()
authorRui Ueyama <ruiu@google.com>
Fri, 15 Nov 2019 05:06:57 +0000 (14:06 +0900)
committerRui Ueyama <ruiu@google.com>
Mon, 18 Nov 2019 02:18:06 +0000 (11:18 +0900)
This change is for those who use lld as a library. Context:
https://reviews.llvm.org/D70287

This patch adds a new parmeter to lld::*::link() so that we can pass
an raw_ostream object representing stdout. Previously, lld::*::link()
took only an stderr object.

Justification for making stdoutOS and stderrOS mandatory: I wanted to
make link() functions to take stdout and stderr in that order.
However, if we change the function signature from

  bool link(ArrayRef<const char *> args, bool canExitEarly,
            raw_ostream &stderrOS = llvm::errs());

to

  bool link(ArrayRef<const char *> args, bool canExitEarly,
            raw_ostream &stdoutOS = llvm::outs(),
            raw_ostream &stderrOS = llvm::errs());

, then the meaning of existing code that passes stderrOS silently
changes (stderrOS would be interpreted as stdoutOS). So, I chose to
make existing code not to compile, so that developers can fix their
code.

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

21 files changed:
lld/COFF/Driver.cpp
lld/COFF/DriverUtils.cpp
lld/COFF/Writer.cpp
lld/Common/ErrorHandler.cpp
lld/ELF/Driver.cpp
lld/ELF/DriverUtils.cpp
lld/ELF/MapFile.cpp
lld/MinGW/Driver.cpp
lld/include/lld/Common/Driver.h
lld/include/lld/Common/ErrorHandler.h
lld/include/lld/Common/LLVM.h
lld/lib/Core/Resolver.cpp
lld/lib/Core/SymbolTable.cpp
lld/lib/Driver/DarwinLdDriver.cpp
lld/lib/ReaderWriter/FileArchive.cpp
lld/lib/ReaderWriter/MachO/LayoutPass.cpp
lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
lld/tools/lld/lld.cpp
lld/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp
lld/wasm/Driver.cpp

index f7daa5f..8a9ba92 100644 (file)
@@ -62,14 +62,17 @@ static Timer inputFileTimer("Input File Reading", Timer::root());
 Configuration *config;
 LinkerDriver *driver;
 
-bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &diag) {
+bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &stdoutOS,
+          raw_ostream &stderrOS) {
   errorHandler().logName = args::getFilenameWithoutExe(args[0]);
-  errorHandler().errorOS = &diag;
   errorHandler().errorLimitExceededMsg =
       "too many errors emitted, stopping now"
       " (use /errorlimit:0 to see all errors)";
   errorHandler().exitEarly = canExitEarly;
-  enableColors(diag.has_colors());
+  enableColors(stderrOS.has_colors());
+
+  lld::stdoutOS = &stdoutOS;
+  lld::stderrOS = &stderrOS;
 
   config = make<Configuration>();
   symtab = make<SymbolTable>();
@@ -1150,7 +1153,7 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
   // because it doesn't start with "/", but we deliberately chose "--" to
   // avoid conflict with /version and for compatibility with clang-cl.
   if (args.hasArg(OPT_dash_dash_version)) {
-    outs() << getLLDVersion() << "\n";
+    lld::outs() << getLLDVersion() << "\n";
     return;
   }
 
index e08b855..cb23c9b 100644 (file)
@@ -907,7 +907,7 @@ std::vector<const char *> ArgParser::tokenize(StringRef s) {
 }
 
 void printHelp(const char *argv0) {
-  COFFOptTable().PrintHelp(outs(),
+  COFFOptTable().PrintHelp(lld::outs(),
                            (std::string(argv0) + " [options] file...").c_str(),
                            "LLVM Linker", false);
 }
index 965b366..fcad773 100644 (file)
@@ -1844,7 +1844,7 @@ void Writer::sortExceptionTable() {
         [](const Entry &a, const Entry &b) { return a.begin < b.begin; });
     return;
   }
-  errs() << "warning: don't know how to handle .pdata.\n";
+  lld::errs() << "warning: don't know how to handle .pdata.\n";
 }
 
 // The CRT section contains, among other things, the array of function
index b91854c..e26d78c 100644 (file)
@@ -26,7 +26,8 @@ using namespace llvm;
 using namespace lld;
 
 // The functions defined in this file can be called from multiple threads,
-// but outs() or errs() are not thread-safe. We protect them using a mutex.
+// but lld::outs() or lld::errs() are not thread-safe. We protect them using a
+// mutex.
 static std::mutex mu;
 
 // We want to separate multi-line messages with a newline. `sep` is "\n"
@@ -39,14 +40,18 @@ static StringRef getSeparator(const Twine &msg) {
   return "";
 }
 
+raw_ostream *lld::stdoutOS;
+raw_ostream *lld::stderrOS;
+
+raw_ostream &lld::outs() { return stdoutOS ? *stdoutOS : llvm::outs(); }
+raw_ostream &lld::errs() { return stderrOS ? *stderrOS : llvm::errs(); }
+
 ErrorHandler &lld::errorHandler() {
   static ErrorHandler handler;
   return handler;
 }
 
-void lld::enableColors(bool enable) {
-  errorHandler().errorOS->enable_colors(enable);
-}
+void lld::enableColors(bool enable) { lld::errs().enable_colors(enable); }
 
 void lld::exitLld(int val) {
   // Delete any temporary file, while keeping the memory mapping open.
@@ -58,8 +63,8 @@ void lld::exitLld(int val) {
   // build allows us to get the output of -time-passes.
   llvm_shutdown();
 
-  outs().flush();
-  errs().flush();
+  lld::outs().flush();
+  lld::errs().flush();
   _exit(val);
 }
 
@@ -149,13 +154,13 @@ void ErrorHandler::log(const Twine &msg) {
   if (!verbose)
     return;
   std::lock_guard<std::mutex> lock(mu);
-  *errorOS << logName << ": " << msg << "\n";
+  lld::errs() << logName << ": " << msg << "\n";
 }
 
 void ErrorHandler::message(const Twine &msg) {
   std::lock_guard<std::mutex> lock(mu);
-  outs() << msg << "\n";
-  outs().flush();
+  lld::outs() << msg << "\n";
+  lld::outs().flush();
 }
 
 void ErrorHandler::warn(const Twine &msg) {
@@ -165,8 +170,8 @@ void ErrorHandler::warn(const Twine &msg) {
   }
 
   std::lock_guard<std::mutex> lock(mu);
-  *errorOS << sep << getLocation(msg) << ": " << Colors::MAGENTA
-           << "warning: " << Colors::RESET << msg << "\n";
+  lld::errs() << sep << getLocation(msg) << ": " << Colors::MAGENTA
+              << "warning: " << Colors::RESET << msg << "\n";
   sep = getSeparator(msg);
 }
 
@@ -190,11 +195,11 @@ void ErrorHandler::error(const Twine &msg) {
   std::lock_guard<std::mutex> lock(mu);
 
   if (errorLimit == 0 || errorCount < errorLimit) {
-    *errorOS << sep << getLocation(msg) << ": " << Colors::RED
-             << "error: " << Colors::RESET << msg << "\n";
+    lld::errs() << sep << getLocation(msg) << ": " << Colors::RED
+                << "error: " << Colors::RESET << msg << "\n";
   } else if (errorCount == errorLimit) {
-    *errorOS << sep << getLocation(msg) << ": " << Colors::RED
-             << "error: " << Colors::RESET << errorLimitExceededMsg << "\n";
+    lld::errs() << sep << getLocation(msg) << ": " << Colors::RED
+                << "error: " << Colors::RESET << errorLimitExceededMsg << "\n";
     if (exitEarly)
       exitLld(1);
   }
index 616a9d4..25a9b29 100644 (file)
@@ -75,14 +75,17 @@ LinkerDriver *driver;
 static void setConfigs(opt::InputArgList &args);
 static void readConfigs(opt::InputArgList &args);
 
-bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &error) {
+bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &stdoutOS,
+          raw_ostream &stderrOS) {
   errorHandler().logName = args::getFilenameWithoutExe(args[0]);
   errorHandler().errorLimitExceededMsg =
       "too many errors emitted, stopping now (use "
       "-error-limit=0 to see all errors)";
-  errorHandler().errorOS = &error;
   errorHandler().exitEarly = canExitEarly;
-  enableColors(error.has_colors());
+  enableColors(stderrOS.has_colors());
+
+  lld::stdoutOS = &stdoutOS;
+  lld::stderrOS = &stderrOS;
 
   inputSections.clear();
   outputSections.clear();
index 43987cd..53134d0 100644 (file)
@@ -145,16 +145,16 @@ opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> argv) {
 
 void printHelp() {
   ELFOptTable().PrintHelp(
-      outs(), (config->progName + " [options] file...").str().c_str(), "lld",
-      false /*ShowHidden*/, true /*ShowAllAliases*/);
-  outs() << "\n";
+      lld::outs(), (config->progName + " [options] file...").str().c_str(),
+      "lld", false /*ShowHidden*/, true /*ShowAllAliases*/);
+  lld::outs() << "\n";
 
   // Scripts generated by Libtool versions up to at least 2.4.6 (the most
   // recent version as of March 2017) expect /: supported targets:.* elf/
   // in a message for the -help option. If it doesn't match, the scripts
   // assume that the linker doesn't support very basic features such as
   // shared libraries. Therefore, we need to print out at least "elf".
-  outs() << config->progName << ": supported targets: elf\n";
+  lld::outs() << config->progName << ": supported targets: elf\n";
 }
 
 static std::string rewritePath(StringRef s) {
index 4d76e22..e5f5c4f 100644 (file)
@@ -213,7 +213,7 @@ void writeMapFile() {
 }
 
 static void print(StringRef a, StringRef b) {
-  outs() << left_justify(a, 49) << " " << b << "\n";
+  lld::outs() << left_justify(a, 49) << " " << b << "\n";
 }
 
 // Output a cross reference table to stdout. This is for --cref.
@@ -244,7 +244,7 @@ void writeCrossReferenceTable() {
   }
 
   // Print out a header.
-  outs() << "Cross Reference Table\n\n";
+  lld::outs() << "Cross Reference Table\n\n";
   print("Symbol", "File");
 
   // Print out a table.
index a5f6449..950156a 100644 (file)
@@ -83,9 +83,9 @@ public:
 
 static void printHelp(const char *argv0) {
   MinGWOptTable().PrintHelp(
-      outs(), (std::string(argv0) + " [options] file...").c_str(), "lld",
+      lld::outs(), (std::string(argv0) + " [options] file...").c_str(), "lld",
       false /*ShowHidden*/, true /*ShowAllAliases*/);
-  outs() << "\n";
+  lld::outs() << "\n";
 }
 
 static cl::TokenizerCallback getQuotingStyle() {
@@ -159,8 +159,11 @@ searchLibrary(StringRef name, ArrayRef<StringRef> searchPaths, bool bStatic) {
 
 // Convert Unix-ish command line arguments to Windows-ish ones and
 // then call coff::link.
-bool mingw::link(ArrayRef<const char *> argsArr, raw_ostream &diag) {
-  enableColors(diag.has_colors());
+bool mingw::link(ArrayRef<const char *> argsArr, bool canExitEarly,
+                 raw_ostream &stdoutOS, raw_ostream &stderrOS) {
+  enableColors(stderrOS.has_colors());
+  lld::stdoutOS = &stdoutOS;
+  lld::stderrOS = &stderrOS;
 
   MinGWOptTable parser;
   opt::InputArgList args = parser.parse(argsArr.slice(1));
@@ -372,7 +375,7 @@ bool mingw::link(ArrayRef<const char *> argsArr, raw_ostream &diag) {
     return false;
 
   if (args.hasArg(OPT_verbose) || args.hasArg(OPT__HASH_HASH_HASH))
-    outs() << llvm::join(linkArgs, " ") << "\n";
+    lld::outs() << llvm::join(linkArgs, " ") << "\n";
 
   if (args.hasArg(OPT__HASH_HASH_HASH))
     return true;
@@ -381,5 +384,5 @@ bool mingw::link(ArrayRef<const char *> argsArr, raw_ostream &diag) {
   std::vector<const char *> vec;
   for (const std::string &s : linkArgs)
     vec.push_back(s.c_str());
-  return coff::link(vec, true);
+  return coff::link(vec, true, stdoutOS, stderrOS);
 }
index e559595..3edd544 100644 (file)
 namespace lld {
 namespace coff {
 bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
-          llvm::raw_ostream &diag = llvm::errs());
+          llvm::raw_ostream &stdout, llvm::raw_ostream &stderr);
 }
 
 namespace mingw {
-bool link(llvm::ArrayRef<const char *> args,
-          llvm::raw_ostream &diag = llvm::errs());
+bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
+          llvm::raw_ostream &stdout, llvm::raw_ostream &stderr);
 }
 
 namespace elf {
 bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
-          llvm::raw_ostream &diag = llvm::errs());
+          llvm::raw_ostream &stdout, llvm::raw_ostream &stderr);
 }
 
 namespace mach_o {
 bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
-          llvm::raw_ostream &diag = llvm::errs());
+          llvm::raw_ostream &stdout, llvm::raw_ostream &stderr);
 }
 
 namespace wasm {
 bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
-          llvm::raw_ostream &diag = llvm::errs());
+          llvm::raw_ostream &stdout, llvm::raw_ostream &stderr);
 }
 }
 
index 5086fa9..ac6f93f 100644 (file)
@@ -59,7 +59,7 @@
 //
 // warn() doesn't do anything but printing out a given message.
 //
-// It is not recommended to use llvm::outs() or llvm::errs() directly in lld
+// It is not recommended to use llvm::outs() or lld::errs() directly in lld
 // because they are not thread-safe. The functions declared in this file are
 // thread-safe.
 //
 
 namespace llvm {
 class DiagnosticInfo;
+class raw_ostream;
 }
 
 namespace lld {
 
+// We wrap stdout and stderr so that you can pass alternative stdout/stderr as
+// arguments to lld::*::link() functions.
+extern llvm::raw_ostream *stdoutOS;
+extern llvm::raw_ostream *stderrOS;
+
+llvm::raw_ostream &outs();
+llvm::raw_ostream &errs();
+
 class ErrorHandler {
 public:
   uint64_t errorCount = 0;
   uint64_t errorLimit = 20;
   StringRef errorLimitExceededMsg = "too many errors emitted, stopping now";
   StringRef logName = "lld";
-  llvm::raw_ostream *errorOS = &llvm::errs();
   bool exitEarly = true;
   bool fatalWarnings = false;
   bool verbose = false;
index 34b7b0d..6639447 100644 (file)
@@ -55,6 +55,9 @@ struct WasmSignature;
 } // namespace llvm
 
 namespace lld {
+llvm::raw_ostream &outs();
+llvm::raw_ostream &errs();
+
 // Casting operators.
 using llvm::cast;
 using llvm::cast_or_null;
index 7e6d95f..182f9ca 100644 (file)
@@ -223,8 +223,8 @@ bool Resolver::resolveUndefines() {
     if (!file)
       return true;
     if (std::error_code ec = file->parse()) {
-      llvm::errs() << "Cannot open " + file->path()
-                   << ": " << ec.message() << "\n";
+      lld::errs() << "Cannot open " + file->path() << ": " << ec.message()
+                  << "\n";
       return false;
     }
     DEBUG_WITH_TYPE("resolver",
@@ -252,8 +252,8 @@ bool Resolver::resolveUndefines() {
       if (auto EC = undefAddedOrError.takeError()) {
         // FIXME: This should be passed to logAllUnhandledErrors but it needs
         // to be passed a Twine instead of a string.
-        llvm::errs() << "Error in " + file->path() << ": ";
-        logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
+        lld::errs() << "Error in " + file->path() << ": ";
+        logAllUnhandledErrors(std::move(EC), lld::errs(), std::string());
         return false;
       }
       undefAdded = undefAddedOrError.get();
@@ -266,8 +266,8 @@ bool Resolver::resolveUndefines() {
       if (auto EC = undefAddedOrError.takeError()) {
         // FIXME: This should be passed to logAllUnhandledErrors but it needs
         // to be passed a Twine instead of a string.
-        llvm::errs() << "Error in " + file->path() << ": ";
-        logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
+        lld::errs() << "Error in " + file->path() << ": ";
+        logAllUnhandledErrors(std::move(EC), lld::errs(), std::string());
         return false;
       }
       undefAdded = undefAddedOrError.get();
@@ -279,8 +279,8 @@ bool Resolver::resolveUndefines() {
       if (auto EC = handleSharedLibrary(*file)) {
         // FIXME: This should be passed to logAllUnhandledErrors but it needs
         // to be passed a Twine instead of a string.
-        llvm::errs() << "Error in " + file->path() << ": ";
-        logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
+        lld::errs() << "Error in " + file->path() << ": ";
+        logAllUnhandledErrors(std::move(EC), lld::errs(), std::string());
         return false;
       }
       break;
@@ -424,15 +424,14 @@ bool Resolver::checkUndefines() {
     // Seems like this symbol is undefined. Warn that.
     foundUndefines = true;
     if (_ctx.printRemainingUndefines()) {
-      llvm::errs() << "Undefined symbol: " << undef->file().path()
-                   << ": " << _ctx.demangle(undef->name())
-                   << "\n";
+      lld::errs() << "Undefined symbol: " << undef->file().path() << ": "
+                  << _ctx.demangle(undef->name()) << "\n";
     }
   }
   if (!foundUndefines)
     return false;
   if (_ctx.printRemainingUndefines())
-    llvm::errs() << "symbol(s) not found\n";
+    lld::errs() << "symbol(s) not found\n";
   return true;
 }
 
index 55cc27c..7ccd1ce 100644 (file)
@@ -157,21 +157,15 @@ bool SymbolTable::addByName(const Atom &newAtom) {
         useNew = true;
         break;
       }
-      llvm::errs() << "Size mismatch: "
-                   << existing->name() << " (" << existingSize << ") "
-                   << newAtom.name() << " (" << newSize << ")\n";
+      lld::errs() << "Size mismatch: " << existing->name() << " ("
+                  << existingSize << ") " << newAtom.name() << " (" << newSize
+                  << ")\n";
       LLVM_FALLTHROUGH;
     }
     case MCR_Error:
-      llvm::errs() << "Duplicate symbols: "
-                   << existing->name()
-                   << ":"
-                   << existing->file().path()
-                   << " and "
-                   << newAtom.name()
-                   << ":"
-                   << newAtom.file().path()
-                   << "\n";
+      lld::errs() << "Duplicate symbols: " << existing->name() << ":"
+                  << existing->file().path() << " and " << newAtom.name() << ":"
+                  << newAtom.file().path() << "\n";
       llvm::report_fatal_error("duplicate symbol error");
       break;
     }
@@ -193,7 +187,7 @@ bool SymbolTable::addByName(const Atom &newAtom) {
     break;
   }
   case NCR_Error:
-    llvm::errs() << "SymbolTable: error while merging " << name << "\n";
+    lld::errs() << "SymbolTable: error while merging " << name << "\n";
     llvm::report_fatal_error("duplicate symbol error");
     break;
   }
index 8566aba..60515d2 100644 (file)
@@ -232,7 +232,7 @@ static std::error_code parseOrderFile(StringRef orderFilePath,
      sym = prefixAndSym.first;
     if (!sym.empty()) {
       ctx.appendOrderedSymbol(sym, prefix);
-      //llvm::errs() << sym << ", prefix=" << prefix << "\n";
+      // lld::errs() << sym << ", prefix=" << prefix << "\n";
     }
   }
   return std::error_code();
@@ -382,7 +382,7 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx) {
         !parsedArgs.getLastArg(OPT_test_file_usage)) {
       // If no -arch and no options at all, print usage message.
       if (parsedArgs.size() == 0) {
-        table.PrintHelp(llvm::outs(),
+        table.PrintHelp(lld::outs(),
                         (std::string(args[0]) + " [options] file...").c_str(),
                         "LLVM Linker", false);
       } else {
@@ -1144,14 +1144,16 @@ static void createFiles(MachOLinkingContext &ctx, bool Implicit) {
 
 /// This is where the link is actually performed.
 bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly,
-          raw_ostream &Error) {
+          raw_ostream &StdoutOS, raw_ostream &StderrOS) {
   errorHandler().logName = args::getFilenameWithoutExe(args[0]);
   errorHandler().errorLimitExceededMsg =
       "too many errors emitted, stopping now (use "
       "'-error-limit 0' to see all errors)";
-  errorHandler().errorOS = &Error;
   errorHandler().exitEarly = CanExitEarly;
-  enableColors(Error.has_colors());
+  enableColors(StderrOS.has_colors());
+
+  lld::stdoutOS = &StdoutOS;
+  lld::stderrOS = &StderrOS;
 
   MachOLinkingContext ctx;
   if (!parse(args, ctx))
@@ -1196,10 +1198,9 @@ bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly,
   if (auto ec = pm.runOnFile(*merged)) {
     // FIXME: This should be passed to logAllUnhandledErrors but it needs
     // to be passed a Twine instead of a string.
-    *errorHandler().errorOS << "Failed to run passes on file '"
-                            << ctx.outputPath() << "': ";
-    logAllUnhandledErrors(std::move(ec), *errorHandler().errorOS,
-                          std::string());
+    lld::errs() << "Failed to run passes on file '" << ctx.outputPath()
+                << "': ";
+    logAllUnhandledErrors(std::move(ec), lld::errs(), std::string());
     return false;
   }
 
@@ -1210,10 +1211,8 @@ bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly,
   if (auto ec = ctx.writeFile(*merged)) {
     // FIXME: This should be passed to logAllUnhandledErrors but it needs
     // to be passed a Twine instead of a string.
-    *errorHandler().errorOS << "Failed to write file '" << ctx.outputPath()
-                            << "': ";
-    logAllUnhandledErrors(std::move(ec), *errorHandler().errorOS,
-                          std::string());
+    lld::errs() << "Failed to write file '" << ctx.outputPath() << "': ";
+    logAllUnhandledErrors(std::move(ec), lld::errs(), std::string());
     return false;
   }
 
index 98f4d06..d73711c 100644 (file)
@@ -145,7 +145,7 @@ private:
                            + mb.getBufferIdentifier() + ")").str();
 
     if (_logLoading)
-      llvm::errs() << memberPath << "\n";
+      lld::errs() << memberPath << "\n";
 
     std::unique_ptr<MemoryBuffer> memberMB(MemoryBuffer::getMemBuffer(
         mb.getBuffer(), mb.getBufferIdentifier(), false));
index 8db6ffb..ea54c2d 100644 (file)
@@ -241,8 +241,8 @@ static bool compareAtomsSub(const LayoutPass::SortKey &lc,
     return leftOrdinal < rightOrdinal;
   }
 
-  llvm::errs() << "Unordered: <" << left->name() << "> <"
-               << right->name() << ">\n";
+  lld::errs() << "Unordered: <" << left->name() << "> <" << right->name()
+              << ">\n";
   llvm_unreachable("Atoms with Same Ordinal!");
 }
 
index 221d895..812f896 100644 (file)
@@ -825,7 +825,7 @@ bool MachOLinkingContext::sectionAligned(StringRef seg, StringRef sect,
 void MachOLinkingContext::addExportSymbol(StringRef sym) {
   // Support old crufty export lists with bogus entries.
   if (sym.endswith(".eh") || sym.startswith(".objc_category_name_")) {
-    llvm::errs() << "warning: ignoring " << sym << " in export list\n";
+    lld::errs() << "warning: ignoring " << sym << " in export list\n";
     return;
   }
   // Only i386 MacOSX uses old ABI, so don't change those.
index f34857b..3e70a1d 100644 (file)
@@ -316,8 +316,8 @@ llvm::Error processSymboledSection(DefinedAtom::ContentType atomType,
             });
 
   // Debug logging of symbols.
-  //for (const Symbol *sym : symbols)
-  //  llvm::errs() << "  sym: "
+  // for (const Symbol *sym : symbols)
+  //  lld::errs() << "  sym: "
   //    << llvm::format("0x%08llx ", (uint64_t)sym->value)
   //    << ", " << sym->name << "\n";
 
index 14dcc95..72ff758 100644 (file)
@@ -51,7 +51,7 @@ enum Flavor {
 };
 
 LLVM_ATTRIBUTE_NORETURN static void die(const Twine &s) {
-  errs() << s << "\n";
+  llvm::errs() << s << "\n";
   exit(1);
 }
 
@@ -150,14 +150,14 @@ int main(int argc, const char **argv) {
   switch (parseFlavor(args)) {
   case Gnu:
     if (isPETarget(args))
-      return !mingw::link(args);
-    return !elf::link(args, canExitEarly());
+      return !mingw::link(args, canExitEarly(), llvm::outs(), llvm::errs());
+    return !elf::link(args, canExitEarly(), llvm::outs(), llvm::errs());
   case WinLink:
-    return !coff::link(args, canExitEarly());
+    return !coff::link(args, canExitEarly(), llvm::outs(), llvm::errs());
   case Darwin:
-    return !mach_o::link(args, canExitEarly());
+    return !mach_o::link(args, canExitEarly(), llvm::outs(), llvm::errs());
   case Wasm:
-    return !wasm::link(args, canExitEarly());
+    return !wasm::link(args, canExitEarly(), llvm::outs(), llvm::errs());
   default:
     die("lld is a generic driver.\n"
         "Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-ld"
index d0cdd50..f2314da 100644 (file)
@@ -328,7 +328,7 @@ TEST(BinaryWriterTest, obj_relocs_x86) {
   EXPECT_EQ(tlv.isExtern, true);
   EXPECT_EQ(tlv.symbol, 1U);
 
-  //llvm::errs() << "temp = " << tmpFl << "\n";
+  // lld::errs() << "temp = " << tmpFl << "\n";
   bufferOwner.reset(nullptr);
   std::error_code ec = llvm::sys::fs::remove(Twine(tmpFl));
   EXPECT_FALSE(ec);
@@ -458,7 +458,7 @@ TEST(BinaryWriterTest, obj_relocs_armv7) {
   EXPECT_EQ(absPointer.isExtern, true);
   EXPECT_EQ(absPointer.symbol, 2U);
 
-  //llvm::errs() << "temp = " << tmpFl << "\n";
+  // lld::errs() << "temp = " << tmpFl << "\n";
   bufferOwner.reset(nullptr);
   std::error_code ec = llvm::sys::fs::remove(Twine(tmpFl));
   EXPECT_FALSE(ec);
index d795221..d1e81ca 100644 (file)
@@ -78,13 +78,16 @@ private:
 };
 } // anonymous namespace
 
-bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &error) {
+bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &stdoutOS,
+          raw_ostream &stderrOS) {
   errorHandler().logName = args::getFilenameWithoutExe(args[0]);
-  errorHandler().errorOS = &error;
   errorHandler().errorLimitExceededMsg =
       "too many errors emitted, stopping now (use "
       "-error-limit=0 to see all errors)";
-  enableColors(error.has_colors());
+  enableColors(stderrOS.has_colors());
+
+  lld::stdoutOS = &stdoutOS;
+  lld::stderrOS = &stderrOS;
 
   config = make<Configuration>();
   symtab = make<SymbolTable>();
@@ -648,7 +651,7 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
 
   // Handle --help
   if (args.hasArg(OPT_help)) {
-    parser.PrintHelp(outs(),
+    parser.PrintHelp(lld::outs(),
                      (std::string(argsArr[0]) + " [options] file...").c_str(),
                      "LLVM Linker", false);
     return;
@@ -656,7 +659,7 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
 
   // Handle --version
   if (args.hasArg(OPT_version) || args.hasArg(OPT_v)) {
-    outs() << getLLDVersion() << "\n";
+    lld::outs() << getLLDVersion() << "\n";
     return;
   }