summaryrefslogtreecommitdiff
path: root/wasm/InputFiles.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'wasm/InputFiles.cpp')
-rw-r--r--wasm/InputFiles.cpp462
1 files changed, 290 insertions, 172 deletions
diff --git a/wasm/InputFiles.cpp b/wasm/InputFiles.cpp
index 1a1a6812c48e..53a24c3cffd4 100644
--- a/wasm/InputFiles.cpp
+++ b/wasm/InputFiles.cpp
@@ -8,9 +8,9 @@
//===----------------------------------------------------------------------===//
#include "InputFiles.h"
-
#include "Config.h"
-#include "InputSegment.h"
+#include "InputChunks.h"
+#include "InputGlobal.h"
#include "SymbolTable.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
@@ -42,64 +42,126 @@ Optional<MemoryBufferRef> lld::wasm::readFile(StringRef Path) {
return MBRef;
}
-void ObjFile::dumpInfo() const {
- log("reloc info for: " + getName() + "\n" +
- " FunctionIndexOffset : " + Twine(FunctionIndexOffset) + "\n" +
- " NumFunctionImports : " + Twine(NumFunctionImports()) + "\n" +
- " NumGlobalImports : " + Twine(NumGlobalImports()) + "\n");
-}
+InputFile *lld::wasm::createObjectFile(MemoryBufferRef MB) {
+ file_magic Magic = identify_magic(MB.getBuffer());
+ if (Magic == file_magic::wasm_object)
+ return make<ObjFile>(MB);
-bool ObjFile::isImportedFunction(uint32_t Index) const {
- return Index < NumFunctionImports();
-}
+ if (Magic == file_magic::bitcode)
+ return make<BitcodeFile>(MB);
-Symbol *ObjFile::getFunctionSymbol(uint32_t Index) const {
- return FunctionSymbols[Index];
+ fatal("unknown file type: " + MB.getBufferIdentifier());
}
-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();
+void ObjFile::dumpInfo() const {
+ log("info for: " + getName() +
+ "\n Symbols : " + Twine(Symbols.size()) +
+ "\n Function Imports : " + Twine(WasmObj->getNumImportedFunctions()) +
+ "\n Global Imports : " + Twine(WasmObj->getNumImportedGlobals()));
}
-uint32_t ObjFile::relocateFunctionIndex(uint32_t Original) const {
- Symbol *Sym = getFunctionSymbol(Original);
- uint32_t Index = Sym->getOutputIndex();
- DEBUG(dbgs() << "relocateFunctionIndex: " << toString(*Sym) << ": "
- << Original << " -> " << Index << "\n");
- return Index;
+// Relocations contain either symbol or type indices. This function takes a
+// relocation and returns relocated index (i.e. translates from the input
+// sybmol/type space to the output symbol/type space).
+uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const {
+ if (Reloc.Type == R_WEBASSEMBLY_TYPE_INDEX_LEB) {
+ assert(TypeIsUsed[Reloc.Index]);
+ return TypeMap[Reloc.Index];
+ }
+ return Symbols[Reloc.Index]->getOutputSymbolIndex();
}
-uint32_t ObjFile::relocateTypeIndex(uint32_t Original) const {
- return TypeMap[Original];
+// Relocations can contain addend for combined sections. This function takes a
+// relocation and returns updated addend by offset in the output section.
+uint32_t ObjFile::calcNewAddend(const WasmRelocation &Reloc) const {
+ switch (Reloc.Type) {
+ case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+ return Reloc.Addend;
+ case R_WEBASSEMBLY_SECTION_OFFSET_I32:
+ return getSectionSymbol(Reloc.Index)->Section->OutputOffset + Reloc.Addend;
+ default:
+ llvm_unreachable("unexpected relocation type");
+ }
}
-uint32_t ObjFile::relocateTableIndex(uint32_t Original) const {
- Symbol *Sym = getTableSymbol(Original);
- uint32_t Index = Sym->getTableIndex();
- DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original
- << " -> " << Index << "\n");
- return Index;
+// Calculate the value we expect to find at the relocation location.
+// This is used as a sanity check before applying a relocation to a given
+// location. It is useful for catching bugs in the compiler and linker.
+uint32_t ObjFile::calcExpectedValue(const WasmRelocation &Reloc) const {
+ switch (Reloc.Type) {
+ case R_WEBASSEMBLY_TABLE_INDEX_I32:
+ case R_WEBASSEMBLY_TABLE_INDEX_SLEB: {
+ const WasmSymbol& Sym = WasmObj->syms()[Reloc.Index];
+ return TableEntries[Sym.Info.ElementIndex];
+ }
+ case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ case R_WEBASSEMBLY_MEMORY_ADDR_LEB: {
+ const WasmSymbol& Sym = WasmObj->syms()[Reloc.Index];
+ if (Sym.isUndefined())
+ return 0;
+ const WasmSegment& Segment = WasmObj->dataSegments()[Sym.Info.DataRef.Segment];
+ return Segment.Data.Offset.Value.Int32 + Sym.Info.DataRef.Offset +
+ Reloc.Addend;
+ }
+ case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+ if (auto *Sym = dyn_cast<DefinedFunction>(getFunctionSymbol(Reloc.Index))) {
+ return Sym->Function->getFunctionInputOffset() +
+ Sym->Function->getFunctionCodeOffset() + Reloc.Addend;
+ }
+ return 0;
+ case R_WEBASSEMBLY_SECTION_OFFSET_I32:
+ return Reloc.Addend;
+ case R_WEBASSEMBLY_TYPE_INDEX_LEB:
+ return Reloc.Index;
+ case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+ case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: {
+ const WasmSymbol& Sym = WasmObj->syms()[Reloc.Index];
+ return Sym.Info.ElementIndex;
+ }
+ default:
+ llvm_unreachable("unknown relocation type");
+ }
}
-uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const {
- Symbol *Sym = getGlobalSymbol(Original);
- uint32_t Index = Sym->getOutputIndex();
- DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original
- << " -> " << Index << "\n");
- return Index;
+// Translate from the relocation's index into the final linked output value.
+uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {
+ switch (Reloc.Type) {
+ case R_WEBASSEMBLY_TABLE_INDEX_I32:
+ case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+ return getFunctionSymbol(Reloc.Index)->getTableIndex();
+ case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ if (auto *Sym = dyn_cast<DefinedData>(getDataSymbol(Reloc.Index)))
+ if (Sym->isLive())
+ return Sym->getVirtualAddress() + Reloc.Addend;
+ return 0;
+ case R_WEBASSEMBLY_TYPE_INDEX_LEB:
+ return TypeMap[Reloc.Index];
+ case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+ return getFunctionSymbol(Reloc.Index)->getFunctionIndex();
+ case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+ return getGlobalSymbol(Reloc.Index)->getGlobalIndex();
+ case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+ if (auto *Sym = dyn_cast<DefinedFunction>(getFunctionSymbol(Reloc.Index))) {
+ return Sym->Function->OutputOffset +
+ Sym->Function->getFunctionCodeOffset() + Reloc.Addend;
+ }
+ return 0;
+ case R_WEBASSEMBLY_SECTION_OFFSET_I32:
+ return getSectionSymbol(Reloc.Index)->Section->OutputOffset + Reloc.Addend;
+ default:
+ llvm_unreachable("unknown relocation type");
+ }
}
void ObjFile::parse() {
// Parse a memory buffer as a wasm file.
- DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n");
+ LLVM_DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n");
std::unique_ptr<Binary> Bin = CHECK(createBinary(MB), toString(this));
auto *Obj = dyn_cast<WasmObjectFile>(Bin.get());
@@ -111,156 +173,175 @@ void ObjFile::parse() {
Bin.release();
WasmObj.reset(Obj);
+ // Build up a map of function indices to table indices for use when
+ // verifying the existing table index relocations
+ uint32_t TotalFunctions =
+ WasmObj->getNumImportedFunctions() + WasmObj->functions().size();
+ TableEntries.resize(TotalFunctions);
+ for (const WasmElemSegment &Seg : WasmObj->elements()) {
+ if (Seg.Offset.Opcode != WASM_OPCODE_I32_CONST)
+ fatal(toString(this) + ": invalid table elements");
+ uint32_t Offset = Seg.Offset.Value.Int32;
+ for (uint32_t Index = 0; Index < Seg.Functions.size(); Index++) {
+
+ uint32_t FunctionIndex = Seg.Functions[Index];
+ TableEntries[FunctionIndex] = Offset + Index;
+ }
+ }
+
// Find the code and data sections. Wasm objects can have at most one code
// and one data section.
+ uint32_t SectionIndex = 0;
for (const SectionRef &Sec : WasmObj->sections()) {
const WasmSection &Section = WasmObj->getWasmSection(Sec);
- if (Section.Type == WASM_SEC_CODE)
+ if (Section.Type == WASM_SEC_CODE) {
CodeSection = &Section;
- else if (Section.Type == WASM_SEC_DATA)
+ } else if (Section.Type == WASM_SEC_DATA) {
DataSection = &Section;
+ } else if (Section.Type == WASM_SEC_CUSTOM) {
+ CustomSections.emplace_back(make<InputSection>(Section, this));
+ CustomSections.back()->copyRelocations(Section);
+ CustomSectionsByIndex[SectionIndex] = CustomSections.back();
+ }
+ SectionIndex++;
}
- initializeSymbols();
-}
+ TypeMap.resize(getWasmObj()->types().size());
+ TypeIsUsed.resize(getWasmObj()->types().size(), false);
-// Return the InputSegment in which a given symbol is defined.
-InputSegment *ObjFile::getSegment(const WasmSymbol &WasmSym) {
- uint32_t Address = WasmObj->getWasmSymbolValue(WasmSym);
- for (InputSegment *Segment : Segments) {
- if (Address >= Segment->startVA() && Address < Segment->endVA()) {
- DEBUG(dbgs() << "Found symbol in segment: " << WasmSym.Name << " -> "
- << Segment->getName() << "\n");
+ ArrayRef<StringRef> Comdats = WasmObj->linkingData().Comdats;
+ UsedComdats.resize(Comdats.size());
+ for (unsigned I = 0; I < Comdats.size(); ++I)
+ UsedComdats[I] = Symtab->addComdat(Comdats[I]);
- return Segment;
- }
+ // Populate `Segments`.
+ for (const WasmSegment &S : WasmObj->dataSegments()) {
+ InputSegment *Seg = make<InputSegment>(S, this);
+ Seg->copyRelocations(*DataSection);
+ Segments.emplace_back(Seg);
+ }
+
+ // Populate `Functions`.
+ ArrayRef<WasmFunction> Funcs = WasmObj->functions();
+ ArrayRef<uint32_t> FuncTypes = WasmObj->functionTypes();
+ ArrayRef<WasmSignature> Types = WasmObj->types();
+ Functions.reserve(Funcs.size());
+
+ for (size_t I = 0, E = Funcs.size(); I != E; ++I) {
+ InputFunction *F =
+ make<InputFunction>(Types[FuncTypes[I]], &Funcs[I], this);
+ F->copyRelocations(*CodeSection);
+ Functions.emplace_back(F);
+ }
+
+ // Populate `Globals`.
+ for (const WasmGlobal &G : WasmObj->globals())
+ Globals.emplace_back(make<InputGlobal>(G, this));
+
+ // Populate `Symbols` based on the WasmSymbols in the object.
+ Symbols.reserve(WasmObj->getNumberOfSymbols());
+ for (const SymbolRef &Sym : WasmObj->symbols()) {
+ const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl());
+ if (Symbol *Sym = createDefined(WasmSym))
+ Symbols.push_back(Sym);
+ else
+ Symbols.push_back(createUndefined(WasmSym));
}
- error("symbol not found in any segment: " + WasmSym.Name);
- return nullptr;
}
-static void copyRelocationsRange(std::vector<WasmRelocation> &To,
- ArrayRef<WasmRelocation> From, size_t Start,
- size_t End) {
- for (const WasmRelocation &R : From)
- if (R.Offset >= Start && R.Offset < End)
- To.push_back(R);
+bool ObjFile::isExcludedByComdat(InputChunk *Chunk) const {
+ uint32_t C = Chunk->getComdat();
+ if (C == UINT32_MAX)
+ return false;
+ return !UsedComdats[C];
}
-void ObjFile::initializeSymbols() {
- Symbols.reserve(WasmObj->getNumberOfSymbols());
+FunctionSymbol *ObjFile::getFunctionSymbol(uint32_t Index) const {
+ return cast<FunctionSymbol>(Symbols[Index]);
+}
- for (const WasmImport &Import : WasmObj->imports()) {
- switch (Import.Kind) {
- case WASM_EXTERNAL_FUNCTION:
- ++FunctionImports;
- break;
- case WASM_EXTERNAL_GLOBAL:
- ++GlobalImports;
- break;
- }
- }
+GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t Index) const {
+ return cast<GlobalSymbol>(Symbols[Index]);
+}
- FunctionSymbols.resize(FunctionImports + WasmObj->functions().size());
- GlobalSymbols.resize(GlobalImports + WasmObj->globals().size());
+SectionSymbol *ObjFile::getSectionSymbol(uint32_t Index) const {
+ return cast<SectionSymbol>(Symbols[Index]);
+}
- for (const WasmSegment &S : WasmObj->dataSegments()) {
- InputSegment *Seg = make<InputSegment>(&S, this);
- copyRelocationsRange(Seg->Relocations, DataSection->Relocations,
- Seg->getInputSectionOffset(),
- Seg->getInputSectionOffset() + Seg->getSize());
- Segments.emplace_back(Seg);
- }
+DataSymbol *ObjFile::getDataSymbol(uint32_t Index) const {
+ return cast<DataSymbol>(Symbols[Index]);
+}
- // Populate `FunctionSymbols` and `GlobalSymbols` based on the WasmSymbols
- // in the object
- for (const SymbolRef &Sym : WasmObj->symbols()) {
- const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl());
- Symbol *S;
- switch (WasmSym.Type) {
- case WasmSymbol::SymbolType::FUNCTION_IMPORT:
- case WasmSymbol::SymbolType::GLOBAL_IMPORT:
- S = createUndefined(WasmSym);
- break;
- case WasmSymbol::SymbolType::GLOBAL_EXPORT:
- S = createDefined(WasmSym, getSegment(WasmSym));
- break;
- case WasmSymbol::SymbolType::FUNCTION_EXPORT:
- S = createDefined(WasmSym);
- break;
- case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
- // These are for debugging only, no need to create linker symbols for them
- continue;
- }
+Symbol *ObjFile::createDefined(const WasmSymbol &Sym) {
+ if (!Sym.isDefined())
+ return nullptr;
- Symbols.push_back(S);
- if (WasmSym.isFunction()) {
- DEBUG(dbgs() << "Function: " << WasmSym.ElementIndex << " -> "
- << toString(*S) << "\n");
- FunctionSymbols[WasmSym.ElementIndex] = S;
- if (WasmSym.HasAltIndex)
- FunctionSymbols[WasmSym.AltIndex] = S;
- } else {
- DEBUG(dbgs() << "Global: " << WasmSym.ElementIndex << " -> "
- << toString(*S) << "\n");
- GlobalSymbols[WasmSym.ElementIndex] = S;
- if (WasmSym.HasAltIndex)
- GlobalSymbols[WasmSym.AltIndex] = S;
+ StringRef Name = Sym.Info.Name;
+ uint32_t Flags = Sym.Info.Flags;
+
+ switch (Sym.Info.Kind) {
+ case WASM_SYMBOL_TYPE_FUNCTION: {
+ InputFunction *Func =
+ Functions[Sym.Info.ElementIndex - WasmObj->getNumImportedFunctions()];
+ if (isExcludedByComdat(Func)) {
+ Func->Live = false;
+ return nullptr;
}
- }
- DEBUG(for (size_t I = 0; I < FunctionSymbols.size(); ++I)
- assert(FunctionSymbols[I] != nullptr);
- for (size_t I = 0; I < GlobalSymbols.size(); ++I)
- assert(GlobalSymbols[I] != nullptr););
-
- // Populate `TableSymbols` with all symbols that are called indirectly
- uint32_t SegmentCount = WasmObj->elements().size();
- if (SegmentCount) {
- if (SegmentCount > 1)
- fatal(getName() + ": contains more than one element segment");
- const WasmElemSegment &Segment = WasmObj->elements()[0];
- if (Segment.Offset.Opcode != WASM_OPCODE_I32_CONST)
- fatal(getName() + ": unsupported element segment");
- if (Segment.TableIndex != 0)
- fatal(getName() + ": unsupported table index in elem segment");
- if (Segment.Offset.Value.Int32 != 0)
- fatal(getName() + ": unsupported element segment offset");
- TableSymbols.reserve(Segment.Functions.size());
- for (uint64_t FunctionIndex : Segment.Functions)
- TableSymbols.push_back(getFunctionSymbol(FunctionIndex));
+ if (Sym.isBindingLocal())
+ return make<DefinedFunction>(Name, Flags, this, Func);
+ return Symtab->addDefinedFunction(Name, Flags, this, Func);
}
+ case WASM_SYMBOL_TYPE_DATA: {
+ InputSegment *Seg = Segments[Sym.Info.DataRef.Segment];
+ if (isExcludedByComdat(Seg)) {
+ Seg->Live = false;
+ return nullptr;
+ }
- DEBUG(dbgs() << "TableSymbols: " << TableSymbols.size() << "\n");
- DEBUG(dbgs() << "Functions : " << FunctionSymbols.size() << "\n");
- DEBUG(dbgs() << "Globals : " << GlobalSymbols.size() << "\n");
-}
+ uint32_t Offset = Sym.Info.DataRef.Offset;
+ uint32_t Size = Sym.Info.DataRef.Size;
-Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {
- return Symtab->addUndefined(this, &Sym);
+ if (Sym.isBindingLocal())
+ return make<DefinedData>(Name, Flags, this, Seg, Offset, Size);
+ return Symtab->addDefinedData(Name, Flags, this, Seg, Offset, Size);
+ }
+ case WASM_SYMBOL_TYPE_GLOBAL: {
+ InputGlobal *Global =
+ Globals[Sym.Info.ElementIndex - WasmObj->getNumImportedGlobals()];
+ if (Sym.isBindingLocal())
+ return make<DefinedGlobal>(Name, Flags, this, Global);
+ return Symtab->addDefinedGlobal(Name, Flags, this, Global);
+ }
+ case WASM_SYMBOL_TYPE_SECTION: {
+ InputSection *Section = CustomSectionsByIndex[Sym.Info.ElementIndex];
+ assert(Sym.isBindingLocal());
+ return make<SectionSymbol>(Name, Flags, Section, this);
+ }
+ }
+ llvm_unreachable("unknown symbol kind");
}
-Symbol *ObjFile::createDefined(const WasmSymbol &Sym,
- const InputSegment *Segment) {
- Symbol *S;
- if (Sym.isLocal()) {
- S = make<Symbol>(Sym.Name, true);
- Symbol::Kind Kind;
- if (Sym.Type == WasmSymbol::SymbolType::FUNCTION_EXPORT)
- Kind = Symbol::Kind::DefinedFunctionKind;
- else if (Sym.Type == WasmSymbol::SymbolType::GLOBAL_EXPORT)
- Kind = Symbol::Kind::DefinedGlobalKind;
- else
- llvm_unreachable("invalid local symbol type");
- S->update(Kind, this, &Sym, Segment);
- return S;
+Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {
+ StringRef Name = Sym.Info.Name;
+ uint32_t Flags = Sym.Info.Flags;
+
+ switch (Sym.Info.Kind) {
+ case WASM_SYMBOL_TYPE_FUNCTION:
+ return Symtab->addUndefinedFunction(Name, Flags, this, Sym.FunctionType);
+ case WASM_SYMBOL_TYPE_DATA:
+ return Symtab->addUndefinedData(Name, Flags, this);
+ case WASM_SYMBOL_TYPE_GLOBAL:
+ return Symtab->addUndefinedGlobal(Name, Flags, this, Sym.GlobalType);
+ case WASM_SYMBOL_TYPE_SECTION:
+ llvm_unreachable("section symbols cannot be undefined");
}
- return Symtab->addDefined(this, &Sym, Segment);
+ llvm_unreachable("unknown symbol kind");
}
void ArchiveFile::parse() {
// Parse a MemoryBufferRef as an archive file.
- DEBUG(dbgs() << "Parsing library: " << toString(this) << "\n");
+ LLVM_DEBUG(dbgs() << "Parsing library: " << toString(this) << "\n");
File = CHECK(Archive::create(MB), toString(this));
// Read the symbol table to construct Lazy symbols.
@@ -269,7 +350,7 @@ void ArchiveFile::parse() {
Symtab->addLazy(this, &Sym);
++Count;
}
- DEBUG(dbgs() << "Read " << Count << " symbols\n");
+ LLVM_DEBUG(dbgs() << "Read " << Count << " symbols\n");
}
void ArchiveFile::addMember(const Archive::Symbol *Sym) {
@@ -282,22 +363,59 @@ void ArchiveFile::addMember(const Archive::Symbol *Sym) {
if (!Seen.insert(C.getChildOffset()).second)
return;
- DEBUG(dbgs() << "loading lazy: " << Sym->getName() << "\n");
- DEBUG(dbgs() << "from archive: " << toString(this) << "\n");
+ LLVM_DEBUG(dbgs() << "loading lazy: " << Sym->getName() << "\n");
+ LLVM_DEBUG(dbgs() << "from archive: " << toString(this) << "\n");
MemoryBufferRef MB =
CHECK(C.getMemoryBufferRef(),
"could not get the buffer for the member defining symbol " +
Sym->getName());
- if (identify_magic(MB.getBuffer()) != file_magic::wasm_object) {
- error("unknown file type: " + MB.getBufferIdentifier());
+ InputFile *Obj = createObjectFile(MB);
+ Obj->ArchiveName = getName();
+ Symtab->addFile(Obj);
+}
+
+static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) {
+ switch (GvVisibility) {
+ case GlobalValue::DefaultVisibility:
+ return WASM_SYMBOL_VISIBILITY_DEFAULT;
+ case GlobalValue::HiddenVisibility:
+ case GlobalValue::ProtectedVisibility:
+ return WASM_SYMBOL_VISIBILITY_HIDDEN;
+ }
+ llvm_unreachable("unknown visibility");
+}
+
+static Symbol *createBitcodeSymbol(const lto::InputFile::Symbol &ObjSym,
+ BitcodeFile &F) {
+ StringRef Name = Saver.save(ObjSym.getName());
+
+ uint32_t Flags = ObjSym.isWeak() ? WASM_SYMBOL_BINDING_WEAK : 0;
+ Flags |= mapVisibility(ObjSym.getVisibility());
+
+ if (ObjSym.isUndefined()) {
+ if (ObjSym.isExecutable())
+ return Symtab->addUndefinedFunction(Name, Flags, &F, nullptr);
+ return Symtab->addUndefinedData(Name, Flags, &F);
+ }
+
+ if (ObjSym.isExecutable())
+ return Symtab->addDefinedFunction(Name, Flags, &F, nullptr);
+ return Symtab->addDefinedData(Name, Flags, &F, nullptr, 0, 0);
+}
+
+void BitcodeFile::parse() {
+ Obj = check(lto::InputFile::create(MemoryBufferRef(
+ MB.getBuffer(), Saver.save(ArchiveName + MB.getBufferIdentifier()))));
+ Triple T(Obj->getTargetTriple());
+ if (T.getArch() != Triple::wasm32) {
+ error(toString(MB.getBufferIdentifier()) + ": machine type must be wasm32");
return;
}
- InputFile *Obj = make<ObjFile>(MB);
- Obj->ParentName = ParentName;
- Symtab->addFile(Obj);
+ for (const lto::InputFile::Symbol &ObjSym : Obj->symbols())
+ Symbols.push_back(createBitcodeSymbol(ObjSym, *this));
}
// Returns a string in the format of "foo.o" or "foo.a(bar.o)".
@@ -305,8 +423,8 @@ std::string lld::toString(const wasm::InputFile *File) {
if (!File)
return "<internal>";
- if (File->ParentName.empty())
+ if (File->ArchiveName.empty())
return File->getName();
- return (File->ParentName + "(" + File->getName() + ")").str();
+ return (File->ArchiveName + "(" + File->getName() + ")").str();
}