[WebAssembly] Output functions individually
The code section is now written out one function at a time rather than all the functions in a given objects being serialized at once. This change lays the groundwork for supporting --gc-sections. Differential Revision: https://reviews.llvm.org/D41315 llvm-svn: 322138
This commit is contained in:
parent
1f562176e9
commit
8d146bbc0c
|
@ -10,6 +10,7 @@
|
|||
#include "InputFiles.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "InputFunction.h"
|
||||
#include "InputSegment.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
|
@ -43,34 +44,20 @@ Optional<MemoryBufferRef> lld::wasm::readFile(StringRef Path) {
|
|||
}
|
||||
|
||||
void ObjFile::dumpInfo() const {
|
||||
log("reloc info for: " + getName() + "\n" +
|
||||
" FunctionIndexOffset : " + Twine(FunctionIndexOffset) + "\n" +
|
||||
" NumFunctionImports : " + Twine(NumFunctionImports()) + "\n" +
|
||||
" NumGlobalImports : " + Twine(NumGlobalImports()) + "\n");
|
||||
log("info for: " + getName() + "\n" +
|
||||
" Total Functions : " + Twine(FunctionSymbols.size()) + "\n" +
|
||||
" Total Globals : " + Twine(GlobalSymbols.size()) + "\n" +
|
||||
" Function Imports : " + Twine(NumFunctionImports) + "\n" +
|
||||
" Global Imports : " + Twine(NumGlobalImports) + "\n" +
|
||||
" Table Entries : " + Twine(TableSymbols.size()) + "\n");
|
||||
}
|
||||
|
||||
bool ObjFile::isImportedFunction(uint32_t Index) const {
|
||||
return Index < NumFunctionImports();
|
||||
}
|
||||
|
||||
Symbol *ObjFile::getFunctionSymbol(uint32_t Index) const {
|
||||
return FunctionSymbols[Index];
|
||||
}
|
||||
|
||||
Symbol *ObjFile::getTableSymbol(uint32_t Index) const {
|
||||
return TableSymbols[Index];
|
||||
}
|
||||
|
||||
Symbol *ObjFile::getGlobalSymbol(uint32_t Index) const {
|
||||
return GlobalSymbols[Index];
|
||||
}
|
||||
|
||||
uint32_t ObjFile::getRelocatedAddress(uint32_t Index) const {
|
||||
return getGlobalSymbol(Index)->getVirtualAddress();
|
||||
uint32_t ObjFile::getRelocatedAddress(uint32_t GlobalIndex) const {
|
||||
return GlobalSymbols[GlobalIndex]->getVirtualAddress();
|
||||
}
|
||||
|
||||
uint32_t ObjFile::relocateFunctionIndex(uint32_t Original) const {
|
||||
Symbol *Sym = getFunctionSymbol(Original);
|
||||
Symbol *Sym = FunctionSymbols[Original];
|
||||
uint32_t Index = Sym->getOutputIndex();
|
||||
DEBUG(dbgs() << "relocateFunctionIndex: " << toString(*Sym) << ": "
|
||||
<< Original << " -> " << Index << "\n");
|
||||
|
@ -82,7 +69,7 @@ uint32_t ObjFile::relocateTypeIndex(uint32_t Original) const {
|
|||
}
|
||||
|
||||
uint32_t ObjFile::relocateTableIndex(uint32_t Original) const {
|
||||
Symbol *Sym = getTableSymbol(Original);
|
||||
Symbol *Sym = TableSymbols[Original];
|
||||
uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0;
|
||||
DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original
|
||||
<< " -> " << Index << "\n");
|
||||
|
@ -90,7 +77,7 @@ uint32_t ObjFile::relocateTableIndex(uint32_t Original) const {
|
|||
}
|
||||
|
||||
uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const {
|
||||
Symbol *Sym = getGlobalSymbol(Original);
|
||||
Symbol *Sym = GlobalSymbols[Original];
|
||||
uint32_t Index = Sym->hasOutputIndex() ? Sym->getOutputIndex() : 0;
|
||||
DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original
|
||||
<< " -> " << Index << "\n");
|
||||
|
@ -125,7 +112,7 @@ void ObjFile::parse() {
|
|||
}
|
||||
|
||||
// Return the InputSegment in which a given symbol is defined.
|
||||
InputSegment *ObjFile::getSegment(const WasmSymbol &WasmSym) {
|
||||
InputSegment *ObjFile::getSegment(const WasmSymbol &WasmSym) const {
|
||||
uint32_t Address = WasmObj->getWasmSymbolValue(WasmSym);
|
||||
for (InputSegment *Segment : Segments) {
|
||||
if (Address >= Segment->startVA() && Address < Segment->endVA()) {
|
||||
|
@ -141,37 +128,61 @@ InputSegment *ObjFile::getSegment(const WasmSymbol &WasmSym) {
|
|||
|
||||
static void copyRelocationsRange(std::vector<WasmRelocation> &To,
|
||||
ArrayRef<WasmRelocation> From, size_t Start,
|
||||
size_t End) {
|
||||
size_t Size) {
|
||||
for (const WasmRelocation &R : From)
|
||||
if (R.Offset >= Start && R.Offset < End)
|
||||
if (R.Offset >= Start && R.Offset < Start + Size)
|
||||
To.push_back(R);
|
||||
}
|
||||
|
||||
// Get the signature for a given function symbol, either by looking
|
||||
// it up in function sections (for defined functions), of the imports section
|
||||
// (for imported functions).
|
||||
const WasmSignature *ObjFile::getFunctionSig(const WasmSymbol &Sym) const {
|
||||
DEBUG(dbgs() << "getFunctionSig: " << Sym.Name << "\n");
|
||||
return &WasmObj->types()[Sym.FunctionType];
|
||||
}
|
||||
|
||||
InputFunction *ObjFile::getFunction(const WasmSymbol &Sym) const {
|
||||
uint32_t FunctionIndex = Sym.ElementIndex - NumFunctionImports;
|
||||
return Functions[FunctionIndex];
|
||||
}
|
||||
|
||||
void ObjFile::initializeSymbols() {
|
||||
Symbols.reserve(WasmObj->getNumberOfSymbols());
|
||||
|
||||
for (const WasmImport &Import : WasmObj->imports()) {
|
||||
switch (Import.Kind) {
|
||||
case WASM_EXTERNAL_FUNCTION:
|
||||
++FunctionImports;
|
||||
++NumFunctionImports;
|
||||
break;
|
||||
case WASM_EXTERNAL_GLOBAL:
|
||||
++GlobalImports;
|
||||
++NumGlobalImports;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FunctionSymbols.resize(FunctionImports + WasmObj->functions().size());
|
||||
GlobalSymbols.resize(GlobalImports + WasmObj->globals().size());
|
||||
FunctionSymbols.resize(NumFunctionImports + WasmObj->functions().size());
|
||||
GlobalSymbols.resize(NumGlobalImports + WasmObj->globals().size());
|
||||
|
||||
for (const WasmSegment &S : WasmObj->dataSegments()) {
|
||||
InputSegment *Seg = make<InputSegment>(&S, this);
|
||||
InputSegment *Seg = make<InputSegment>(S, *this);
|
||||
copyRelocationsRange(Seg->Relocations, DataSection->Relocations,
|
||||
Seg->getInputSectionOffset(),
|
||||
Seg->getInputSectionOffset() + Seg->getSize());
|
||||
Seg->getInputSectionOffset(), Seg->getSize());
|
||||
Segments.emplace_back(Seg);
|
||||
}
|
||||
|
||||
ArrayRef<WasmFunction> Funcs = WasmObj->functions();
|
||||
ArrayRef<uint32_t> FuncTypes = WasmObj->functionTypes();
|
||||
ArrayRef<WasmSignature> Types = WasmObj->types();
|
||||
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);
|
||||
}
|
||||
|
||||
// Populate `FunctionSymbols` and `GlobalSymbols` based on the WasmSymbols
|
||||
// in the object
|
||||
for (const SymbolRef &Sym : WasmObj->symbols()) {
|
||||
|
@ -179,14 +190,16 @@ void ObjFile::initializeSymbols() {
|
|||
Symbol *S;
|
||||
switch (WasmSym.Type) {
|
||||
case WasmSymbol::SymbolType::FUNCTION_IMPORT:
|
||||
S = createUndefined(WasmSym, getFunctionSig(WasmSym));
|
||||
break;
|
||||
case WasmSymbol::SymbolType::GLOBAL_IMPORT:
|
||||
S = createUndefined(WasmSym);
|
||||
break;
|
||||
case WasmSymbol::SymbolType::GLOBAL_EXPORT:
|
||||
S = createDefined(WasmSym, getSegment(WasmSym));
|
||||
S = createDefined(WasmSym, getSegment(WasmSym), nullptr);
|
||||
break;
|
||||
case WasmSymbol::SymbolType::FUNCTION_EXPORT:
|
||||
S = createDefined(WasmSym);
|
||||
S = createDefined(WasmSym, nullptr, getFunction(WasmSym));
|
||||
break;
|
||||
case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
|
||||
// These are for debugging only, no need to create linker symbols for them
|
||||
|
@ -228,7 +241,7 @@ void ObjFile::initializeSymbols() {
|
|||
fatal(getName() + ": unsupported element segment offset");
|
||||
TableSymbols.reserve(Segment.Functions.size());
|
||||
for (uint64_t FunctionIndex : Segment.Functions)
|
||||
TableSymbols.push_back(getFunctionSymbol(FunctionIndex));
|
||||
TableSymbols.push_back(FunctionSymbols[FunctionIndex]);
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << "TableSymbols: " << TableSymbols.size() << "\n");
|
||||
|
@ -236,12 +249,14 @@ void ObjFile::initializeSymbols() {
|
|||
DEBUG(dbgs() << "Globals : " << GlobalSymbols.size() << "\n");
|
||||
}
|
||||
|
||||
Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {
|
||||
return Symtab->addUndefined(this, &Sym);
|
||||
Symbol *ObjFile::createUndefined(const WasmSymbol &Sym,
|
||||
const WasmSignature *Signature) {
|
||||
return Symtab->addUndefined(this, &Sym, Signature);
|
||||
}
|
||||
|
||||
Symbol *ObjFile::createDefined(const WasmSymbol &Sym,
|
||||
const InputSegment *Segment) {
|
||||
const InputSegment *Segment,
|
||||
InputFunction *Function) {
|
||||
Symbol *S;
|
||||
if (Sym.isLocal()) {
|
||||
S = make<Symbol>(Sym.Name, true);
|
||||
|
@ -252,10 +267,10 @@ Symbol *ObjFile::createDefined(const WasmSymbol &Sym,
|
|||
Kind = Symbol::Kind::DefinedGlobalKind;
|
||||
else
|
||||
llvm_unreachable("invalid local symbol type");
|
||||
S->update(Kind, this, &Sym, Segment);
|
||||
S->update(Kind, this, &Sym, Segment, Function);
|
||||
return S;
|
||||
}
|
||||
return Symtab->addDefined(this, &Sym, Segment);
|
||||
return Symtab->addDefined(this, &Sym, Segment, Function);
|
||||
}
|
||||
|
||||
void ArchiveFile::parse() {
|
||||
|
|
|
@ -26,11 +26,13 @@ using llvm::object::WasmObjectFile;
|
|||
using llvm::object::WasmSection;
|
||||
using llvm::object::WasmSymbol;
|
||||
using llvm::wasm::WasmImport;
|
||||
using llvm::wasm::WasmSignature;
|
||||
|
||||
namespace lld {
|
||||
namespace wasm {
|
||||
|
||||
class Symbol;
|
||||
class InputFunction;
|
||||
class InputSegment;
|
||||
|
||||
class InputFile {
|
||||
|
@ -95,34 +97,27 @@ public:
|
|||
uint32_t relocateTableIndex(uint32_t Original) const;
|
||||
uint32_t getRelocatedAddress(uint32_t Index) const;
|
||||
|
||||
// Returns true if the given function index is an imported function,
|
||||
// as opposed to the locally defined function.
|
||||
bool isImportedFunction(uint32_t Index) const;
|
||||
size_t getNumGlobalImports() const { return NumGlobalImports; }
|
||||
|
||||
size_t NumFunctionImports() const { return FunctionImports; }
|
||||
size_t NumGlobalImports() const { return GlobalImports; }
|
||||
|
||||
int32_t FunctionIndexOffset = 0;
|
||||
const WasmSection *CodeSection = nullptr;
|
||||
std::vector<OutputRelocation> CodeRelocations;
|
||||
int32_t CodeOffset = 0;
|
||||
const WasmSection *DataSection = nullptr;
|
||||
|
||||
std::vector<uint32_t> TypeMap;
|
||||
std::vector<InputSegment *> Segments;
|
||||
std::vector<InputFunction *> Functions;
|
||||
|
||||
ArrayRef<Symbol *> getSymbols() { return Symbols; }
|
||||
ArrayRef<Symbol *> getTableSymbols() { return TableSymbols; }
|
||||
|
||||
private:
|
||||
Symbol *createDefined(const WasmSymbol &Sym,
|
||||
const InputSegment *Segment = nullptr);
|
||||
Symbol *createUndefined(const WasmSymbol &Sym);
|
||||
const InputSegment *Segment = nullptr,
|
||||
InputFunction *Function = nullptr);
|
||||
Symbol *createUndefined(const WasmSymbol &Sym,
|
||||
const WasmSignature *Signature = nullptr);
|
||||
void initializeSymbols();
|
||||
InputSegment *getSegment(const WasmSymbol &WasmSym);
|
||||
Symbol *getFunctionSymbol(uint32_t FunctionIndex) const;
|
||||
Symbol *getTableSymbol(uint32_t TableIndex) const;
|
||||
Symbol *getGlobalSymbol(uint32_t GlobalIndex) const;
|
||||
InputSegment *getSegment(const WasmSymbol &WasmSym) const;
|
||||
const WasmSignature *getFunctionSig(const WasmSymbol &Sym) const;
|
||||
InputFunction *getFunction(const WasmSymbol &Sym) const;
|
||||
|
||||
// List of all symbols referenced or defined by this file.
|
||||
std::vector<Symbol *> Symbols;
|
||||
|
@ -136,8 +131,9 @@ private:
|
|||
// List of all indirect symbols indexed by table index space.
|
||||
std::vector<Symbol *> TableSymbols;
|
||||
|
||||
uint32_t GlobalImports = 0;
|
||||
uint32_t FunctionImports = 0;
|
||||
const WasmSection *DataSection = nullptr;
|
||||
uint32_t NumGlobalImports = 0;
|
||||
uint32_t NumFunctionImports = 0;
|
||||
std::unique_ptr<WasmObjectFile> WasmObj;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
//===- 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
|
|
@ -36,7 +36,7 @@ class OutputSegment;
|
|||
|
||||
class InputSegment {
|
||||
public:
|
||||
InputSegment(const WasmSegment *Seg, const ObjFile *F)
|
||||
InputSegment(const WasmSegment &Seg, const ObjFile &F)
|
||||
: Segment(Seg), File(F) {}
|
||||
|
||||
// Translate an offset in the input segment to an offset in the output
|
||||
|
@ -47,21 +47,21 @@ public:
|
|||
|
||||
uint32_t getOutputSegmentOffset() const { return OutputSegmentOffset; }
|
||||
|
||||
uint32_t getInputSectionOffset() const { return Segment->SectionOffset; }
|
||||
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 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; }
|
||||
StringRef getName() const { return Segment.Data.Name; }
|
||||
|
||||
const WasmSegment *Segment;
|
||||
const ObjFile *File;
|
||||
const WasmSegment &Segment;
|
||||
const ObjFile &File;
|
||||
std::vector<WasmRelocation> Relocations;
|
||||
std::vector<OutputRelocation> OutRelocations;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "Config.h"
|
||||
#include "InputFiles.h"
|
||||
#include "InputFunction.h"
|
||||
#include "OutputSegment.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
|
@ -150,6 +151,7 @@ static void calcRelocations(const ObjFile &File,
|
|||
for (const WasmRelocation &Reloc : Relocs) {
|
||||
OutputRelocation NewReloc;
|
||||
NewReloc.Reloc = Reloc;
|
||||
assert(Reloc.Offset + OutputOffset > 0);
|
||||
NewReloc.Reloc.Offset += OutputOffset;
|
||||
DEBUG(dbgs() << "reloc: type=" << Reloc.Type << " index=" << Reloc.Index
|
||||
<< " offset=" << Reloc.Offset
|
||||
|
@ -191,27 +193,20 @@ void OutputSection::createHeader(size_t BodySize) {
|
|||
" total=" + Twine(getSize()));
|
||||
}
|
||||
|
||||
CodeSection::CodeSection(uint32_t NumFunctions, ArrayRef<ObjFile *> Objs)
|
||||
: OutputSection(WASM_SEC_CODE), InputObjects(Objs) {
|
||||
CodeSection::CodeSection(ArrayRef<InputFunction *> Functions)
|
||||
: OutputSection(WASM_SEC_CODE), Functions(Functions) {
|
||||
assert(Functions.size() > 0);
|
||||
|
||||
raw_string_ostream OS(CodeSectionHeader);
|
||||
writeUleb128(OS, NumFunctions, "function count");
|
||||
writeUleb128(OS, Functions.size(), "function count");
|
||||
OS.flush();
|
||||
BodySize = CodeSectionHeader.size();
|
||||
|
||||
for (ObjFile *File : InputObjects) {
|
||||
if (!File->CodeSection)
|
||||
continue;
|
||||
|
||||
File->CodeOffset = BodySize;
|
||||
ArrayRef<uint8_t> Content = File->CodeSection->Content;
|
||||
unsigned HeaderSize = 0;
|
||||
decodeULEB128(Content.data(), &HeaderSize);
|
||||
|
||||
calcRelocations(*File, File->CodeSection->Relocations,
|
||||
File->CodeRelocations, BodySize - HeaderSize);
|
||||
|
||||
size_t PayloadSize = Content.size() - HeaderSize;
|
||||
BodySize += PayloadSize;
|
||||
for (InputFunction *Func : Functions) {
|
||||
Func->OutputOffset = BodySize;
|
||||
calcRelocations(Func->File, Func->Relocations, Func->OutRelocations,
|
||||
Func->OutputOffset - Func->Function.CodeSectionOffset);
|
||||
BodySize += Func->Function.Size;
|
||||
}
|
||||
|
||||
createHeader(BodySize);
|
||||
|
@ -220,6 +215,8 @@ CodeSection::CodeSection(uint32_t NumFunctions, ArrayRef<ObjFile *> Objs)
|
|||
void CodeSection::writeTo(uint8_t *Buf) {
|
||||
log("writing " + toString(*this));
|
||||
log(" size=" + Twine(getSize()));
|
||||
log(" headersize=" + Twine(Header.size()));
|
||||
log(" codeheadersize=" + Twine(CodeSectionHeader.size()));
|
||||
Buf += Offset;
|
||||
|
||||
// Write section header
|
||||
|
@ -233,35 +230,25 @@ void CodeSection::writeTo(uint8_t *Buf) {
|
|||
Buf += CodeSectionHeader.size();
|
||||
|
||||
// Write code section bodies
|
||||
parallelForEach(InputObjects, [ContentsStart](ObjFile *File) {
|
||||
if (!File->CodeSection)
|
||||
return;
|
||||
|
||||
ArrayRef<uint8_t> Content(File->CodeSection->Content);
|
||||
|
||||
// Payload doesn't include the initial header (function count)
|
||||
unsigned HeaderSize = 0;
|
||||
decodeULEB128(Content.data(), &HeaderSize);
|
||||
|
||||
size_t PayloadSize = Content.size() - HeaderSize;
|
||||
memcpy(ContentsStart + File->CodeOffset, Content.data() + HeaderSize,
|
||||
PayloadSize);
|
||||
|
||||
log("applying relocations for: " + File->getName());
|
||||
applyRelocations(ContentsStart, File->CodeRelocations);
|
||||
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);
|
||||
applyRelocations(ContentsStart, Func->OutRelocations);
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t CodeSection::numRelocations() const {
|
||||
uint32_t Count = 0;
|
||||
for (ObjFile *File : InputObjects)
|
||||
Count += File->CodeRelocations.size();
|
||||
for (const InputFunction *Func : Functions)
|
||||
Count += Func->OutRelocations.size();
|
||||
return Count;
|
||||
}
|
||||
|
||||
void CodeSection::writeRelocations(raw_ostream &OS) const {
|
||||
for (ObjFile *File : InputObjects)
|
||||
for (const OutputRelocation &Reloc : File->CodeRelocations)
|
||||
for (const InputFunction *Func : Functions)
|
||||
for (const OutputRelocation &Reloc : Func->OutRelocations)
|
||||
writeReloc(OS, Reloc);
|
||||
}
|
||||
|
||||
|
@ -289,7 +276,7 @@ DataSection::DataSection(ArrayRef<OutputSegment *> Segments)
|
|||
uint32_t OutputOffset = Segment->getSectionOffset() +
|
||||
Segment->Header.size() +
|
||||
InputSeg->getOutputSegmentOffset();
|
||||
calcRelocations(*InputSeg->File, InputSeg->Relocations,
|
||||
calcRelocations(InputSeg->File, InputSeg->Relocations,
|
||||
InputSeg->OutRelocations, OutputOffset - InputOffset);
|
||||
}
|
||||
BodySize += Segment->Size;
|
||||
|
@ -319,7 +306,7 @@ void DataSection::writeTo(uint8_t *Buf) {
|
|||
|
||||
// Write segment data payload
|
||||
for (const InputSegment *Input : Segment->InputSegments) {
|
||||
ArrayRef<uint8_t> Content(Input->Segment->Data.Content);
|
||||
ArrayRef<uint8_t> Content(Input->Segment.Data.Content);
|
||||
memcpy(SegStart + Segment->Header.size() +
|
||||
Input->getOutputSegmentOffset(),
|
||||
Content.data(), Content.size());
|
||||
|
|
|
@ -28,7 +28,7 @@ std::string toString(const wasm::OutputSection &Section);
|
|||
namespace wasm {
|
||||
|
||||
class OutputSegment;
|
||||
class ObjFile;
|
||||
class InputFunction;
|
||||
|
||||
class OutputSection {
|
||||
public:
|
||||
|
@ -104,14 +104,14 @@ public:
|
|||
|
||||
class CodeSection : public OutputSection {
|
||||
public:
|
||||
explicit CodeSection(uint32_t NumFunctions, ArrayRef<ObjFile *> Objs);
|
||||
explicit CodeSection(ArrayRef<InputFunction *> Functions);
|
||||
size_t getSize() const override { return Header.size() + BodySize; }
|
||||
void writeTo(uint8_t *Buf) override;
|
||||
uint32_t numRelocations() const override;
|
||||
void writeRelocations(raw_ostream &OS) const override;
|
||||
|
||||
protected:
|
||||
ArrayRef<ObjFile *> InputObjects;
|
||||
ArrayRef<InputFunction *> Functions;
|
||||
std::string CodeSectionHeader;
|
||||
size_t BodySize = 0;
|
||||
};
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "SymbolTable.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "InputFunction.h"
|
||||
#include "WriterUtils.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "lld/Common/Memory.h"
|
||||
|
@ -76,16 +77,6 @@ void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) {
|
|||
toString(NewFile));
|
||||
}
|
||||
|
||||
// Get the signature for a given function symbol, either by looking
|
||||
// it up in function sections (for defined functions), of the imports section
|
||||
// (for imported functions).
|
||||
static const WasmSignature *getFunctionSig(const ObjFile &Obj,
|
||||
const WasmSymbol &Sym) {
|
||||
DEBUG(dbgs() << "getFunctionSig: " << Sym.Name << "\n");
|
||||
const WasmObjectFile *WasmObj = Obj.getWasmObj();
|
||||
return &WasmObj->types()[Sym.FunctionType];
|
||||
}
|
||||
|
||||
// Check the type of new symbol matches that of the symbol is replacing.
|
||||
// For functions this can also involve verifying that the signatures match.
|
||||
static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
|
||||
|
@ -140,32 +131,30 @@ Symbol *SymbolTable::addDefinedGlobal(StringRef Name) {
|
|||
}
|
||||
|
||||
Symbol *SymbolTable::addDefined(InputFile *F, const WasmSymbol *Sym,
|
||||
const InputSegment *Segment) {
|
||||
const InputSegment *Segment,
|
||||
InputFunction *Function) {
|
||||
DEBUG(dbgs() << "addDefined: " << Sym->Name << "\n");
|
||||
Symbol *S;
|
||||
bool WasInserted;
|
||||
Symbol::Kind Kind = Symbol::DefinedFunctionKind;
|
||||
const WasmSignature *NewSig = nullptr;
|
||||
if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_EXPORT)
|
||||
Kind = Symbol::DefinedGlobalKind;
|
||||
else
|
||||
NewSig = getFunctionSig(*cast<ObjFile>(F), *Sym);
|
||||
|
||||
std::tie(S, WasInserted) = insert(Sym->Name);
|
||||
if (WasInserted) {
|
||||
S->update(Kind, F, Sym, Segment, NewSig);
|
||||
S->update(Kind, F, Sym, Segment, Function);
|
||||
} else if (S->isLazy()) {
|
||||
// The existing symbol is lazy. Replace it without checking types since
|
||||
// lazy symbols don't have any type information.
|
||||
DEBUG(dbgs() << "replacing existing lazy symbol: " << Sym->Name << "\n");
|
||||
S->update(Kind, F, Sym, Segment, NewSig);
|
||||
S->update(Kind, F, Sym, Segment, Function);
|
||||
} else if (!S->isDefined()) {
|
||||
// The existing symbol table entry is undefined. The new symbol replaces
|
||||
// it, after checking the type matches
|
||||
DEBUG(dbgs() << "resolving existing undefined symbol: " << Sym->Name
|
||||
<< "\n");
|
||||
checkSymbolTypes(*S, *F, *Sym, NewSig);
|
||||
S->update(Kind, F, Sym, Segment, NewSig);
|
||||
checkSymbolTypes(*S, *F, *Sym, Function ? &Function->Signature : nullptr);
|
||||
S->update(Kind, F, Sym, Segment, Function);
|
||||
} else if (Sym->isWeak()) {
|
||||
// the new symbol is weak we can ignore it
|
||||
DEBUG(dbgs() << "existing symbol takes precedence\n");
|
||||
|
@ -173,8 +162,8 @@ Symbol *SymbolTable::addDefined(InputFile *F, const WasmSymbol *Sym,
|
|||
// the new symbol is not weak and the existing symbol is, so we replace
|
||||
// it
|
||||
DEBUG(dbgs() << "replacing existing weak symbol\n");
|
||||
checkSymbolTypes(*S, *F, *Sym, NewSig);
|
||||
S->update(Kind, F, Sym, Segment, NewSig);
|
||||
checkSymbolTypes(*S, *F, *Sym, Function ? &Function->Signature : nullptr);
|
||||
S->update(Kind, F, Sym, Segment, Function);
|
||||
} else {
|
||||
// neither symbol is week. They conflict.
|
||||
reportDuplicate(S, F);
|
||||
|
@ -188,33 +177,34 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef Name,
|
|||
bool WasInserted;
|
||||
std::tie(S, WasInserted) = insert(Name);
|
||||
if (WasInserted) {
|
||||
S->update(Symbol::UndefinedFunctionKind, nullptr, nullptr, nullptr, Type);
|
||||
S->update(Symbol::UndefinedFunctionKind);
|
||||
S->setFunctionType(Type);
|
||||
} else if (!S->isFunction()) {
|
||||
error("symbol type mismatch: " + Name);
|
||||
}
|
||||
return S;
|
||||
}
|
||||
|
||||
Symbol *SymbolTable::addUndefined(InputFile *F, const WasmSymbol *Sym) {
|
||||
Symbol *SymbolTable::addUndefined(InputFile *F, const WasmSymbol *Sym,
|
||||
const WasmSignature *Type) {
|
||||
DEBUG(dbgs() << "addUndefined: " << Sym->Name << "\n");
|
||||
Symbol *S;
|
||||
bool WasInserted;
|
||||
Symbol::Kind Kind = Symbol::UndefinedFunctionKind;
|
||||
const WasmSignature *NewSig = nullptr;
|
||||
if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_IMPORT)
|
||||
Kind = Symbol::UndefinedGlobalKind;
|
||||
else
|
||||
NewSig = getFunctionSig(*cast<ObjFile>(F), *Sym);
|
||||
std::tie(S, WasInserted) = insert(Sym->Name);
|
||||
if (WasInserted) {
|
||||
S->update(Kind, F, Sym, nullptr, NewSig);
|
||||
S->update(Kind, F, Sym);
|
||||
if (Type)
|
||||
S->setFunctionType(Type);
|
||||
} else if (S->isLazy()) {
|
||||
DEBUG(dbgs() << "resolved by existing lazy\n");
|
||||
auto *AF = cast<ArchiveFile>(S->getFile());
|
||||
AF->addMember(&S->getArchiveSymbol());
|
||||
} else if (S->isDefined()) {
|
||||
DEBUG(dbgs() << "resolved by existing\n");
|
||||
checkSymbolTypes(*S, *F, *Sym, NewSig);
|
||||
checkSymbolTypes(*S, *F, *Sym, Type);
|
||||
}
|
||||
return S;
|
||||
}
|
||||
|
|
|
@ -50,8 +50,10 @@ public:
|
|||
Symbol *find(StringRef Name);
|
||||
|
||||
Symbol *addDefined(InputFile *F, const WasmSymbol *Sym,
|
||||
const InputSegment *Segment = nullptr);
|
||||
Symbol *addUndefined(InputFile *F, const WasmSymbol *Sym);
|
||||
const InputSegment *Segment = nullptr,
|
||||
InputFunction *Function = nullptr);
|
||||
Symbol *addUndefined(InputFile *F, const WasmSymbol *Sym,
|
||||
const WasmSignature *Signature = nullptr);
|
||||
Symbol *addUndefinedFunction(StringRef Name, const WasmSignature *Type);
|
||||
Symbol *addDefinedGlobal(StringRef Name);
|
||||
void addLazy(ArchiveFile *F, const Archive::Symbol *Sym);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "Config.h"
|
||||
#include "InputFiles.h"
|
||||
#include "InputFunction.h"
|
||||
#include "InputSegment.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "lld/Common/Strings.h"
|
||||
|
@ -21,21 +22,20 @@ using namespace llvm;
|
|||
using namespace lld;
|
||||
using namespace lld::wasm;
|
||||
|
||||
uint32_t Symbol::getGlobalIndex() const {
|
||||
assert(!Sym->isFunction());
|
||||
return Sym->ElementIndex;
|
||||
}
|
||||
|
||||
uint32_t Symbol::getFunctionIndex() const {
|
||||
assert(Sym->isFunction());
|
||||
return Sym->ElementIndex;
|
||||
}
|
||||
|
||||
const WasmSignature &Symbol::getFunctionType() const {
|
||||
if (Function != nullptr)
|
||||
return Function->Signature;
|
||||
|
||||
assert(FunctionType != nullptr);
|
||||
return *FunctionType;
|
||||
}
|
||||
|
||||
void Symbol::setFunctionType(const WasmSignature *Type) {
|
||||
assert(FunctionType == nullptr);
|
||||
assert(Function == nullptr);
|
||||
FunctionType = Type;
|
||||
}
|
||||
|
||||
uint32_t Symbol::getVirtualAddress() const {
|
||||
assert(isGlobal());
|
||||
DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
|
||||
|
@ -44,15 +44,28 @@ uint32_t Symbol::getVirtualAddress() const {
|
|||
if (VirtualAddress.hasValue())
|
||||
return VirtualAddress.getValue();
|
||||
|
||||
assert(Sym != nullptr);
|
||||
ObjFile *Obj = cast<ObjFile>(File);
|
||||
assert(Sym != nullptr);
|
||||
const WasmGlobal &Global =
|
||||
Obj->getWasmObj()->globals()[getGlobalIndex() - Obj->NumGlobalImports()];
|
||||
Obj->getWasmObj()
|
||||
->globals()[Sym->ElementIndex - Obj->getNumGlobalImports()];
|
||||
assert(Global.Type == llvm::wasm::WASM_TYPE_I32);
|
||||
assert(Segment);
|
||||
return Segment->translateVA(Global.InitExpr.Value.Int32);
|
||||
}
|
||||
|
||||
bool Symbol::hasOutputIndex() const {
|
||||
if (Function)
|
||||
return Function->hasOutputIndex();
|
||||
return OutputIndex.hasValue();
|
||||
}
|
||||
|
||||
uint32_t Symbol::getOutputIndex() const {
|
||||
if (Function)
|
||||
return Function->getOutputIndex();
|
||||
return OutputIndex.getValue();
|
||||
}
|
||||
|
||||
void Symbol::setVirtualAddress(uint32_t Value) {
|
||||
DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n");
|
||||
assert(!VirtualAddress.hasValue());
|
||||
|
@ -61,6 +74,7 @@ void Symbol::setVirtualAddress(uint32_t Value) {
|
|||
|
||||
void Symbol::setOutputIndex(uint32_t Index) {
|
||||
DEBUG(dbgs() << "setOutputIndex " << Name << " -> " << Index << "\n");
|
||||
assert(!Function);
|
||||
assert(!OutputIndex.hasValue());
|
||||
OutputIndex = Index;
|
||||
}
|
||||
|
@ -72,12 +86,12 @@ void Symbol::setTableIndex(uint32_t Index) {
|
|||
}
|
||||
|
||||
void Symbol::update(Kind K, InputFile *F, const WasmSymbol *WasmSym,
|
||||
const InputSegment *Seg, const WasmSignature *Sig) {
|
||||
const InputSegment *Seg, const InputFunction *Func) {
|
||||
SymbolKind = K;
|
||||
File = F;
|
||||
Sym = WasmSym;
|
||||
Segment = Seg;
|
||||
FunctionType = Sig;
|
||||
Function = Func;
|
||||
}
|
||||
|
||||
bool Symbol::isWeak() const { return Sym && Sym->isWeak(); }
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace wasm {
|
|||
|
||||
class InputFile;
|
||||
class InputSegment;
|
||||
class InputFunction;
|
||||
|
||||
class Symbol {
|
||||
public:
|
||||
|
@ -66,16 +67,14 @@ public:
|
|||
// Returns the file from which this symbol was created.
|
||||
InputFile *getFile() const { return File; }
|
||||
|
||||
uint32_t getGlobalIndex() const;
|
||||
uint32_t getFunctionIndex() const;
|
||||
|
||||
bool hasFunctionType() const { return FunctionType != nullptr; }
|
||||
const WasmSignature &getFunctionType() const;
|
||||
void setFunctionType(const WasmSignature *Type);
|
||||
|
||||
uint32_t getOutputIndex() const { return OutputIndex.getValue(); }
|
||||
uint32_t getOutputIndex() const;
|
||||
|
||||
// Returns true if an output index has been set for this symbol
|
||||
bool hasOutputIndex() const { return OutputIndex.hasValue(); }
|
||||
bool hasOutputIndex() const;
|
||||
|
||||
// Set the output index of the symbol (in the function or global index
|
||||
// space of the output object.
|
||||
|
@ -97,7 +96,7 @@ public:
|
|||
|
||||
void update(Kind K, InputFile *F = nullptr, const WasmSymbol *Sym = nullptr,
|
||||
const InputSegment *Segment = nullptr,
|
||||
const WasmSignature *Sig = nullptr);
|
||||
const InputFunction *Function = nullptr);
|
||||
|
||||
void setArchiveSymbol(const Archive::Symbol &Sym) { ArchiveSymbol = Sym; }
|
||||
const Archive::Symbol &getArchiveSymbol() { return ArchiveSymbol; }
|
||||
|
@ -116,10 +115,11 @@ protected:
|
|||
InputFile *File = nullptr;
|
||||
const WasmSymbol *Sym = nullptr;
|
||||
const InputSegment *Segment = nullptr;
|
||||
const InputFunction *Function = nullptr;
|
||||
llvm::Optional<uint32_t> OutputIndex;
|
||||
llvm::Optional<uint32_t> TableIndex;
|
||||
llvm::Optional<uint32_t> VirtualAddress;
|
||||
const WasmSignature *FunctionType;
|
||||
const WasmSignature *FunctionType = nullptr;
|
||||
};
|
||||
|
||||
} // namespace wasm
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "Writer.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "InputFunction.h"
|
||||
#include "OutputSections.h"
|
||||
#include "OutputSegment.h"
|
||||
#include "SymbolTable.h"
|
||||
|
@ -68,7 +69,7 @@ private:
|
|||
void openFile();
|
||||
|
||||
uint32_t getTypeIndex(const WasmSignature &Sig);
|
||||
void assignSymbolIndexes();
|
||||
void assignIndexes();
|
||||
void calculateImports();
|
||||
void calculateOffsets();
|
||||
void calculateTypes();
|
||||
|
@ -102,15 +103,15 @@ private:
|
|||
|
||||
uint64_t FileSize = 0;
|
||||
uint32_t DataSize = 0;
|
||||
uint32_t NumFunctions = 0;
|
||||
uint32_t NumMemoryPages = 0;
|
||||
uint32_t InitialTableOffset = 0;
|
||||
|
||||
std::vector<const WasmSignature *> Types;
|
||||
DenseMap<WasmSignature, int32_t, WasmSignatureDenseMapInfo> TypeIndices;
|
||||
std::vector<const Symbol *> FunctionImports;
|
||||
std::vector<const Symbol *> GlobalImports;
|
||||
std::vector<const Symbol *> ImportedFunctions;
|
||||
std::vector<const Symbol *> ImportedGlobals;
|
||||
std::vector<const Symbol *> DefinedGlobals;
|
||||
std::vector<InputFunction *> DefinedFunctions;
|
||||
std::vector<const Symbol *> IndirectFunctions;
|
||||
|
||||
// Elements that are used to construct the final output
|
||||
|
@ -136,7 +137,7 @@ static void debugPrint(const char *fmt, ...) {
|
|||
}
|
||||
|
||||
void Writer::createImportSection() {
|
||||
uint32_t NumImports = FunctionImports.size() + GlobalImports.size();
|
||||
uint32_t NumImports = ImportedFunctions.size() + ImportedGlobals.size();
|
||||
if (Config->ImportMemory)
|
||||
++NumImports;
|
||||
|
||||
|
@ -148,7 +149,7 @@ void Writer::createImportSection() {
|
|||
|
||||
writeUleb128(OS, NumImports, "import count");
|
||||
|
||||
for (const Symbol *Sym : FunctionImports) {
|
||||
for (const Symbol *Sym : ImportedFunctions) {
|
||||
WasmImport Import;
|
||||
Import.Module = "env";
|
||||
Import.Field = Sym->getName();
|
||||
|
@ -168,7 +169,7 @@ void Writer::createImportSection() {
|
|||
writeImport(OS, Import);
|
||||
}
|
||||
|
||||
for (const Symbol *Sym : GlobalImports) {
|
||||
for (const Symbol *Sym : ImportedGlobals) {
|
||||
WasmImport Import;
|
||||
Import.Module = "env";
|
||||
Import.Field = Sym->getName();
|
||||
|
@ -188,16 +189,15 @@ void Writer::createTypeSection() {
|
|||
}
|
||||
|
||||
void Writer::createFunctionSection() {
|
||||
if (!NumFunctions)
|
||||
if (DefinedFunctions.empty())
|
||||
return;
|
||||
|
||||
SyntheticSection *Section = createSyntheticSection(WASM_SEC_FUNCTION);
|
||||
raw_ostream &OS = Section->getStream();
|
||||
|
||||
writeUleb128(OS, NumFunctions, "function count");
|
||||
for (ObjFile *File : Symtab->ObjectFiles)
|
||||
for (uint32_t Sig : File->getWasmObj()->functionTypes())
|
||||
writeUleb128(OS, File->relocateTypeIndex(Sig), "sig index");
|
||||
writeUleb128(OS, DefinedFunctions.size(), "function count");
|
||||
for (const InputFunction *Func : DefinedFunctions)
|
||||
writeUleb128(OS, TypeIndices.lookup(Func->Signature), "sig index");
|
||||
}
|
||||
|
||||
void Writer::createMemorySection() {
|
||||
|
@ -337,12 +337,12 @@ void Writer::createElemSection() {
|
|||
}
|
||||
|
||||
void Writer::createCodeSection() {
|
||||
if (!NumFunctions)
|
||||
if (DefinedFunctions.empty())
|
||||
return;
|
||||
|
||||
log("createCodeSection");
|
||||
|
||||
auto Section = make<CodeSection>(NumFunctions, Symtab->ObjectFiles);
|
||||
auto Section = make<CodeSection>(DefinedFunctions);
|
||||
OutputSections.push_back(Section);
|
||||
}
|
||||
|
||||
|
@ -555,32 +555,17 @@ void Writer::createSections() {
|
|||
}
|
||||
}
|
||||
|
||||
void Writer::calculateOffsets() {
|
||||
for (ObjFile *File : Symtab->ObjectFiles) {
|
||||
const WasmObjectFile *WasmFile = File->getWasmObj();
|
||||
|
||||
// Function Index
|
||||
File->FunctionIndexOffset =
|
||||
FunctionImports.size() - File->NumFunctionImports() + NumFunctions;
|
||||
NumFunctions += WasmFile->functions().size();
|
||||
|
||||
// Memory
|
||||
if (WasmFile->memories().size() > 1)
|
||||
fatal(File->getName() + ": contains more than one memory");
|
||||
}
|
||||
}
|
||||
|
||||
void Writer::calculateImports() {
|
||||
for (Symbol *Sym : Symtab->getSymbols()) {
|
||||
if (!Sym->isUndefined() || Sym->isWeak())
|
||||
continue;
|
||||
|
||||
if (Sym->isFunction()) {
|
||||
Sym->setOutputIndex(FunctionImports.size());
|
||||
FunctionImports.push_back(Sym);
|
||||
Sym->setOutputIndex(ImportedFunctions.size());
|
||||
ImportedFunctions.push_back(Sym);
|
||||
} else {
|
||||
Sym->setOutputIndex(GlobalImports.size());
|
||||
GlobalImports.push_back(Sym);
|
||||
Sym->setOutputIndex(ImportedGlobals.size());
|
||||
ImportedGlobals.push_back(Sym);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -600,8 +585,9 @@ void Writer::calculateTypes() {
|
|||
}
|
||||
}
|
||||
|
||||
void Writer::assignSymbolIndexes() {
|
||||
uint32_t GlobalIndex = GlobalImports.size();
|
||||
void Writer::assignIndexes() {
|
||||
uint32_t GlobalIndex = ImportedGlobals.size();
|
||||
uint32_t FunctionIndex = ImportedFunctions.size();
|
||||
|
||||
if (Config->StackPointerSymbol) {
|
||||
DefinedGlobals.emplace_back(Config->StackPointerSymbol);
|
||||
|
@ -614,17 +600,15 @@ void Writer::assignSymbolIndexes() {
|
|||
uint32_t TableIndex = InitialTableOffset;
|
||||
|
||||
for (ObjFile *File : Symtab->ObjectFiles) {
|
||||
DEBUG(dbgs() << "assignSymbolIndexes: " << File->getName() << "\n");
|
||||
if (Config->EmitRelocs) {
|
||||
DEBUG(dbgs() << "Globals: " << File->getName() << "\n");
|
||||
for (Symbol *Sym : File->getSymbols()) {
|
||||
// Create wasm globals for data symbols defined in this file
|
||||
if (!Sym->isDefined() || File != Sym->getFile())
|
||||
continue;
|
||||
if (Sym->isFunction())
|
||||
continue;
|
||||
|
||||
for (Symbol *Sym : File->getSymbols()) {
|
||||
// Assign indexes for symbols defined with this file.
|
||||
if (!Sym->isDefined() || File != Sym->getFile())
|
||||
continue;
|
||||
if (Sym->isFunction()) {
|
||||
auto *Obj = cast<ObjFile>(Sym->getFile());
|
||||
Sym->setOutputIndex(Obj->FunctionIndexOffset +
|
||||
Sym->getFunctionIndex());
|
||||
} else if (Config->EmitRelocs) {
|
||||
DefinedGlobals.emplace_back(Sym);
|
||||
Sym->setOutputIndex(GlobalIndex++);
|
||||
}
|
||||
|
@ -632,6 +616,15 @@ void Writer::assignSymbolIndexes() {
|
|||
}
|
||||
|
||||
for (ObjFile *File : Symtab->ObjectFiles) {
|
||||
DEBUG(dbgs() << "Functions: " << File->getName() << "\n");
|
||||
for (InputFunction *Func : File->Functions) {
|
||||
DefinedFunctions.emplace_back(Func);
|
||||
Func->setOutputIndex(FunctionIndex++);
|
||||
}
|
||||
}
|
||||
|
||||
for (ObjFile *File : Symtab->ObjectFiles) {
|
||||
DEBUG(dbgs() << "Table Indexes: " << File->getName() << "\n");
|
||||
for (Symbol *Sym : File->getTableSymbols()) {
|
||||
if (Sym->hasTableIndex() || !Sym->hasOutputIndex())
|
||||
continue;
|
||||
|
@ -681,22 +674,20 @@ void Writer::run() {
|
|||
calculateTypes();
|
||||
log("-- calculateImports");
|
||||
calculateImports();
|
||||
log("-- calculateOffsets");
|
||||
calculateOffsets();
|
||||
log("-- assignIndexes");
|
||||
assignIndexes();
|
||||
|
||||
if (errorHandler().Verbose) {
|
||||
log("Defined Functions: " + Twine(NumFunctions));
|
||||
log("Defined Functions: " + Twine(DefinedFunctions.size()));
|
||||
log("Defined Globals : " + Twine(DefinedGlobals.size()));
|
||||
log("Function Imports : " + Twine(FunctionImports.size()));
|
||||
log("Global Imports : " + Twine(GlobalImports.size()));
|
||||
log("Function Imports : " + Twine(ImportedFunctions.size()));
|
||||
log("Global Imports : " + Twine(ImportedGlobals.size()));
|
||||
log("Total Imports : " +
|
||||
Twine(FunctionImports.size() + GlobalImports.size()));
|
||||
Twine(ImportedFunctions.size() + ImportedGlobals.size()));
|
||||
for (ObjFile *File : Symtab->ObjectFiles)
|
||||
File->dumpInfo();
|
||||
}
|
||||
|
||||
log("-- assignSymbolIndexes");
|
||||
assignSymbolIndexes();
|
||||
log("-- layoutMemory");
|
||||
layoutMemory();
|
||||
|
||||
|
|
Loading…
Reference in New Issue