2021-02-27 08:09:32 +08:00
|
|
|
//===- OutputSegment.h -----------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "OutputSegment.h"
|
|
|
|
#include "InputChunks.h"
|
|
|
|
#include "lld/Common/Memory.h"
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "lld"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::wasm;
|
|
|
|
|
|
|
|
namespace lld {
|
|
|
|
|
|
|
|
namespace wasm {
|
|
|
|
|
2021-05-15 07:25:04 +08:00
|
|
|
void OutputSegment::addInputSegment(InputChunk *inSeg) {
|
2021-02-27 08:09:32 +08:00
|
|
|
alignment = std::max(alignment, inSeg->alignment);
|
|
|
|
inputSegments.push_back(inSeg);
|
|
|
|
size = llvm::alignTo(size, 1ULL << inSeg->alignment);
|
|
|
|
LLVM_DEBUG(dbgs() << "addInputSegment: " << inSeg->getName()
|
|
|
|
<< " oname=" << name << " size=" << inSeg->getSize()
|
|
|
|
<< " align=" << inSeg->alignment << " at:" << size << "\n");
|
|
|
|
inSeg->outputSeg = this;
|
|
|
|
inSeg->outputSegmentOffset = size;
|
|
|
|
size += inSeg->getSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
// This function scans over the input segments.
|
|
|
|
//
|
2021-05-15 07:25:04 +08:00
|
|
|
// It removes MergeInputChunks from the input section array and adds
|
2021-02-27 08:09:32 +08:00
|
|
|
// new synthetic sections at the location of the first input section
|
|
|
|
// that it replaces. It then finalizes each synthetic section in order
|
|
|
|
// to compute an output offset for each piece of each input section.
|
|
|
|
void OutputSegment::finalizeInputSegments() {
|
|
|
|
LLVM_DEBUG(llvm::dbgs() << "finalizeInputSegments: " << name << "\n");
|
2021-05-15 07:25:04 +08:00
|
|
|
std::vector<SyntheticMergedChunk *> mergedSegments;
|
|
|
|
std::vector<InputChunk *> newSegments;
|
|
|
|
for (InputChunk *s : inputSegments) {
|
|
|
|
MergeInputChunk *ms = dyn_cast<MergeInputChunk>(s);
|
2021-02-27 08:09:32 +08:00
|
|
|
if (!ms) {
|
|
|
|
newSegments.push_back(s);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// A segment should not make it here unless its alive
|
|
|
|
assert(ms->live);
|
|
|
|
|
2021-05-15 07:25:04 +08:00
|
|
|
auto i = llvm::find_if(mergedSegments, [=](SyntheticMergedChunk *seg) {
|
|
|
|
return seg->flags == ms->flags && seg->alignment == ms->alignment;
|
|
|
|
});
|
2021-02-27 08:09:32 +08:00
|
|
|
if (i == mergedSegments.end()) {
|
2021-05-13 07:48:34 +08:00
|
|
|
LLVM_DEBUG(llvm::dbgs() << "new merge segment: " << name
|
2021-02-27 08:09:32 +08:00
|
|
|
<< " alignment=" << ms->alignment << "\n");
|
2021-05-13 07:48:34 +08:00
|
|
|
auto *syn = make<SyntheticMergedChunk>(name, ms->alignment, ms->flags);
|
2021-02-27 08:09:32 +08:00
|
|
|
syn->outputSeg = this;
|
|
|
|
mergedSegments.push_back(syn);
|
|
|
|
i = std::prev(mergedSegments.end());
|
|
|
|
newSegments.push_back(syn);
|
|
|
|
} else {
|
2021-05-13 07:48:34 +08:00
|
|
|
LLVM_DEBUG(llvm::dbgs() << "adding to merge segment: " << name << "\n");
|
2021-02-27 08:09:32 +08:00
|
|
|
}
|
2021-05-15 07:25:04 +08:00
|
|
|
(*i)->addMergeChunk(ms);
|
2021-02-27 08:09:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (auto *ms : mergedSegments)
|
|
|
|
ms->finalizeContents();
|
|
|
|
|
|
|
|
inputSegments = newSegments;
|
|
|
|
size = 0;
|
2021-05-15 07:25:04 +08:00
|
|
|
for (InputChunk *seg : inputSegments) {
|
2021-02-27 08:09:32 +08:00
|
|
|
size = llvm::alignTo(size, 1ULL << seg->alignment);
|
|
|
|
LLVM_DEBUG(llvm::dbgs() << "outputSegmentOffset set: " << seg->getName()
|
|
|
|
<< " -> " << size << "\n");
|
|
|
|
seg->outputSegmentOffset = size;
|
|
|
|
size += seg->getSize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace wasm
|
|
|
|
} // namespace lld
|