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 18*d32f71a9SSam Clegg namespace lld::wasm { 193b8d2be5SSam Clegg addInputSegment(InputChunk * inSeg)205a9b25e1SSam Cleggvoid OutputSegment::addInputSegment(InputChunk *inSeg) { 213b8d2be5SSam Clegg alignment = std::max(alignment, inSeg->alignment); 223b8d2be5SSam Clegg inputSegments.push_back(inSeg); 2315653172SGuillaume Chatelet size = llvm::alignTo(size, 1ULL << inSeg->alignment); 2487099a04SSam Clegg LLVM_DEBUG(dbgs() << "addInputSegment: " << inSeg->name << " oname=" << name 2515653172SGuillaume Chatelet << " size=" << inSeg->getSize() 2615653172SGuillaume Chatelet << " align=" << inSeg->alignment << " at:" << size << "\n"); 273b8d2be5SSam Clegg inSeg->outputSeg = this; 283b8d2be5SSam Clegg inSeg->outputSegmentOffset = size; 293b8d2be5SSam Clegg size += inSeg->getSize(); 303b8d2be5SSam Clegg } 313b8d2be5SSam Clegg 323b8d2be5SSam Clegg // This function scans over the input segments. 333b8d2be5SSam Clegg // 345a9b25e1SSam Clegg // It removes MergeInputChunks from the input section array and adds 353b8d2be5SSam Clegg // new synthetic sections at the location of the first input section 363b8d2be5SSam Clegg // that it replaces. It then finalizes each synthetic section in order 373b8d2be5SSam Clegg // to compute an output offset for each piece of each input section. finalizeInputSegments()383b8d2be5SSam Cleggvoid OutputSegment::finalizeInputSegments() { 393b8d2be5SSam Clegg LLVM_DEBUG(llvm::dbgs() << "finalizeInputSegments: " << name << "\n"); 405a9b25e1SSam Clegg std::vector<SyntheticMergedChunk *> mergedSegments; 415a9b25e1SSam Clegg std::vector<InputChunk *> newSegments; 425a9b25e1SSam Clegg for (InputChunk *s : inputSegments) { 435a9b25e1SSam Clegg MergeInputChunk *ms = dyn_cast<MergeInputChunk>(s); 443b8d2be5SSam Clegg if (!ms) { 453b8d2be5SSam Clegg newSegments.push_back(s); 463b8d2be5SSam Clegg continue; 473b8d2be5SSam Clegg } 483b8d2be5SSam Clegg 493b8d2be5SSam Clegg // A segment should not make it here unless its alive 503b8d2be5SSam Clegg assert(ms->live); 513b8d2be5SSam Clegg 525a9b25e1SSam Clegg auto i = llvm::find_if(mergedSegments, [=](SyntheticMergedChunk *seg) { 533b8d2be5SSam Clegg return seg->flags == ms->flags && seg->alignment == ms->alignment; 543b8d2be5SSam Clegg }); 553b8d2be5SSam Clegg if (i == mergedSegments.end()) { 5645b7cf99SSam Clegg LLVM_DEBUG(llvm::dbgs() << "new merge segment: " << name 5715653172SGuillaume Chatelet << " alignment=" << ms->alignment << "\n"); 5815653172SGuillaume Chatelet auto *syn = make<SyntheticMergedChunk>(name, ms->alignment, ms->flags); 593b8d2be5SSam Clegg syn->outputSeg = this; 603b8d2be5SSam Clegg mergedSegments.push_back(syn); 613b8d2be5SSam Clegg i = std::prev(mergedSegments.end()); 623b8d2be5SSam Clegg newSegments.push_back(syn); 633b8d2be5SSam Clegg } else { 6445b7cf99SSam Clegg LLVM_DEBUG(llvm::dbgs() << "adding to merge segment: " << name << "\n"); 653b8d2be5SSam Clegg } 665a9b25e1SSam Clegg (*i)->addMergeChunk(ms); 673b8d2be5SSam Clegg } 683b8d2be5SSam Clegg 693b8d2be5SSam Clegg for (auto *ms : mergedSegments) 703b8d2be5SSam Clegg ms->finalizeContents(); 713b8d2be5SSam Clegg 723b8d2be5SSam Clegg inputSegments = newSegments; 733b8d2be5SSam Clegg size = 0; 745a9b25e1SSam Clegg for (InputChunk *seg : inputSegments) { 7515653172SGuillaume Chatelet size = llvm::alignTo(size, 1ULL << seg->alignment); 7687099a04SSam Clegg LLVM_DEBUG(llvm::dbgs() << "outputSegmentOffset set: " << seg->name 773b8d2be5SSam Clegg << " -> " << size << "\n"); 783b8d2be5SSam Clegg seg->outputSegmentOffset = size; 793b8d2be5SSam Clegg size += seg->getSize(); 803b8d2be5SSam Clegg } 813b8d2be5SSam Clegg } 823b8d2be5SSam Clegg 83*d32f71a9SSam Clegg } // namespace lld::wasm 84