xref: /openbsd-src/gnu/llvm/lld/wasm/OutputSegment.cpp (revision dfe94b169149f14cc1aee2cf6dad58a8d9a1860c)
11cf9926bSpatrick //===- OutputSegment.h -----------------------------------------*- C++ -*-===//
21cf9926bSpatrick //
31cf9926bSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41cf9926bSpatrick // See https://llvm.org/LICENSE.txt for license information.
51cf9926bSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61cf9926bSpatrick //
71cf9926bSpatrick //===----------------------------------------------------------------------===//
81cf9926bSpatrick 
91cf9926bSpatrick #include "OutputSegment.h"
101cf9926bSpatrick #include "InputChunks.h"
111cf9926bSpatrick #include "lld/Common/Memory.h"
121cf9926bSpatrick 
131cf9926bSpatrick #define DEBUG_TYPE "lld"
141cf9926bSpatrick 
151cf9926bSpatrick using namespace llvm;
161cf9926bSpatrick using namespace llvm::wasm;
171cf9926bSpatrick 
181cf9926bSpatrick namespace lld {
191cf9926bSpatrick 
201cf9926bSpatrick namespace wasm {
211cf9926bSpatrick 
addInputSegment(InputChunk * inSeg)221cf9926bSpatrick void OutputSegment::addInputSegment(InputChunk *inSeg) {
231cf9926bSpatrick   alignment = std::max(alignment, inSeg->alignment);
241cf9926bSpatrick   inputSegments.push_back(inSeg);
251cf9926bSpatrick   size = llvm::alignTo(size, 1ULL << inSeg->alignment);
26*dfe94b16Srobert   LLVM_DEBUG(dbgs() << "addInputSegment: " << inSeg->name << " oname=" << name
27*dfe94b16Srobert                     << " size=" << inSeg->getSize()
281cf9926bSpatrick                     << " align=" << inSeg->alignment << " at:" << size << "\n");
291cf9926bSpatrick   inSeg->outputSeg = this;
301cf9926bSpatrick   inSeg->outputSegmentOffset = size;
311cf9926bSpatrick   size += inSeg->getSize();
321cf9926bSpatrick }
331cf9926bSpatrick 
341cf9926bSpatrick // This function scans over the input segments.
351cf9926bSpatrick //
361cf9926bSpatrick // It removes MergeInputChunks from the input section array and adds
371cf9926bSpatrick // new synthetic sections at the location of the first input section
381cf9926bSpatrick // that it replaces. It then finalizes each synthetic section in order
391cf9926bSpatrick // to compute an output offset for each piece of each input section.
finalizeInputSegments()401cf9926bSpatrick void OutputSegment::finalizeInputSegments() {
411cf9926bSpatrick   LLVM_DEBUG(llvm::dbgs() << "finalizeInputSegments: " << name << "\n");
421cf9926bSpatrick   std::vector<SyntheticMergedChunk *> mergedSegments;
431cf9926bSpatrick   std::vector<InputChunk *> newSegments;
441cf9926bSpatrick   for (InputChunk *s : inputSegments) {
451cf9926bSpatrick     MergeInputChunk *ms = dyn_cast<MergeInputChunk>(s);
461cf9926bSpatrick     if (!ms) {
471cf9926bSpatrick       newSegments.push_back(s);
481cf9926bSpatrick       continue;
491cf9926bSpatrick     }
501cf9926bSpatrick 
511cf9926bSpatrick     // A segment should not make it here unless its alive
521cf9926bSpatrick     assert(ms->live);
531cf9926bSpatrick 
541cf9926bSpatrick     auto i = llvm::find_if(mergedSegments, [=](SyntheticMergedChunk *seg) {
551cf9926bSpatrick       return seg->flags == ms->flags && seg->alignment == ms->alignment;
561cf9926bSpatrick     });
571cf9926bSpatrick     if (i == mergedSegments.end()) {
581cf9926bSpatrick       LLVM_DEBUG(llvm::dbgs() << "new merge segment: " << name
591cf9926bSpatrick                               << " alignment=" << ms->alignment << "\n");
601cf9926bSpatrick       auto *syn = make<SyntheticMergedChunk>(name, ms->alignment, ms->flags);
611cf9926bSpatrick       syn->outputSeg = this;
621cf9926bSpatrick       mergedSegments.push_back(syn);
631cf9926bSpatrick       i = std::prev(mergedSegments.end());
641cf9926bSpatrick       newSegments.push_back(syn);
651cf9926bSpatrick     } else {
661cf9926bSpatrick       LLVM_DEBUG(llvm::dbgs() << "adding to merge segment: " << name << "\n");
671cf9926bSpatrick     }
681cf9926bSpatrick     (*i)->addMergeChunk(ms);
691cf9926bSpatrick   }
701cf9926bSpatrick 
711cf9926bSpatrick   for (auto *ms : mergedSegments)
721cf9926bSpatrick     ms->finalizeContents();
731cf9926bSpatrick 
741cf9926bSpatrick   inputSegments = newSegments;
751cf9926bSpatrick   size = 0;
761cf9926bSpatrick   for (InputChunk *seg : inputSegments) {
771cf9926bSpatrick     size = llvm::alignTo(size, 1ULL << seg->alignment);
78*dfe94b16Srobert     LLVM_DEBUG(llvm::dbgs() << "outputSegmentOffset set: " << seg->name
791cf9926bSpatrick                             << " -> " << size << "\n");
801cf9926bSpatrick     seg->outputSegmentOffset = size;
811cf9926bSpatrick     size += seg->getSize();
821cf9926bSpatrick   }
831cf9926bSpatrick }
841cf9926bSpatrick 
851cf9926bSpatrick } // namespace wasm
861cf9926bSpatrick } // namespace lld
87