[WebAssembly] Add InputChunk as common base class for InputSegment and InputFunction. NFC.

Differential Revision: https://reviews.llvm.org/D41419

llvm-svn: 322148
This commit is contained in:
Sam Clegg 2018-01-10 01:13:34 +00:00
parent 050b4b05a0
commit 5fa274bea4
13 changed files with 165 additions and 183 deletions

View File

@ -4,8 +4,8 @@ add_public_tablegen_target(WasmOptionsTableGen)
add_lld_library(lldWasm
Driver.cpp
InputChunks.cpp
InputFiles.cpp
InputSegment.cpp
OutputSections.cpp
SymbolTable.cpp
Symbols.cpp

View File

@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
#include "InputSegment.h"
#include "InputChunks.h"
#include "OutputSegment.h"
#include "lld/Common/LLVM.h"
@ -18,8 +18,16 @@ using namespace lld::wasm;
uint32_t InputSegment::translateVA(uint32_t Address) const {
assert(Address >= startVA() && Address < endVA());
int32_t Delta = OutputSeg->StartVA + OutputSegmentOffset - startVA();
int32_t Delta = OutputSeg->StartVA + OutputOffset - startVA();
DEBUG(dbgs() << "translateVA: " << getName() << " Delta=" << Delta
<< " Address=" << Address << "\n");
return Address + Delta;
}
void InputChunk::copyRelocations(const WasmSection &Section) {
size_t Start = getInputSectionOffset();
size_t Size = getSize();
for (const WasmRelocation &R : Section.Relocations)
if (R.Offset >= Start && R.Offset < Start + Size)
Relocations.push_back(R);
}

125
lld/wasm/InputChunks.h Normal file
View File

@ -0,0 +1,125 @@
//===- InputChunks.h --------------------------------------------*- C++ -*-===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// An input chunk represents an indivisible blocks of code or data from an input
// file. i.e. a single wasm data segment or a single wasm function.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_WASM_INPUT_CHUNKS_H
#define LLD_WASM_INPUT_CHUNKS_H
#include "InputFiles.h"
#include "WriterUtils.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Object/Wasm.h"
using llvm::object::WasmSegment;
using llvm::wasm::WasmFunction;
using llvm::wasm::WasmRelocation;
using llvm::wasm::WasmSignature;
using llvm::object::WasmSection;
namespace lld {
namespace wasm {
class ObjFile;
class OutputSegment;
class InputChunk {
public:
InputChunk(const ObjFile &F) : File(F) {}
virtual ~InputChunk() = default;
void copyRelocations(const WasmSection &Section);
virtual const uint8_t *getData() const = 0;
virtual uint32_t getSize() const = 0;
virtual uint32_t getInputSectionOffset() const = 0;
int32_t OutputOffset = 0;
std::vector<WasmRelocation> Relocations;
std::vector<OutputRelocation> OutRelocations;
const ObjFile &File;
};
// Represents a WebAssembly data segment which can be included as part of
// an output data segments. Note that in WebAssembly, unlike ELF and other
// formats, used the term "data segment" to refer to the continous regions of
// memory that make on the data section. See:
// https://webassembly.github.io/spec/syntax/modules.html#syntax-data
//
// For example, by default, clang will produce a separate data section for
// each global variable.
class InputSegment : public InputChunk {
public:
InputSegment(const WasmSegment &Seg, const ObjFile &F)
: InputChunk(F), Segment(Seg) {}
// Translate an offset in the input segment to an offset in the output
// segment.
uint32_t translateVA(uint32_t Address) const;
const OutputSegment *getOutputSegment() const { return OutputSeg; }
void setOutputSegment(const OutputSegment *Segment, uint32_t Offset) {
OutputSeg = Segment;
OutputOffset = Offset;
}
const uint8_t *getData() const override {
return Segment.Data.Content.data();
}
uint32_t getSize() const override { return Segment.Data.Content.size(); }
uint32_t getInputSectionOffset() const override {
return Segment.SectionOffset;
}
uint32_t getAlignment() const { return Segment.Data.Alignment; }
uint32_t startVA() const { return Segment.Data.Offset.Value.Int32; }
uint32_t endVA() const { return startVA() + getSize(); }
StringRef getName() const { return Segment.Data.Name; }
protected:
const WasmSegment &Segment;
const OutputSegment *OutputSeg = nullptr;
};
// Represents a single wasm function within and input file. These are
// combined to create the final output CODE section.
class InputFunction : public InputChunk {
public:
InputFunction(const WasmSignature &S, const WasmFunction &Func,
const ObjFile &F)
: InputChunk(F), Signature(S), Function(Func) {}
uint32_t getSize() const override { return Function.Size; }
const uint8_t *getData() const override {
return File.CodeSection->Content.data() + Function.CodeSectionOffset;
}
uint32_t getInputSectionOffset() const override {
return Function.CodeSectionOffset;
};
uint32_t getOutputIndex() const { return OutputIndex.getValue(); };
bool hasOutputIndex() const { return OutputIndex.hasValue(); };
void setOutputIndex(uint32_t Index) {
assert(!hasOutputIndex());
OutputIndex = Index;
};
const WasmSignature &Signature;
protected:
const WasmFunction &Function;
llvm::Optional<uint32_t> OutputIndex;
};
} // namespace wasm
} // namespace lld
#endif // LLD_WASM_INPUT_CHUNKS_H

View File

@ -10,8 +10,7 @@
#include "InputFiles.h"
#include "Config.h"
#include "InputFunction.h"
#include "InputSegment.h"
#include "InputChunks.h"
#include "SymbolTable.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
@ -126,14 +125,6 @@ InputSegment *ObjFile::getSegment(const WasmSymbol &WasmSym) const {
return nullptr;
}
static void copyRelocationsRange(std::vector<WasmRelocation> &To,
ArrayRef<WasmRelocation> From, size_t Start,
size_t Size) {
for (const WasmRelocation &R : From)
if (R.Offset >= Start && R.Offset < Start + Size)
To.push_back(R);
}
// Get the value stored in the wasm global represented by this symbol.
// This represents the virtual address of the symbol in the input file.
uint32_t ObjFile::getGlobalValue(const WasmSymbol &Sym) const {
@ -175,8 +166,7 @@ void ObjFile::initializeSymbols() {
for (const WasmSegment &S : WasmObj->dataSegments()) {
InputSegment *Seg = make<InputSegment>(S, *this);
copyRelocationsRange(Seg->Relocations, DataSection->Relocations,
Seg->getInputSectionOffset(), Seg->getSize());
Seg->copyRelocations(*DataSection);
Segments.emplace_back(Seg);
}
@ -186,10 +176,9 @@ void ObjFile::initializeSymbols() {
for (size_t I = 0; I < Funcs.size(); ++I) {
const WasmFunction &Func = Funcs[I];
const WasmSignature &Sig = Types[FuncTypes[I]];
InputFunction *Function = make<InputFunction>(Sig, Func, *this);
copyRelocationsRange(Function->Relocations, CodeSection->Relocations,
Func.CodeSectionOffset, Func.Size);
Functions.emplace_back(Function);
InputFunction *F = make<InputFunction>(Sig, Func, *this);
F->copyRelocations(*CodeSection);
Functions.emplace_back(F);
}
// Populate `FunctionSymbols` and `GlobalSymbols` based on the WasmSymbols

View File

@ -98,6 +98,7 @@ public:
uint32_t getRelocatedAddress(uint32_t Index) const;
const WasmSection *CodeSection = nullptr;
const WasmSection *DataSection = nullptr;
std::vector<uint32_t> TypeMap;
std::vector<InputSegment *> Segments;
@ -131,7 +132,6 @@ private:
// List of all indirect symbols indexed by table index space.
std::vector<Symbol *> TableSymbols;
const WasmSection *DataSection = nullptr;
uint32_t NumGlobalImports = 0;
uint32_t NumFunctionImports = 0;
std::unique_ptr<WasmObjectFile> WasmObj;

View File

@ -1,57 +0,0 @@
//===- InpuFunction.h -------------------------------------------*- C++ -*-===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Represents a WebAssembly function in an input file which could also be
// assigned a function index in the output.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_WASM_INPUT_FUNCTION_H
#define LLD_WASM_INPUT_FUNCTION_H
#include "WriterUtils.h"
#include "llvm/Object/Wasm.h"
using llvm::wasm::WasmRelocation;
using llvm::wasm::WasmFunction;
namespace lld {
namespace wasm {
class ObjFile;
class InputFunction {
public:
InputFunction(const WasmSignature &S, const WasmFunction &Func,
const ObjFile &F)
: Signature(S), Function(Func), File(F) {}
uint32_t getOutputIndex() const { return OutputIndex.getValue(); };
bool hasOutputIndex() const { return OutputIndex.hasValue(); };
void setOutputIndex(uint32_t Index) {
assert(!hasOutputIndex());
OutputIndex = Index;
};
const WasmSignature &Signature;
const WasmFunction &Function;
int32_t OutputOffset = 0;
std::vector<WasmRelocation> Relocations;
std::vector<OutputRelocation> OutRelocations;
const ObjFile &File;
protected:
llvm::Optional<uint32_t> OutputIndex;
};
} // namespace wasm
} // namespace lld
#endif // LLD_WASM_INPUT_FUNCTION_H

View File

@ -1,76 +0,0 @@
//===- InputSegment.h -------------------------------------------*- C++ -*-===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Represents a WebAssembly data segment which can be included as part of
// an output data segments. Note that in WebAssembly, unlike ELF and other
// formats, used the term "data segment" to refer to the continous regions of
// memory that make on the data section. See:
// https://webassembly.github.io/spec/syntax/modules.html#syntax-data
//
// For example, by default, clang will produce a separate data section for
// each global variable.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_WASM_INPUT_SEGMENT_H
#define LLD_WASM_INPUT_SEGMENT_H
#include "WriterUtils.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Object/Wasm.h"
using llvm::object::WasmSegment;
using llvm::wasm::WasmRelocation;
namespace lld {
namespace wasm {
class ObjFile;
class OutputSegment;
class InputSegment {
public:
InputSegment(const WasmSegment &Seg, const ObjFile &F)
: Segment(Seg), File(F) {}
// Translate an offset in the input segment to an offset in the output
// segment.
uint32_t translateVA(uint32_t Address) const;
const OutputSegment *getOutputSegment() const { return OutputSeg; }
uint32_t getOutputSegmentOffset() const { return OutputSegmentOffset; }
uint32_t getInputSectionOffset() const { return Segment.SectionOffset; }
void setOutputSegment(const OutputSegment *Segment, uint32_t Offset) {
OutputSeg = Segment;
OutputSegmentOffset = Offset;
}
uint32_t getSize() const { return Segment.Data.Content.size(); }
uint32_t getAlignment() const { return Segment.Data.Alignment; }
uint32_t startVA() const { return Segment.Data.Offset.Value.Int32; }
uint32_t endVA() const { return startVA() + getSize(); }
StringRef getName() const { return Segment.Data.Name; }
const WasmSegment &Segment;
const ObjFile &File;
std::vector<WasmRelocation> Relocations;
std::vector<OutputRelocation> OutRelocations;
protected:
const OutputSegment *OutputSeg = nullptr;
uint32_t OutputSegmentOffset = 0;
};
} // namespace wasm
} // namespace lld
#endif // LLD_WASM_INPUT_SEGMENT_H

View File

@ -10,8 +10,8 @@
#include "OutputSections.h"
#include "Config.h"
#include "InputChunks.h"
#include "InputFiles.h"
#include "InputFunction.h"
#include "OutputSegment.h"
#include "SymbolTable.h"
#include "lld/Common/ErrorHandler.h"
@ -202,11 +202,11 @@ CodeSection::CodeSection(ArrayRef<InputFunction *> Functions)
OS.flush();
BodySize = CodeSectionHeader.size();
for (InputFunction *Func : Functions) {
for (InputChunk *Func : Functions) {
Func->OutputOffset = BodySize;
calcRelocations(Func->File, Func->Relocations, Func->OutRelocations,
Func->OutputOffset - Func->Function.CodeSectionOffset);
BodySize += Func->Function.Size;
Func->OutputOffset - Func->getInputSectionOffset());
BodySize += Func->getSize();
}
createHeader(BodySize);
@ -230,24 +230,22 @@ void CodeSection::writeTo(uint8_t *Buf) {
Buf += CodeSectionHeader.size();
// Write code section bodies
parallelForEach(Functions, [ContentsStart](InputFunction *Func) {
ArrayRef<uint8_t> Content(Func->File.CodeSection->Content);
memcpy(ContentsStart + Func->OutputOffset,
Content.data() + Func->Function.CodeSectionOffset,
Func->Function.Size);
parallelForEach(Functions, [ContentsStart](InputChunk *Func) {
memcpy(ContentsStart + Func->OutputOffset, Func->getData(),
Func->getSize());
applyRelocations(ContentsStart, Func->OutRelocations);
});
}
uint32_t CodeSection::numRelocations() const {
uint32_t Count = 0;
for (const InputFunction *Func : Functions)
for (const InputChunk *Func : Functions)
Count += Func->OutRelocations.size();
return Count;
}
void CodeSection::writeRelocations(raw_ostream &OS) const {
for (const InputFunction *Func : Functions)
for (const InputChunk *Func : Functions)
for (const OutputRelocation &Reloc : Func->OutRelocations)
writeReloc(OS, Reloc);
}
@ -271,13 +269,12 @@ DataSection::DataSection(ArrayRef<OutputSegment *> Segments)
Segment->setSectionOffset(BodySize);
BodySize += Segment->Header.size();
log("Data segment: size=" + Twine(Segment->Size));
for (InputSegment *InputSeg : Segment->InputSegments) {
uint32_t InputOffset = InputSeg->getInputSectionOffset();
for (InputChunk *InputSeg : Segment->InputSegments) {
uint32_t OutputOffset = Segment->getSectionOffset() +
Segment->Header.size() +
InputSeg->getOutputSegmentOffset();
Segment->Header.size() + InputSeg->OutputOffset;
calcRelocations(InputSeg->File, InputSeg->Relocations,
InputSeg->OutRelocations, OutputOffset - InputOffset);
InputSeg->OutRelocations,
OutputOffset - InputSeg->getInputSectionOffset());
}
BodySize += Segment->Size;
}
@ -305,11 +302,9 @@ void DataSection::writeTo(uint8_t *Buf) {
memcpy(SegStart, Segment->Header.data(), Segment->Header.size());
// Write segment data payload
for (const InputSegment *Input : Segment->InputSegments) {
ArrayRef<uint8_t> Content(Input->Segment.Data.Content);
memcpy(SegStart + Segment->Header.size() +
Input->getOutputSegmentOffset(),
Content.data(), Content.size());
for (const InputChunk *Input : Segment->InputSegments) {
memcpy(SegStart + Segment->Header.size() + Input->OutputOffset,
Input->getData(), Input->getSize());
applyRelocations(ContentsStart, Input->OutRelocations);
}
});
@ -318,14 +313,14 @@ void DataSection::writeTo(uint8_t *Buf) {
uint32_t DataSection::numRelocations() const {
uint32_t Count = 0;
for (const OutputSegment *Seg : Segments)
for (const InputSegment *InputSeg : Seg->InputSegments)
for (const InputChunk *InputSeg : Seg->InputSegments)
Count += InputSeg->OutRelocations.size();
return Count;
}
void DataSection::writeRelocations(raw_ostream &OS) const {
for (const OutputSegment *Seg : Segments)
for (const InputSegment *InputSeg : Seg->InputSegments)
for (const InputChunk *InputSeg : Seg->InputSegments)
for (const OutputRelocation &Reloc : InputSeg->OutRelocations)
writeReloc(OS, Reloc);
}

View File

@ -10,7 +10,7 @@
#ifndef LLD_WASM_OUTPUT_SECTIONS_H
#define LLD_WASM_OUTPUT_SECTIONS_H
#include "InputSegment.h"
#include "InputChunks.h"
#include "WriterUtils.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/DenseMap.h"
@ -28,7 +28,6 @@ std::string toString(const wasm::OutputSection &Section);
namespace wasm {
class OutputSegment;
class InputFunction;
class OutputSection {
public:

View File

@ -10,7 +10,7 @@
#ifndef LLD_WASM_OUTPUT_SEGMENT_H
#define LLD_WASM_OUTPUT_SEGMENT_H
#include "InputSegment.h"
#include "InputChunks.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Object/Wasm.h"

View File

@ -10,7 +10,7 @@
#include "SymbolTable.h"
#include "Config.h"
#include "InputFunction.h"
#include "InputChunks.h"
#include "WriterUtils.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"

View File

@ -10,9 +10,8 @@
#include "Symbols.h"
#include "Config.h"
#include "InputChunks.h"
#include "InputFiles.h"
#include "InputFunction.h"
#include "InputSegment.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Strings.h"

View File

@ -10,7 +10,7 @@
#include "Writer.h"
#include "Config.h"
#include "InputFunction.h"
#include "InputChunks.h"
#include "OutputSections.h"
#include "OutputSegment.h"
#include "SymbolTable.h"