You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
5.8 KiB
207 lines
5.8 KiB
//===- InputFiles.h ---------------------------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLD_WASM_INPUT_FILES_H
|
|
#define LLD_WASM_INPUT_FILES_H
|
|
|
|
#include "Symbols.h"
|
|
#include "lld/Common/LLVM.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/DenseSet.h"
|
|
#include "llvm/ADT/Triple.h"
|
|
#include "llvm/LTO/LTO.h"
|
|
#include "llvm/Object/Archive.h"
|
|
#include "llvm/Object/Wasm.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include <vector>
|
|
|
|
namespace llvm {
|
|
class TarWriter;
|
|
}
|
|
|
|
namespace lld {
|
|
namespace wasm {
|
|
|
|
class InputChunk;
|
|
class InputFunction;
|
|
class InputSegment;
|
|
class InputGlobal;
|
|
class InputEvent;
|
|
class InputSection;
|
|
|
|
// If --reproduce option is given, all input files are written
|
|
// to this tar archive.
|
|
extern std::unique_ptr<llvm::TarWriter> tar;
|
|
|
|
class InputFile {
|
|
public:
|
|
enum Kind {
|
|
ObjectKind,
|
|
SharedKind,
|
|
ArchiveKind,
|
|
BitcodeKind,
|
|
};
|
|
|
|
virtual ~InputFile() {}
|
|
|
|
// Returns the filename.
|
|
StringRef getName() const { return mb.getBufferIdentifier(); }
|
|
|
|
Kind kind() const { return fileKind; }
|
|
|
|
// An archive file name if this file is created from an archive.
|
|
std::string archiveName;
|
|
|
|
ArrayRef<Symbol *> getSymbols() const { return symbols; }
|
|
|
|
MutableArrayRef<Symbol *> getMutableSymbols() { return symbols; }
|
|
|
|
// An InputFile is considered live if any of the symbols defined by it
|
|
// are live.
|
|
void markLive() { live = true; }
|
|
bool isLive() const { return live; }
|
|
|
|
protected:
|
|
InputFile(Kind k, MemoryBufferRef m)
|
|
: mb(m), fileKind(k), live(!config->gcSections) {}
|
|
|
|
void checkArch(llvm::Triple::ArchType arch) const;
|
|
|
|
MemoryBufferRef mb;
|
|
|
|
// List of all symbols referenced or defined by this file.
|
|
std::vector<Symbol *> symbols;
|
|
|
|
private:
|
|
const Kind fileKind;
|
|
bool live;
|
|
};
|
|
|
|
// .a file (ar archive)
|
|
class ArchiveFile : public InputFile {
|
|
public:
|
|
explicit ArchiveFile(MemoryBufferRef m) : InputFile(ArchiveKind, m) {}
|
|
static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; }
|
|
|
|
void addMember(const llvm::object::Archive::Symbol *sym);
|
|
|
|
void parse();
|
|
|
|
private:
|
|
std::unique_ptr<llvm::object::Archive> file;
|
|
llvm::DenseSet<uint64_t> seen;
|
|
};
|
|
|
|
// .o file (wasm object file)
|
|
class ObjFile : public InputFile {
|
|
public:
|
|
explicit ObjFile(MemoryBufferRef m, StringRef archiveName)
|
|
: InputFile(ObjectKind, m) {
|
|
this->archiveName = std::string(archiveName);
|
|
|
|
// If this isn't part of an archive, it's eagerly linked, so mark it live.
|
|
if (archiveName.empty())
|
|
markLive();
|
|
}
|
|
static bool classof(const InputFile *f) { return f->kind() == ObjectKind; }
|
|
|
|
void parse(bool ignoreComdats = false);
|
|
|
|
// Returns the underlying wasm file.
|
|
const WasmObjectFile *getWasmObj() const { return wasmObj.get(); }
|
|
|
|
void dumpInfo() const;
|
|
|
|
uint32_t calcNewIndex(const WasmRelocation &reloc) const;
|
|
uint64_t calcNewValue(const WasmRelocation &reloc, uint64_t tombstone) const;
|
|
uint64_t calcNewAddend(const WasmRelocation &reloc) const;
|
|
uint64_t calcExpectedValue(const WasmRelocation &reloc) const;
|
|
Symbol *getSymbol(const WasmRelocation &reloc) const {
|
|
return symbols[reloc.Index];
|
|
};
|
|
|
|
const WasmSection *codeSection = nullptr;
|
|
const WasmSection *dataSection = nullptr;
|
|
|
|
// Maps input type indices to output type indices
|
|
std::vector<uint32_t> typeMap;
|
|
std::vector<bool> typeIsUsed;
|
|
// Maps function indices to table indices
|
|
std::vector<uint32_t> tableEntries;
|
|
std::vector<uint32_t> tableEntriesRel;
|
|
std::vector<bool> keptComdats;
|
|
std::vector<InputSegment *> segments;
|
|
std::vector<InputFunction *> functions;
|
|
std::vector<InputGlobal *> globals;
|
|
std::vector<InputEvent *> events;
|
|
std::vector<InputSection *> customSections;
|
|
llvm::DenseMap<uint32_t, InputSection *> customSectionsByIndex;
|
|
|
|
Symbol *getSymbol(uint32_t index) const { return symbols[index]; }
|
|
FunctionSymbol *getFunctionSymbol(uint32_t index) const;
|
|
DataSymbol *getDataSymbol(uint32_t index) const;
|
|
GlobalSymbol *getGlobalSymbol(uint32_t index) const;
|
|
SectionSymbol *getSectionSymbol(uint32_t index) const;
|
|
EventSymbol *getEventSymbol(uint32_t index) const;
|
|
|
|
private:
|
|
Symbol *createDefined(const WasmSymbol &sym);
|
|
Symbol *createUndefined(const WasmSymbol &sym, bool isCalledDirectly);
|
|
|
|
bool isExcludedByComdat(InputChunk *chunk) const;
|
|
|
|
std::unique_ptr<WasmObjectFile> wasmObj;
|
|
};
|
|
|
|
// .so file.
|
|
class SharedFile : public InputFile {
|
|
public:
|
|
explicit SharedFile(MemoryBufferRef m) : InputFile(SharedKind, m) {}
|
|
static bool classof(const InputFile *f) { return f->kind() == SharedKind; }
|
|
};
|
|
|
|
// .bc file
|
|
class BitcodeFile : public InputFile {
|
|
public:
|
|
explicit BitcodeFile(MemoryBufferRef m, StringRef archiveName)
|
|
: InputFile(BitcodeKind, m) {
|
|
this->archiveName = std::string(archiveName);
|
|
|
|
// If this isn't part of an archive, it's eagerly linked, so mark it live.
|
|
if (archiveName.empty())
|
|
markLive();
|
|
}
|
|
static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
|
|
|
|
void parse();
|
|
std::unique_ptr<llvm::lto::InputFile> obj;
|
|
|
|
// Set to true once LTO is complete in order prevent further bitcode objects
|
|
// being added.
|
|
static bool doneLTO;
|
|
};
|
|
|
|
inline bool isBitcode(MemoryBufferRef mb) {
|
|
return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode;
|
|
}
|
|
|
|
// Will report a fatal() error if the input buffer is not a valid bitcode
|
|
// or wasm object file.
|
|
InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "");
|
|
|
|
// Opens a given file.
|
|
llvm::Optional<MemoryBufferRef> readFile(StringRef path);
|
|
|
|
} // namespace wasm
|
|
|
|
std::string toString(const wasm::InputFile *file);
|
|
|
|
} // namespace lld
|
|
|
|
#endif
|