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 | |
20 | void 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. |
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>(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 |