13b8d2be5SSam Clegg //===- OutputSegment.h -----------------------------------------*- C++ -*-===// 23b8d2be5SSam Clegg // 33b8d2be5SSam Clegg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43b8d2be5SSam Clegg // See https://llvm.org/LICENSE.txt for license information. 53b8d2be5SSam Clegg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63b8d2be5SSam Clegg // 73b8d2be5SSam Clegg //===----------------------------------------------------------------------===// 83b8d2be5SSam Clegg 93b8d2be5SSam Clegg #include "OutputSegment.h" 103b8d2be5SSam Clegg #include "InputChunks.h" 113b8d2be5SSam Clegg #include "lld/Common/Memory.h" 123b8d2be5SSam Clegg 133b8d2be5SSam Clegg #define DEBUG_TYPE "lld" 143b8d2be5SSam Clegg 153b8d2be5SSam Clegg using namespace llvm; 163b8d2be5SSam Clegg using namespace llvm::wasm; 173b8d2be5SSam Clegg 183b8d2be5SSam Clegg namespace lld { 193b8d2be5SSam Clegg 203b8d2be5SSam Clegg namespace wasm { 213b8d2be5SSam Clegg addInputSegment(InputChunk * inSeg)225a9b25e1SSam Cleggvoid OutputSegment::addInputSegment(InputChunk *inSeg) { 233b8d2be5SSam Clegg alignment = std::max(alignment, inSeg->alignment); 243b8d2be5SSam Clegg inputSegments.push_back(inSeg); 253b8d2be5SSam Clegg size = llvm::alignTo(size, 1ULL << inSeg->alignment); 26*87099a04SSam Clegg LLVM_DEBUG(dbgs() << "addInputSegment: " << inSeg->name << " oname=" << name 27*87099a04SSam Clegg << " size=" << inSeg->getSize() 283b8d2be5SSam Clegg << " align=" << inSeg->alignment << " at:" << size << "\n"); 293b8d2be5SSam Clegg inSeg->outputSeg = this; 303b8d2be5SSam Clegg inSeg->outputSegmentOffset = size; 313b8d2be5SSam Clegg size += inSeg->getSize(); 323b8d2be5SSam Clegg } 333b8d2be5SSam Clegg 343b8d2be5SSam Clegg // This function scans over the input segments. 353b8d2be5SSam Clegg // 365a9b25e1SSam Clegg // It removes MergeInputChunks from the input section array and adds 373b8d2be5SSam Clegg // new synthetic sections at the location of the first input section 383b8d2be5SSam Clegg // that it replaces. It then finalizes each synthetic section in order 393b8d2be5SSam Clegg // to compute an output offset for each piece of each input section. finalizeInputSegments()403b8d2be5SSam Cleggvoid OutputSegment::finalizeInputSegments() { 413b8d2be5SSam Clegg LLVM_DEBUG(llvm::dbgs() << "finalizeInputSegments: " << name << "\n"); 425a9b25e1SSam Clegg std::vector<SyntheticMergedChunk *> mergedSegments; 435a9b25e1SSam Clegg std::vector<InputChunk *> newSegments; 445a9b25e1SSam Clegg for (InputChunk *s : inputSegments) { 455a9b25e1SSam Clegg MergeInputChunk *ms = dyn_cast<MergeInputChunk>(s); 463b8d2be5SSam Clegg if (!ms) { 473b8d2be5SSam Clegg newSegments.push_back(s); 483b8d2be5SSam Clegg continue; 493b8d2be5SSam Clegg } 503b8d2be5SSam Clegg 513b8d2be5SSam Clegg // A segment should not make it here unless its alive 523b8d2be5SSam Clegg assert(ms->live); 533b8d2be5SSam Clegg 545a9b25e1SSam Clegg auto i = llvm::find_if(mergedSegments, [=](SyntheticMergedChunk *seg) { 553b8d2be5SSam Clegg return seg->flags == ms->flags && seg->alignment == ms->alignment; 563b8d2be5SSam Clegg }); 573b8d2be5SSam Clegg if (i == mergedSegments.end()) { 5845b7cf99SSam Clegg LLVM_DEBUG(llvm::dbgs() << "new merge segment: " << name 593b8d2be5SSam Clegg << " alignment=" << ms->alignment << "\n"); 6045b7cf99SSam Clegg auto *syn = make<SyntheticMergedChunk>(name, ms->alignment, ms->flags); 613b8d2be5SSam Clegg syn->outputSeg = this; 623b8d2be5SSam Clegg mergedSegments.push_back(syn); 633b8d2be5SSam Clegg i = std::prev(mergedSegments.end()); 643b8d2be5SSam Clegg newSegments.push_back(syn); 653b8d2be5SSam Clegg } else { 6645b7cf99SSam Clegg LLVM_DEBUG(llvm::dbgs() << "adding to merge segment: " << name << "\n"); 673b8d2be5SSam Clegg } 685a9b25e1SSam Clegg (*i)->addMergeChunk(ms); 693b8d2be5SSam Clegg } 703b8d2be5SSam Clegg 713b8d2be5SSam Clegg for (auto *ms : mergedSegments) 723b8d2be5SSam Clegg ms->finalizeContents(); 733b8d2be5SSam Clegg 743b8d2be5SSam Clegg inputSegments = newSegments; 753b8d2be5SSam Clegg size = 0; 765a9b25e1SSam Clegg for (InputChunk *seg : inputSegments) { 773b8d2be5SSam Clegg size = llvm::alignTo(size, 1ULL << seg->alignment); 78*87099a04SSam Clegg LLVM_DEBUG(llvm::dbgs() << "outputSegmentOffset set: " << seg->name 793b8d2be5SSam Clegg << " -> " << size << "\n"); 803b8d2be5SSam Clegg seg->outputSegmentOffset = size; 813b8d2be5SSam Clegg size += seg->getSize(); 823b8d2be5SSam Clegg } 833b8d2be5SSam Clegg } 843b8d2be5SSam Clegg 853b8d2be5SSam Clegg } // namespace wasm 863b8d2be5SSam Clegg } // namespace lld 87