mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 03:29:57 +00:00
ArrayRef-ify Driver::parse and related functions.
llvm-svn: 240236
This commit is contained in:
parent
8da889f1a5
commit
b2b1c7c3e1
@ -43,12 +43,12 @@ namespace coff {
|
||||
Configuration *Config;
|
||||
LinkerDriver *Driver;
|
||||
|
||||
bool link(int Argc, const char *Argv[]) {
|
||||
bool link(llvm::ArrayRef<const char*> Args) {
|
||||
auto C = make_unique<Configuration>();
|
||||
Config = C.get();
|
||||
auto D = make_unique<LinkerDriver>();
|
||||
Driver = D.get();
|
||||
return Driver->link(Argc, Argv);
|
||||
return Driver->link(Args);
|
||||
}
|
||||
|
||||
// Drop directory components and replace extension with ".exe".
|
||||
@ -214,7 +214,7 @@ static WindowsSubsystem inferSubsystem() {
|
||||
.Default(IMAGE_SUBSYSTEM_UNKNOWN);
|
||||
}
|
||||
|
||||
bool LinkerDriver::link(int Argc, const char *Argv[]) {
|
||||
bool LinkerDriver::link(llvm::ArrayRef<const char*> ArgsArr) {
|
||||
// Needed for LTO.
|
||||
llvm::InitializeAllTargetInfos();
|
||||
llvm::InitializeAllTargets();
|
||||
@ -225,11 +225,11 @@ bool LinkerDriver::link(int Argc, const char *Argv[]) {
|
||||
|
||||
// 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 (Argc > 1 && StringRef(Argv[1]).equals_lower("/lib"))
|
||||
return llvm::libDriverMain(Argc - 1, Argv + 1) == 0;
|
||||
if (ArgsArr.size() > 1 && StringRef(ArgsArr[1]).equals_lower("/lib"))
|
||||
return llvm::libDriverMain(ArgsArr.slice(1)) == 0;
|
||||
|
||||
// Parse command line options.
|
||||
auto ArgsOrErr = Parser.parse(Argc, Argv);
|
||||
auto ArgsOrErr = Parser.parse(ArgsArr);
|
||||
if (auto EC = ArgsOrErr.getError()) {
|
||||
llvm::errs() << EC.message() << "\n";
|
||||
return false;
|
||||
@ -238,7 +238,7 @@ bool LinkerDriver::link(int Argc, const char *Argv[]) {
|
||||
|
||||
// Handle /help
|
||||
if (Args->hasArg(OPT_help)) {
|
||||
printHelp(Argv[0]);
|
||||
printHelp(ArgsArr[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -35,14 +35,14 @@ using llvm::Optional;
|
||||
class InputFile;
|
||||
|
||||
// Entry point of the COFF linker.
|
||||
bool link(int Argc, const char *Argv[]);
|
||||
bool link(llvm::ArrayRef<const char*> Args);
|
||||
|
||||
class ArgParser {
|
||||
public:
|
||||
ArgParser() : Alloc(AllocAux) {}
|
||||
// Parses command line options.
|
||||
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>> parse(int Argc,
|
||||
const char *Argv[]);
|
||||
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>>
|
||||
parse(llvm::ArrayRef<const char *> Args);
|
||||
|
||||
// Tokenizes a given string and then parses as command line options.
|
||||
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>> parse(StringRef S) {
|
||||
@ -65,7 +65,7 @@ private:
|
||||
class LinkerDriver {
|
||||
public:
|
||||
LinkerDriver() : Alloc(AllocAux) {}
|
||||
bool link(int Argc, const char *Argv[]);
|
||||
bool link(llvm::ArrayRef<const char*> Args);
|
||||
|
||||
// Used by the resolver to parse .drectve section contents.
|
||||
std::error_code
|
||||
|
@ -571,8 +571,9 @@ ArgParser::parse(std::vector<const char *> Argv) {
|
||||
}
|
||||
|
||||
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>>
|
||||
ArgParser::parse(int Argc, const char *Argv[]) {
|
||||
std::vector<const char *> V(Argv + 1, Argv + Argc);
|
||||
ArgParser::parse(llvm::ArrayRef<const char*> Args) {
|
||||
Args = Args.slice(1);
|
||||
std::vector<const char *> V(Args.begin(), Args.end());
|
||||
return parse(V);
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ private:
|
||||
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(llvm::MutableArrayRef<const char*> args,
|
||||
raw_ostream &diag = llvm::errs());
|
||||
|
||||
private:
|
||||
@ -67,12 +67,12 @@ class GnuLdDriver : public Driver {
|
||||
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(llvm::ArrayRef<const char*> args,
|
||||
raw_ostream &diag = 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[],
|
||||
static bool parse(llvm::ArrayRef<const char*> args,
|
||||
std::unique_ptr<ELFLinkingContext> &context,
|
||||
raw_ostream &diag = llvm::errs());
|
||||
|
||||
@ -103,12 +103,12 @@ class DarwinLdDriver : public Driver {
|
||||
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(llvm::ArrayRef<const char*> args,
|
||||
raw_ostream &diag = llvm::errs());
|
||||
|
||||
/// Uses darwin style ld command line options to update LinkingContext object.
|
||||
/// Returns true iff there was an error.
|
||||
static bool parse(int argc, const char *argv[], MachOLinkingContext &info,
|
||||
static bool parse(llvm::ArrayRef<const char*> args, MachOLinkingContext &info,
|
||||
raw_ostream &diag = llvm::errs());
|
||||
|
||||
private:
|
||||
@ -120,20 +120,20 @@ class WinLinkDriver : public Driver {
|
||||
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(llvm::ArrayRef<const char*> args,
|
||||
raw_ostream &diag = 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[], PECOFFLinkingContext &info,
|
||||
static bool parse(llvm::ArrayRef<const char*> args, PECOFFLinkingContext &info,
|
||||
raw_ostream &diag = llvm::errs(),
|
||||
bool isDirective = false);
|
||||
|
||||
// Same as parse(), but restricted to the context of directives.
|
||||
static bool parseDirectives(int argc, const char *argv[],
|
||||
static bool parseDirectives(int argc, const char** argv,
|
||||
PECOFFLinkingContext &info,
|
||||
raw_ostream &diag = llvm::errs()) {
|
||||
return parse(argc, argv, info, diag, true);
|
||||
return parse(llvm::makeArrayRef(argv, argc), info, diag, true);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -142,7 +142,7 @@ private:
|
||||
|
||||
/// Driver for Windows 'link.exe' command line options
|
||||
namespace coff {
|
||||
bool link(int argc, const char *argv[]);
|
||||
bool link(llvm::ArrayRef<const char*> args);
|
||||
}
|
||||
|
||||
/// Driver for lld unit tests
|
||||
@ -150,12 +150,12 @@ class CoreDriver : public Driver {
|
||||
public:
|
||||
/// 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(llvm::ArrayRef<const char*> args,
|
||||
raw_ostream &diag = 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[], CoreLinkingContext &info,
|
||||
static bool parse(llvm::ArrayRef<const char*> args, CoreLinkingContext &info,
|
||||
raw_ostream &diag = llvm::errs());
|
||||
|
||||
private:
|
||||
|
@ -73,7 +73,7 @@ static const Registry::KindStrings coreKindStrings[] = {
|
||||
LLD_KIND_STRING_END
|
||||
};
|
||||
|
||||
bool CoreDriver::link(int argc, const char *argv[], raw_ostream &diagnostics) {
|
||||
bool CoreDriver::link(llvm::ArrayRef<const char*> args, raw_ostream &diagnostics) {
|
||||
CoreLinkingContext ctx;
|
||||
|
||||
// Register possible input file parsers.
|
||||
@ -81,20 +81,19 @@ bool CoreDriver::link(int argc, const char *argv[], raw_ostream &diagnostics) {
|
||||
ctx.registry().addKindTable(Reference::KindNamespace::testing,
|
||||
Reference::KindArch::all, coreKindStrings);
|
||||
|
||||
if (!parse(argc, argv, ctx))
|
||||
if (!parse(args, ctx))
|
||||
return false;
|
||||
return Driver::link(ctx);
|
||||
}
|
||||
|
||||
bool CoreDriver::parse(int argc, const char *argv[], CoreLinkingContext &ctx,
|
||||
bool CoreDriver::parse(llvm::ArrayRef<const char*> args, CoreLinkingContext &ctx,
|
||||
raw_ostream &diagnostics) {
|
||||
// Parse command line options using CoreOptions.td
|
||||
std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
|
||||
CoreOptTable table;
|
||||
unsigned missingIndex;
|
||||
unsigned missingCount;
|
||||
parsedArgs.reset(table.ParseArgs(llvm::makeArrayRef(argv, argc).slice(1),
|
||||
missingIndex, missingCount));
|
||||
parsedArgs.reset(table.ParseArgs(args.slice(1), missingIndex, missingCount));
|
||||
if (missingCount) {
|
||||
diagnostics << "error: missing arg value for '"
|
||||
<< parsedArgs->getArgString(missingIndex) << "' expected "
|
||||
|
@ -267,17 +267,17 @@ static bool parseNumberBase16(StringRef numStr, uint64_t &baseAddress) {
|
||||
|
||||
namespace lld {
|
||||
|
||||
bool DarwinLdDriver::linkMachO(int argc, const char *argv[],
|
||||
bool DarwinLdDriver::linkMachO(llvm::ArrayRef<const char*> args,
|
||||
raw_ostream &diagnostics) {
|
||||
MachOLinkingContext ctx;
|
||||
if (!parse(argc, argv, ctx, diagnostics))
|
||||
if (!parse(args, ctx, diagnostics))
|
||||
return false;
|
||||
if (ctx.doNothing())
|
||||
return true;
|
||||
return link(ctx, diagnostics);
|
||||
}
|
||||
|
||||
bool DarwinLdDriver::parse(int argc, const char *argv[],
|
||||
bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
|
||||
MachOLinkingContext &ctx, raw_ostream &diagnostics) {
|
||||
// Parse command line options using DarwinLdOptions.td
|
||||
std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
|
||||
@ -285,8 +285,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
||||
unsigned missingIndex;
|
||||
unsigned missingCount;
|
||||
bool globalWholeArchive = false;
|
||||
parsedArgs.reset(table.ParseArgs(llvm::makeArrayRef(argv, argc).slice(1),
|
||||
missingIndex, missingCount));
|
||||
parsedArgs.reset(table.ParseArgs(args.slice(1), missingIndex, missingCount));
|
||||
if (missingCount) {
|
||||
diagnostics << "error: missing arg value for '"
|
||||
<< parsedArgs->getArgString(missingIndex) << "' expected "
|
||||
@ -344,7 +343,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
||||
&& !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(), argv[0], "LLVM Linker", false);
|
||||
table.PrintHelp(llvm::outs(), args[0], "LLVM Linker", false);
|
||||
else
|
||||
diagnostics << "error: -arch not specified and could not be inferred\n";
|
||||
return false;
|
||||
|
@ -82,21 +82,20 @@ public:
|
||||
// at the original @file position. If file cannot be read, @file is not expanded
|
||||
// and left unmodified. @file can appear in a response file, so it's a recursive
|
||||
// process.
|
||||
static std::tuple<int, const char **>
|
||||
maybeExpandResponseFiles(int argc, const char **argv, BumpPtrAllocator &alloc) {
|
||||
static llvm::ArrayRef<const char*>
|
||||
maybeExpandResponseFiles(llvm::ArrayRef<const char*> args, BumpPtrAllocator &alloc) {
|
||||
// Expand response files.
|
||||
SmallVector<const char *, 256> smallvec;
|
||||
for (int i = 0; i < argc; ++i)
|
||||
smallvec.push_back(argv[i]);
|
||||
for (const char *arg : args)
|
||||
smallvec.push_back(arg);
|
||||
llvm::BumpPtrStringSaver saver(alloc);
|
||||
llvm::cl::ExpandResponseFiles(saver, llvm::cl::TokenizeGNUCommandLine, smallvec);
|
||||
|
||||
// Pack the results to a C-array and return it.
|
||||
argc = smallvec.size();
|
||||
const char **copy = alloc.Allocate<const char *>(argc + 1);
|
||||
const char **copy = alloc.Allocate<const char *>(smallvec.size() + 1);
|
||||
std::copy(smallvec.begin(), smallvec.end(), copy);
|
||||
copy[argc] = nullptr;
|
||||
return std::make_tuple(argc, copy);
|
||||
copy[smallvec.size()] = nullptr;
|
||||
return llvm::makeArrayRef(copy, smallvec.size() + 1);
|
||||
}
|
||||
|
||||
// Parses an argument of --defsym=<sym>=<number>
|
||||
@ -134,11 +133,11 @@ static bool parseMaxPageSize(StringRef opt, uint64_t &val) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GnuLdDriver::linkELF(int argc, const char *argv[], raw_ostream &diag) {
|
||||
bool GnuLdDriver::linkELF(llvm::ArrayRef<const char*> args, raw_ostream &diag) {
|
||||
BumpPtrAllocator alloc;
|
||||
std::tie(argc, argv) = maybeExpandResponseFiles(argc, argv, alloc);
|
||||
args = maybeExpandResponseFiles(args, alloc);
|
||||
std::unique_ptr<ELFLinkingContext> options;
|
||||
if (!parse(argc, argv, options, diag))
|
||||
if (!parse(args, options, diag))
|
||||
return false;
|
||||
if (!options)
|
||||
return true;
|
||||
@ -338,7 +337,7 @@ getBool(const llvm::opt::InputArgList &parsedArgs,
|
||||
return llvm::None;
|
||||
}
|
||||
|
||||
bool GnuLdDriver::parse(int argc, const char *argv[],
|
||||
bool GnuLdDriver::parse(llvm::ArrayRef<const char*> args,
|
||||
std::unique_ptr<ELFLinkingContext> &context,
|
||||
raw_ostream &diag) {
|
||||
// Parse command line options using GnuLdOptions.td
|
||||
@ -347,7 +346,7 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
||||
unsigned missingIndex;
|
||||
unsigned missingCount;
|
||||
|
||||
parsedArgs.reset(table.ParseArgs(llvm::makeArrayRef(argv, argc).slice(1),
|
||||
parsedArgs.reset(table.ParseArgs(args.slice(1),
|
||||
missingIndex, missingCount));
|
||||
if (missingCount) {
|
||||
diag << "error: missing arg value for '"
|
||||
@ -358,7 +357,7 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
||||
|
||||
// Handle --help
|
||||
if (parsedArgs->hasArg(OPT_help)) {
|
||||
table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
|
||||
table.PrintHelp(llvm::outs(), args[0], "LLVM Linker", false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -367,7 +366,7 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
|
||||
if (auto *arg = parsedArgs->getLastArg(OPT_target)) {
|
||||
baseTriple = llvm::Triple(arg->getValue());
|
||||
} else {
|
||||
baseTriple = getDefaultTarget(argv[0]);
|
||||
baseTriple = getDefaultTarget(args[0]);
|
||||
}
|
||||
llvm::Triple triple(baseTriple);
|
||||
|
||||
|
@ -127,27 +127,26 @@ static ProgramNameParts parseProgramName(StringRef programName) {
|
||||
|
||||
// Removes the argument from argv along with its value, if exists, and updates
|
||||
// argc.
|
||||
static void removeArg(llvm::opt::Arg *arg, int &argc, const char **&argv) {
|
||||
static void removeArg(llvm::opt::Arg *arg, llvm::MutableArrayRef<const char*> &args) {
|
||||
unsigned int numToRemove = arg->getNumValues() + 1;
|
||||
unsigned int argIndex = arg->getIndex() + 1;
|
||||
|
||||
std::rotate(&argv[argIndex], &argv[argIndex + numToRemove], argv + argc);
|
||||
argc -= numToRemove;
|
||||
auto sub = args.slice(arg->getIndex() + 1);
|
||||
std::rotate(sub.begin(), sub.begin() + numToRemove, sub.end());
|
||||
args = args.drop_back(numToRemove);
|
||||
}
|
||||
|
||||
static Flavor getFlavor(int &argc, const char **&argv,
|
||||
static Flavor getFlavor(llvm::MutableArrayRef<const char*> &args,
|
||||
std::unique_ptr<llvm::opt::InputArgList> &parsedArgs) {
|
||||
if (llvm::opt::Arg *argCore = parsedArgs->getLastArg(OPT_core)) {
|
||||
removeArg(argCore, argc, argv);
|
||||
removeArg(argCore, args);
|
||||
return Flavor::core;
|
||||
}
|
||||
if (llvm::opt::Arg *argFlavor = parsedArgs->getLastArg(OPT_flavor)) {
|
||||
removeArg(argFlavor, argc, argv);
|
||||
removeArg(argFlavor, args);
|
||||
return strToFlavor(argFlavor->getValue());
|
||||
}
|
||||
|
||||
#if LLVM_ON_UNIX
|
||||
if (llvm::sys::path::filename(argv[0]).equals("ld")) {
|
||||
if (llvm::sys::path::filename(args[0]).equals("ld")) {
|
||||
#if __APPLE__
|
||||
// On a Darwin systems, if linker binary is named "ld", use Darwin driver.
|
||||
return Flavor::darwin_ld;
|
||||
@ -157,13 +156,13 @@ static Flavor getFlavor(int &argc, const char **&argv,
|
||||
}
|
||||
#endif
|
||||
|
||||
StringRef name = llvm::sys::path::stem(argv[0]);
|
||||
StringRef name = llvm::sys::path::stem(args[0]);
|
||||
return strToFlavor(parseProgramName(name)._flavor);
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
|
||||
bool UniversalDriver::link(int argc, const char *argv[],
|
||||
bool UniversalDriver::link(llvm::MutableArrayRef<const char*> args,
|
||||
raw_ostream &diagnostics) {
|
||||
// Parse command line options using GnuLdOptions.td
|
||||
std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
|
||||
@ -172,9 +171,9 @@ bool UniversalDriver::link(int argc, const char *argv[],
|
||||
unsigned missingCount;
|
||||
|
||||
// Program name
|
||||
StringRef programName = llvm::sys::path::stem(argv[0]);
|
||||
StringRef programName = llvm::sys::path::stem(args[0]);
|
||||
|
||||
parsedArgs.reset(table.ParseArgs(llvm::makeArrayRef(argv, argc).slice(1),
|
||||
parsedArgs.reset(table.ParseArgs(args.slice(1),
|
||||
missingIndex, missingCount));
|
||||
|
||||
if (missingCount) {
|
||||
@ -197,21 +196,20 @@ bool UniversalDriver::link(int argc, const char *argv[],
|
||||
return true;
|
||||
}
|
||||
|
||||
Flavor flavor = getFlavor(argc, argv, parsedArgs);
|
||||
std::vector<const char *> args(argv, argv + argc);
|
||||
Flavor flavor = getFlavor(args, parsedArgs);
|
||||
|
||||
// Switch to appropriate driver.
|
||||
switch (flavor) {
|
||||
case Flavor::gnu_ld:
|
||||
return GnuLdDriver::linkELF(args.size(), args.data(), diagnostics);
|
||||
return GnuLdDriver::linkELF(args, diagnostics);
|
||||
case Flavor::darwin_ld:
|
||||
return DarwinLdDriver::linkMachO(args.size(), args.data(), diagnostics);
|
||||
return DarwinLdDriver::linkMachO(args, diagnostics);
|
||||
case Flavor::win_link:
|
||||
return WinLinkDriver::linkPECOFF(args.size(), args.data(), diagnostics);
|
||||
return WinLinkDriver::linkPECOFF(args, diagnostics);
|
||||
case Flavor::win_link2:
|
||||
return coff::link(args.size(), args.data());
|
||||
return coff::link(args);
|
||||
case Flavor::core:
|
||||
return CoreDriver::link(args.size(), args.data(), diagnostics);
|
||||
return CoreDriver::link(args, diagnostics);
|
||||
case Flavor::invalid:
|
||||
diagnostics << "Select the appropriate flavor\n";
|
||||
table.PrintHelp(llvm::outs(), programName.data(), "LLVM Linker", false);
|
||||
|
@ -666,12 +666,12 @@ handleFailIfMismatchOption(StringRef option,
|
||||
// Process "LINK" environment variable. If defined, the value of the variable
|
||||
// should be processed as command line arguments.
|
||||
static std::vector<const char *> processLinkEnv(PECOFFLinkingContext &ctx,
|
||||
int argc, const char **argv) {
|
||||
llvm::ArrayRef<const char*> args) {
|
||||
std::vector<const char *> ret;
|
||||
// The first argument is the name of the command. This should stay at the head
|
||||
// of the argument list.
|
||||
assert(argc > 0);
|
||||
ret.push_back(argv[0]);
|
||||
assert(!args.empty());
|
||||
ret.push_back(args[0]);
|
||||
|
||||
// Add arguments specified by the LINK environment variable.
|
||||
llvm::Optional<std::string> env = llvm::sys::Process::GetEnv("LINK");
|
||||
@ -680,8 +680,8 @@ static std::vector<const char *> processLinkEnv(PECOFFLinkingContext &ctx,
|
||||
ret.push_back(ctx.allocate(arg).data());
|
||||
|
||||
// Add the rest of arguments passed via the command line.
|
||||
for (int i = 1; i < argc; ++i)
|
||||
ret.push_back(argv[i]);
|
||||
for (const char* arg : args.slice(1))
|
||||
ret.push_back(arg);
|
||||
ret.push_back(nullptr);
|
||||
return ret;
|
||||
}
|
||||
@ -713,16 +713,16 @@ static bool readResponseFile(StringRef path, PECOFFLinkingContext &ctx,
|
||||
|
||||
// Expand arguments starting with "@". It's an error if a specified file does
|
||||
// not exist. Returns true on success.
|
||||
static bool expandResponseFiles(int &argc, const char **&argv,
|
||||
static bool expandResponseFiles(llvm::ArrayRef<const char*> &args,
|
||||
PECOFFLinkingContext &ctx, raw_ostream &diag,
|
||||
bool &expanded) {
|
||||
std::vector<const char *> newArgv;
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if (argv[i][0] != '@') {
|
||||
newArgv.push_back(argv[i]);
|
||||
for (const char *arg : args) {
|
||||
if (arg[0] != '@') {
|
||||
newArgv.push_back(arg);
|
||||
continue;
|
||||
}
|
||||
StringRef filename = StringRef(argv[i] + 1);
|
||||
StringRef filename = StringRef(arg + 1);
|
||||
if (!readResponseFile(filename, ctx, newArgv)) {
|
||||
diag << "error: cannot read response file: " << filename << "\n";
|
||||
return false;
|
||||
@ -731,20 +731,19 @@ static bool expandResponseFiles(int &argc, const char **&argv,
|
||||
}
|
||||
if (!expanded)
|
||||
return true;
|
||||
argc = newArgv.size();
|
||||
newArgv.push_back(nullptr);
|
||||
argv = &ctx.allocateCopy(newArgv)[0];
|
||||
args = llvm::makeArrayRef(&ctx.allocateCopy(newArgv)[0], newArgv.size() - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parses the given command line options and returns the result. Returns NULL if
|
||||
// there's an error in the options.
|
||||
static std::unique_ptr<llvm::opt::InputArgList>
|
||||
parseArgs(int argc, const char **argv, PECOFFLinkingContext &ctx,
|
||||
parseArgs(llvm::ArrayRef<const char*> args, PECOFFLinkingContext &ctx,
|
||||
raw_ostream &diag, bool isReadingDirectiveSection) {
|
||||
// Expand arguments starting with "@".
|
||||
bool expanded = false;
|
||||
if (!expandResponseFiles(argc, argv, ctx, diag, expanded))
|
||||
if (!expandResponseFiles(args, ctx, diag, expanded))
|
||||
return nullptr;
|
||||
|
||||
// Parse command line options using WinLinkOptions.td
|
||||
@ -752,7 +751,7 @@ parseArgs(int argc, const char **argv, PECOFFLinkingContext &ctx,
|
||||
WinLinkOptTable table;
|
||||
unsigned missingIndex;
|
||||
unsigned missingCount;
|
||||
parsedArgs.reset(table.ParseArgs(llvm::makeArrayRef(argv, argc).slice(1),
|
||||
parsedArgs.reset(table.ParseArgs(args.slice(1),
|
||||
missingIndex, missingCount));
|
||||
if (missingCount) {
|
||||
diag << "error: missing arg value for '"
|
||||
@ -780,8 +779,8 @@ parseArgs(int argc, const char **argv, PECOFFLinkingContext &ctx,
|
||||
if (!isReadingDirectiveSection && expanded &&
|
||||
parsedArgs->getLastArg(OPT_verbose)) {
|
||||
diag << "Command line:";
|
||||
for (int i = 0; i < argc; ++i)
|
||||
diag << " " << argv[i];
|
||||
for (const char *arg : args)
|
||||
diag << " " << arg;
|
||||
diag << "\n\n";
|
||||
}
|
||||
|
||||
@ -802,10 +801,10 @@ static bool hasLibrary(PECOFFLinkingContext &ctx, File *file) {
|
||||
// If the first command line argument is "/lib", link.exe acts as if it's
|
||||
// "lib.exe" command. This is for backward compatibility.
|
||||
// http://msdn.microsoft.com/en-us/library/h34w59b3.aspx
|
||||
static bool maybeRunLibCommand(int argc, const char **argv, raw_ostream &diag) {
|
||||
if (argc <= 1)
|
||||
static bool maybeRunLibCommand(llvm::ArrayRef<const char*> args, raw_ostream &diag) {
|
||||
if (args.size() <= 1)
|
||||
return false;
|
||||
if (!StringRef(argv[1]).equals_lower("/lib"))
|
||||
if (!StringRef(args[1]).equals_lower("/lib"))
|
||||
return false;
|
||||
ErrorOr<std::string> pathOrErr = llvm::sys::findProgramByName("lib.exe");
|
||||
if (!pathOrErr) {
|
||||
@ -817,8 +816,8 @@ static bool maybeRunLibCommand(int argc, const char **argv, raw_ostream &diag) {
|
||||
// Run lib.exe
|
||||
std::vector<const char *> vec;
|
||||
vec.push_back(path.c_str());
|
||||
for (int i = 2; i < argc; ++i)
|
||||
vec.push_back(argv[i]);
|
||||
for (const char *arg : args.slice(2))
|
||||
vec.push_back(arg);
|
||||
vec.push_back(nullptr);
|
||||
|
||||
if (llvm::sys::ExecuteAndWait(path.c_str(), &vec[0]) != 0)
|
||||
@ -840,8 +839,8 @@ void addFiles(PECOFFLinkingContext &ctx, StringRef path, raw_ostream &diag,
|
||||
// Main driver
|
||||
//
|
||||
|
||||
bool WinLinkDriver::linkPECOFF(int argc, const char **argv, raw_ostream &diag) {
|
||||
if (maybeRunLibCommand(argc, argv, diag))
|
||||
bool WinLinkDriver::linkPECOFF(llvm::ArrayRef<const char*> args, raw_ostream &diag) {
|
||||
if (maybeRunLibCommand(args, diag))
|
||||
return true;
|
||||
|
||||
PECOFFLinkingContext ctx;
|
||||
@ -851,9 +850,9 @@ bool WinLinkDriver::linkPECOFF(int argc, const char **argv, raw_ostream &diag) {
|
||||
ctx.registry().addSupportArchives(ctx.logInputFiles());
|
||||
ctx.registry().addSupportYamlFiles();
|
||||
|
||||
std::vector<const char *> newargv = processLinkEnv(ctx, argc, argv);
|
||||
std::vector<const char *> newargv = processLinkEnv(ctx, args);
|
||||
processLibEnv(ctx);
|
||||
if (!parse(newargv.size() - 1, &newargv[0], ctx, diag))
|
||||
if (!parse(llvm::makeArrayRef(newargv).drop_back(1), ctx, diag))
|
||||
return false;
|
||||
|
||||
// Create the file if needed.
|
||||
@ -864,7 +863,7 @@ bool WinLinkDriver::linkPECOFF(int argc, const char **argv, raw_ostream &diag) {
|
||||
return link(ctx, diag);
|
||||
}
|
||||
|
||||
bool WinLinkDriver::parse(int argc, const char *argv[],
|
||||
bool WinLinkDriver::parse(llvm::ArrayRef<const char*> args,
|
||||
PECOFFLinkingContext &ctx, raw_ostream &diag,
|
||||
bool isReadingDirectiveSection) {
|
||||
// Parse may be called from multiple threads simultaneously to parse .drectve
|
||||
@ -875,7 +874,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
|
||||
std::map<StringRef, StringRef> failIfMismatchMap;
|
||||
// Parse the options.
|
||||
std::unique_ptr<llvm::opt::InputArgList> parsedArgs =
|
||||
parseArgs(argc, argv, ctx, diag, isReadingDirectiveSection);
|
||||
parseArgs(args, ctx, diag, isReadingDirectiveSection);
|
||||
if (!parsedArgs)
|
||||
return false;
|
||||
|
||||
@ -886,7 +885,7 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
|
||||
// Handle /help
|
||||
if (parsedArgs->hasArg(OPT_help)) {
|
||||
WinLinkOptTable table;
|
||||
table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
|
||||
table.PrintHelp(llvm::outs(), args[0], "LLVM Linker", false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -32,5 +32,6 @@ int main(int argc, const char *argv[]) {
|
||||
llvm::PrettyStackTraceProgram stackPrinter(argc, argv);
|
||||
llvm::llvm_shutdown_obj shutdown;
|
||||
|
||||
return UniversalDriver::link(argc, argv) ? 0 : 1;
|
||||
return !UniversalDriver::link(
|
||||
llvm::MutableArrayRef<const char *>(argv, argc));
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ protected:
|
||||
|
||||
// Call the parser.
|
||||
raw_string_ostream os(_errorMessage);
|
||||
return D::parse(vec.size(), &vec[0], _ctx, os);
|
||||
return D::parse(vec, _ctx, os);
|
||||
}
|
||||
|
||||
T _ctx;
|
||||
|
@ -25,7 +25,7 @@ TEST(UniversalDriver, flavor) {
|
||||
|
||||
std::string diags;
|
||||
raw_string_ostream os(diags);
|
||||
UniversalDriver::link(array_lengthof(args), args, os);
|
||||
UniversalDriver::link(args, os);
|
||||
EXPECT_EQ(os.str().find("failed to determine driver flavor"),
|
||||
std::string::npos);
|
||||
EXPECT_NE(os.str().find("No input files"),
|
||||
|
Loading…
Reference in New Issue
Block a user