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