Index: lld/Common/Args.cpp =================================================================== --- /dev/null +++ lld/Common/Args.cpp @@ -0,0 +1,62 @@ +//===- Args.cpp -----------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lld/Common/Args.h" +#include "lld/Common/ErrorHandler.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Option/ArgList.h" + +using namespace llvm; +using namespace lld; + +int args::getInteger(opt::InputArgList &Args, unsigned Key, int Default) { + int V = Default; + if (auto *Arg = Args.getLastArg(Key)) { + StringRef S = Arg->getValue(); + if (!to_integer(S, V, 10)) + error(Arg->getSpelling() + ": number expected, but got '" + S + "'"); + } + return V; +} + +std::vector args::getArgs(opt::InputArgList &Args, int Id) { + std::vector V; + for (auto *Arg : Args.filtered(Id)) + V.push_back(Arg->getValue()); + return V; +} + +uint64_t args::getZOptionValue(opt::InputArgList &Args, int Id, StringRef Key, + uint64_t Default) { + for (auto *Arg : Args.filtered(Id)) { + std::pair KV = StringRef(Arg->getValue()).split('='); + if (KV.first == Key) { + uint64_t Result = Default; + if (!to_integer(KV.second, Result)) + error("invalid " + Key + ": " + KV.second); + return Result; + } + } + return Default; +} + +std::vector args::getLines(MemoryBufferRef MB) { + SmallVector Arr; + MB.getBuffer().split(Arr, '\n'); + + std::vector Ret; + for (StringRef S : Arr) { + S = S.trim(); + if (!S.empty() && S[0] != '#') + Ret.push_back(S); + } + return Ret; +} Index: lld/Common/CMakeLists.txt =================================================================== --- lld/Common/CMakeLists.txt +++ lld/Common/CMakeLists.txt @@ -3,6 +3,7 @@ endif() add_lld_library(lldCommon + Args.cpp ErrorHandler.cpp Reproduce.cpp Strings.cpp Index: lld/ELF/Driver.cpp =================================================================== --- lld/ELF/Driver.cpp +++ lld/ELF/Driver.cpp @@ -38,6 +38,7 @@ #include "SyntheticSections.h" #include "Target.h" #include "Writer.h" +#include "lld/Common/Args.h" #include "lld/Common/Driver.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Threads.h" @@ -293,16 +294,6 @@ } } -static int getInteger(opt::InputArgList &Args, unsigned Key, int Default) { - int V = Default; - if (auto *Arg = Args.getLastArg(Key)) { - StringRef S = Arg->getValue(); - if (!to_integer(S, V, 10)) - error(Arg->getSpelling() + ": number expected, but got '" + S + "'"); - } - return V; -} - static const char *getReproduceOption(opt::InputArgList &Args) { if (auto *Arg = Args.getLastArg(OPT_reproduce)) return Arg->getValue(); @@ -316,26 +307,12 @@ return false; } -static uint64_t getZOptionValue(opt::InputArgList &Args, StringRef Key, - uint64_t Default) { - for (auto *Arg : Args.filtered(OPT_z)) { - std::pair KV = StringRef(Arg->getValue()).split('='); - if (KV.first == Key) { - uint64_t Result = Default; - if (!to_integer(KV.second, Result)) - error("invalid " + Key + ": " + KV.second); - return Result; - } - } - return Default; -} - void LinkerDriver::main(ArrayRef ArgsArr, bool CanExitEarly) { ELFOptTable Parser; opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); // Interpret this flag early because error() depends on them. - errorHandler().ErrorLimit = getInteger(Args, OPT_error_limit, 20); + errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); // Handle -help if (Args.hasArg(OPT_help)) { @@ -413,15 +390,8 @@ } } -static std::vector getArgs(opt::InputArgList &Args, int Id) { - std::vector V; - for (auto *Arg : Args.filtered(Id)) - V.push_back(Arg->getValue()); - return V; -} - static std::string getRpath(opt::InputArgList &Args) { - std::vector V = getArgs(Args, OPT_rpath); + std::vector V = args::getArgs(Args, OPT_rpath); return llvm::join(V.begin(), V.end(), ":"); } @@ -596,19 +566,6 @@ return {BuildIdKind::None, {}}; } -static std::vector getLines(MemoryBufferRef MB) { - SmallVector Arr; - MB.getBuffer().split(Arr, '\n'); - - std::vector Ret; - for (StringRef S : Arr) { - S = S.trim(); - if (!S.empty()) - Ret.push_back(S); - } - return Ret; -} - static bool getCompressDebugSections(opt::InputArgList &Args) { StringRef S = Args.getLastArgValue(OPT_compress_debug_sections, "none"); if (S == "none") @@ -631,7 +588,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition) || hasZOption(Args, "muldefs"); - Config->AuxiliaryList = getArgs(Args, OPT_auxiliary); + Config->AuxiliaryList = args::getArgs(Args, OPT_auxiliary); Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic); Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions); Config->Chroot = Args.getLastArgValue(OPT_chroot); @@ -651,7 +608,7 @@ Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false); errorHandler().FatalWarnings = Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); - Config->FilterList = getArgs(Args, OPT_filter); + Config->FilterList = args::getArgs(Args, OPT_filter); Config->Fini = Args.getLastArgValue(OPT_fini, "_fini"); Config->GcSections = Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false); Config->GdbIndex = Args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false); @@ -659,8 +616,8 @@ Config->Init = Args.getLastArgValue(OPT_init, "_init"); Config->LTOAAPipeline = Args.getLastArgValue(OPT_lto_aa_pipeline); Config->LTONewPmPasses = Args.getLastArgValue(OPT_lto_newpm_passes); - Config->LTOO = getInteger(Args, OPT_lto_O, 2); - Config->LTOPartitions = getInteger(Args, OPT_lto_partitions, 1); + Config->LTOO = args::getInteger(Args, OPT_lto_O, 2); + Config->LTOPartitions = args::getInteger(Args, OPT_lto_partitions, 1); Config->MapFile = Args.getLastArgValue(OPT_Map); Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique); Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version); @@ -670,7 +627,7 @@ Config->Omagic = Args.hasFlag(OPT_omagic, OPT_no_omagic, false); Config->OptRemarksFilename = Args.getLastArgValue(OPT_opt_remarks_filename); Config->OptRemarksWithHotness = Args.hasArg(OPT_opt_remarks_with_hotness); - Config->Optimize = getInteger(Args, OPT_O, 1); + Config->Optimize = args::getInteger(Args, OPT_O, 1); Config->OrphanHandling = getOrphanHandling(Args); Config->OutputFile = Args.getLastArgValue(OPT_o); Config->Pie = Args.hasFlag(OPT_pie, OPT_nopie, false); @@ -679,7 +636,7 @@ Config->Rpath = getRpath(Args); Config->Relocatable = Args.hasArg(OPT_relocatable); Config->SaveTemps = Args.hasArg(OPT_save_temps); - Config->SearchPaths = getArgs(Args, OPT_library_path); + Config->SearchPaths = args::getArgs(Args, OPT_library_path); Config->SectionStartMap = getSectionStartMap(Args); Config->Shared = Args.hasArg(OPT_shared); Config->SingleRoRx = Args.hasArg(OPT_no_rosegment); @@ -693,10 +650,10 @@ Config->ThinLTOCachePolicy = check( parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)), "--thinlto-cache-policy: invalid cache policy"); - Config->ThinLTOJobs = getInteger(Args, OPT_thinlto_jobs, -1u); + Config->ThinLTOJobs = args::getInteger(Args, OPT_thinlto_jobs, -1u); ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); Config->Trace = Args.hasArg(OPT_trace); - Config->Undefined = getArgs(Args, OPT_undefined); + Config->Undefined = args::getArgs(Args, OPT_undefined); Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args); Config->Verbose = Args.hasArg(OPT_verbose); errorHandler().Verbose = Config->Verbose; @@ -710,7 +667,7 @@ Config->ZOrigin = hasZOption(Args, "origin"); Config->ZRelro = !hasZOption(Args, "norelro"); Config->ZRodynamic = hasZOption(Args, "rodynamic"); - Config->ZStackSize = getZOptionValue(Args, "stack-size", 0); + Config->ZStackSize = args::getZOptionValue(Args, OPT_z, "stack-size", 0); Config->ZText = !hasZOption(Args, "notext"); Config->ZWxneeded = hasZOption(Args, "wxneeded"); @@ -785,14 +742,14 @@ if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file)) if (Optional Buffer = readFile(Arg->getValue())) - Config->SymbolOrderingFile = getLines(*Buffer); + Config->SymbolOrderingFile = args::getLines(*Buffer); // If --retain-symbol-file is used, we'll keep only the symbols listed in // the file and discard all others. if (auto *Arg = Args.getLastArg(OPT_retain_symbols_file)) { Config->DefaultSymbolVersion = VER_NDX_LOCAL; if (Optional Buffer = readFile(Arg->getValue())) - for (StringRef S : getLines(*Buffer)) + for (StringRef S : args::getLines(*Buffer)) Config->VersionScriptGlobals.push_back( {S, /*IsExternCpp*/ false, /*HasWildcard*/ false}); } @@ -923,8 +880,8 @@ // Parse -z max-page-size=. The default value is defined by // each target. static uint64_t getMaxPageSize(opt::InputArgList &Args) { - uint64_t Val = - getZOptionValue(Args, "max-page-size", Target->DefaultMaxPageSize); + uint64_t Val = args::getZOptionValue(Args, OPT_z, "max-page-size", + Target->DefaultMaxPageSize); if (!isPowerOf2_64(Val)) error("max-page-size: value isn't a power of 2"); return Val; Index: lld/include/lld/Common/Args.h =================================================================== --- /dev/null +++ lld/include/lld/Common/Args.h @@ -0,0 +1,35 @@ +//===- Args.h ---------------------------------------------------*- C++ -*-===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_ARGS_H +#define LLD_ARGS_H + +#include "lld/Common/LLVM.h" +#include "llvm/Support/MemoryBuffer.h" +#include + +namespace llvm { +namespace opt { +class InputArgList; +} +} // namespace llvm + +namespace lld { +namespace args { +int getInteger(llvm::opt::InputArgList &Args, unsigned Key, int Default); +std::vector getArgs(llvm::opt::InputArgList &Args, int Id); + +uint64_t getZOptionValue(llvm::opt::InputArgList &Args, int Id, StringRef Key, + uint64_t Default); + +std::vector getLines(MemoryBufferRef MB); +} // namespace args +} // namespace lld + +#endif Index: lld/wasm/Driver.cpp =================================================================== --- lld/wasm/Driver.cpp +++ lld/wasm/Driver.cpp @@ -12,6 +12,7 @@ #include "Memory.h" #include "SymbolTable.h" #include "Writer.h" +#include "lld/Common/Args.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Threads.h" #include "lld/Common/Version.h" @@ -104,52 +105,6 @@ #undef OPTION }; -static std::vector getArgs(opt::InputArgList &Args, int Id) { - std::vector V; - for (auto *Arg : Args.filtered(Id)) - V.push_back(Arg->getValue()); - return V; -} - -static int getInteger(opt::InputArgList &Args, unsigned Key, int Default) { - int V = Default; - if (auto *Arg = Args.getLastArg(Key)) { - StringRef S = Arg->getValue(); - if (S.getAsInteger(10, V)) - error(Arg->getSpelling() + ": number expected, but got " + S); - } - return V; -} - -static uint64_t getZOptionValue(opt::InputArgList &Args, StringRef Key, - uint64_t Default) { - for (auto *Arg : Args.filtered(OPT_z)) { - StringRef Value = Arg->getValue(); - size_t Pos = Value.find("="); - if (Pos != StringRef::npos && Key == Value.substr(0, Pos)) { - Value = Value.substr(Pos + 1); - uint64_t Res; - if (Value.getAsInteger(0, Res)) - error("invalid " + Key + ": " + Value); - return Res; - } - } - return Default; -} - -static std::vector getLines(MemoryBufferRef MB) { - SmallVector Arr; - MB.getBuffer().split(Arr, '\n'); - - std::vector Ret; - for (StringRef S : Arr) { - S = S.trim(); - if (!S.empty() && S[0] != '#') - Ret.push_back(S); - } - return Ret; -} - // Set color diagnostics according to -color-diagnostics={auto,always,never} // or -no-color-diagnostics flags. static void handleColorDiagnostics(opt::InputArgList &Args) { @@ -283,7 +238,7 @@ V.push_back(Arg->getValue()); cl::ParseCommandLineOptions(V.size(), V.data()); - errorHandler().ErrorLimit = getInteger(Args, OPT_error_limit, 20); + errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); if (Args.hasArg(OPT_version) || Args.hasArg(OPT_v)) { outs() << getLLDVersion() << "\n"; @@ -296,21 +251,22 @@ Config->ImportMemory = Args.hasArg(OPT_import_memory); Config->OutputFile = Args.getLastArgValue(OPT_o); Config->Relocatable = Args.hasArg(OPT_relocatable); - Config->SearchPaths = getArgs(Args, OPT_L); + Config->SearchPaths = args::getArgs(Args, OPT_L); Config->StripAll = Args.hasArg(OPT_strip_all); Config->StripDebug = Args.hasArg(OPT_strip_debug); Config->Sysroot = Args.getLastArgValue(OPT_sysroot); errorHandler().Verbose = Args.hasArg(OPT_verbose); ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); - Config->InitialMemory = getInteger(Args, OPT_initial_memory, 0); - Config->GlobalBase = getInteger(Args, OPT_global_base, 1024); - Config->MaxMemory = getInteger(Args, OPT_max_memory, 0); - Config->ZStackSize = getZOptionValue(Args, "stack-size", WasmPageSize); + Config->InitialMemory = args::getInteger(Args, OPT_initial_memory, 0); + Config->GlobalBase = args::getInteger(Args, OPT_global_base, 1024); + Config->MaxMemory = args::getInteger(Args, OPT_max_memory, 0); + Config->ZStackSize = + args::getZOptionValue(Args, OPT_z, "stack-size", WasmPageSize); if (auto *Arg = Args.getLastArg(OPT_allow_undefined_file)) if (Optional Buf = readFile(Arg->getValue())) - for (StringRef Sym : getLines(*Buf)) + for (StringRef Sym : args::getLines(*Buf)) Config->AllowUndefinedSymbols.insert(Sym); if (Config->OutputFile.empty())