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 
183b8d2be5SSam Clegg namespace lld {
193b8d2be5SSam Clegg 
203b8d2be5SSam Clegg namespace wasm {
213b8d2be5SSam Clegg 
addInputSegment(InputChunk * inSeg)225a9b25e1SSam Clegg void OutputSegment::addInputSegment(InputChunk *inSeg) {
233b8d2be5SSam Clegg   alignment = std::max(alignment, inSeg->alignment);
243b8d2be5SSam Clegg   inputSegments.push_back(inSeg);
253b8d2be5SSam Clegg   size = llvm::alignTo(size, 1ULL << inSeg->alignment);
26*87099a04SSam Clegg   LLVM_DEBUG(dbgs() << "addInputSegment: " << inSeg->name << " oname=" << name
27*87099a04SSam Clegg                     << " size=" << inSeg->getSize()
283b8d2be5SSam Clegg                     << " align=" << inSeg->alignment << " at:" << size << "\n");
293b8d2be5SSam Clegg   inSeg->outputSeg = this;
303b8d2be5SSam Clegg   inSeg->outputSegmentOffset = size;
313b8d2be5SSam Clegg   size += inSeg->getSize();
323b8d2be5SSam Clegg }
333b8d2be5SSam Clegg 
343b8d2be5SSam Clegg // This function scans over the input segments.
353b8d2be5SSam Clegg //
365a9b25e1SSam Clegg // It removes MergeInputChunks from the input section array and adds
373b8d2be5SSam Clegg // new synthetic sections at the location of the first input section
383b8d2be5SSam Clegg // that it replaces. It then finalizes each synthetic section in order
393b8d2be5SSam Clegg // to compute an output offset for each piece of each input section.
finalizeInputSegments()403b8d2be5SSam Clegg void OutputSegment::finalizeInputSegments() {
413b8d2be5SSam Clegg   LLVM_DEBUG(llvm::dbgs() << "finalizeInputSegments: " << name << "\n");
425a9b25e1SSam Clegg   std::vector<SyntheticMergedChunk *> mergedSegments;
435a9b25e1SSam Clegg   std::vector<InputChunk *> newSegments;
445a9b25e1SSam Clegg   for (InputChunk *s : inputSegments) {
455a9b25e1SSam Clegg     MergeInputChunk *ms = dyn_cast<MergeInputChunk>(s);
463b8d2be5SSam Clegg     if (!ms) {
473b8d2be5SSam Clegg       newSegments.push_back(s);
483b8d2be5SSam Clegg       continue;
493b8d2be5SSam Clegg     }
503b8d2be5SSam Clegg 
513b8d2be5SSam Clegg     // A segment should not make it here unless its alive
523b8d2be5SSam Clegg     assert(ms->live);
533b8d2be5SSam Clegg 
545a9b25e1SSam Clegg     auto i = llvm::find_if(mergedSegments, [=](SyntheticMergedChunk *seg) {
553b8d2be5SSam Clegg       return seg->flags == ms->flags && seg->alignment == ms->alignment;
563b8d2be5SSam Clegg     });
573b8d2be5SSam Clegg     if (i == mergedSegments.end()) {
5845b7cf99SSam Clegg       LLVM_DEBUG(llvm::dbgs() << "new merge segment: " << name
593b8d2be5SSam Clegg                               << " alignment=" << ms->alignment << "\n");
6045b7cf99SSam Clegg       auto *syn = make<SyntheticMergedChunk>(name, ms->alignment, ms->flags);
613b8d2be5SSam Clegg       syn->outputSeg = this;
623b8d2be5SSam Clegg       mergedSegments.push_back(syn);
633b8d2be5SSam Clegg       i = std::prev(mergedSegments.end());
643b8d2be5SSam Clegg       newSegments.push_back(syn);
653b8d2be5SSam Clegg     } else {
6645b7cf99SSam Clegg       LLVM_DEBUG(llvm::dbgs() << "adding to merge segment: " << name << "\n");
673b8d2be5SSam Clegg     }
685a9b25e1SSam Clegg     (*i)->addMergeChunk(ms);
693b8d2be5SSam Clegg   }
703b8d2be5SSam Clegg 
713b8d2be5SSam Clegg   for (auto *ms : mergedSegments)
723b8d2be5SSam Clegg     ms->finalizeContents();
733b8d2be5SSam Clegg 
743b8d2be5SSam Clegg   inputSegments = newSegments;
753b8d2be5SSam Clegg   size = 0;
765a9b25e1SSam Clegg   for (InputChunk *seg : inputSegments) {
773b8d2be5SSam Clegg     size = llvm::alignTo(size, 1ULL << seg->alignment);
78*87099a04SSam Clegg     LLVM_DEBUG(llvm::dbgs() << "outputSegmentOffset set: " << seg->name
793b8d2be5SSam Clegg                             << " -> " << size << "\n");
803b8d2be5SSam Clegg     seg->outputSegmentOffset = size;
813b8d2be5SSam Clegg     size += seg->getSize();
823b8d2be5SSam Clegg   }
833b8d2be5SSam Clegg }
843b8d2be5SSam Clegg 
853b8d2be5SSam Clegg } // namespace wasm
863b8d2be5SSam Clegg } // namespace lld
87