diff options
Diffstat (limited to 'lld/wasm/Driver.cpp')
-rw-r--r-- | lld/wasm/Driver.cpp | 690 |
1 files changed, 345 insertions, 345 deletions
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index a3852d47b60..d190dba7eac 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -40,7 +40,7 @@ using namespace llvm::wasm; using namespace lld; using namespace lld::wasm; -Configuration *lld::wasm::Config; +Configuration *lld::wasm::config; namespace { @@ -65,39 +65,39 @@ static void initLLVM() { class LinkerDriver { public: - void link(ArrayRef<const char *> ArgsArr); + void link(ArrayRef<const char *> argsArr); private: - void createFiles(opt::InputArgList &Args); - void addFile(StringRef Path); - void addLibrary(StringRef Name); + void createFiles(opt::InputArgList &args); + void addFile(StringRef path); + void addLibrary(StringRef name); // True if we are in --whole-archive and --no-whole-archive. - bool InWholeArchive = false; + bool inWholeArchive = false; - std::vector<InputFile *> Files; + std::vector<InputFile *> files; }; } // anonymous namespace -bool lld::wasm::link(ArrayRef<const char *> Args, bool CanExitEarly, - raw_ostream &Error) { - errorHandler().LogName = args::getFilenameWithoutExe(Args[0]); - errorHandler().ErrorOS = &Error; - errorHandler().ColorDiagnostics = Error.has_colors(); - errorHandler().ErrorLimitExceededMsg = +bool lld::wasm::link(ArrayRef<const char *> args, bool canExitEarly, + raw_ostream &error) { + errorHandler().logName = args::getFilenameWithoutExe(args[0]); + errorHandler().errorOS = &error; + errorHandler().colorDiagnostics = error.has_colors(); + errorHandler().errorLimitExceededMsg = "too many errors emitted, stopping now (use " "-error-limit=0 to see all errors)"; - Config = make<Configuration>(); - Symtab = make<SymbolTable>(); + config = make<Configuration>(); + symtab = make<SymbolTable>(); initLLVM(); - LinkerDriver().link(Args); + LinkerDriver().link(args); // Exit immediately if we don't need to return to the caller. // This saves time because the overhead of calling destructors // for all globally-allocated objects is not negligible. - if (CanExitEarly) + if (canExitEarly) exitLld(errorCount() ? 1 : 0); freeArena(); @@ -110,7 +110,7 @@ bool lld::wasm::link(ArrayRef<const char *> Args, bool CanExitEarly, #undef PREFIX // Create table mapping all options defined in Options.td -static const opt::OptTable::Info OptInfo[] = { +static const opt::OptTable::Info optInfo[] = { #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, @@ -121,57 +121,57 @@ static const opt::OptTable::Info OptInfo[] = { namespace { class WasmOptTable : public llvm::opt::OptTable { public: - WasmOptTable() : OptTable(OptInfo) {} - opt::InputArgList parse(ArrayRef<const char *> Argv); + WasmOptTable() : OptTable(optInfo) {} + opt::InputArgList parse(ArrayRef<const char *> argv); }; } // namespace // Set color diagnostics according to -color-diagnostics={auto,always,never} // or -no-color-diagnostics flags. -static void handleColorDiagnostics(opt::InputArgList &Args) { - auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, +static void handleColorDiagnostics(opt::InputArgList &args) { + auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, OPT_no_color_diagnostics); - if (!Arg) + if (!arg) return; - if (Arg->getOption().getID() == OPT_color_diagnostics) { - errorHandler().ColorDiagnostics = true; - } else if (Arg->getOption().getID() == OPT_no_color_diagnostics) { - errorHandler().ColorDiagnostics = false; + if (arg->getOption().getID() == OPT_color_diagnostics) { + errorHandler().colorDiagnostics = true; + } else if (arg->getOption().getID() == OPT_no_color_diagnostics) { + errorHandler().colorDiagnostics = false; } else { - StringRef S = Arg->getValue(); - if (S == "always") - errorHandler().ColorDiagnostics = true; - else if (S == "never") - errorHandler().ColorDiagnostics = false; - else if (S != "auto") - error("unknown option: --color-diagnostics=" + S); + StringRef s = arg->getValue(); + if (s == "always") + errorHandler().colorDiagnostics = true; + else if (s == "never") + errorHandler().colorDiagnostics = false; + else if (s != "auto") + error("unknown option: --color-diagnostics=" + s); } } // Find a file by concatenating given paths. -static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) { - SmallString<128> S; - path::append(S, Path1, Path2); - if (fs::exists(S)) - return S.str().str(); +static Optional<std::string> findFile(StringRef path1, const Twine &path2) { + SmallString<128> s; + path::append(s, path1, path2); + if (fs::exists(s)) + return s.str().str(); return None; } -opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> Argv) { - SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size()); +opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> argv) { + SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size()); - unsigned MissingIndex; - unsigned MissingCount; + unsigned missingIndex; + unsigned missingCount; // Expand response files (arguments in the form of @<filename>) - cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Vec); + cl::ExpandResponseFiles(saver, cl::TokenizeGNUCommandLine, vec); - opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount); + opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount); - handleColorDiagnostics(Args); - for (auto *Arg : Args.filtered(OPT_UNKNOWN)) - error("unknown argument: " + Arg->getAsString(Args)); - return Args; + handleColorDiagnostics(args); + for (auto *arg : args.filtered(OPT_UNKNOWN)) + error("unknown argument: " + arg->getAsString(args)); + return args; } // Currently we allow a ".imports" to live alongside a library. This can @@ -181,189 +181,189 @@ opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> Argv) { // In the long run this information would be better stored as a symbol // attribute/flag in the object file itself. // See: https://github.com/WebAssembly/tool-conventions/issues/35 -static void readImportFile(StringRef Filename) { - if (Optional<MemoryBufferRef> Buf = readFile(Filename)) - for (StringRef Sym : args::getLines(*Buf)) - Config->AllowUndefinedSymbols.insert(Sym); +static void readImportFile(StringRef filename) { + if (Optional<MemoryBufferRef> buf = readFile(filename)) + for (StringRef sym : args::getLines(*buf)) + config->allowUndefinedSymbols.insert(sym); } // Returns slices of MB by parsing MB as an archive file. // Each slice consists of a member file in the archive. -std::vector<MemoryBufferRef> static getArchiveMembers(MemoryBufferRef MB) { - std::unique_ptr<Archive> File = - CHECK(Archive::create(MB), - MB.getBufferIdentifier() + ": failed to parse archive"); - - std::vector<MemoryBufferRef> V; - Error Err = Error::success(); - for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) { - Archive::Child C = - CHECK(COrErr, MB.getBufferIdentifier() + +std::vector<MemoryBufferRef> static getArchiveMembers(MemoryBufferRef mb) { + std::unique_ptr<Archive> file = + CHECK(Archive::create(mb), + mb.getBufferIdentifier() + ": failed to parse archive"); + + std::vector<MemoryBufferRef> v; + Error err = Error::success(); + for (const ErrorOr<Archive::Child> &cOrErr : file->children(err)) { + Archive::Child c = + CHECK(cOrErr, mb.getBufferIdentifier() + ": could not get the child of the archive"); - MemoryBufferRef MBRef = - CHECK(C.getMemoryBufferRef(), - MB.getBufferIdentifier() + + MemoryBufferRef mbref = + CHECK(c.getMemoryBufferRef(), + mb.getBufferIdentifier() + ": could not get the buffer for a child of the archive"); - V.push_back(MBRef); + v.push_back(mbref); } - if (Err) - fatal(MB.getBufferIdentifier() + - ": Archive::children failed: " + toString(std::move(Err))); + if (err) + fatal(mb.getBufferIdentifier() + + ": Archive::children failed: " + toString(std::move(err))); // Take ownership of memory buffers created for members of thin archives. - for (std::unique_ptr<MemoryBuffer> &MB : File->takeThinBuffers()) - make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); + for (std::unique_ptr<MemoryBuffer> &mb : file->takeThinBuffers()) + make<std::unique_ptr<MemoryBuffer>>(std::move(mb)); - return V; + return v; } -void LinkerDriver::addFile(StringRef Path) { - Optional<MemoryBufferRef> Buffer = readFile(Path); - if (!Buffer.hasValue()) +void LinkerDriver::addFile(StringRef path) { + Optional<MemoryBufferRef> buffer = readFile(path); + if (!buffer.hasValue()) return; - MemoryBufferRef MBRef = *Buffer; + MemoryBufferRef mbref = *buffer; - switch (identify_magic(MBRef.getBuffer())) { + switch (identify_magic(mbref.getBuffer())) { case file_magic::archive: { - SmallString<128> ImportFile = Path; - path::replace_extension(ImportFile, ".imports"); - if (fs::exists(ImportFile)) - readImportFile(ImportFile.str()); + SmallString<128> importFile = path; + path::replace_extension(importFile, ".imports"); + if (fs::exists(importFile)) + readImportFile(importFile.str()); // Handle -whole-archive. - if (InWholeArchive) { - for (MemoryBufferRef &M : getArchiveMembers(MBRef)) - Files.push_back(createObjectFile(M, Path)); + if (inWholeArchive) { + for (MemoryBufferRef &m : getArchiveMembers(mbref)) + files.push_back(createObjectFile(m, path)); return; } - std::unique_ptr<Archive> File = - CHECK(Archive::create(MBRef), Path + ": failed to parse archive"); + std::unique_ptr<Archive> file = + CHECK(Archive::create(mbref), path + ": failed to parse archive"); - if (!File->isEmpty() && !File->hasSymbolTable()) { - error(MBRef.getBufferIdentifier() + + if (!file->isEmpty() && !file->hasSymbolTable()) { + error(mbref.getBufferIdentifier() + ": archive has no index; run ranlib to add one"); } - Files.push_back(make<ArchiveFile>(MBRef)); + files.push_back(make<ArchiveFile>(mbref)); return; } case file_magic::bitcode: case file_magic::wasm_object: - Files.push_back(createObjectFile(MBRef)); + files.push_back(createObjectFile(mbref)); break; default: - error("unknown file type: " + MBRef.getBufferIdentifier()); + error("unknown file type: " + mbref.getBufferIdentifier()); } } // Add a given library by searching it from input search paths. -void LinkerDriver::addLibrary(StringRef Name) { - for (StringRef Dir : Config->SearchPaths) { - if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a")) { - addFile(*S); +void LinkerDriver::addLibrary(StringRef name) { + for (StringRef dir : config->searchPaths) { + if (Optional<std::string> s = findFile(dir, "lib" + name + ".a")) { + addFile(*s); return; } } - error("unable to find library -l" + Name); + error("unable to find library -l" + name); } -void LinkerDriver::createFiles(opt::InputArgList &Args) { - for (auto *Arg : Args) { - switch (Arg->getOption().getID()) { +void LinkerDriver::createFiles(opt::InputArgList &args) { + for (auto *arg : args) { + switch (arg->getOption().getID()) { case OPT_l: - addLibrary(Arg->getValue()); + addLibrary(arg->getValue()); break; case OPT_INPUT: - addFile(Arg->getValue()); + addFile(arg->getValue()); break; case OPT_whole_archive: - InWholeArchive = true; + inWholeArchive = true; break; case OPT_no_whole_archive: - InWholeArchive = false; + inWholeArchive = false; break; } } } -static StringRef getEntry(opt::InputArgList &Args) { - auto *Arg = Args.getLastArg(OPT_entry, OPT_no_entry); - if (!Arg) { - if (Args.hasArg(OPT_relocatable)) +static StringRef getEntry(opt::InputArgList &args) { + auto *arg = args.getLastArg(OPT_entry, OPT_no_entry); + if (!arg) { + if (args.hasArg(OPT_relocatable)) return ""; - if (Args.hasArg(OPT_shared)) + if (args.hasArg(OPT_shared)) return "__wasm_call_ctors"; return "_start"; } - if (Arg->getOption().getID() == OPT_no_entry) + if (arg->getOption().getID() == OPT_no_entry) return ""; - return Arg->getValue(); + return arg->getValue(); } // Initializes Config members by the command line options. -static void readConfigs(opt::InputArgList &Args) { - Config->AllowUndefined = Args.hasArg(OPT_allow_undefined); - Config->CheckFeatures = - Args.hasFlag(OPT_check_features, OPT_no_check_features, true); - Config->CompressRelocations = Args.hasArg(OPT_compress_relocations); - Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true); - Config->DisableVerify = Args.hasArg(OPT_disable_verify); - Config->EmitRelocs = Args.hasArg(OPT_emit_relocs); - Config->Entry = getEntry(Args); - Config->ExportAll = Args.hasArg(OPT_export_all); - Config->ExportDynamic = Args.hasFlag(OPT_export_dynamic, +static void readConfigs(opt::InputArgList &args) { + config->allowUndefined = args.hasArg(OPT_allow_undefined); + config->checkFeatures = + args.hasFlag(OPT_check_features, OPT_no_check_features, true); + config->compressRelocations = args.hasArg(OPT_compress_relocations); + config->demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true); + config->disableVerify = args.hasArg(OPT_disable_verify); + config->emitRelocs = args.hasArg(OPT_emit_relocs); + config->entry = getEntry(args); + config->exportAll = args.hasArg(OPT_export_all); + config->exportDynamic = args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false); - Config->ExportTable = Args.hasArg(OPT_export_table); - errorHandler().FatalWarnings = - Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); - Config->ImportMemory = Args.hasArg(OPT_import_memory); - Config->SharedMemory = Args.hasArg(OPT_shared_memory); + config->exportTable = args.hasArg(OPT_export_table); + errorHandler().fatalWarnings = + args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); + config->importMemory = args.hasArg(OPT_import_memory); + config->sharedMemory = args.hasArg(OPT_shared_memory); // TODO: Make passive segments the default with shared memory - Config->PassiveSegments = - Args.hasFlag(OPT_passive_segments, OPT_active_segments, false); - Config->ImportTable = Args.hasArg(OPT_import_table); - Config->LTOO = args::getInteger(Args, OPT_lto_O, 2); - Config->LTOPartitions = args::getInteger(Args, OPT_lto_partitions, 1); - Config->Optimize = args::getInteger(Args, OPT_O, 0); - Config->OutputFile = Args.getLastArgValue(OPT_o); - Config->Relocatable = Args.hasArg(OPT_relocatable); - Config->GcSections = - Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !Config->Relocatable); - Config->MergeDataSegments = - Args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments, - !Config->Relocatable); - Config->Pie = Args.hasFlag(OPT_pie, OPT_no_pie, false); - Config->PrintGcSections = - Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false); - Config->SaveTemps = Args.hasArg(OPT_save_temps); - Config->SearchPaths = args::getStrings(Args, OPT_L); - Config->Shared = Args.hasArg(OPT_shared); - Config->StripAll = Args.hasArg(OPT_strip_all); - Config->StripDebug = Args.hasArg(OPT_strip_debug); - Config->StackFirst = Args.hasArg(OPT_stack_first); - Config->Trace = Args.hasArg(OPT_trace); - Config->ThinLTOCacheDir = Args.getLastArgValue(OPT_thinlto_cache_dir); - Config->ThinLTOCachePolicy = CHECK( - parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)), + config->passiveSegments = + args.hasFlag(OPT_passive_segments, OPT_active_segments, false); + config->importTable = args.hasArg(OPT_import_table); + config->ltoo = args::getInteger(args, OPT_lto_O, 2); + config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1); + config->optimize = args::getInteger(args, OPT_O, 0); + config->outputFile = args.getLastArgValue(OPT_o); + config->relocatable = args.hasArg(OPT_relocatable); + config->gcSections = + args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !config->relocatable); + config->mergeDataSegments = + args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments, + !config->relocatable); + config->pie = args.hasFlag(OPT_pie, OPT_no_pie, false); + config->printGcSections = + args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false); + config->saveTemps = args.hasArg(OPT_save_temps); + config->searchPaths = args::getStrings(args, OPT_L); + config->shared = args.hasArg(OPT_shared); + config->stripAll = args.hasArg(OPT_strip_all); + config->stripDebug = args.hasArg(OPT_strip_debug); + config->stackFirst = args.hasArg(OPT_stack_first); + config->trace = args.hasArg(OPT_trace); + config->thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir); + config->thinLTOCachePolicy = CHECK( + parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)), "--thinlto-cache-policy: invalid cache policy"); - Config->ThinLTOJobs = args::getInteger(Args, OPT_thinlto_jobs, -1u); - errorHandler().Verbose = Args.hasArg(OPT_verbose); - LLVM_DEBUG(errorHandler().Verbose = true); - ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); - - 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_features)) { - Config->Features = + config->thinLTOJobs = args::getInteger(args, OPT_thinlto_jobs, -1u); + errorHandler().verbose = args.hasArg(OPT_verbose); + LLVM_DEBUG(errorHandler().verbose = true); + threadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true); + + 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_features)) { + config->features = llvm::Optional<std::vector<std::string>>(std::vector<std::string>()); - for (StringRef S : Arg->getValues()) - Config->Features->push_back(S); + for (StringRef s : arg->getValues()) + config->features->push_back(s); } } @@ -372,183 +372,183 @@ static void readConfigs(opt::InputArgList &Args) { // This function initialize such members. See Config.h for the details // of these values. static void setConfigs() { - Config->Pic = Config->Pie || Config->Shared; + config->isPic = config->pie || config->shared; - if (Config->Pic) { - if (Config->ExportTable) + if (config->isPic) { + if (config->exportTable) error("-shared/-pie is incompatible with --export-table"); - Config->ImportTable = true; + config->importTable = true; } - if (Config->Shared) { - Config->ImportMemory = true; - Config->ExportDynamic = true; - Config->AllowUndefined = true; + if (config->shared) { + config->importMemory = true; + config->exportDynamic = true; + config->allowUndefined = true; } } // Some command line options or some combinations of them are not allowed. // This function checks for such errors. -static void checkOptions(opt::InputArgList &Args) { - if (!Config->StripDebug && !Config->StripAll && Config->CompressRelocations) +static void checkOptions(opt::InputArgList &args) { + if (!config->stripDebug && !config->stripAll && config->compressRelocations) error("--compress-relocations is incompatible with output debug" " information. Please pass --strip-debug or --strip-all"); - if (Config->LTOO > 3) - error("invalid optimization level for LTO: " + Twine(Config->LTOO)); - if (Config->LTOPartitions == 0) + if (config->ltoo > 3) + error("invalid optimization level for LTO: " + Twine(config->ltoo)); + if (config->ltoPartitions == 0) error("--lto-partitions: number of threads must be > 0"); - if (Config->ThinLTOJobs == 0) + if (config->thinLTOJobs == 0) error("--thinlto-jobs: number of threads must be > 0"); - if (Config->Pie && Config->Shared) + if (config->pie && config->shared) error("-shared and -pie may not be used together"); - if (Config->OutputFile.empty()) + if (config->outputFile.empty()) error("no output file specified"); - if (Config->ImportTable && Config->ExportTable) + if (config->importTable && config->exportTable) error("--import-table and --export-table may not be used together"); - if (Config->Relocatable) { - if (!Config->Entry.empty()) + if (config->relocatable) { + if (!config->entry.empty()) error("entry point specified for relocatable output file"); - if (Config->GcSections) + if (config->gcSections) error("-r and --gc-sections may not be used together"); - if (Config->CompressRelocations) + if (config->compressRelocations) error("-r -and --compress-relocations may not be used together"); - if (Args.hasArg(OPT_undefined)) + if (args.hasArg(OPT_undefined)) error("-r -and --undefined may not be used together"); - if (Config->Pie) + if (config->pie) error("-r and -pie may not be used together"); } } // Force Sym to be entered in the output. Used for -u or equivalent. -static Symbol *handleUndefined(StringRef Name) { - Symbol *Sym = Symtab->find(Name); - if (!Sym) +static Symbol *handleUndefined(StringRef name) { + Symbol *sym = symtab->find(name); + if (!sym) return nullptr; // Since symbol S may not be used inside the program, LTO may // eliminate it. Mark the symbol as "used" to prevent it. - Sym->IsUsedInRegularObj = true; + sym->isUsedInRegularObj = true; - if (auto *LazySym = dyn_cast<LazySymbol>(Sym)) - LazySym->fetch(); + if (auto *lazySym = dyn_cast<LazySymbol>(sym)) + lazySym->fetch(); - return Sym; + return sym; } static UndefinedGlobal * -createUndefinedGlobal(StringRef Name, llvm::wasm::WasmGlobalType *Type) { - auto *Sym = - cast<UndefinedGlobal>(Symtab->addUndefinedGlobal(Name, Name, - DefaultModule, 0, - nullptr, Type)); - Config->AllowUndefinedSymbols.insert(Sym->getName()); - Sym->IsUsedInRegularObj = true; - return Sym; +createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) { + auto *sym = + cast<UndefinedGlobal>(symtab->addUndefinedGlobal(name, name, + defaultModule, 0, + nullptr, type)); + config->allowUndefinedSymbols.insert(sym->getName()); + sym->isUsedInRegularObj = true; + return sym; } // Create ABI-defined synthetic symbols static void createSyntheticSymbols() { - static WasmSignature NullSignature = {{}, {}}; - static llvm::wasm::WasmGlobalType GlobalTypeI32 = {WASM_TYPE_I32, false}; - static llvm::wasm::WasmGlobalType MutableGlobalTypeI32 = {WASM_TYPE_I32, + static WasmSignature nullSignature = {{}, {}}; + static llvm::wasm::WasmGlobalType globalTypeI32 = {WASM_TYPE_I32, false}; + static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {WASM_TYPE_I32, true}; - if (!Config->Relocatable) { - WasmSym::CallCtors = Symtab->addSyntheticFunction( + if (!config->relocatable) { + WasmSym::callCtors = symtab->addSyntheticFunction( "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN, - make<SyntheticFunction>(NullSignature, "__wasm_call_ctors")); + make<SyntheticFunction>(nullSignature, "__wasm_call_ctors")); - if (Config->PassiveSegments) { + if (config->passiveSegments) { // Passive segments are used to avoid memory being reinitialized on each // thread's instantiation. These passive segments are initialized and // dropped in __wasm_init_memory, which is the first function called from // __wasm_call_ctors. - WasmSym::InitMemory = Symtab->addSyntheticFunction( + WasmSym::initMemory = symtab->addSyntheticFunction( "__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN, - make<SyntheticFunction>(NullSignature, "__wasm_init_memory")); + make<SyntheticFunction>(nullSignature, "__wasm_init_memory")); } - if (Config->Pic) { + if (config->isPic) { // For PIC code we create a synthetic function __wasm_apply_relocs which // is called from __wasm_call_ctors before the user-level constructors. - WasmSym::ApplyRelocs = Symtab->addSyntheticFunction( + WasmSym::applyRelocs = symtab->addSyntheticFunction( "__wasm_apply_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN, - make<SyntheticFunction>(NullSignature, "__wasm_apply_relocs")); + make<SyntheticFunction>(nullSignature, "__wasm_apply_relocs")); } } // The __stack_pointer is imported in the shared library case, and exported // in the non-shared (executable) case. - if (Config->Shared) { - WasmSym::StackPointer = - createUndefinedGlobal("__stack_pointer", &MutableGlobalTypeI32); + if (config->shared) { + WasmSym::stackPointer = + createUndefinedGlobal("__stack_pointer", &mutableGlobalTypeI32); } else { - llvm::wasm::WasmGlobal Global; - Global.Type = {WASM_TYPE_I32, true}; - Global.InitExpr.Value.Int32 = 0; - Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; - Global.SymbolName = "__stack_pointer"; - auto *StackPointer = make<InputGlobal>(Global, nullptr); - StackPointer->Live = true; + llvm::wasm::WasmGlobal global; + global.Type = {WASM_TYPE_I32, true}; + global.InitExpr.Value.Int32 = 0; + global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; + global.SymbolName = "__stack_pointer"; + auto *stackPointer = make<InputGlobal>(global, nullptr); + stackPointer->live = true; // For non-PIC code // TODO(sbc): Remove WASM_SYMBOL_VISIBILITY_HIDDEN when the mutable global // spec proposal is implemented in all major browsers. // See: https://github.com/WebAssembly/mutable-global - WasmSym::StackPointer = Symtab->addSyntheticGlobal( - "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, StackPointer); - WasmSym::DataEnd = Symtab->addOptionalDataSymbol("__data_end"); - WasmSym::GlobalBase = Symtab->addOptionalDataSymbol("__global_base"); - WasmSym::HeapBase = Symtab->addOptionalDataSymbol("__heap_base"); + WasmSym::stackPointer = symtab->addSyntheticGlobal( + "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, stackPointer); + WasmSym::dataEnd = symtab->addOptionalDataSymbol("__data_end"); + WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base"); + WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base"); } - if (Config->Pic) { + if (config->isPic) { // For PIC code, we import two global variables (__memory_base and // __table_base) from the environment and use these as the offset at // which to load our static data and function table. // See: // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md - WasmSym::MemoryBase = - createUndefinedGlobal("__memory_base", &GlobalTypeI32); - WasmSym::TableBase = createUndefinedGlobal("__table_base", &GlobalTypeI32); - WasmSym::MemoryBase->markLive(); - WasmSym::TableBase->markLive(); + WasmSym::memoryBase = + createUndefinedGlobal("__memory_base", &globalTypeI32); + WasmSym::tableBase = createUndefinedGlobal("__table_base", &globalTypeI32); + WasmSym::memoryBase->markLive(); + WasmSym::tableBase->markLive(); } - WasmSym::DsoHandle = Symtab->addSyntheticDataSymbol( + WasmSym::dsoHandle = symtab->addSyntheticDataSymbol( "__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN); } // Reconstructs command line arguments so that so that you can re-run // the same command with the same inputs. This is for --reproduce. -static std::string createResponseFile(const opt::InputArgList &Args) { - SmallString<0> Data; - raw_svector_ostream OS(Data); +static std::string createResponseFile(const opt::InputArgList &args) { + SmallString<0> data; + raw_svector_ostream os(data); // Copy the command line to the output while rewriting paths. - for (auto *Arg : Args) { - switch (Arg->getOption().getID()) { + for (auto *arg : args) { + switch (arg->getOption().getID()) { case OPT_reproduce: break; case OPT_INPUT: - OS << quote(relativeToRoot(Arg->getValue())) << "\n"; + os << quote(relativeToRoot(arg->getValue())) << "\n"; break; case OPT_o: // If -o path contains directories, "lld @response.txt" will likely // fail because the archive we are creating doesn't contain empty // directories for the output path (-o doesn't create directories). // Strip directories to prevent the issue. - OS << "-o " << quote(sys::path::filename(Arg->getValue())) << "\n"; + os << "-o " << quote(sys::path::filename(arg->getValue())) << "\n"; break; default: - OS << toString(*Arg) << "\n"; + os << toString(*arg) << "\n"; } } - return Data.str(); + return data.str(); } // The --wrap option is a feature to rename symbols so that you can write @@ -560,13 +560,13 @@ static std::string createResponseFile(const opt::InputArgList &Args) { // // This data structure is instantiated for each -wrap option. struct WrappedSymbol { - Symbol *Sym; - Symbol *Real; - Symbol *Wrap; + Symbol *sym; + Symbol *real; + Symbol *wrap; }; -static Symbol *addUndefined(StringRef Name) { - return Symtab->addUndefinedFunction(Name, "", "", 0, nullptr, nullptr, false); +static Symbol *addUndefined(StringRef name) { + return symtab->addUndefinedFunction(name, "", "", 0, nullptr, nullptr, false); } // Handles -wrap option. @@ -574,34 +574,34 @@ static Symbol *addUndefined(StringRef Name) { // This function instantiates wrapper symbols. At this point, they seem // like they are not being used at all, so we explicitly set some flags so // that LTO won't eliminate them. -static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &Args) { - std::vector<WrappedSymbol> V; - DenseSet<StringRef> Seen; +static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) { + std::vector<WrappedSymbol> v; + DenseSet<StringRef> seen; - for (auto *Arg : Args.filtered(OPT_wrap)) { - StringRef Name = Arg->getValue(); - if (!Seen.insert(Name).second) + for (auto *arg : args.filtered(OPT_wrap)) { + StringRef name = arg->getValue(); + if (!seen.insert(name).second) continue; - Symbol *Sym = Symtab->find(Name); - if (!Sym) + Symbol *sym = symtab->find(name); + if (!sym) continue; - Symbol *Real = addUndefined(Saver.save("__real_" + Name)); - Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); - V.push_back({Sym, Real, Wrap}); + Symbol *real = addUndefined(saver.save("__real_" + name)); + Symbol *wrap = addUndefined(saver.save("__wrap_" + name)); + v.push_back({sym, real, wrap}); // We want to tell LTO not to inline symbols to be overwritten // because LTO doesn't know the final symbol contents after renaming. - Real->CanInline = false; - Sym->CanInline = false; + real->canInline = false; + sym->canInline = false; // Tell LTO not to eliminate these symbols. - Sym->IsUsedInRegularObj = true; - Wrap->IsUsedInRegularObj = true; - Real->IsUsedInRegularObj = false; + sym->isUsedInRegularObj = true; + wrap->isUsedInRegularObj = true; + real->isUsedInRegularObj = false; } - return V; + return v; } // Do renaming for -wrap by updating pointers to symbols. @@ -609,158 +609,158 @@ static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &Args) { // When this function is executed, only InputFiles and symbol table // contain pointers to symbol objects. We visit them to replace pointers, // so that wrapped symbols are swapped as instructed by the command line. -static void wrapSymbols(ArrayRef<WrappedSymbol> Wrapped) { - DenseMap<Symbol *, Symbol *> Map; - for (const WrappedSymbol &W : Wrapped) { - Map[W.Sym] = W.Wrap; - Map[W.Real] = W.Sym; +static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) { + DenseMap<Symbol *, Symbol *> map; + for (const WrappedSymbol &w : wrapped) { + map[w.sym] = w.wrap; + map[w.real] = w.sym; } // Update pointers in input files. - parallelForEach(Symtab->ObjectFiles, [&](InputFile *File) { - MutableArrayRef<Symbol *> Syms = File->getMutableSymbols(); - for (size_t I = 0, E = Syms.size(); I != E; ++I) - if (Symbol *S = Map.lookup(Syms[I])) - Syms[I] = S; + parallelForEach(symtab->objectFiles, [&](InputFile *file) { + MutableArrayRef<Symbol *> syms = file->getMutableSymbols(); + for (size_t i = 0, e = syms.size(); i != e; ++i) + if (Symbol *s = map.lookup(syms[i])) + syms[i] = s; }); // Update pointers in the symbol table. - for (const WrappedSymbol &W : Wrapped) - Symtab->wrap(W.Sym, W.Real, W.Wrap); + for (const WrappedSymbol &w : wrapped) + symtab->wrap(w.sym, w.real, w.wrap); } -void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { - WasmOptTable Parser; - opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); +void LinkerDriver::link(ArrayRef<const char *> argsArr) { + WasmOptTable parser; + opt::InputArgList args = parser.parse(argsArr.slice(1)); // Handle --help - if (Args.hasArg(OPT_help)) { - Parser.PrintHelp(outs(), - (std::string(ArgsArr[0]) + " [options] file...").c_str(), + if (args.hasArg(OPT_help)) { + parser.PrintHelp(outs(), + (std::string(argsArr[0]) + " [options] file...").c_str(), "LLVM Linker", false); return; } // Handle --version - if (Args.hasArg(OPT_version) || Args.hasArg(OPT_v)) { + if (args.hasArg(OPT_version) || args.hasArg(OPT_v)) { outs() << getLLDVersion() << "\n"; return; } // Handle --reproduce - if (auto *Arg = Args.getLastArg(OPT_reproduce)) { - StringRef Path = Arg->getValue(); - Expected<std::unique_ptr<TarWriter>> 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"); + if (auto *arg = args.getLastArg(OPT_reproduce)) { + StringRef path = arg->getValue(); + Expected<std::unique_ptr<TarWriter>> 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())); + error("--reproduce: " + toString(errOrWriter.takeError())); } } // Parse and evaluate -mllvm options. - std::vector<const char *> V; - V.push_back("wasm-ld (LLVM option parsing)"); - for (auto *Arg : Args.filtered(OPT_mllvm)) - V.push_back(Arg->getValue()); - cl::ParseCommandLineOptions(V.size(), V.data()); + std::vector<const char *> v; + v.push_back("wasm-ld (LLVM option parsing)"); + for (auto *arg : args.filtered(OPT_mllvm)) + v.push_back(arg->getValue()); + cl::ParseCommandLineOptions(v.size(), v.data()); - errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); + errorHandler().errorLimit = args::getInteger(args, OPT_error_limit, 20); - readConfigs(Args); + readConfigs(args); setConfigs(); - checkOptions(Args); + checkOptions(args); - if (auto *Arg = Args.getLastArg(OPT_allow_undefined_file)) - readImportFile(Arg->getValue()); + if (auto *arg = args.getLastArg(OPT_allow_undefined_file)) + readImportFile(arg->getValue()); - if (!Args.hasArg(OPT_INPUT)) { + if (!args.hasArg(OPT_INPUT)) { error("no input files"); return; } // Handle --trace-symbol. - for (auto *Arg : Args.filtered(OPT_trace_symbol)) - Symtab->trace(Arg->getValue()); + for (auto *arg : args.filtered(OPT_trace_symbol)) + symtab->trace(arg->getValue()); - for (auto *Arg : Args.filtered(OPT_export)) - Config->ExportedSymbols.insert(Arg->getValue()); + for (auto *arg : args.filtered(OPT_export)) + config->exportedSymbols.insert(arg->getValue()); - if (!Config->Relocatable) + if (!config->relocatable) createSyntheticSymbols(); - createFiles(Args); + createFiles(args); if (errorCount()) return; // Add all files to the symbol table. This will add almost all // symbols that we need to the symbol table. - for (InputFile *F : Files) - Symtab->addFile(F); + for (InputFile *f : files) + symtab->addFile(f); if (errorCount()) return; // Handle the `--undefined <sym>` options. - for (auto *Arg : Args.filtered(OPT_undefined)) - handleUndefined(Arg->getValue()); + for (auto *arg : args.filtered(OPT_undefined)) + handleUndefined(arg->getValue()); // Handle the `--export <sym>` options // This works like --undefined but also exports the symbol if its found - for (auto *Arg : Args.filtered(OPT_export)) - handleUndefined(Arg->getValue()); - - Symbol *EntrySym = nullptr; - if (!Config->Relocatable && !Config->Entry.empty()) { - EntrySym = handleUndefined(Config->Entry); - if (EntrySym && EntrySym->isDefined()) - EntrySym->ForceExport = true; + for (auto *arg : args.filtered(OPT_export)) + handleUndefined(arg->getValue()); + + Symbol *entrySym = nullptr; + if (!config->relocatable && !config->entry.empty()) { + entrySym = handleUndefined(config->entry); + if (entrySym && entrySym->isDefined()) + entrySym->forceExport = true; else error("entry symbol not defined (pass --no-entry to supress): " + - Config->Entry); + config->entry); } if (errorCount()) return; // Create wrapped symbols for -wrap option. - std::vector<WrappedSymbol> Wrapped = addWrappedSymbols(Args); + std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args); // Do link-time optimization if given files are LLVM bitcode files. // This compiles bitcode files into real object files. - Symtab->addCombinedLTOObject(); + symtab->addCombinedLTOObject(); if (errorCount()) return; // Resolve any variant symbols that were created due to signature // mismatchs. - Symtab->handleSymbolVariants(); + symtab->handleSymbolVariants(); if (errorCount()) return; // Apply symbol renames for -wrap. - if (!Wrapped.empty()) - wrapSymbols(Wrapped); - - for (auto *Arg : Args.filtered(OPT_export)) { - Symbol *Sym = Symtab->find(Arg->getValue()); - if (Sym && Sym->isDefined()) - Sym->ForceExport = true; - else if (!Config->AllowUndefined) + if (!wrapped.empty()) + wrapSymbols(wrapped); + + for (auto *arg : args.filtered(OPT_export)) { + Symbol *sym = symtab->find(arg->getValue()); + if (sym && sym->isDefined()) + sym->forceExport = true; + else if (!config->allowUndefined) error(Twine("symbol exported via --export not found: ") + - Arg->getValue()); + arg->getValue()); } - if (!Config->Relocatable) { + if (!config->relocatable) { // Add synthetic dummies for weak undefined functions. Must happen // after LTO otherwise functions may not yet have signatures. - Symtab->handleWeakUndefines(); + symtab->handleWeakUndefines(); } - if (EntrySym) - EntrySym->setHidden(false); + if (entrySym) + entrySym->setHidden(false); if (errorCount()) return; |