Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -14,6 +14,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" +#include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/Support/CachePruning.h" #include "llvm/Support/CodeGen.h" @@ -276,6 +277,10 @@ // 4 for ELF32, 8 for ELF64. int Wordsize; + + // Target triple, inferred from program name or defaulted to LLVM + // default target. + llvm::Triple TargetTriple; }; // The only instance of Configuration struct. Index: ELF/Driver.h =================================================================== --- ELF/Driver.h +++ ELF/Driver.h @@ -31,6 +31,7 @@ void addLibrary(StringRef Name); private: + void setTargetTriple(StringRef argv0, llvm::opt::InputArgList &Args); void readConfigs(llvm::opt::InputArgList &Args); void createFiles(llvm::opt::InputArgList &Args); void inferMachineType(); Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -54,6 +54,7 @@ #include "llvm/Support/LEB128.h" #include "llvm/Support/Path.h" #include "llvm/Support/TarWriter.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include @@ -378,6 +379,25 @@ return; } + if (const char *Path = getReproduceOption(Args)) { + // Note that --reproduce is a debug option so you can ignore it + // if you are trying to understand the whole picture of the code. + Expected> ErrOrWriter = + TarWriter::create(Path, path::stem(Path)); + if (ErrOrWriter) { + Tar = std::move(*ErrOrWriter); + Tar->append("response.txt", createResponseFile(Args)); + Tar->append("version.txt", getLLDVersion() + "\n"); + } else { + error("--reproduce: " + toString(ErrOrWriter.takeError())); + } + } + + initLLVM(); + setTargetTriple(ArgsArr[0], Args); + readConfigs(Args); + checkZOptions(Args); + // Handle -v or -version. // // A note about "compatible with GNU linkers" message: this is a hack for @@ -393,26 +413,11 @@ // lot of "configure" scripts out there that are generated by old version // of Libtool. We cannot convince every software developer to migrate to // the latest version and re-generate scripts. So we have this hack. - if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) + if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) { message(getLLDVersion() + " (compatible with GNU linkers)"); - - if (const char *Path = getReproduceOption(Args)) { - // Note that --reproduce is a debug option so you can ignore it - // if you are trying to understand the whole picture of the code. - Expected> ErrOrWriter = - TarWriter::create(Path, path::stem(Path)); - if (ErrOrWriter) { - Tar = std::move(*ErrOrWriter); - Tar->append("response.txt", createResponseFile(Args)); - Tar->append("version.txt", getLLDVersion() + "\n"); - } else { - error("--reproduce: " + toString(ErrOrWriter.takeError())); - } + message("Target: " + Config->TargetTriple.str()); } - readConfigs(Args); - checkZOptions(Args); - // The behavior of -v or --version is a bit strange, but this is // needed for compatibility with GNU linkers. if (Args.hasArg(OPT_v) && !Args.hasArg(OPT_INPUT)) @@ -420,7 +425,6 @@ if (Args.hasArg(OPT_version)) return; - initLLVM(); createFiles(Args); if (errorCount()) return; @@ -746,6 +750,34 @@ error(Msg + ": " + StringRef(Err).trim()); } +void LinkerDriver::setTargetTriple(StringRef argv0, opt::InputArgList &Args) { + std::string TargetError; + + // Firstly, see if user specified explicit --target + StringRef TargetOpt = Args.getLastArgValue(OPT_target); + if (!TargetOpt.empty()) { + if (llvm::TargetRegistry::lookupTarget(TargetOpt, TargetError)) { + Config->TargetTriple = llvm::Triple(TargetOpt); + return; + } else + error("Unsupported --target=" + TargetOpt + ": " + TargetError); + } + + // Secondly, try to get it from program name prefix + std::string ProgName = llvm::sys::path::stem(argv0); + size_t LastComponent = ProgName.rfind('-'); + if (LastComponent != std::string::npos) { + std::string Prefix = ProgName.substr(0, LastComponent); + if (llvm::TargetRegistry::lookupTarget(Prefix, TargetError)) { + Config->TargetTriple = llvm::Triple(Prefix); + return; + } + } + + // Finally, use the default target triple + Config->TargetTriple = llvm::Triple(getDefaultTargetTriple()); +} + // Initializes Config members by the command line options. void LinkerDriver::readConfigs(opt::InputArgList &Args) { errorHandler().Verbose = Args.hasArg(OPT_verbose); @@ -1172,7 +1204,7 @@ // each target. static uint64_t getMaxPageSize(opt::InputArgList &Args) { uint64_t Val = args::getZOptionValue(Args, OPT_z, "max-page-size", - Target->DefaultMaxPageSize); + lld::elf::Target->DefaultMaxPageSize); if (!isPowerOf2_64(Val)) error("max-page-size: value isn't a power of 2"); return Val; Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -313,6 +313,8 @@ defm sysroot: Eq<"sysroot", "Set the system root">; +defm target: Eq<"target", "Apply configuration defaults for a given target">; + def target1_rel: F<"target1-rel">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_REL32">; def target1_abs: F<"target1-abs">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_ABS32 (default)">;