xref: /freebsd/contrib/llvm-project/lld/COFF/MarkLive.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- MarkLive.cpp -------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
9349cc55cSDimitry Andric #include "COFFLinkerContext.h"
100b57cec5SDimitry Andric #include "Chunks.h"
110b57cec5SDimitry Andric #include "Symbols.h"
120b57cec5SDimitry Andric #include "lld/Common/Timer.h"
130b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
145f757f3fSDimitry Andric #include "llvm/Support/TimeProfiler.h"
150b57cec5SDimitry Andric #include <vector>
160b57cec5SDimitry Andric 
17bdd1243dSDimitry Andric namespace lld::coff {
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric // Set live bit on for each reachable chunk. Unmarked (unreachable)
200b57cec5SDimitry Andric // COMDAT chunks will be ignored by Writer, so they will be excluded
210b57cec5SDimitry Andric // from the final output.
markLive(COFFLinkerContext & ctx)22349cc55cSDimitry Andric void markLive(COFFLinkerContext &ctx) {
235f757f3fSDimitry Andric   llvm::TimeTraceScope timeScope("Mark live");
24349cc55cSDimitry Andric   ScopedTimer t(ctx.gcTimer);
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric   // We build up a worklist of sections which have been marked as live. We only
270b57cec5SDimitry Andric   // push into the worklist when we discover an unmarked section, and we mark
280b57cec5SDimitry Andric   // as we push, so sections never appear twice in the list.
290b57cec5SDimitry Andric   SmallVector<SectionChunk *, 256> worklist;
300b57cec5SDimitry Andric 
31d65cd7a5SDimitry Andric   // COMDAT section chunks are dead by default. Add non-COMDAT chunks. Do not
32d65cd7a5SDimitry Andric   // traverse DWARF sections. They are live, but they should not keep other
33d65cd7a5SDimitry Andric   // sections alive.
34349cc55cSDimitry Andric   for (Chunk *c : ctx.symtab.getChunks())
350b57cec5SDimitry Andric     if (auto *sc = dyn_cast<SectionChunk>(c))
36d65cd7a5SDimitry Andric       if (sc->live && !sc->isDWARF())
370b57cec5SDimitry Andric         worklist.push_back(sc);
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric   auto enqueue = [&](SectionChunk *c) {
400b57cec5SDimitry Andric     if (c->live)
410b57cec5SDimitry Andric       return;
420b57cec5SDimitry Andric     c->live = true;
430b57cec5SDimitry Andric     worklist.push_back(c);
440b57cec5SDimitry Andric   };
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   auto addSym = [&](Symbol *b) {
470b57cec5SDimitry Andric     if (auto *sym = dyn_cast<DefinedRegular>(b))
480b57cec5SDimitry Andric       enqueue(sym->getChunk());
490b57cec5SDimitry Andric     else if (auto *sym = dyn_cast<DefinedImportData>(b))
500b57cec5SDimitry Andric       sym->file->live = true;
510b57cec5SDimitry Andric     else if (auto *sym = dyn_cast<DefinedImportThunk>(b))
520b57cec5SDimitry Andric       sym->wrappedSym->file->live = sym->wrappedSym->file->thunkLive = true;
530b57cec5SDimitry Andric   };
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   // Add GC root chunks.
56bdd1243dSDimitry Andric   for (Symbol *b : ctx.config.gcroot)
570b57cec5SDimitry Andric     addSym(b);
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   while (!worklist.empty()) {
600b57cec5SDimitry Andric     SectionChunk *sc = worklist.pop_back_val();
610b57cec5SDimitry Andric     assert(sc->live && "We mark as live when pushing onto the worklist!");
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric     // Mark all symbols listed in the relocation table for this section.
640b57cec5SDimitry Andric     for (Symbol *b : sc->symbols())
650b57cec5SDimitry Andric       if (b)
660b57cec5SDimitry Andric         addSym(b);
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric     // Mark associative sections if any.
690b57cec5SDimitry Andric     for (SectionChunk &c : sc->children())
700b57cec5SDimitry Andric       enqueue(&c);
71*0fca6ea1SDimitry Andric 
72*0fca6ea1SDimitry Andric     // Mark EC entry thunks.
73*0fca6ea1SDimitry Andric     if (Defined *entryThunk = sc->getEntryThunk())
74*0fca6ea1SDimitry Andric       addSym(entryThunk);
750b57cec5SDimitry Andric   }
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric }
78