xref: /freebsd/contrib/llvm-project/lld/COFF/MarkLive.cpp (revision d65cd7a57bf0600b722afc770838a5d0c1c3a8e1)
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 
90b57cec5SDimitry Andric #include "Chunks.h"
100b57cec5SDimitry Andric #include "Symbols.h"
110b57cec5SDimitry Andric #include "lld/Common/Timer.h"
120b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
130b57cec5SDimitry Andric #include <vector>
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric namespace lld {
160b57cec5SDimitry Andric namespace coff {
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric static Timer gctimer("GC", Timer::root());
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric // Set live bit on for each reachable chunk. Unmarked (unreachable)
210b57cec5SDimitry Andric // COMDAT chunks will be ignored by Writer, so they will be excluded
220b57cec5SDimitry Andric // from the final output.
230b57cec5SDimitry Andric void markLive(ArrayRef<Chunk *> chunks) {
240b57cec5SDimitry Andric   ScopedTimer t(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 
31*d65cd7a5SDimitry Andric   // COMDAT section chunks are dead by default. Add non-COMDAT chunks. Do not
32*d65cd7a5SDimitry Andric   // traverse DWARF sections. They are live, but they should not keep other
33*d65cd7a5SDimitry Andric   // sections alive.
340b57cec5SDimitry Andric   for (Chunk *c : chunks)
350b57cec5SDimitry Andric     if (auto *sc = dyn_cast<SectionChunk>(c))
36*d65cd7a5SDimitry 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.
560b57cec5SDimitry Andric   for (Symbol *b : 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);
710b57cec5SDimitry Andric   }
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric }
76