xref: /llvm-project/lld/wasm/OutputSegment.cpp (revision d32f71a91a432db2d9ea32694a8308534b6697ec)
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 
15 using namespace llvm;
16 using namespace llvm::wasm;
17 
18 namespace lld::wasm {
19 
addInputSegment(InputChunk * inSeg)20 void OutputSegment::addInputSegment(InputChunk *inSeg) {
21   alignment = std::max(alignment, inSeg->alignment);
22   inputSegments.push_back(inSeg);
23   size = llvm::alignTo(size, 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.
finalizeInputSegments()38 void 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>(s);
44     if (!ms) {
45       newSegments.push_back(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(mergedSegments, [=](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>(name, ms->alignment, ms->flags);
59       syn->outputSeg = this;
60       mergedSegments.push_back(syn);
61       i = std::prev(mergedSegments.end());
62       newSegments.push_back(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(size, 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