11cf9926bSpatrick //===- OutputSegment.h -----------------------------------------*- C++ -*-===// 21cf9926bSpatrick // 31cf9926bSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41cf9926bSpatrick // See https://llvm.org/LICENSE.txt for license information. 51cf9926bSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61cf9926bSpatrick // 71cf9926bSpatrick //===----------------------------------------------------------------------===// 81cf9926bSpatrick 91cf9926bSpatrick #include "OutputSegment.h" 101cf9926bSpatrick #include "InputChunks.h" 111cf9926bSpatrick #include "lld/Common/Memory.h" 121cf9926bSpatrick 131cf9926bSpatrick #define DEBUG_TYPE "lld" 141cf9926bSpatrick 151cf9926bSpatrick using namespace llvm; 161cf9926bSpatrick using namespace llvm::wasm; 171cf9926bSpatrick 181cf9926bSpatrick namespace lld { 191cf9926bSpatrick 201cf9926bSpatrick namespace wasm { 211cf9926bSpatrick addInputSegment(InputChunk * inSeg)221cf9926bSpatrickvoid OutputSegment::addInputSegment(InputChunk *inSeg) { 231cf9926bSpatrick alignment = std::max(alignment, inSeg->alignment); 241cf9926bSpatrick inputSegments.push_back(inSeg); 251cf9926bSpatrick size = llvm::alignTo(size, 1ULL << inSeg->alignment); 26*dfe94b16Srobert LLVM_DEBUG(dbgs() << "addInputSegment: " << inSeg->name << " oname=" << name 27*dfe94b16Srobert << " size=" << inSeg->getSize() 281cf9926bSpatrick << " align=" << inSeg->alignment << " at:" << size << "\n"); 291cf9926bSpatrick inSeg->outputSeg = this; 301cf9926bSpatrick inSeg->outputSegmentOffset = size; 311cf9926bSpatrick size += inSeg->getSize(); 321cf9926bSpatrick } 331cf9926bSpatrick 341cf9926bSpatrick // This function scans over the input segments. 351cf9926bSpatrick // 361cf9926bSpatrick // It removes MergeInputChunks from the input section array and adds 371cf9926bSpatrick // new synthetic sections at the location of the first input section 381cf9926bSpatrick // that it replaces. It then finalizes each synthetic section in order 391cf9926bSpatrick // to compute an output offset for each piece of each input section. finalizeInputSegments()401cf9926bSpatrickvoid OutputSegment::finalizeInputSegments() { 411cf9926bSpatrick LLVM_DEBUG(llvm::dbgs() << "finalizeInputSegments: " << name << "\n"); 421cf9926bSpatrick std::vector<SyntheticMergedChunk *> mergedSegments; 431cf9926bSpatrick std::vector<InputChunk *> newSegments; 441cf9926bSpatrick for (InputChunk *s : inputSegments) { 451cf9926bSpatrick MergeInputChunk *ms = dyn_cast<MergeInputChunk>(s); 461cf9926bSpatrick if (!ms) { 471cf9926bSpatrick newSegments.push_back(s); 481cf9926bSpatrick continue; 491cf9926bSpatrick } 501cf9926bSpatrick 511cf9926bSpatrick // A segment should not make it here unless its alive 521cf9926bSpatrick assert(ms->live); 531cf9926bSpatrick 541cf9926bSpatrick auto i = llvm::find_if(mergedSegments, [=](SyntheticMergedChunk *seg) { 551cf9926bSpatrick return seg->flags == ms->flags && seg->alignment == ms->alignment; 561cf9926bSpatrick }); 571cf9926bSpatrick if (i == mergedSegments.end()) { 581cf9926bSpatrick LLVM_DEBUG(llvm::dbgs() << "new merge segment: " << name 591cf9926bSpatrick << " alignment=" << ms->alignment << "\n"); 601cf9926bSpatrick auto *syn = make<SyntheticMergedChunk>(name, ms->alignment, ms->flags); 611cf9926bSpatrick syn->outputSeg = this; 621cf9926bSpatrick mergedSegments.push_back(syn); 631cf9926bSpatrick i = std::prev(mergedSegments.end()); 641cf9926bSpatrick newSegments.push_back(syn); 651cf9926bSpatrick } else { 661cf9926bSpatrick LLVM_DEBUG(llvm::dbgs() << "adding to merge segment: " << name << "\n"); 671cf9926bSpatrick } 681cf9926bSpatrick (*i)->addMergeChunk(ms); 691cf9926bSpatrick } 701cf9926bSpatrick 711cf9926bSpatrick for (auto *ms : mergedSegments) 721cf9926bSpatrick ms->finalizeContents(); 731cf9926bSpatrick 741cf9926bSpatrick inputSegments = newSegments; 751cf9926bSpatrick size = 0; 761cf9926bSpatrick for (InputChunk *seg : inputSegments) { 771cf9926bSpatrick size = llvm::alignTo(size, 1ULL << seg->alignment); 78*dfe94b16Srobert LLVM_DEBUG(llvm::dbgs() << "outputSegmentOffset set: " << seg->name 791cf9926bSpatrick << " -> " << size << "\n"); 801cf9926bSpatrick seg->outputSegmentOffset = size; 811cf9926bSpatrick size += seg->getSize(); 821cf9926bSpatrick } 831cf9926bSpatrick } 841cf9926bSpatrick 851cf9926bSpatrick } // namespace wasm 861cf9926bSpatrick } // namespace lld 87