xref: /openbsd/gnu/llvm/lld/wasm/OutputSegment.cpp (revision a0747c9f)
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 {
19 
20 namespace wasm {
21 
22 void 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->getName()
27                     << " oname=" << name << " 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.
40 void 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->getName()
79                             << " -> " << size << "\n");
80     seg->outputSegmentOffset = size;
81     size += seg->getSize();
82   }
83 }
84 
85 } // namespace wasm
86 } // namespace lld
87