1//===- OutputSegment.h -----------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "OutputSegment.h"
10#include "InputChunks.h"
11#include "lld/Common/Memory.h"
12
13#define DEBUG_TYPE "lld"
14
15using namespace llvm;
16using namespace llvm::wasm;
17
18namespace lld {
19
20namespace wasm {
21
22void OutputSegment::addInputSegment(InputChunk *inSeg) {
23  alignment = std::max(alignment, inSeg->alignment);
24  inputSegments.push_back(inSeg);
25  size = llvm::alignTo(size, 1ULL << inSeg->alignment);
26  LLVM_DEBUG(dbgs() << "addInputSegment: " << inSeg->name << " oname=" << name
27                    << " size=" << inSeg->getSize()
28                    << " align=" << inSeg->alignment << " at:" << size << "\n");
29  inSeg->outputSeg = this;
30  inSeg->outputSegmentOffset = size;
31  size += inSeg->getSize();
32}
33
34// This function scans over the input segments.
35//
36// It removes MergeInputChunks from the input section array and adds
37// new synthetic sections at the location of the first input section
38// that it replaces. It then finalizes each synthetic section in order
39// to compute an output offset for each piece of each input section.
40void OutputSegment::finalizeInputSegments() {
41  LLVM_DEBUG(llvm::dbgs() << "finalizeInputSegments: " << name << "\n");
42  std::vector<SyntheticMergedChunk *> mergedSegments;
43  std::vector<InputChunk *> newSegments;
44  for (InputChunk *s : inputSegments) {
45    MergeInputChunk *ms = dyn_cast<MergeInputChunk>(s);
46    if (!ms) {
47      newSegments.push_back(s);
48      continue;
49    }
50
51    // A segment should not make it here unless its alive
52    assert(ms->live);
53
54    auto i = llvm::find_if(mergedSegments, [=](SyntheticMergedChunk *seg) {
55      return seg->flags == ms->flags && seg->alignment == ms->alignment;
56    });
57    if (i == mergedSegments.end()) {
58      LLVM_DEBUG(llvm::dbgs() << "new merge segment: " << name
59                              << " alignment=" << ms->alignment << "\n");
60      auto *syn = make<SyntheticMergedChunk>(name, ms->alignment, ms->flags);
61      syn->outputSeg = this;
62      mergedSegments.push_back(syn);
63      i = std::prev(mergedSegments.end());
64      newSegments.push_back(syn);
65    } else {
66      LLVM_DEBUG(llvm::dbgs() << "adding to merge segment: " << name << "\n");
67    }
68    (*i)->addMergeChunk(ms);
69  }
70
71  for (auto *ms : mergedSegments)
72    ms->finalizeContents();
73
74  inputSegments = newSegments;
75  size = 0;
76  for (InputChunk *seg : inputSegments) {
77    size = llvm::alignTo(size, 1ULL << seg->alignment);
78    LLVM_DEBUG(llvm::dbgs() << "outputSegmentOffset set: " << seg->name
79                            << " -> " << size << "\n");
80    seg->outputSegmentOffset = size;
81    size += seg->getSize();
82  }
83}
84
85} // namespace wasm
86} // namespace lld
87