diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -800,8 +800,8 @@ // before calling finalizeContents(). LLVM_DEBUG(llvm::dbgs() << "splitSections\n"); parallelForEach(symtab->objectFiles, [](ObjFile *file) { - for (InputSegment *seg : file->segments) { - if (auto *s = dyn_cast(seg)) + for (InputChunk *seg : file->segments) { + if (auto *s = dyn_cast(seg)) s->splitIntoPieces(); } }); diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h --- a/lld/wasm/InputChunks.h +++ b/lld/wasm/InputChunks.h @@ -46,34 +46,62 @@ Section }; - Kind kind() const { return sectionKind; } + StringRef name; + StringRef debugName; - virtual uint32_t getSize() const { return data().size(); } + StringRef getName() const { return name; } + StringRef getDebugName() const { return debugName; } + Kind kind() const { return (Kind)sectionKind; } + + uint32_t getSize() const; virtual uint32_t getInputSize() const { return getSize(); }; - virtual void writeTo(uint8_t *buf) const; + void writeTo(uint8_t *buf) const; void relocate(uint8_t *buf) const; ArrayRef getRelocations() const { return relocations; } void setRelocations(ArrayRef rs) { relocations = rs; } - uint64_t getOffset(uint64_t offset) const { return outSecOff + offset; } - virtual StringRef getName() const = 0; - virtual StringRef getDebugName() const = 0; - virtual uint32_t getComdat() const = 0; + // Translate an offset in the input section to an offset in the output + // section. + uint64_t getOffset(uint64_t offset) const; + // For data segments translate and offset into the input segment into + // and offset into the output segment + uint64_t getSegmentOffset(uint64_t offset) const; + uint64_t getVA(uint64_t offset = 0) const; + + uint32_t getComdat() const { return comdat; } StringRef getComdatName() const; - virtual uint32_t getInputSectionOffset() const = 0; + uint32_t getInputSectionOffset() const { return inputSectionOffset; } size_t getNumRelocations() const { return relocations.size(); } void writeRelocations(llvm::raw_ostream &os) const; + void generateRelocationCode(raw_ostream &os) const; + + bool isTLS() const { + // Older object files don't include WASM_SEG_FLAG_TLS and instead + // relied on the naming convention. + return flags & llvm::wasm::WASM_SEG_FLAG_TLS || name.startswith(".tdata") || + name.startswith(".tbss"); + } ObjFile *file; OutputSection *outputSec = nullptr; + uint32_t comdat = UINT32_MAX; + uint32_t inputSectionOffset = 0; + uint32_t alignment; + uint32_t flags; + + // Only applies to data segments. + uint32_t outputSegmentOffset = 0; + const OutputSegment *outputSeg = nullptr; // After assignAddresses is called, this represents the offset from // the beginning of the output section this chunk was assigned to. int32_t outSecOff = 0; + uint8_t sectionKind : 3; + // Signals that the section is part of the output. The garbage collector, // and COMDAT handling can set a sections' Live bit. // If GC is disabled, all sections start out as live by default. @@ -83,14 +111,16 @@ unsigned discarded : 1; protected: - InputChunk(ObjFile *f, Kind k) - : file(f), live(!config->gcSections), discarded(false), sectionKind(k) {} + InputChunk(ObjFile *f, Kind k, StringRef name, uint32_t alignment = 0, + uint32_t flags = 0) + : name(name), file(f), alignment(alignment), flags(flags), sectionKind(k), + live(!config->gcSections), discarded(false) {} virtual ~InputChunk() = default; - virtual ArrayRef data() const = 0; + ArrayRef data() const { return rawData; } virtual uint64_t getTombstone() const { return 0; } ArrayRef relocations; - Kind sectionKind; + mutable ArrayRef rawData; }; // Represents a WebAssembly data segment which can be included as part of @@ -104,64 +134,34 @@ class InputSegment : public InputChunk { public: InputSegment(const WasmSegment *seg, ObjFile *f) - : InputChunk(f, InputChunk::DataSegment), segment(seg) { - alignment = segment->Data.Alignment; - flags = segment->Data.LinkingFlags; - } - - InputSegment(uint32_t alignment, uint32_t flags) - : InputChunk(nullptr, InputChunk::DataSegment), alignment(alignment), - flags(flags) {} - - static bool classof(const InputChunk *c) { - return c->kind() == DataSegment || c->kind() == Merge || - c->kind() == MergedSegment; + : InputChunk(f, InputChunk::DataSegment, seg->Data.Name, + seg->Data.Alignment, seg->Data.LinkingFlags), + segment(seg) { + rawData = segment->Data.Content; + comdat = segment->Data.Comdat; + inputSectionOffset = segment->SectionOffset; } - void generateRelocationCode(raw_ostream &os) const; - - StringRef getName() const override { return segment->Data.Name; } - StringRef getDebugName() const override { return StringRef(); } - uint32_t getComdat() const override { return segment->Data.Comdat; } - uint32_t getInputSectionOffset() const override { - return segment->SectionOffset; - } - - // Translate an offset in the input section to an offset in the output - // section. - uint64_t getOffset(uint64_t offset) const; - - uint64_t getVA(uint64_t offset = 0) const; - - bool isTLS() const { - // Older object files don't include WASM_SEG_FLAG_TLS and instead - // relied on the naming convention. - return flags & llvm::wasm::WASM_SEG_FLAG_TLS || - getName().startswith(".tdata") || getName().startswith(".tbss"); - } + InputSegment(StringRef name, uint32_t alignment, uint32_t flags) + : InputChunk(nullptr, InputChunk::DataSegment, name, alignment, flags) {} - const OutputSegment *outputSeg = nullptr; - uint32_t outputSegmentOffset = 0; - uint32_t alignment = 0; - uint32_t flags = 0; + static bool classof(const InputChunk *c) { return c->kind() == DataSegment; } protected: - ArrayRef data() const override { return segment->Data.Content; } - const WasmSegment *segment = nullptr; }; -class SyntheticMergedDataSegment; +class SyntheticMergedChunk; // Merge segment handling copied from lld/ELF/InputSection.h. Keep in sync // where possible. -// SegmentPiece represents a piece of splittable segment contents. +// SectionPiece represents a piece of splittable segment contents. // We allocate a lot of these and binary search on them. This means that they // have to be as compact as possible, which is why we don't store the size (can // be found by looking at the next one). -struct SegmentPiece { - SegmentPiece(size_t off, uint32_t hash, bool live) +struct SectionPiece { + SectionPiece(size_t off, uint32_t hash, bool live) : inputOff(off), live(live || !config->gcSections), hash(hash >> 1) {} uint32_t inputOff; @@ -170,13 +170,17 @@ uint64_t outputOff = 0; }; -static_assert(sizeof(SegmentPiece) == 16, "SectionPiece is too big"); +static_assert(sizeof(SectionPiece) == 16, "SectionPiece is too big"); // This corresponds segments marked as WASM_SEG_FLAG_STRINGS. -class MergeInputSegment : public InputSegment { +class MergeInputChunk : public InputChunk { public: - MergeInputSegment(const WasmSegment *seg, ObjFile *f) : InputSegment(seg, f) { - sectionKind = Merge; + MergeInputChunk(const WasmSegment *seg, ObjFile *f) + : InputChunk(f, Merge, seg->Data.Name, seg->Data.Alignment, + seg->Data.LinkingFlags) { + rawData = seg->Data.Content; + comdat = seg->Data.Comdat; + inputSectionOffset = seg->SectionOffset; } static bool classof(const InputChunk *s) { return s->kind() == Merge; } @@ -188,7 +192,7 @@ // Splittable sections are handled as a sequence of data // rather than a single large blob of data. - std::vector pieces; + std::vector pieces; // Returns I'th piece's data. This function is very hot when // string merging is enabled, so we want to inline. @@ -201,52 +205,43 @@ } // Returns the SectionPiece at a given input section offset. - SegmentPiece *getSegmentPiece(uint64_t offset); - const SegmentPiece *getSegmentPiece(uint64_t offset) const { - return const_cast(this)->getSegmentPiece(offset); + SectionPiece *getSectionPiece(uint64_t offset); + const SectionPiece *getSectionPiece(uint64_t offset) const { + return const_cast(this)->getSectionPiece(offset); } - SyntheticMergedDataSegment *parent = nullptr; + SyntheticMergedChunk *parent = nullptr; private: void splitStrings(ArrayRef a); }; -// SyntheticMergedDataSegment is a class that allows us to put mergeable +// SyntheticMergedChunk is a class that allows us to put mergeable // sections with different attributes in a single output sections. To do that we -// put them into SyntheticMergedDataSegment synthetic input sections which are +// put them into SyntheticMergedChunk synthetic input sections which are // attached to regular output sections. -class SyntheticMergedDataSegment : public InputSegment { +class SyntheticMergedChunk : public InputChunk { public: - SyntheticMergedDataSegment(StringRef name, uint32_t alignment, uint32_t flags) - : InputSegment(alignment, flags), name(name), - builder(llvm::StringTableBuilder::RAW, 1ULL << alignment) { - sectionKind = InputChunk::MergedSegment; - } + SyntheticMergedChunk(StringRef name, uint32_t alignment, uint32_t flags) + : InputChunk(nullptr, InputChunk::MergedSegment, name, alignment, flags), + builder(llvm::StringTableBuilder::RAW, 1ULL << alignment) {} static bool classof(const InputChunk *c) { return c->kind() == InputChunk::MergedSegment; } - uint32_t getSize() const override; - - StringRef getName() const override { return name; } - - uint32_t getComdat() const override { return segments[0]->getComdat(); } - - void writeTo(uint8_t *buf) const override; - - void addMergeSegment(MergeInputSegment *ms) { + void addMergeSegment(MergeInputChunk *ms) { + comdat = ms->getComdat(); ms->parent = this; segments.push_back(ms); } void finalizeContents(); -protected: - std::vector segments; - StringRef name; llvm::StringTableBuilder builder; + +protected: + std::vector segments; }; // Represents a single wasm function within and input file. These are @@ -254,44 +249,40 @@ class InputFunction : public InputChunk { public: InputFunction(const WasmSignature &s, const WasmFunction *func, ObjFile *f) - : InputChunk(f, InputChunk::Function), signature(s), function(func), - exportName(func && func->ExportName.hasValue() - ? (*func->ExportName).str() - : llvm::Optional()) {} + : InputChunk(f, InputChunk::Function, func->SymbolName), signature(s), + function(func), exportName(func && func->ExportName.hasValue() + ? (*func->ExportName).str() + : llvm::Optional()) { + inputSectionOffset = function->CodeSectionOffset; + rawData = + file->codeSection->Content.slice(inputSectionOffset, function->Size); + debugName = function->DebugName; + comdat = function->Comdat; + } + + InputFunction(StringRef name, const WasmSignature &s) + : InputChunk(nullptr, InputChunk::Function, name), signature(s) {} static bool classof(const InputChunk *c) { return c->kind() == InputChunk::Function || c->kind() == InputChunk::SyntheticFunction; } - void writeTo(uint8_t *buf) const override; - StringRef getName() const override { return function->SymbolName; } - StringRef getDebugName() const override { return function->DebugName; } llvm::Optional getExportName() const { return exportName.hasValue() ? llvm::Optional(*exportName) : llvm::Optional(); } void setExportName(std::string exportName) { this->exportName = exportName; } - uint32_t getComdat() const override { return function->Comdat; } uint32_t getFunctionInputOffset() const { return getInputSectionOffset(); } uint32_t getFunctionCodeOffset() const { return function->CodeOffset; } - uint32_t getSize() const override { - if (config->compressRelocations && file) { - assert(compressedSize); - return compressedSize; - } - return data().size(); - } uint32_t getInputSize() const override { return function->Size; } uint32_t getFunctionIndex() const { return functionIndex.getValue(); } bool hasFunctionIndex() const { return functionIndex.hasValue(); } void setFunctionIndex(uint32_t index); - uint32_t getInputSectionOffset() const override { - return function->CodeSectionOffset; - } uint32_t getTableIndex() const { return tableIndex.getValue(); } bool hasTableIndex() const { return tableIndex.hasValue(); } void setTableIndex(uint32_t index); + void writeCompressed(uint8_t *buf) const; // The size of a given input function can depend on the values of the // LEB relocations within it. This finalizeContents method is called after @@ -301,13 +292,12 @@ const WasmSignature &signature; -protected: - ArrayRef data() const override { - assert(!config->compressRelocations); - return file->codeSection->Content.slice(getInputSectionOffset(), - function->Size); + uint32_t getCompressedSize() const { + assert(compressedSize); + return compressedSize; } +protected: const WasmFunction *function; llvm::Optional exportName; llvm::Optional functionIndex; @@ -320,46 +310,30 @@ public: SyntheticFunction(const WasmSignature &s, StringRef name, StringRef debugName = {}) - : InputFunction(s, nullptr, nullptr), name(name), debugName(debugName) { + : InputFunction(name, s) { sectionKind = InputChunk::SyntheticFunction; + this->debugName = debugName; } static bool classof(const InputChunk *c) { return c->kind() == InputChunk::SyntheticFunction; } - StringRef getName() const override { return name; } - StringRef getDebugName() const override { return debugName; } - uint32_t getComdat() const override { return UINT32_MAX; } - - void setBody(ArrayRef body_) { body = body_; } - -protected: - ArrayRef data() const override { return body; } - - StringRef name; - StringRef debugName; - ArrayRef body; + void setBody(ArrayRef body_) { rawData = body_; } }; // Represents a single Wasm Section within an input file. class InputSection : public InputChunk { public: InputSection(const WasmSection &s, ObjFile *f) - : InputChunk(f, InputChunk::Section), section(s), tombstoneValue(getTombstoneForSection(s.Name)) { + : InputChunk(f, InputChunk::Section, s.Name), section(s), + tombstoneValue(getTombstoneForSection(s.Name)) { assert(section.Type == llvm::wasm::WASM_SEC_CUSTOM); + comdat = section.Comdat; + rawData = section.Content; } - StringRef getName() const override { return section.Name; } - StringRef getDebugName() const override { return StringRef(); } - uint32_t getComdat() const override { return section.Comdat; } - protected: - ArrayRef data() const override { return section.Content; } - - // Offset within the input section. This is only zero since this chunk - // type represents an entire input section, not part of one. - uint32_t getInputSectionOffset() const override { return 0; } uint64_t getTombstone() const override { return tombstoneValue; } static uint64_t getTombstoneForSection(StringRef name); diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp --- a/lld/wasm/InputChunks.cpp +++ b/lld/wasm/InputChunks.cpp @@ -57,8 +57,31 @@ return file->getWasmObj()->linkingData().Comdats[index]; } +uint32_t InputChunk::getSize() const { + if (const auto *ms = dyn_cast(this)) + return ms->builder.getSize(); + + if (const auto *f = dyn_cast(this)) { + if (config->compressRelocations && f->file) { + return f->getCompressedSize(); + } + } + + return data().size(); +} + // Copy this input chunk to an mmap'ed output file and apply relocations. void InputChunk::writeTo(uint8_t *buf) const { + if (const auto *f = dyn_cast(this)) { + if (file && config->compressRelocations) + return f->writeCompressed(buf); + } else if (const auto *ms = dyn_cast(this)) { + ms->builder.write(buf + outSecOff); + // Apply relocations + ms->relocate(buf + outSecOff); + return; + } + // Copy contents memcpy(buf + outSecOff, data().data(), data().size()); @@ -259,10 +282,7 @@ // Override the default writeTo method so that we can (optionally) write the // compressed version of the function. -void InputFunction::writeTo(uint8_t *buf) const { - if (!file || !config->compressRelocations) - return InputChunk::writeTo(buf); - +void InputFunction::writeCompressed(uint8_t *buf) const { buf += outSecOff; uint8_t *orig = buf; (void)orig; @@ -294,26 +314,30 @@ LLVM_DEBUG(dbgs() << " total: " << (buf + chunkSize - orig) << "\n"); } -uint64_t InputSegment::getOffset(uint64_t offset) const { - if (const MergeInputSegment *ms = dyn_cast(this)) { - LLVM_DEBUG(dbgs() << "getOffset(merged): " << getName() << "\n"); +uint64_t InputChunk::getOffset(uint64_t offset) const { + return outSecOff + offset; +} + +uint64_t InputChunk::getSegmentOffset(uint64_t offset) const { + if (const auto *ms = dyn_cast(this)) { + LLVM_DEBUG(dbgs() << "getSegmentOffset(merged): " << getName() << "\n"); LLVM_DEBUG(dbgs() << "offset: " << offset << "\n"); LLVM_DEBUG(dbgs() << "parentOffset: " << ms->getParentOffset(offset) << "\n"); assert(ms->parent); - return ms->parent->getOffset(ms->getParentOffset(offset)); + return ms->parent->getSegmentOffset(ms->getParentOffset(offset)); } return outputSegmentOffset + offset; } -uint64_t InputSegment::getVA(uint64_t offset) const { - return (outputSeg ? outputSeg->startVA : 0) + getOffset(offset); +uint64_t InputChunk::getVA(uint64_t offset) const { + return (outputSeg ? outputSeg->startVA : 0) + getSegmentOffset(offset); } // Generate code to apply relocations to the data section at runtime. // This is only called when generating shared libaries (PIC) where address are // not known at static link time. -void InputSegment::generateRelocationCode(raw_ostream &os) const { +void InputChunk::generateRelocationCode(raw_ostream &os) const { LLVM_DEBUG(dbgs() << "generating runtime relocations: " << getName() << " count=" << relocations.size() << "\n"); @@ -382,7 +406,7 @@ // Split WASM_SEG_FLAG_STRINGS section. Such a section is a sequence of // null-terminated strings. -void MergeInputSegment::splitStrings(ArrayRef data) { +void MergeInputChunk::splitStrings(ArrayRef data) { LLVM_DEBUG(llvm::dbgs() << "splitStrings\n"); size_t off = 0; StringRef s = toStringRef(data); @@ -405,15 +429,15 @@ // // Note that this function is called from parallelForEach. This must be // thread-safe (i.e. no memory allocation from the pools). -void MergeInputSegment::splitIntoPieces() { +void MergeInputChunk::splitIntoPieces() { assert(pieces.empty()); // As of now we only support WASM_SEG_FLAG_STRINGS but in the future we // could add other types of splitting (see ELF's splitIntoPieces). - assert(segment->Data.LinkingFlags & WASM_SEG_FLAG_STRINGS); + assert(flags & WASM_SEG_FLAG_STRINGS); splitStrings(data()); } -SegmentPiece *MergeInputSegment::getSegmentPiece(uint64_t offset) { +SectionPiece *MergeInputChunk::getSectionPiece(uint64_t offset) { if (this->data().size() <= offset) fatal(toString(this) + ": offset is outside the section"); @@ -421,36 +445,25 @@ // In that case we need to do a binary search of the original section piece // vector. auto it = partition_point( - pieces, [=](SegmentPiece p) { return p.inputOff <= offset; }); + pieces, [=](SectionPiece p) { return p.inputOff <= offset; }); return &it[-1]; } // Returns the offset in an output section for a given input offset. // Because contents of a mergeable section is not contiguous in output, // it is not just an addition to a base output offset. -uint64_t MergeInputSegment::getParentOffset(uint64_t offset) const { +uint64_t MergeInputChunk::getParentOffset(uint64_t offset) const { // If Offset is not at beginning of a section piece, it is not in the map. // In that case we need to search from the original section piece vector. - const SegmentPiece *piece = getSegmentPiece(offset); + const SectionPiece *piece = getSectionPiece(offset); uint64_t addend = offset - piece->inputOff; return piece->outputOff + addend; } -uint32_t SyntheticMergedDataSegment::getSize() const { - return builder.getSize(); -} - -void SyntheticMergedDataSegment::writeTo(uint8_t *buf) const { - builder.write(buf + outSecOff); - - // Apply relocations - relocate(buf + outSecOff); -} - -void SyntheticMergedDataSegment::finalizeContents() { +void SyntheticMergedChunk::finalizeContents() { // Add all string pieces to the string table builder to create section // contents. - for (MergeInputSegment *sec : segments) + for (MergeInputChunk *sec : segments) for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) if (sec->pieces[i].live) builder.add(sec->getData(i)); @@ -461,7 +474,7 @@ // finalize() fixed tail-optimized strings, so we can now get // offsets of strings. Get an offset for each string and save it // to a corresponding SectionPiece for easy access. - for (MergeInputSegment *sec : segments) + for (MergeInputChunk *sec : segments) for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) if (sec->pieces[i].live) sec->pieces[i].outputOff = builder.getOffset(sec->getData(i)); diff --git a/lld/wasm/InputFiles.h b/lld/wasm/InputFiles.h --- a/lld/wasm/InputFiles.h +++ b/lld/wasm/InputFiles.h @@ -136,7 +136,7 @@ std::vector tableEntries; std::vector tableEntriesRel; std::vector keptComdats; - std::vector segments; + std::vector segments; std::vector functions; std::vector globals; std::vector events; diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -464,9 +464,9 @@ // Populate `Segments`. for (const WasmSegment &s : wasmObj->dataSegments()) { - InputSegment *seg; + InputChunk *seg; if (shouldMerge(s)) { - seg = make(&s, this); + seg = make(&s, this); } else seg = make(&s, this); seg->discarded = isExcludedByComdat(seg); @@ -568,7 +568,7 @@ return symtab->addDefinedFunction(name, flags, this, func); } case WASM_SYMBOL_TYPE_DATA: { - InputSegment *seg = segments[sym.Info.DataRef.Segment]; + InputChunk *seg = segments[sym.Info.DataRef.Segment]; auto offset = sym.Info.DataRef.Offset; auto size = sym.Info.DataRef.Size; if (sym.isBindingLocal()) diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp --- a/lld/wasm/OutputSections.cpp +++ b/lld/wasm/OutputSections.cpp @@ -178,7 +178,7 @@ log("Data segment: size=" + Twine(segment->size) + ", startVA=" + Twine::utohexstr(segment->startVA) + ", name=" + segment->name); - for (InputSegment *inputSeg : segment->inputSegments) { + for (InputChunk *inputSeg : segment->inputSegments) { inputSeg->outputSec = this; inputSeg->outSecOff = segment->sectionOffset + segment->header.size() + inputSeg->outputSegmentOffset; diff --git a/lld/wasm/OutputSegment.h b/lld/wasm/OutputSegment.h --- a/lld/wasm/OutputSegment.h +++ b/lld/wasm/OutputSegment.h @@ -22,7 +22,7 @@ public: OutputSegment(StringRef n) : name(n) {} - void addInputSegment(InputSegment *inSeg); + void addInputSegment(InputChunk *inSeg); void finalizeInputSegments(); bool isTLS() const { return name == ".tdata"; } @@ -35,7 +35,7 @@ uint32_t sectionOffset = 0; uint32_t alignment = 0; uint64_t startVA = 0; - std::vector inputSegments; + std::vector inputSegments; // Sum of the size of the all the input segments uint32_t size = 0; diff --git a/lld/wasm/OutputSegment.cpp b/lld/wasm/OutputSegment.cpp --- a/lld/wasm/OutputSegment.cpp +++ b/lld/wasm/OutputSegment.cpp @@ -19,7 +19,7 @@ namespace wasm { -void OutputSegment::addInputSegment(InputSegment *inSeg) { +void OutputSegment::addInputSegment(InputChunk *inSeg) { alignment = std::max(alignment, inSeg->alignment); inputSegments.push_back(inSeg); size = llvm::alignTo(size, 1ULL << inSeg->alignment); @@ -33,16 +33,16 @@ // This function scans over the input segments. // -// It removes MergeInputSegments from the input section array and adds +// It removes MergeInputChunks from the input section array and adds // 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"); - std::vector mergedSegments; - std::vector newSegments; - for (InputSegment *s : inputSegments) { - MergeInputSegment *ms = dyn_cast(s); + std::vector mergedSegments; + std::vector newSegments; + for (InputChunk *s : inputSegments) { + MergeInputChunk *ms = dyn_cast(s); if (!ms) { newSegments.push_back(s); continue; @@ -51,15 +51,14 @@ // A segment should not make it here unless its alive assert(ms->live); - auto i = - llvm::find_if(mergedSegments, [=](SyntheticMergedDataSegment *seg) { - return seg->flags == ms->flags && seg->alignment == ms->alignment; - }); + auto i = llvm::find_if(mergedSegments, [=](SyntheticMergedChunk *seg) { + return seg->flags == ms->flags && seg->alignment == ms->alignment; + }); if (i == mergedSegments.end()) { LLVM_DEBUG(llvm::dbgs() << "new merge section: " << name << " alignment=" << ms->alignment << "\n"); - SyntheticMergedDataSegment *syn = - make(name, ms->alignment, ms->flags); + SyntheticMergedChunk *syn = + make(name, ms->alignment, ms->flags); syn->outputSeg = this; mergedSegments.push_back(syn); i = std::prev(mergedSegments.end()); @@ -75,7 +74,7 @@ inputSegments = newSegments; size = 0; - for (InputSegment *seg : inputSegments) { + for (InputChunk *seg : inputSegments) { size = llvm::alignTo(size, 1ULL << seg->alignment); LLVM_DEBUG(llvm::dbgs() << "outputSegmentOffset set: " << seg->getName() << " -> " << size << "\n"); diff --git a/lld/wasm/SymbolTable.h b/lld/wasm/SymbolTable.h --- a/lld/wasm/SymbolTable.h +++ b/lld/wasm/SymbolTable.h @@ -54,8 +54,7 @@ Symbol *addDefinedFunction(StringRef name, uint32_t flags, InputFile *file, InputFunction *function); Symbol *addDefinedData(StringRef name, uint32_t flags, InputFile *file, - InputSegment *segment, uint64_t address, - uint64_t size); + InputChunk *segment, uint64_t address, uint64_t size); Symbol *addDefinedGlobal(StringRef name, uint32_t flags, InputFile *file, InputGlobal *g); Symbol *addDefinedEvent(StringRef name, uint32_t flags, InputFile *file, diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -365,7 +365,7 @@ } Symbol *SymbolTable::addDefinedData(StringRef name, uint32_t flags, - InputFile *file, InputSegment *segment, + InputFile *file, InputChunk *segment, uint64_t address, uint64_t size) { LLVM_DEBUG(dbgs() << "addDefinedData:" << name << " addr:" << address << "\n"); diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h --- a/lld/wasm/Symbols.h +++ b/lld/wasm/Symbols.h @@ -278,8 +278,8 @@ class DefinedData : public DataSymbol { public: // Constructor for regular data symbols originating from input files. - DefinedData(StringRef name, uint32_t flags, InputFile *f, - InputSegment *segment, uint64_t value, uint64_t size) + DefinedData(StringRef name, uint32_t flags, InputFile *f, InputChunk *segment, + uint64_t value, uint64_t size) : DataSymbol(name, DefinedDataKind, flags, f), segment(segment), value(value), size(size) {} @@ -298,7 +298,7 @@ uint64_t getOutputSegmentIndex() const; uint64_t getSize() const { return size; } - InputSegment *segment = nullptr; + InputChunk *segment = nullptr; uint64_t value = 0; protected: diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -160,8 +160,8 @@ // (splittable) sections, each piece of data has independent liveness bit. // So we explicitly tell it which offset is in use. if (auto *d = dyn_cast(this)) { - if (auto *ms = dyn_cast(c)) { - ms->getSegmentPiece(d->value)->live = true; + if (auto *ms = dyn_cast(c)) { + ms->getSectionPiece(d->value)->live = true; } } c->live = true; @@ -301,7 +301,7 @@ uint64_t DefinedData::getOutputSegmentOffset() const { LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n"); - return segment->getOffset(value); + return segment->getSegmentOffset(value); } uint64_t DefinedData::getOutputSegmentIndex() const { diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -569,7 +569,7 @@ continue; StringRef comdat = inputSegments[0]->getComdatName(); #ifndef NDEBUG - for (const InputSegment *isec : inputSegments) + for (const InputChunk *isec : inputSegments) assert(isec->getComdatName() == comdat); #endif if (!comdat.empty()) diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -460,7 +460,7 @@ } // Find TLS data segments - auto isTLS = [](InputSegment *segment) { + auto isTLS = [](InputChunk *segment) { return segment->live && segment->isTLS(); }; tlsUsed = tlsUsed || @@ -816,7 +816,7 @@ out.tableSec->assignIndexes(); } -static StringRef getOutputDataSegmentName(const InputSegment &seg) { +static StringRef getOutputDataSegmentName(const InputChunk &seg) { // We always merge .tbss and .tdata into a single TLS segment so all TLS // symbols are be relative to single __tls_base. if (seg.isTLS()) @@ -852,7 +852,7 @@ void Writer::createOutputSegments() { for (ObjFile *file : symtab->objectFiles) { - for (InputSegment *segment : file->segments) { + for (InputChunk *segment : file->segments) { if (!segment->live) continue; StringRef name = getOutputDataSegmentName(*segment); @@ -919,7 +919,7 @@ combined->initFlags = WASM_DATA_SEGMENT_IS_PASSIVE; } bool first = true; - for (InputSegment *inSeg : s->inputSegments) { + for (InputChunk *inSeg : s->inputSegments) { if (first) inSeg->alignment = std::max(inSeg->alignment, s->alignment); first = false; @@ -1201,7 +1201,7 @@ raw_string_ostream os(bodyContent); writeUleb128(os, 0, "num locals"); for (const OutputSegment *seg : segments) - for (const InputSegment *inSeg : seg->inputSegments) + for (const InputChunk *inSeg : seg->inputSegments) inSeg->generateRelocationCode(os); writeU8(os, WASM_OPCODE_END, "END");