xref: /freebsd/contrib/llvm-project/lld/COFF/MarkLive.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- MarkLive.cpp -------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "COFFLinkerContext.h"
10 #include "Chunks.h"
11 #include "Symbols.h"
12 #include "lld/Common/Timer.h"
13 #include "llvm/Support/TimeProfiler.h"
14 
15 namespace lld::coff {
16 
17 // Set live bit on for each reachable chunk. Unmarked (unreachable)
18 // COMDAT chunks will be ignored by Writer, so they will be excluded
19 // from the final output.
markLive(COFFLinkerContext & ctx)20 void markLive(COFFLinkerContext &ctx) {
21   llvm::TimeTraceScope timeScope("Mark live");
22   ScopedTimer t(ctx.gcTimer);
23 
24   // We build up a worklist of sections which have been marked as live. We only
25   // push into the worklist when we discover an unmarked section, and we mark
26   // as we push, so sections never appear twice in the list.
27   SmallVector<SectionChunk *, 256> worklist;
28 
29   // COMDAT section chunks are dead by default. Add non-COMDAT chunks. Do not
30   // traverse DWARF sections. They are live, but they should not keep other
31   // sections alive.
32   for (Chunk *c : ctx.driver.getChunks())
33     if (auto *sc = dyn_cast<SectionChunk>(c))
34       if (sc->live && !sc->isDWARF())
35         worklist.push_back(sc);
36 
37   auto enqueue = [&](SectionChunk *c) {
38     if (c->live)
39       return;
40     c->live = true;
41     worklist.push_back(c);
42   };
43 
44   std::function<void(Symbol *)> addSym;
45 
46   auto addImportFile = [&](ImportFile *file) {
47     file->live = true;
48     if (file->impchkThunk && file->impchkThunk->exitThunk)
49       addSym(file->impchkThunk->exitThunk);
50   };
51 
52   addSym = [&](Symbol *b) {
53     if (auto *sym = dyn_cast<DefinedRegular>(b)) {
54       enqueue(sym->getChunk());
55     } else if (auto *sym = dyn_cast<DefinedImportData>(b)) {
56       addImportFile(sym->file);
57     } else if (auto *sym = dyn_cast<DefinedImportThunk>(b)) {
58       addImportFile(sym->wrappedSym->file);
59       sym->getChunk()->live = true;
60     }
61   };
62 
63   // Add GC root chunks.
64   for (Symbol *b : ctx.config.gcroot)
65     addSym(b);
66 
67   while (!worklist.empty()) {
68     SectionChunk *sc = worklist.pop_back_val();
69     assert(sc->live && "We mark as live when pushing onto the worklist!");
70 
71     // Mark all symbols listed in the relocation table for this section.
72     for (Symbol *b : sc->symbols())
73       if (b)
74         addSym(b);
75 
76     // Mark associative sections if any.
77     for (SectionChunk &c : sc->children())
78       enqueue(&c);
79 
80     // Mark EC entry thunks.
81     if (Defined *entryThunk = sc->getEntryThunk())
82       addSym(entryThunk);
83   }
84 }
85 }
86