xref: /freebsd/contrib/llvm-project/lld/COFF/MarkLive.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
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 
9*349cc55cSDimitry 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"
140b57cec5SDimitry Andric #include <vector>
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric namespace lld {
170b57cec5SDimitry Andric namespace 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.
22*349cc55cSDimitry Andric void markLive(COFFLinkerContext &ctx) {
23*349cc55cSDimitry Andric   ScopedTimer t(ctx.gcTimer);
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric   // We build up a worklist of sections which have been marked as live. We only
260b57cec5SDimitry Andric   // push into the worklist when we discover an unmarked section, and we mark
270b57cec5SDimitry Andric   // as we push, so sections never appear twice in the list.
280b57cec5SDimitry Andric   SmallVector<SectionChunk *, 256> worklist;
290b57cec5SDimitry Andric 
30d65cd7a5SDimitry Andric   // COMDAT section chunks are dead by default. Add non-COMDAT chunks. Do not
31d65cd7a5SDimitry Andric   // traverse DWARF sections. They are live, but they should not keep other
32d65cd7a5SDimitry Andric   // sections alive.
33*349cc55cSDimitry Andric   for (Chunk *c : ctx.symtab.getChunks())
340b57cec5SDimitry Andric     if (auto *sc = dyn_cast<SectionChunk>(c))
35d65cd7a5SDimitry Andric       if (sc->live && !sc->isDWARF())
360b57cec5SDimitry Andric         worklist.push_back(sc);
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   auto enqueue = [&](SectionChunk *c) {
390b57cec5SDimitry Andric     if (c->live)
400b57cec5SDimitry Andric       return;
410b57cec5SDimitry Andric     c->live = true;
420b57cec5SDimitry Andric     worklist.push_back(c);
430b57cec5SDimitry Andric   };
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   auto addSym = [&](Symbol *b) {
460b57cec5SDimitry Andric     if (auto *sym = dyn_cast<DefinedRegular>(b))
470b57cec5SDimitry Andric       enqueue(sym->getChunk());
480b57cec5SDimitry Andric     else if (auto *sym = dyn_cast<DefinedImportData>(b))
490b57cec5SDimitry Andric       sym->file->live = true;
500b57cec5SDimitry Andric     else if (auto *sym = dyn_cast<DefinedImportThunk>(b))
510b57cec5SDimitry Andric       sym->wrappedSym->file->live = sym->wrappedSym->file->thunkLive = true;
520b57cec5SDimitry Andric   };
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   // Add GC root chunks.
550b57cec5SDimitry Andric   for (Symbol *b : config->gcroot)
560b57cec5SDimitry Andric     addSym(b);
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   while (!worklist.empty()) {
590b57cec5SDimitry Andric     SectionChunk *sc = worklist.pop_back_val();
600b57cec5SDimitry Andric     assert(sc->live && "We mark as live when pushing onto the worklist!");
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric     // Mark all symbols listed in the relocation table for this section.
630b57cec5SDimitry Andric     for (Symbol *b : sc->symbols())
640b57cec5SDimitry Andric       if (b)
650b57cec5SDimitry Andric         addSym(b);
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric     // Mark associative sections if any.
680b57cec5SDimitry Andric     for (SectionChunk &c : sc->children())
690b57cec5SDimitry Andric       enqueue(&c);
700b57cec5SDimitry Andric   }
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric }
74