diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -61,14 +61,17 @@ Configuration *config; LinkerDriver *driver; -bool link(ArrayRef args, bool canExitEarly, raw_ostream &diag) { +bool link(ArrayRef 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(); symtab = make(); @@ -1149,7 +1152,7 @@ // 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; } diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -907,7 +907,7 @@ } void printHelp(const char *argv0) { - COFFOptTable().PrintHelp(outs(), + COFFOptTable().PrintHelp(lld::outs(), (std::string(argv0) + " [options] file...").c_str(), "LLVM Linker", false); } diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -1843,7 +1843,7 @@ [](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 diff --git a/lld/Common/ErrorHandler.cpp b/lld/Common/ErrorHandler.cpp --- a/lld/Common/ErrorHandler.cpp +++ b/lld/Common/ErrorHandler.cpp @@ -26,7 +26,8 @@ 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 @@ 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 @@ // 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 @@ if (!verbose) return; std::lock_guard lock(mu); - *errorOS << logName << ": " << msg << "\n"; + lld::errs() << logName << ": " << msg << "\n"; } void ErrorHandler::message(const Twine &msg) { std::lock_guard lock(mu); - outs() << msg << "\n"; - outs().flush(); + lld::outs() << msg << "\n"; + lld::outs().flush(); } void ErrorHandler::warn(const Twine &msg) { @@ -165,8 +170,8 @@ } std::lock_guard 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 @@ std::lock_guard 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); } diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -75,14 +75,17 @@ static void setConfigs(opt::InputArgList &args); static void readConfigs(opt::InputArgList &args); -bool link(ArrayRef args, bool canExitEarly, raw_ostream &error) { +bool link(ArrayRef 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(); diff --git a/lld/ELF/DriverUtils.cpp b/lld/ELF/DriverUtils.cpp --- a/lld/ELF/DriverUtils.cpp +++ b/lld/ELF/DriverUtils.cpp @@ -145,16 +145,16 @@ 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) { diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp --- a/lld/ELF/MapFile.cpp +++ b/lld/ELF/MapFile.cpp @@ -213,7 +213,7 @@ } 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 @@ } // Print out a header. - outs() << "Cross Reference Table\n\n"; + lld::outs() << "Cross Reference Table\n\n"; print("Symbol", "File"); // Print out a table. diff --git a/lld/MinGW/Driver.cpp b/lld/MinGW/Driver.cpp --- a/lld/MinGW/Driver.cpp +++ b/lld/MinGW/Driver.cpp @@ -83,9 +83,9 @@ 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,9 @@ // Convert Unix-ish command line arguments to Windows-ish ones and // then call coff::link. -bool mingw::link(ArrayRef argsArr, raw_ostream &diag) { - enableColors(diag.has_colors()); +bool mingw::link(ArrayRef argsArr, bool canExitEarly, + raw_ostream &stdoutOS, raw_ostream &stderrOS) { + enableColors(stderrOS.has_colors()); MinGWOptTable parser; opt::InputArgList args = parser.parse(argsArr.slice(1)); @@ -372,7 +373,7 @@ 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 +382,5 @@ std::vector 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); } diff --git a/lld/include/lld/Common/Driver.h b/lld/include/lld/Common/Driver.h --- a/lld/include/lld/Common/Driver.h +++ b/lld/include/lld/Common/Driver.h @@ -15,27 +15,27 @@ namespace lld { namespace coff { bool link(llvm::ArrayRef args, bool canExitEarly, - llvm::raw_ostream &diag = llvm::errs()); + llvm::raw_ostream &stdout, llvm::raw_ostream &stderr); } namespace mingw { -bool link(llvm::ArrayRef args, - llvm::raw_ostream &diag = llvm::errs()); +bool link(llvm::ArrayRef args, bool canExitEarly, + llvm::raw_ostream &stdout, llvm::raw_ostream &stderr); } namespace elf { bool link(llvm::ArrayRef args, bool canExitEarly, - llvm::raw_ostream &diag = llvm::errs()); + llvm::raw_ostream &stdout, llvm::raw_ostream &stderr); } namespace mach_o { bool link(llvm::ArrayRef args, bool canExitEarly, - llvm::raw_ostream &diag = llvm::errs()); + llvm::raw_ostream &stdout, llvm::raw_ostream &stderr); } namespace wasm { bool link(llvm::ArrayRef args, bool canExitEarly, - llvm::raw_ostream &diag = llvm::errs()); + llvm::raw_ostream &stdout, llvm::raw_ostream &stderr); } } diff --git a/lld/include/lld/Common/ErrorHandler.h b/lld/include/lld/Common/ErrorHandler.h --- a/lld/include/lld/Common/ErrorHandler.h +++ b/lld/include/lld/Common/ErrorHandler.h @@ -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. // @@ -76,17 +76,25 @@ 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; diff --git a/lld/include/lld/Common/LLVM.h b/lld/include/lld/Common/LLVM.h --- a/lld/include/lld/Common/LLVM.h +++ b/lld/include/lld/Common/LLVM.h @@ -55,6 +55,9 @@ } // namespace llvm namespace lld { +llvm::raw_ostream &outs(); +llvm::raw_ostream &errs(); + // Casting operators. using llvm::cast; using llvm::cast_or_null; diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp --- a/lld/lib/Core/Resolver.cpp +++ b/lld/lib/Core/Resolver.cpp @@ -223,8 +223,8 @@ 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 @@ 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 @@ 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 @@ 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 @@ // 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; } diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp --- a/lld/lib/Core/SymbolTable.cpp +++ b/lld/lib/Core/SymbolTable.cpp @@ -157,21 +157,15 @@ 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 @@ 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; } diff --git a/lld/lib/Driver/DarwinLdDriver.cpp b/lld/lib/Driver/DarwinLdDriver.cpp --- a/lld/lib/Driver/DarwinLdDriver.cpp +++ b/lld/lib/Driver/DarwinLdDriver.cpp @@ -232,7 +232,7 @@ 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 @@ !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 @@ /// This is where the link is actually performed. bool link(llvm::ArrayRef 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 @@ 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 @@ 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; } diff --git a/lld/lib/ReaderWriter/FileArchive.cpp b/lld/lib/ReaderWriter/FileArchive.cpp --- a/lld/lib/ReaderWriter/FileArchive.cpp +++ b/lld/lib/ReaderWriter/FileArchive.cpp @@ -145,7 +145,7 @@ + mb.getBufferIdentifier() + ")").str(); if (_logLoading) - llvm::errs() << memberPath << "\n"; + lld::errs() << memberPath << "\n"; std::unique_ptr memberMB(MemoryBuffer::getMemBuffer( mb.getBuffer(), mb.getBufferIdentifier(), false)); diff --git a/lld/lib/ReaderWriter/MachO/LayoutPass.cpp b/lld/lib/ReaderWriter/MachO/LayoutPass.cpp --- a/lld/lib/ReaderWriter/MachO/LayoutPass.cpp +++ b/lld/lib/ReaderWriter/MachO/LayoutPass.cpp @@ -241,8 +241,8 @@ 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!"); } diff --git a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp --- a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp +++ b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp @@ -825,7 +825,7 @@ 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. diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -316,8 +316,8 @@ }); // 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"; diff --git a/lld/tools/lld/lld.cpp b/lld/tools/lld/lld.cpp --- a/lld/tools/lld/lld.cpp +++ b/lld/tools/lld/lld.cpp @@ -51,7 +51,7 @@ }; LLVM_ATTRIBUTE_NORETURN static void die(const Twine &s) { - errs() << s << "\n"; + llvm::errs() << s << "\n"; exit(1); } @@ -150,14 +150,14 @@ 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" diff --git a/lld/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp b/lld/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp --- a/lld/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp +++ b/lld/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp @@ -328,7 +328,7 @@ 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 @@ 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); diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -78,13 +78,16 @@ }; } // anonymous namespace -bool link(ArrayRef args, bool canExitEarly, raw_ostream &error) { +bool link(ArrayRef 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(); symtab = make(); @@ -648,7 +651,7 @@ // 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 @@ // Handle --version if (args.hasArg(OPT_version) || args.hasArg(OPT_v)) { - outs() << getLLDVersion() << "\n"; + lld::outs() << getLLDVersion() << "\n"; return; }