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/ADT/STLExtras.h" |
14 | #include "llvm/Support/TimeProfiler.h" |
15 | #include <vector> |
16 | |
17 | namespace lld::coff { |
18 | |
19 | // Set live bit on for each reachable chunk. Unmarked (unreachable) |
20 | // COMDAT chunks will be ignored by Writer, so they will be excluded |
21 | // from the final output. |
22 | void markLive(COFFLinkerContext &ctx) { |
23 | llvm::TimeTraceScope timeScope("Mark live"); |
24 | ScopedTimer t(ctx.gcTimer); |
25 | |
26 | // We build up a worklist of sections which have been marked as live. We only |
27 | // push into the worklist when we discover an unmarked section, and we mark |
28 | // as we push, so sections never appear twice in the list. |
29 | SmallVector<SectionChunk *, 256> worklist; |
30 | |
31 | // COMDAT section chunks are dead by default. Add non-COMDAT chunks. Do not |
32 | // traverse DWARF sections. They are live, but they should not keep other |
33 | // sections alive. |
34 | for (Chunk *c : ctx.symtab.getChunks()) |
35 | if (auto *sc = dyn_cast<SectionChunk>(Val: c)) |
36 | if (sc->live && !sc->isDWARF()) |
37 | worklist.push_back(Elt: sc); |
38 | |
39 | auto enqueue = [&](SectionChunk *c) { |
40 | if (c->live) |
41 | return; |
42 | c->live = true; |
43 | worklist.push_back(Elt: c); |
44 | }; |
45 | |
46 | auto addSym = [&](Symbol *b) { |
47 | if (auto *sym = dyn_cast<DefinedRegular>(Val: b)) |
48 | enqueue(sym->getChunk()); |
49 | else if (auto *sym = dyn_cast<DefinedImportData>(Val: b)) |
50 | sym->file->live = true; |
51 | else if (auto *sym = dyn_cast<DefinedImportThunk>(Val: b)) |
52 | sym->wrappedSym->file->live = sym->wrappedSym->file->thunkLive = true; |
53 | }; |
54 | |
55 | // Add GC root chunks. |
56 | for (Symbol *b : ctx.config.gcroot) |
57 | addSym(b); |
58 | |
59 | while (!worklist.empty()) { |
60 | SectionChunk *sc = worklist.pop_back_val(); |
61 | assert(sc->live && "We mark as live when pushing onto the worklist!"); |
62 | |
63 | // Mark all symbols listed in the relocation table for this section. |
64 | for (Symbol *b : sc->symbols()) |
65 | if (b) |
66 | addSym(b); |
67 | |
68 | // Mark associative sections if any. |
69 | for (SectionChunk &c : sc->children()) |
70 | enqueue(&c); |
71 | } |
72 | } |
73 | } |
74 |