1 //===- MarkLive.cpp -------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "COFFLinkerContext.h"
12 #include "lld/Common/Timer.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/Support/TimeProfiler.h"
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
);
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
;
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
34 for (Chunk
*c
: ctx
.symtab
.getChunks())
35 if (auto *sc
= dyn_cast
<SectionChunk
>(c
))
36 if (sc
->live
&& !sc
->isDWARF())
37 worklist
.push_back(sc
);
39 auto enqueue
= [&](SectionChunk
*c
) {
43 worklist
.push_back(c
);
46 std::function
<void(Symbol
*)> addSym
;
48 auto addImportFile
= [&](ImportFile
*file
) {
50 if (file
->impchkThunk
&& file
->impchkThunk
->exitThunk
)
51 addSym(file
->impchkThunk
->exitThunk
);
54 addSym
= [&](Symbol
*b
) {
55 if (auto *sym
= dyn_cast
<DefinedRegular
>(b
)) {
56 enqueue(sym
->getChunk());
57 } else if (auto *sym
= dyn_cast
<DefinedImportData
>(b
)) {
58 addImportFile(sym
->file
);
59 } else if (auto *sym
= dyn_cast
<DefinedImportThunk
>(b
)) {
60 addImportFile(sym
->wrappedSym
->file
);
61 sym
->getChunk()->live
= true;
65 // Add GC root chunks.
66 for (Symbol
*b
: ctx
.config
.gcroot
)
69 while (!worklist
.empty()) {
70 SectionChunk
*sc
= worklist
.pop_back_val();
71 assert(sc
->live
&& "We mark as live when pushing onto the worklist!");
73 // Mark all symbols listed in the relocation table for this section.
74 for (Symbol
*b
: sc
->symbols())
78 // Mark associative sections if any.
79 for (SectionChunk
&c
: sc
->children())
82 // Mark EC entry thunks.
83 if (Defined
*entryThunk
= sc
->getEntryThunk())