[lld-macho] Specify the complete set of command-line options for ld64

This is a complete Options.td compiled from ld(1) dated 2018-03-07 and
cross checked with ld64 source code version 512.4 dated 2018-03-18.

This is the first in a series of diffs for argument handling. Follow-ups
will include switch cases for all the new instances of `OPT_foo`, and
parsing/validation of arguments attached to options, e.g., more code
akin to `OPT_platform_version` and associated `parsePlatformVersion()`.

Reviewed By: smeenai

Differential Revision: https://reviews.llvm.org/D80582
This commit is contained in:
Greg McGary
2020-06-15 12:50:20 -07:00
committed by Shoaib Meenai
parent 35651fdd45
commit 7df80e3f23
5 changed files with 1368 additions and 49 deletions
+66 -15
View File
@@ -37,6 +37,7 @@
using namespace llvm;
using namespace llvm::MachO;
using namespace llvm::sys;
using namespace llvm::opt;
using namespace lld;
using namespace lld::macho;
@@ -74,6 +75,12 @@ opt::InputArgList MachOOptTable::parse(ArrayRef<const char *> argv) {
return args;
}
void MachOOptTable::printHelp(const char *argv0, bool showHidden) const {
PrintHelp(lld::outs(), (std::string(argv0) + " [options] file...").c_str(),
"LLVM Linker", showHidden);
lld::outs() << "\n";
}
static Optional<std::string> findLibrary(StringRef name) {
std::string stub = (llvm::Twine("lib") + name + ".tbd").str();
std::string shared = (llvm::Twine("lib") + name + ".dylib").str();
@@ -259,15 +266,41 @@ static bool markSubLibrary(StringRef searchName) {
return false;
}
static void handlePlatformVersion(opt::ArgList::iterator &it,
const opt::ArgList::iterator &end) {
// -platform_version takes 3 args, which LLVM's option library doesn't
// support directly. So this explicitly handles that.
// FIXME: stash skipped args for later use.
for (int i = 0; i < 3; ++i) {
++it;
if (it == end || (*it)->getOption().getID() != OPT_INPUT)
fatal("usage: -platform_version platform min_version sdk_version");
static void handlePlatformVersion(const opt::Arg *arg) {
// TODO: implementation coming very soon ...
}
static void warnIfDeprecatedOption(const opt::Option &opt) {
if (!opt.getGroup().isValid())
return;
if (opt.getGroup().getID() == OPT_grp_deprecated) {
warn("Option `" + opt.getPrefixedName() + "' is deprecated in ld64:");
warn(opt.getHelpText());
}
}
static void warnIfUnimplementedOption(const opt::Option &opt) {
if (!opt.getGroup().isValid())
return;
switch (opt.getGroup().getID()) {
case OPT_grp_deprecated:
// warn about deprecated options elsewhere
break;
case OPT_grp_undocumented:
warn("Option `" + opt.getPrefixedName() +
"' is undocumented. Should lld implement it?");
break;
case OPT_grp_obsolete:
warn("Option `" + opt.getPrefixedName() +
"' is obsolete. Please modernize your usage.");
break;
case OPT_grp_ignored:
warn("Option `" + opt.getPrefixedName() + "' is ignored.");
break;
default:
warn("Option `" + opt.getPrefixedName() +
"' is not yet implemented. Stay tuned...");
break;
}
}
@@ -282,6 +315,14 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
MachOOptTable parser;
opt::InputArgList args = parser.parse(argsArr.slice(1));
if (args.hasArg(OPT_help_hidden)) {
parser.printHelp(argsArr[0], /*showHidden=*/true);
return true;
} else if (args.hasArg(OPT_help)) {
parser.printHelp(argsArr[0], /*showHidden=*/false);
return true;
}
config = make<Configuration>();
symtab = make<SymbolTable>();
target = createTargetInfo(args);
@@ -302,9 +343,9 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
return !errorCount();
}
for (opt::ArgList::iterator it = args.begin(), end = args.end(); it != end;
++it) {
const opt::Arg *arg = *it;
for (const auto &arg : args) {
const auto &opt = arg->getOption();
warnIfDeprecatedOption(opt);
switch (arg->getOption().getID()) {
case OPT_INPUT:
addFile(arg->getValue());
@@ -318,10 +359,20 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
error("library not found for -l" + name);
break;
}
case OPT_platform_version: {
handlePlatformVersion(it, end); // Can advance "it".
case OPT_platform_version:
handlePlatformVersion(arg);
break;
case OPT_o:
case OPT_dylib:
case OPT_e:
case OPT_L:
case OPT_Z:
case OPT_arch:
// handled elsewhere
break;
default:
warnIfUnimplementedOption(opt);
break;
}
}
}
+1
View File
@@ -19,6 +19,7 @@ class MachOOptTable : public llvm::opt::OptTable {
public:
MachOOptTable();
llvm::opt::InputArgList parse(ArrayRef<const char *> argv);
void printHelp(const char *argv0, bool showHidden) const;
};
// Create enum with OPT_xxx values for each option in Options.td
+1284 -30
View File
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -1,16 +1,17 @@
# RUN: not lld -flavor darwinnew -arch x86_64 -platform_version 2>&1 \
# RUN: | FileCheck --check-prefix=FAIL %s
# RUN: | FileCheck --check-prefix=MISSING %s
# RUN: not lld -flavor darwinnew -arch x86_64 -platform_version macos 2>&1 \
# RUN: | FileCheck --check-prefix=FAIL %s
# RUN: | FileCheck --check-prefix=MISSING %s
# RUN: not lld -flavor darwinnew -arch x86_64 -platform_version macos 10.15 2>&1 \
# RUN: | FileCheck --check-prefix=FAIL %s
# RUN: | FileCheck --check-prefix=MISSING %s
# RUN: not lld -flavor darwinnew -arch x86_64 -platform_version macos -lfoo 10.15 2>&1 \
# RUN: | FileCheck --check-prefix=FAIL %s
# RUN: | FileCheck --check-prefix=GOOD %s
# RUN: not lld -flavor darwinnew -arch x86_64 -platform_version macos 10.15 10.15.4 2>&1 \
# RUN: | FileCheck --check-prefix=GOOD %s
# RUN: not lld -flavor darwinnew -arch x86_64 -platform_version macos 10.15 10.15.4 foobar 2>&1 \
# RUN: | FileCheck --check-prefix=FAIL_FILE %s
MISSING: -platform_version: missing argument
FAIL: usage: -platform_version platform min_version sdk_version
GOOD: undefined symbol: _main
FAIL_FILE: cannot open foobar
+12
View File
@@ -135,6 +135,18 @@ public:
return Ret;
}
/// Get the help text for this option.
StringRef getHelpText() const {
assert(Info && "Must have a valid info!");
return Info->HelpText;
}
/// Get the meta-variable list for this option.
StringRef getMetaVar() const {
assert(Info && "Must have a valid info!");
return Info->MetaVar;
}
unsigned getNumArgs() const { return Info->Param; }
bool hasNoOptAsInput() const { return Info->Flags & RenderAsInput;}