xref: /llvm-project/lld/wasm/OutputSegment.cpp (revision d32f71a91a432db2d9ea32694a8308534b6697ec)
13b8d2be5SSam Clegg //===- OutputSegment.h -----------------------------------------*- C++ -*-===//
23b8d2be5SSam Clegg //
33b8d2be5SSam Clegg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43b8d2be5SSam Clegg // See https://llvm.org/LICENSE.txt for license information.
53b8d2be5SSam Clegg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63b8d2be5SSam Clegg //
73b8d2be5SSam Clegg //===----------------------------------------------------------------------===//
83b8d2be5SSam Clegg 
93b8d2be5SSam Clegg #include "OutputSegment.h"
103b8d2be5SSam Clegg #include "InputChunks.h"
113b8d2be5SSam Clegg #include "lld/Common/Memory.h"
123b8d2be5SSam Clegg 
133b8d2be5SSam Clegg #define DEBUG_TYPE "lld"
143b8d2be5SSam Clegg 
153b8d2be5SSam Clegg using namespace llvm;
163b8d2be5SSam Clegg using namespace llvm::wasm;
173b8d2be5SSam Clegg 
18*d32f71a9SSam Clegg namespace lld::wasm {
193b8d2be5SSam Clegg 
addInputSegment(InputChunk * inSeg)205a9b25e1SSam Clegg void OutputSegment::addInputSegment(InputChunk *inSeg) {
213b8d2be5SSam Clegg   alignment = std::max(alignment, inSeg->alignment);
223b8d2be5SSam Clegg   inputSegments.push_back(inSeg);
2315653172SGuillaume Chatelet   size = llvm::alignTo(size, 1ULL << inSeg->alignment);
2487099a04SSam Clegg   LLVM_DEBUG(dbgs() << "addInputSegment: " << inSeg->name << " oname=" << name
2515653172SGuillaume Chatelet                     << " size=" << inSeg->getSize()
2615653172SGuillaume Chatelet                     << " align=" << inSeg->alignment << " at:" << size << "\n");
273b8d2be5SSam Clegg   inSeg->outputSeg = this;
283b8d2be5SSam Clegg   inSeg->outputSegmentOffset = size;
293b8d2be5SSam Clegg   size += inSeg->getSize();
303b8d2be5SSam Clegg }
313b8d2be5SSam Clegg 
323b8d2be5SSam Clegg // This function scans over the input segments.
333b8d2be5SSam Clegg //
345a9b25e1SSam Clegg // It removes MergeInputChunks from the input section array and adds
353b8d2be5SSam Clegg // new synthetic sections at the location of the first input section
363b8d2be5SSam Clegg // that it replaces. It then finalizes each synthetic section in order
373b8d2be5SSam Clegg // to compute an output offset for each piece of each input section.
finalizeInputSegments()383b8d2be5SSam Clegg void OutputSegment::finalizeInputSegments() {
393b8d2be5SSam Clegg   LLVM_DEBUG(llvm::dbgs() << "finalizeInputSegments: " << name << "\n");
405a9b25e1SSam Clegg   std::vector<SyntheticMergedChunk *> mergedSegments;
415a9b25e1SSam Clegg   std::vector<InputChunk *> newSegments;
425a9b25e1SSam Clegg   for (InputChunk *s : inputSegments) {
435a9b25e1SSam Clegg     MergeInputChunk *ms = dyn_cast<MergeInputChunk>(s);
443b8d2be5SSam Clegg     if (!ms) {
453b8d2be5SSam Clegg       newSegments.push_back(s);
463b8d2be5SSam Clegg       continue;
473b8d2be5SSam Clegg     }
483b8d2be5SSam Clegg 
493b8d2be5SSam Clegg     // A segment should not make it here unless its alive
503b8d2be5SSam Clegg     assert(ms->live);
513b8d2be5SSam Clegg 
525a9b25e1SSam Clegg     auto i = llvm::find_if(mergedSegments, [=](SyntheticMergedChunk *seg) {
533b8d2be5SSam Clegg       return seg->flags == ms->flags && seg->alignment == ms->alignment;
543b8d2be5SSam Clegg     });
553b8d2be5SSam Clegg     if (i == mergedSegments.end()) {
5645b7cf99SSam Clegg       LLVM_DEBUG(llvm::dbgs() << "new merge segment: " << name
5715653172SGuillaume Chatelet                               << " alignment=" << ms->alignment << "\n");
5815653172SGuillaume Chatelet       auto *syn = make<SyntheticMergedChunk>(name, ms->alignment, ms->flags);
593b8d2be5SSam Clegg       syn->outputSeg = this;
603b8d2be5SSam Clegg       mergedSegments.push_back(syn);
613b8d2be5SSam Clegg       i = std::prev(mergedSegments.end());
623b8d2be5SSam Clegg       newSegments.push_back(syn);
633b8d2be5SSam Clegg     } else {
6445b7cf99SSam Clegg       LLVM_DEBUG(llvm::dbgs() << "adding to merge segment: " << name << "\n");
653b8d2be5SSam Clegg     }
665a9b25e1SSam Clegg     (*i)->addMergeChunk(ms);
673b8d2be5SSam Clegg   }
683b8d2be5SSam Clegg 
693b8d2be5SSam Clegg   for (auto *ms : mergedSegments)
703b8d2be5SSam Clegg     ms->finalizeContents();
713b8d2be5SSam Clegg 
723b8d2be5SSam Clegg   inputSegments = newSegments;
733b8d2be5SSam Clegg   size = 0;
745a9b25e1SSam Clegg   for (InputChunk *seg : inputSegments) {
7515653172SGuillaume Chatelet     size = llvm::alignTo(size, 1ULL << seg->alignment);
7687099a04SSam Clegg     LLVM_DEBUG(llvm::dbgs() << "outputSegmentOffset set: " << seg->name
773b8d2be5SSam Clegg                             << " -> " << size << "\n");
783b8d2be5SSam Clegg     seg->outputSegmentOffset = size;
793b8d2be5SSam Clegg     size += seg->getSize();
803b8d2be5SSam Clegg   }
813b8d2be5SSam Clegg }
823b8d2be5SSam Clegg 
83*d32f71a9SSam Clegg } // namespace lld::wasm
84