xref: /llvm-project-15.0.7/lld/wasm/Driver.cpp (revision 77a4adc4)
1 //===- Driver.cpp ---------------------------------------------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lld/Common/Driver.h"
11 #include "Config.h"
12 #include "InputChunks.h"
13 #include "InputGlobal.h"
14 #include "MarkLive.h"
15 #include "SymbolTable.h"
16 #include "Writer.h"
17 #include "lld/Common/Args.h"
18 #include "lld/Common/ErrorHandler.h"
19 #include "lld/Common/Memory.h"
20 #include "lld/Common/Strings.h"
21 #include "lld/Common/Threads.h"
22 #include "lld/Common/Version.h"
23 #include "llvm/ADT/Twine.h"
24 #include "llvm/Object/Wasm.h"
25 #include "llvm/Option/ArgList.h"
26 #include "llvm/Support/CommandLine.h"
27 #include "llvm/Support/Path.h"
28 #include "llvm/Support/Process.h"
29 #include "llvm/Support/TargetSelect.h"
30 
31 #define DEBUG_TYPE "lld"
32 
33 using namespace llvm;
34 using namespace llvm::object;
35 using namespace llvm::sys;
36 using namespace llvm::wasm;
37 
38 using namespace lld;
39 using namespace lld::wasm;
40 
41 Configuration *lld::wasm::Config;
42 
43 namespace {
44 
45 // Create enum with OPT_xxx values for each option in Options.td
46 enum {
47   OPT_INVALID = 0,
48 #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
49 #include "Options.inc"
50 #undef OPTION
51 };
52 
53 // This function is called on startup. We need this for LTO since
54 // LTO calls LLVM functions to compile bitcode files to native code.
55 // Technically this can be delayed until we read bitcode files, but
56 // we don't bother to do lazily because the initialization is fast.
57 static void initLLVM() {
58   InitializeAllTargets();
59   InitializeAllTargetMCs();
60   InitializeAllAsmPrinters();
61   InitializeAllAsmParsers();
62 }
63 
64 class LinkerDriver {
65 public:
66   void link(ArrayRef<const char *> ArgsArr);
67 
68 private:
69   void createFiles(opt::InputArgList &Args);
70   void addFile(StringRef Path);
71   void addLibrary(StringRef Name);
72 
73   // True if we are in --whole-archive and --no-whole-archive.
74   bool InWholeArchive = false;
75 
76   std::vector<InputFile *> Files;
77 };
78 } // anonymous namespace
79 
80 bool lld::wasm::link(ArrayRef<const char *> Args, bool CanExitEarly,
81                      raw_ostream &Error) {
82   errorHandler().LogName = args::getFilenameWithoutExe(Args[0]);
83   errorHandler().ErrorOS = &Error;
84   errorHandler().ColorDiagnostics = Error.has_colors();
85   errorHandler().ErrorLimitExceededMsg =
86       "too many errors emitted, stopping now (use "
87       "-error-limit=0 to see all errors)";
88 
89   Config = make<Configuration>();
90   Symtab = make<SymbolTable>();
91 
92   initLLVM();
93   LinkerDriver().link(Args);
94 
95   // Exit immediately if we don't need to return to the caller.
96   // This saves time because the overhead of calling destructors
97   // for all globally-allocated objects is not negligible.
98   if (CanExitEarly)
99     exitLld(errorCount() ? 1 : 0);
100 
101   freeArena();
102   return !errorCount();
103 }
104 
105 // Create prefix string literals used in Options.td
106 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
107 #include "Options.inc"
108 #undef PREFIX
109 
110 // Create table mapping all options defined in Options.td
111 static const opt::OptTable::Info OptInfo[] = {
112 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
113   {X1, X2, X10,         X11,         OPT_##ID, opt::Option::KIND##Class,       \
114    X9, X8, OPT_##GROUP, OPT_##ALIAS, X7,       X12},
115 #include "Options.inc"
116 #undef OPTION
117 };
118 
119 namespace {
120 class WasmOptTable : public llvm::opt::OptTable {
121 public:
122   WasmOptTable() : OptTable(OptInfo) {}
123   opt::InputArgList parse(ArrayRef<const char *> Argv);
124 };
125 } // namespace
126 
127 // Set color diagnostics according to -color-diagnostics={auto,always,never}
128 // or -no-color-diagnostics flags.
129 static void handleColorDiagnostics(opt::InputArgList &Args) {
130   auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,
131                               OPT_no_color_diagnostics);
132   if (!Arg)
133     return;
134   if (Arg->getOption().getID() == OPT_color_diagnostics) {
135     errorHandler().ColorDiagnostics = true;
136   } else if (Arg->getOption().getID() == OPT_no_color_diagnostics) {
137     errorHandler().ColorDiagnostics = false;
138   } else {
139     StringRef S = Arg->getValue();
140     if (S == "always")
141       errorHandler().ColorDiagnostics = true;
142     else if (S == "never")
143       errorHandler().ColorDiagnostics = false;
144     else if (S != "auto")
145       error("unknown option: --color-diagnostics=" + S);
146   }
147 }
148 
149 // Find a file by concatenating given paths.
150 static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) {
151   SmallString<128> S;
152   path::append(S, Path1, Path2);
153   if (fs::exists(S))
154     return S.str().str();
155   return None;
156 }
157 
158 opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> Argv) {
159   SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
160 
161   unsigned MissingIndex;
162   unsigned MissingCount;
163 
164   // Expand response files (arguments in the form of @<filename>)
165   cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Vec);
166 
167   opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
168 
169   handleColorDiagnostics(Args);
170   for (auto *Arg : Args.filtered(OPT_UNKNOWN))
171     error("unknown argument: " + Arg->getSpelling());
172   return Args;
173 }
174 
175 // Currently we allow a ".imports" to live alongside a library. This can
176 // be used to specify a list of symbols which can be undefined at link
177 // time (imported from the environment.  For example libc.a include an
178 // import file that lists the syscall functions it relies on at runtime.
179 // In the long run this information would be better stored as a symbol
180 // attribute/flag in the object file itself.
181 // See: https://github.com/WebAssembly/tool-conventions/issues/35
182 static void readImportFile(StringRef Filename) {
183   if (Optional<MemoryBufferRef> Buf = readFile(Filename))
184     for (StringRef Sym : args::getLines(*Buf))
185       Config->AllowUndefinedSymbols.insert(Sym);
186 }
187 
188 // Returns slices of MB by parsing MB as an archive file.
189 // Each slice consists of a member file in the archive.
190 std::vector<MemoryBufferRef> static getArchiveMembers(MemoryBufferRef MB) {
191   std::unique_ptr<Archive> File =
192       CHECK(Archive::create(MB),
193             MB.getBufferIdentifier() + ": failed to parse archive");
194 
195   std::vector<MemoryBufferRef> V;
196   Error Err = Error::success();
197   for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) {
198     Archive::Child C =
199         CHECK(COrErr, MB.getBufferIdentifier() +
200                           ": could not get the child of the archive");
201     MemoryBufferRef MBRef =
202         CHECK(C.getMemoryBufferRef(),
203               MB.getBufferIdentifier() +
204                   ": could not get the buffer for a child of the archive");
205     V.push_back(MBRef);
206   }
207   if (Err)
208     fatal(MB.getBufferIdentifier() +
209           ": Archive::children failed: " + toString(std::move(Err)));
210 
211   // Take ownership of memory buffers created for members of thin archives.
212   for (std::unique_ptr<MemoryBuffer> &MB : File->takeThinBuffers())
213     make<std::unique_ptr<MemoryBuffer>>(std::move(MB));
214 
215   return V;
216 }
217 
218 void LinkerDriver::addFile(StringRef Path) {
219   Optional<MemoryBufferRef> Buffer = readFile(Path);
220   if (!Buffer.hasValue())
221     return;
222   MemoryBufferRef MBRef = *Buffer;
223 
224   switch (identify_magic(MBRef.getBuffer())) {
225   case file_magic::archive: {
226     // Handle -whole-archive.
227     if (InWholeArchive) {
228       for (MemoryBufferRef &M : getArchiveMembers(MBRef))
229         Files.push_back(createObjectFile(M));
230       return;
231     }
232 
233     SmallString<128> ImportFile = Path;
234     path::replace_extension(ImportFile, ".imports");
235     if (fs::exists(ImportFile))
236       readImportFile(ImportFile.str());
237 
238     Files.push_back(make<ArchiveFile>(MBRef));
239     return;
240   }
241   case file_magic::bitcode:
242   case file_magic::wasm_object:
243     Files.push_back(createObjectFile(MBRef));
244     break;
245   default:
246     error("unknown file type: " + MBRef.getBufferIdentifier());
247   }
248 }
249 
250 // Add a given library by searching it from input search paths.
251 void LinkerDriver::addLibrary(StringRef Name) {
252   for (StringRef Dir : Config->SearchPaths) {
253     if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a")) {
254       addFile(*S);
255       return;
256     }
257   }
258 
259   error("unable to find library -l" + Name);
260 }
261 
262 void LinkerDriver::createFiles(opt::InputArgList &Args) {
263   for (auto *Arg : Args) {
264     switch (Arg->getOption().getUnaliasedOption().getID()) {
265     case OPT_l:
266       addLibrary(Arg->getValue());
267       break;
268     case OPT_INPUT:
269       addFile(Arg->getValue());
270       break;
271     case OPT_whole_archive:
272       InWholeArchive = true;
273       break;
274     case OPT_no_whole_archive:
275       InWholeArchive = false;
276       break;
277     }
278   }
279 }
280 
281 static StringRef getEntry(opt::InputArgList &Args, StringRef Default) {
282   auto *Arg = Args.getLastArg(OPT_entry, OPT_no_entry);
283   if (!Arg)
284     return Default;
285   if (Arg->getOption().getID() == OPT_no_entry)
286     return "";
287   return Arg->getValue();
288 }
289 
290 static const uint8_t UnreachableFn[] = {
291     0x03 /* ULEB length */, 0x00 /* ULEB num locals */,
292     0x00 /* opcode unreachable */, 0x0b /* opcode end */
293 };
294 
295 // For weak undefined functions, there may be "call" instructions that reference
296 // the symbol. In this case, we need to synthesise a dummy/stub function that
297 // will abort at runtime, so that relocations can still provided an operand to
298 // the call instruction that passes Wasm validation.
299 static void handleWeakUndefines() {
300   for (Symbol *Sym : Symtab->getSymbols()) {
301     if (!Sym->isUndefined() || !Sym->isWeak())
302       continue;
303     auto *FuncSym = dyn_cast<FunctionSymbol>(Sym);
304     if (!FuncSym)
305       continue;
306 
307     // It is possible for undefined functions not to have a signature (eg. if
308     // added via "--undefined"), but weak undefined ones do have a signature.
309     assert(FuncSym->FunctionType);
310     const WasmSignature &Sig = *FuncSym->FunctionType;
311 
312     // Add a synthetic dummy for weak undefined functions.  These dummies will
313     // be GC'd if not used as the target of any "call" instructions.
314     std::string SymName = toString(*Sym);
315     StringRef DebugName = Saver.save("undefined function " + SymName);
316     SyntheticFunction *Func =
317         make<SyntheticFunction>(Sig, Sym->getName(), DebugName);
318     Func->setBody(UnreachableFn);
319     // Ensure it compares equal to the null pointer, and so that table relocs
320     // don't pull in the stub body (only call-operand relocs should do that).
321     Func->setTableIndex(0);
322     Symtab->SyntheticFunctions.emplace_back(Func);
323     // Hide our dummy to prevent export.
324     uint32_t Flags = WASM_SYMBOL_VISIBILITY_HIDDEN;
325     replaceSymbol<DefinedFunction>(Sym, Sym->getName(), Flags, nullptr, Func);
326   }
327 }
328 
329 // Some Config members do not directly correspond to any particular
330 // command line options, but computed based on other Config values.
331 // This function initialize such members. See Config.h for the details
332 // of these values.
333 static void setConfigs(opt::InputArgList &Args) {
334   Config->AllowUndefined = Args.hasArg(OPT_allow_undefined);
335   Config->CompressRelocations = Args.hasArg(OPT_compress_relocations);
336   Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true);
337   Config->DisableVerify = Args.hasArg(OPT_disable_verify);
338   Config->Entry = getEntry(Args, Args.hasArg(OPT_relocatable) ? "" : "_start");
339   Config->ExportAll = Args.hasArg(OPT_export_all);
340   Config->ExportDynamic = Args.hasFlag(OPT_export_dynamic,
341       OPT_no_export_dynamic, false);
342   Config->ExportTable = Args.hasArg(OPT_export_table);
343   errorHandler().FatalWarnings =
344       Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
345   Config->ImportMemory = Args.hasArg(OPT_import_memory);
346   Config->SharedMemory = Args.hasArg(OPT_shared_memory);
347   Config->ImportTable = Args.hasArg(OPT_import_table);
348   Config->LTOO = args::getInteger(Args, OPT_lto_O, 2);
349   Config->LTOPartitions = args::getInteger(Args, OPT_lto_partitions, 1);
350   Config->Optimize = args::getInteger(Args, OPT_O, 0);
351   Config->OutputFile = Args.getLastArgValue(OPT_o);
352   Config->Relocatable = Args.hasArg(OPT_relocatable);
353   Config->GcSections =
354       Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !Config->Relocatable);
355   Config->MergeDataSegments =
356       Args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments,
357                    !Config->Relocatable);
358   Config->Pie = Args.hasFlag(OPT_pie, OPT_no_pie, false);
359   Config->PrintGcSections =
360       Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
361   Config->SaveTemps = Args.hasArg(OPT_save_temps);
362   Config->SearchPaths = args::getStrings(Args, OPT_L);
363   Config->Shared = Args.hasArg(OPT_shared);
364   Config->StripAll = Args.hasArg(OPT_strip_all);
365   Config->StripDebug = Args.hasArg(OPT_strip_debug);
366   Config->StackFirst = Args.hasArg(OPT_stack_first);
367   Config->ThinLTOCacheDir = Args.getLastArgValue(OPT_thinlto_cache_dir);
368   Config->ThinLTOCachePolicy = CHECK(
369       parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)),
370       "--thinlto-cache-policy: invalid cache policy");
371   Config->ThinLTOJobs = args::getInteger(Args, OPT_thinlto_jobs, -1u);
372   errorHandler().Verbose = Args.hasArg(OPT_verbose);
373   ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true);
374 
375   Config->InitialMemory = args::getInteger(Args, OPT_initial_memory, 0);
376   Config->GlobalBase = args::getInteger(Args, OPT_global_base, 1024);
377   Config->MaxMemory = args::getInteger(Args, OPT_max_memory, 0);
378   Config->ZStackSize =
379       args::getZOptionValue(Args, OPT_z, "stack-size", WasmPageSize);
380 }
381 
382 // Some command line options or some combinations of them are not allowed.
383 // This function checks for such errors.
384 static void checkOptions(opt::InputArgList &Args) {
385   if (!Config->StripDebug && !Config->StripAll && Config->CompressRelocations)
386     error("--compress-relocations is incompatible with output debug"
387           " information. Please pass --strip-debug or --strip-all");
388 
389   if (Config->LTOO > 3)
390     error("invalid optimization level for LTO: " + Twine(Config->LTOO));
391   if (Config->LTOPartitions == 0)
392     error("--lto-partitions: number of threads must be > 0");
393   if (Config->ThinLTOJobs == 0)
394     error("--thinlto-jobs: number of threads must be > 0");
395 
396   if (Config->Pie && Config->Shared)
397     error("-shared and -pie may not be used together");
398 
399   if (Config->OutputFile.empty())
400     error("no output file specified");
401 
402   if (Config->ImportTable && Config->ExportTable)
403     error("--import-table and --export-table may not be used together");
404 
405   if (Config->Relocatable) {
406     if (!Config->Entry.empty())
407       error("entry point specified for relocatable output file");
408     if (Config->GcSections)
409       error("-r and --gc-sections may not be used together");
410     if (Config->CompressRelocations)
411       error("-r -and --compress-relocations may not be used together");
412     if (Args.hasArg(OPT_undefined))
413       error("-r -and --undefined may not be used together");
414     if (Config->Pie)
415       error("-r and -pie may not be used together");
416   }
417 }
418 
419 // Force Sym to be entered in the output. Used for -u or equivalent.
420 static Symbol *handleUndefined(StringRef Name) {
421   Symbol *Sym = Symtab->find(Name);
422   if (!Sym)
423     return nullptr;
424 
425   // Since symbol S may not be used inside the program, LTO may
426   // eliminate it. Mark the symbol as "used" to prevent it.
427   Sym->IsUsedInRegularObj = true;
428 
429   if (auto *LazySym = dyn_cast<LazySymbol>(Sym))
430     LazySym->fetch();
431 
432   return Sym;
433 }
434 
435 static UndefinedGlobal *
436 createUndefinedGlobal(StringRef Name, llvm::wasm::WasmGlobalType *Type) {
437   auto *Sym =
438       cast<UndefinedGlobal>(Symtab->addUndefinedGlobal(Name, 0, nullptr, Type));
439   Config->AllowUndefinedSymbols.insert(Sym->getName());
440   Sym->IsUsedInRegularObj = true;
441   return Sym;
442 }
443 
444 // Create ABI-defined synthetic symbols
445 static void createSyntheticSymbols() {
446   static WasmSignature NullSignature = {{}, {}};
447   static llvm::wasm::WasmGlobalType GlobalTypeI32 = {WASM_TYPE_I32, false};
448   static llvm::wasm::WasmGlobalType MutableGlobalTypeI32 = {WASM_TYPE_I32,
449                                                             true};
450 
451   WasmSym::CallCtors = Symtab->addSyntheticFunction(
452       "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
453       make<SyntheticFunction>(NullSignature, "__wasm_call_ctors"));
454 
455   // The __stack_pointer is imported in the shared library case, and exported
456   // in the non-shared (executable) case.
457   if (Config->Shared) {
458     WasmSym::StackPointer =
459         createUndefinedGlobal("__stack_pointer", &MutableGlobalTypeI32);
460   } else {
461     llvm::wasm::WasmGlobal Global;
462     Global.Type = {WASM_TYPE_I32, true};
463     Global.InitExpr.Value.Int32 = 0;
464     Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
465     Global.SymbolName = "__stack_pointer";
466     InputGlobal *StackPointer = make<InputGlobal>(Global, nullptr);
467     StackPointer->Live = true;
468     // For non-PIC code
469     // TODO(sbc): Remove WASM_SYMBOL_VISIBILITY_HIDDEN when the mutable global
470     // spec proposal is implemented in all major browsers.
471     // See: https://github.com/WebAssembly/mutable-global
472     WasmSym::StackPointer = Symtab->addSyntheticGlobal(
473         "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, StackPointer);
474     WasmSym::HeapBase = Symtab->addSyntheticDataSymbol("__heap_base", 0);
475     WasmSym::DataEnd = Symtab->addSyntheticDataSymbol("__data_end", 0);
476 
477     // These two synthetic symbols exist purely for the embedder so we always
478     // want to export them.
479     WasmSym::HeapBase->ForceExport = true;
480     WasmSym::DataEnd->ForceExport = true;
481   }
482 
483   if (Config->Pic) {
484     // For PIC code, we import two global variables (__memory_base and
485     // __table_base) from the environment and use these as the offset at
486     // which to load our static data and function table.
487     // See:
488     // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
489     WasmSym::MemoryBase =
490         createUndefinedGlobal("__memory_base", &GlobalTypeI32);
491     WasmSym::TableBase = createUndefinedGlobal("__table_base", &GlobalTypeI32);
492     WasmSym::MemoryBase->markLive();
493     WasmSym::TableBase->markLive();
494   }
495 
496   WasmSym::DsoHandle = Symtab->addSyntheticDataSymbol(
497       "__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN);
498 }
499 
500 void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
501   WasmOptTable Parser;
502   opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
503 
504   // Handle --help
505   if (Args.hasArg(OPT_help)) {
506     Parser.PrintHelp(outs(),
507                      (std::string(ArgsArr[0]) + " [options] file...").c_str(),
508                      "LLVM Linker", false);
509     return;
510   }
511 
512   // Handle --version
513   if (Args.hasArg(OPT_version) || Args.hasArg(OPT_v)) {
514     outs() << getLLDVersion() << "\n";
515     return;
516   }
517 
518   // Parse and evaluate -mllvm options.
519   std::vector<const char *> V;
520   V.push_back("wasm-ld (LLVM option parsing)");
521   for (auto *Arg : Args.filtered(OPT_mllvm))
522     V.push_back(Arg->getValue());
523   cl::ParseCommandLineOptions(V.size(), V.data());
524 
525   errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20);
526 
527   setConfigs(Args);
528   checkOptions(Args);
529 
530   if (auto *Arg = Args.getLastArg(OPT_allow_undefined_file))
531     readImportFile(Arg->getValue());
532 
533   if (!Args.hasArg(OPT_INPUT)) {
534     error("no input files");
535     return;
536   }
537 
538   Config->Pic = Config->Pie || Config->Shared;
539 
540   if (Config->Pic) {
541     if (Config->ExportTable)
542       error("-shared/-pie is incompatible with --export-table");
543     Config->ImportTable = true;
544   }
545 
546   if (Config->Shared)
547     Config->ExportDynamic = true;
548 
549   if (!Config->Relocatable)
550     createSyntheticSymbols();
551 
552   createFiles(Args);
553   if (errorCount())
554     return;
555 
556   // Add all files to the symbol table. This will add almost all
557   // symbols that we need to the symbol table.
558   for (InputFile *F : Files)
559     Symtab->addFile(F);
560   if (errorCount())
561     return;
562 
563   // Handle the `--undefined <sym>` options.
564   for (auto *Arg : Args.filtered(OPT_undefined))
565     handleUndefined(Arg->getValue());
566 
567   // Handle the `--export <sym>` options
568   // This works like --undefined but also exports the symbol if its found
569   for (auto *Arg : Args.filtered(OPT_export)) {
570     Symbol *Sym = handleUndefined(Arg->getValue());
571     if (Sym && Sym->isDefined())
572       Sym->ForceExport = true;
573     else if (!Config->AllowUndefined)
574       error(Twine("symbol exported via --export not found: ") +
575             Arg->getValue());
576   }
577 
578   Symbol *EntrySym = nullptr;
579   if (!Config->Relocatable) {
580     // Add synthetic dummies for weak undefined functions.
581     handleWeakUndefines();
582 
583     if (!Config->Shared && !Config->Entry.empty()) {
584       EntrySym = handleUndefined(Config->Entry);
585       if (EntrySym && EntrySym->isDefined())
586         EntrySym->ForceExport = true;
587       else
588         error("entry symbol not defined (pass --no-entry to supress): " +
589               Config->Entry);
590     }
591 
592     // Make sure we have resolved all symbols.
593     if (!Config->AllowUndefined)
594       Symtab->reportRemainingUndefines();
595   }
596 
597   if (errorCount())
598     return;
599 
600   // Do link-time optimization if given files are LLVM bitcode files.
601   // This compiles bitcode files into real object files.
602   Symtab->addCombinedLTOObject();
603   if (errorCount())
604     return;
605 
606   if (EntrySym)
607     EntrySym->setHidden(false);
608 
609   if (errorCount())
610     return;
611 
612   // Do size optimizations: garbage collection
613   markLive();
614 
615   // Write the result to the file.
616   writeResult();
617 }
618