This reverts commit 185657. It will be used by unit tests.
llvm-svn: 186366
#include "lld/Core/LLVM.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Support/raw_ostream.h"
#include <memory>
#include <vector>
protected:
/// Performs link using specified options.
- static bool link(const TargetInfo &targetInfo);
+ static bool link(const TargetInfo &targetInfo,
+ raw_ostream &diagnostics = llvm::errs());
private:
Driver() LLVM_DELETED_FUNCTION;
};
class UniversalDriver : public Driver {
public:
/// Determine flavor and pass control to Driver for that flavor.
- static bool link(int argc, const char *argv[]);
+ static bool link(int argc, const char *argv[],
+ raw_ostream &diagnostics = llvm::errs());
private:
UniversalDriver() LLVM_DELETED_FUNCTION;
public:
/// Parses command line arguments same as gnu/binutils ld and performs link.
/// Returns true iff an error occurred.
- static bool linkELF(int argc, const char *argv[]);
+ static bool linkELF(int argc, const char *argv[],
+ raw_ostream &diagnostics = llvm::errs());
/// Uses gnu/binutils style ld command line options to fill in options struct.
/// Returns true iff there was an error.
static bool parse(int argc, const char *argv[],
- std::unique_ptr<ELFTargetInfo> &targetInfo);
+ std::unique_ptr<ELFTargetInfo> &targetInfo,
+ raw_ostream &diagnostics = llvm::errs());
private:
static llvm::Triple getDefaultTarget(const char *progName);
public:
/// Parses command line arguments same as darwin's ld and performs link.
/// Returns true iff there was an error.
- static bool linkMachO(int argc, const char *argv[]);
+ static bool linkMachO(int argc, const char *argv[],
+ raw_ostream &diagnostics = llvm::errs());
/// Uses darwin style ld command line options to update targetInfo object.
/// Returns true iff there was an error.
- static bool parse(int argc, const char *argv[], MachOTargetInfo &info);
+ static bool parse(int argc, const char *argv[], MachOTargetInfo &info,
+ raw_ostream &diagnostics = llvm::errs());
private:
DarwinLdDriver() LLVM_DELETED_FUNCTION;
};
public:
/// Parses command line arguments same as Windows link.exe and performs link.
/// Returns true iff there was an error.
- static bool linkPECOFF(int argc, const char *argv[]);
+ static bool linkPECOFF(int argc, const char *argv[],
+ raw_ostream &diagnostics = llvm::errs());
/// Uses Windows style link command line options to fill in options struct.
/// Returns true iff there was an error.
- static bool parse(int argc, const char *argv[], PECOFFTargetInfo &info);
+ static bool parse(int argc, const char *argv[], PECOFFTargetInfo &info,
+ raw_ostream &diagnostics = llvm::errs());
private:
WinLinkDriver() LLVM_DELETED_FUNCTION;
/// Parses command line arguments same as lld-core and performs link.
/// Returns true iff there was an error.
- static bool link(int argc, const char *argv[]);
+ static bool link(int argc, const char *argv[],
+ raw_ostream &diagnostics = llvm::errs());
/// Uses lld-core command line options to fill in options struct.
/// Returns true iff there was an error.
- static bool parse(int argc, const char *argv[], CoreTargetInfo &info);
+ static bool parse(int argc, const char *argv[], CoreTargetInfo &info,
+ raw_ostream &diagnostics = llvm::errs());
private:
CoreDriver() LLVM_DELETED_FUNCTION;
namespace lld {
-bool CoreDriver::link(int argc, const char *argv[]) {
+bool CoreDriver::link(int argc, const char *argv[], raw_ostream &diagnostics) {
CoreTargetInfo info;
if (parse(argc, argv, info))
return true;
-
+
return Driver::link(info);
}
-bool CoreDriver::parse(int argc, const char *argv[], CoreTargetInfo &info) {
+
+bool CoreDriver::parse(int argc, const char *argv[],
+ CoreTargetInfo &info, raw_ostream &diagnostics) {
// Parse command line options using CoreOptions.td
std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
CoreOptTable table;
parsedArgs.reset(table.ParseArgs(&argv[1], &argv[argc],
missingIndex, missingCount));
if (missingCount) {
- llvm::errs() << "error: missing arg value for '"
- << parsedArgs->getArgString(missingIndex) << "' expected "
- << missingCount << " argument(s).\n";
+ diagnostics << "error: missing arg value for '"
+ << parsedArgs->getArgString(missingIndex)
+ << "' expected " << missingCount << " argument(s).\n";
return true;
}
for (auto it = parsedArgs->filtered_begin(OPT_UNKNOWN),
ie = parsedArgs->filtered_end(); it != ie; ++it) {
- llvm::errs() << "warning: ignoring unknown argument: "
+ diagnostics << "warning: ignoring unknown argument: "
<< (*it)->getAsString(*parsedArgs) << "\n";
}
namespace lld {
-bool DarwinLdDriver::linkMachO(int argc, const char *argv[]) {
+bool DarwinLdDriver::linkMachO(int argc, const char *argv[],
+ raw_ostream &diagnostics) {
MachOTargetInfo info;
- if (parse(argc, argv, info))
+ if (parse(argc, argv, info, diagnostics))
return true;
-
- return link(info);
+
+ return link(info, diagnostics);
}
-bool DarwinLdDriver::parse(int argc, const char *argv[],
- MachOTargetInfo &info) {
+
+
+bool DarwinLdDriver::parse(int argc, const char *argv[],
+ MachOTargetInfo &info, raw_ostream &diagnostics) {
// Parse command line options using DarwinOptions.td
std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
DarwinLdOptTable table;
parsedArgs.reset(table.ParseArgs(&argv[1], &argv[argc],
missingIndex, missingCount));
if (missingCount) {
- llvm::errs() << "error: missing arg value for '"
- << parsedArgs->getArgString(missingIndex) << "' expected "
- << missingCount << " argument(s).\n";
+ diagnostics << "error: missing arg value for '"
+ << parsedArgs->getArgString(missingIndex)
+ << "' expected " << missingCount << " argument(s).\n";
return true;
}
for (auto it = parsedArgs->filtered_begin(OPT_UNKNOWN),
ie = parsedArgs->filtered_end(); it != ie; ++it) {
- llvm::errs() << "warning: ignoring unknown argument: "
+ diagnostics << "warning: ignoring unknown argument: "
<< (*it)->getAsString(*parsedArgs) << "\n";
}
switch (minOS->getOption().getID()) {
case OPT_macosx_version_min:
if (info.setOS(MachOTargetInfo::OS::macOSX, minOS->getValue())) {
- llvm::errs() << "error: malformed macosx_version_min value\n";
+ diagnostics << "error: malformed macosx_version_min value\n";
return true;
}
break;
case OPT_ios_version_min:
if (info.setOS(MachOTargetInfo::OS::iOS, minOS->getValue())) {
- llvm::errs() << "error: malformed ios_version_min value\n";
+ diagnostics << "error: malformed ios_version_min value\n";
return true;
}
break;
case OPT_ios_simulator_version_min:
if (info.setOS(MachOTargetInfo::OS::iOS_simulator, minOS->getValue())) {
- llvm::errs() << "error: malformed ios_simulator_version_min value\n";
+ diagnostics << "error: malformed ios_simulator_version_min value\n";
return true;
}
break;
it != ie; ++it) {
info.appendInputFile((*it)->getValue());
}
-
+
// Validate the combination of options used.
- if (info.validate(llvm::errs()))
+ if (info.validate(diagnostics))
return true;
return false;
namespace lld {
/// This is where the link is actually performed.
-bool Driver::link(const TargetInfo &targetInfo) {
+bool Driver::link(const TargetInfo &targetInfo, raw_ostream &diagnostics) {
// Honor -mllvm
if (!targetInfo.llvmOptions().empty()) {
unsigned numArgs = targetInfo.llvmOptions().size();
if (targetInfo.logInputFiles())
llvm::outs() << input.getPath() << "\n";
- tg.spawn([ &, index]{
+ tg.spawn([&, index] {
if (error_code ec = targetInfo.readFile(input.getPath(), files[index])) {
- llvm::errs() << "Failed to read file: " << input.getPath() << ": "
- << ec.message() << "\n";
+ diagnostics << "Failed to read file: " << input.getPath()
+ << ": " << ec.message() << "\n";
fail = true;
return;
}
// Give linked atoms to Writer to generate output file.
ScopedTask writeTask(getDefaultDomain(), "Write");
if (error_code ec = targetInfo.writeFile(merged)) {
- llvm::errs() << "Failed to write file '" << targetInfo.outputPath()
- << "': " << ec.message() << "\n";
+ diagnostics << "Failed to write file '" << targetInfo.outputPath()
+ << "': " << ec.message() << "\n";
return true;
}
} // namespace
-bool GnuLdDriver::linkELF(int argc, const char *argv[]) {
+
+
+bool GnuLdDriver::linkELF(int argc, const char *argv[],
+ raw_ostream &diagnostics) {
std::unique_ptr<ELFTargetInfo> options;
- bool error = parse(argc, argv, options);
+ bool error = parse(argc, argv, options, diagnostics);
if (error)
return true;
if (!options)
return false;
- return link(*options);
+ return link(*options, diagnostics);
}
bool GnuLdDriver::parse(int argc, const char *argv[],
- std::unique_ptr<ELFTargetInfo> &targetInfo) {
+ std::unique_ptr<ELFTargetInfo> &targetInfo,
+ raw_ostream &diagnostics) {
// Parse command line options using LDOptions.td
std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
GnuLdOptTable table;
parsedArgs.reset(
table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount));
if (missingCount) {
- llvm::errs() << "error: missing arg value for '"
- << parsedArgs->getArgString(missingIndex) << "' expected "
- << missingCount << " argument(s).\n";
+ diagnostics << "error: missing arg value for '"
+ << parsedArgs->getArgString(missingIndex) << "' expected "
+ << missingCount << " argument(s).\n";
return true;
}
for (auto it = parsedArgs->filtered_begin(OPT_UNKNOWN),
ie = parsedArgs->filtered_end(); it != ie; ++it) {
- llvm::errs() << "warning: ignoring unknown argument: "
- << (*it)->getAsString(*parsedArgs) << "\n";
+ diagnostics << "warning: ignoring unknown argument: " << (*it)->getAsString(
+ *parsedArgs)
+ << "\n";
}
// Handle --help
std::unique_ptr<ELFTargetInfo> options(ELFTargetInfo::create(triple));
if (!options) {
- llvm::errs() << "unknown target triple\n";
+ diagnostics << "unknown target triple\n";
return true;
}
break;
case OPT_l:
if (options->appendLibrary((*it)->getValue())) {
- llvm::errs() << "Failed to find library for " << (*it)->getValue()
- << "\n";
+ diagnostics << "Failed to find library for " << (*it)->getValue()
+ << "\n";
return true;
}
break;
}
// Validate the combination of options used.
- if (options->validate(llvm::errs()))
+ if (options->validate(diagnostics))
return true;
targetInfo.swap(options);
return ret;
}
-Flavor selectFlavor(std::vector<const char *> &args) {
+Flavor selectFlavor(std::vector<const char *> &args, raw_ostream &diag) {
// -core as first arg is shorthand for -flavor core.
if (args.size() > 1 && StringRef(args[1]) == "-core") {
args.erase(args.begin() + 1);
args.erase(args.begin() + 1);
args.erase(args.begin() + 1);
if (flavor == Flavor::invalid)
- llvm::errs() << "error: '" << args[2] << "' invalid value for -flavor.\n";
+ diag << "error: '" << args[2] << "' invalid value for -flavor.\n";
return flavor;
}
// If flavor still undetermined, then error out.
if (flavor == Flavor::invalid)
- llvm::errs() << "error: failed to determine driver flavor from program name"
- << " '" << args[0] << "'.\n"
- << "select a flavor with -flavor [gnu|darwin|link|core].\n";
+ diag << "error: failed to determine driver flavor from program name"
+ << " '" << args[0] << "'.\n"
+ << "select a flavor with -flavor [gnu|darwin|link|core].\n";
return flavor;
}
}
namespace lld {
-bool UniversalDriver::link(int argc, const char *argv[]) {
+bool UniversalDriver::link(int argc, const char *argv[],
+ raw_ostream &diagnostics) {
// Convert argv[] C-array to vector.
std::vector<const char *> args(argv, argv + argc);
// Determine flavor of link based on command name or -flavor argument.
// Note: 'args' is modified to remove -flavor option.
- Flavor flavor = selectFlavor(args);
+ Flavor flavor = selectFlavor(args, diagnostics);
// Switch to appropriate driver.
switch (flavor) {
case Flavor::gnu_ld:
- return GnuLdDriver::linkELF(args.size(), args.data());
+ return GnuLdDriver::linkELF(args.size(), args.data(), diagnostics);
case Flavor::darwin_ld:
- return DarwinLdDriver::linkMachO(args.size(), args.data());
+ return DarwinLdDriver::linkMachO(args.size(), args.data(), diagnostics);
case Flavor::win_link:
- return WinLinkDriver::linkPECOFF(args.size(), args.data());
+ return WinLinkDriver::linkPECOFF(args.size(), args.data(), diagnostics);
case Flavor::core:
- return CoreDriver::link(args.size(), args.data());
+ return CoreDriver::link(args.size(), args.data(), diagnostics);
case Flavor::invalid:
return true;
}
} // namespace
-bool WinLinkDriver::linkPECOFF(int argc, const char *argv[]) {
+bool WinLinkDriver::linkPECOFF(int argc, const char *argv[],
+ raw_ostream &diagnostics) {
PECOFFTargetInfo info;
- if (parse(argc, argv, info))
+ if (parse(argc, argv, info, diagnostics))
return true;
- return link(info);
+ return link(info, diagnostics);
}
bool WinLinkDriver::parse(int argc, const char *argv[],
- PECOFFTargetInfo &info) {
+ PECOFFTargetInfo &info, raw_ostream &diagnostics) {
// Arguments after "--" are interpreted as filenames even if they start with
// a hyphen or a slash. This is not compatible with link.exe but useful for
// us to test lld on Unix.
parsedArgs.reset(
table.ParseArgs(&argv[1], &argv[argEnd], missingIndex, missingCount));
if (missingCount) {
- llvm::errs() << "error: missing arg value for '"
- << parsedArgs->getArgString(missingIndex) << "' expected "
- << missingCount << " argument(s).\n";
+ diagnostics << "error: missing arg value for '"
+ << parsedArgs->getArgString(missingIndex) << "' expected "
+ << missingCount << " argument(s).\n";
return true;
}
// Show warning for unknown arguments
for (auto it = parsedArgs->filtered_begin(OPT_UNKNOWN),
ie = parsedArgs->filtered_end(); it != ie; ++it) {
- llvm::errs() << "warning: ignoring unknown argument: "
- << (*it)->getAsString(*parsedArgs) << "\n";
+ diagnostics << "warning: ignoring unknown argument: "
+ << (*it)->getAsString(*parsedArgs) << "\n";
}
// Copy -mllvm
// Handle -stack
if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_stack))
- if (!parseStackOption(info, arg->getValue(), llvm::errs()))
+ if (!parseStackOption(info, arg->getValue(), diagnostics))
return true;
// Handle -heap
if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_heap))
- if (!parseHeapOption(info, arg->getValue(), llvm::errs()))
+ if (!parseHeapOption(info, arg->getValue(), diagnostics))
return true;
// Handle -subsystem
if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_subsystem))
- if (!parseSubsystemOption(info, arg->getValue(), llvm::errs()))
+ if (!parseSubsystemOption(info, arg->getValue(), diagnostics))
return true;
// Handle -entry
info.setOutputPath(getDefaultOutputFileName(info, inputPaths[0]));
// Validate the combination of options used.
- return info.validate(llvm::errs());
+ return info.validate(diagnostics);
}
} // namespace lld