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::wasm {
19
20void OutputSegment::addInputSegment(InputChunk *inSeg) {
21 alignment = std::max(a: alignment, b: inSeg->alignment);
22 inputSegments.push_back(x: inSeg);
23 size = llvm::alignTo(Value: size, Align: 1ULL << inSeg->alignment);
24 LLVM_DEBUG(dbgs() << "addInputSegment: " << inSeg->name << " oname=" << name
25 << " size=" << inSeg->getSize()
26 << " align=" << inSeg->alignment << " at:" << size << "\n");
27 inSeg->outputSeg = this;
28 inSeg->outputSegmentOffset = size;
29 size += inSeg->getSize();
30}
31
32// This function scans over the input segments.
33//
34// It removes MergeInputChunks from the input section array and adds
35// new synthetic sections at the location of the first input section
36// that it replaces. It then finalizes each synthetic section in order
37// to compute an output offset for each piece of each input section.
38void OutputSegment::finalizeInputSegments() {
39 LLVM_DEBUG(llvm::dbgs() << "finalizeInputSegments: " << name << "\n");
40 std::vector<SyntheticMergedChunk *> mergedSegments;
41 std::vector<InputChunk *> newSegments;
42 for (InputChunk *s : inputSegments) {
43 MergeInputChunk *ms = dyn_cast<MergeInputChunk>(Val: s);
44 if (!ms) {
45 newSegments.push_back(x: s);
46 continue;
47 }
48
49 // A segment should not make it here unless its alive
50 assert(ms->live);
51
52 auto i = llvm::find_if(Range&: mergedSegments, P: [=](SyntheticMergedChunk *seg) {
53 return seg->flags == ms->flags && seg->alignment == ms->alignment;
54 });
55 if (i == mergedSegments.end()) {
56 LLVM_DEBUG(llvm::dbgs() << "new merge segment: " << name
57 << " alignment=" << ms->alignment << "\n");
58 auto *syn = make<SyntheticMergedChunk>(args&: name, args&: ms->alignment, args&: ms->flags);
59 syn->outputSeg = this;
60 mergedSegments.push_back(x: syn);
61 i = std::prev(x: mergedSegments.end());
62 newSegments.push_back(x: syn);
63 } else {
64 LLVM_DEBUG(llvm::dbgs() << "adding to merge segment: " << name << "\n");
65 }
66 (*i)->addMergeChunk(ms);
67 }
68
69 for (auto *ms : mergedSegments)
70 ms->finalizeContents();
71
72 inputSegments = newSegments;
73 size = 0;
74 for (InputChunk *seg : inputSegments) {
75 size = llvm::alignTo(Value: size, Align: 1ULL << seg->alignment);
76 LLVM_DEBUG(llvm::dbgs() << "outputSegmentOffset set: " << seg->name
77 << " -> " << size << "\n");
78 seg->outputSegmentOffset = size;
79 size += seg->getSize();
80 }
81}
82
83} // namespace lld::wasm
84