Skip to content

Commit

Permalink
[WebAssembly] Add first claass symbol table to wasm objects
Browse files Browse the repository at this point in the history
This is combination of two patches by Nicholas Wilson:
  1. https://reviews.llvm.org/D41954
  2. https://reviews.llvm.org/D42495

Along with a few local modifications:
- One change I made was to add the UNDEFINED bit to the binary format
  to avoid the extra byte used when writing data symbols.  Although this
  bit is redundant for other symbols types (i.e. undefined can be
  implied if a function or global is a wasm import)
- I prefer to be explicit and consistent and not have derived flags.
- Some field renaming.
- Some reverting of unrelated minor changes.
- No test output differences.

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

llvm-svn: 325860
  • Loading branch information
sbc100 committed Feb 23, 2018
1 parent 0fd6a53 commit 6c899ba
Show file tree
Hide file tree
Showing 43 changed files with 1,032 additions and 897 deletions.
51 changes: 34 additions & 17 deletions llvm/include/llvm/BinaryFormat/Wasm.h
Expand Up @@ -119,16 +119,37 @@ struct WasmElemSegment {
std::vector<uint32_t> Functions;
};

// Represents the location of a Wasm data symbol within a WasmDataSegment, as
// the index of the segment, and the offset and size within the segment.
struct WasmDataReference {
uint32_t Segment;
uint32_t Offset;
uint32_t Size;
};

struct WasmRelocation {
uint32_t Type; // The type of the relocation.
uint32_t Index; // Index into function or global index space.
uint32_t Index; // Index into either symbol or type index space.
uint64_t Offset; // Offset from the start of the section.
int64_t Addend; // A value to add to the symbol.
};

struct WasmInitFunc {
uint32_t Priority;
uint32_t FunctionIndex;
uint32_t Symbol;
};

struct WasmSymbolInfo {
StringRef Name;
uint32_t Kind;
uint32_t Flags;
union {
// For function or global symbols, the index in function of global index
// space.
uint32_t ElementIndex;
// For a data symbols, the address of the data relative to segment.
WasmDataReference DataRef;
};
};

struct WasmFunctionName {
Expand All @@ -139,6 +160,7 @@ struct WasmFunctionName {
struct WasmLinkingData {
uint32_t DataSize;
std::vector<WasmInitFunc> InitFunctions;
std::vector<WasmSymbolInfo> SymbolTable;
};

enum : unsigned {
Expand Down Expand Up @@ -205,11 +227,11 @@ enum : unsigned {

// Kind codes used in the custom "linking" section
enum : unsigned {
WASM_SYMBOL_INFO = 0x2,
WASM_DATA_SIZE = 0x3,
WASM_SEGMENT_INFO = 0x5,
WASM_INIT_FUNCS = 0x6,
WASM_COMDAT_INFO = 0x7,
WASM_SYMBOL_TABLE = 0x8,
};

// Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO
Expand All @@ -218,14 +240,22 @@ enum : unsigned {
WASM_COMDAT_FUNCTION = 0x1,
};

// Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE
enum WasmSymbolType : unsigned {
WASM_SYMBOL_TYPE_FUNCTION = 0x0,
WASM_SYMBOL_TYPE_DATA = 0x1,
WASM_SYMBOL_TYPE_GLOBAL = 0x2,
};

const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0x4;
const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc;

const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0;
const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1;
const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2;
const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0;
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4;
const unsigned WASM_SYMBOL_UNDEFINED = 0x10;

#define WASM_RELOC(name, value) name = value,

Expand All @@ -235,19 +265,6 @@ enum : unsigned {

#undef WASM_RELOC

struct Global {
ValType Type;
bool Mutable;

// The initial value for this global is either the value of an imported
// global, in which case InitialModule and InitialName specify the global
// import, or a value, in which case InitialModule is empty and InitialValue
// holds the value.
StringRef InitialModule;
StringRef InitialName;
uint64_t InitialValue;
};

} // end namespace wasm
} // end namespace llvm

Expand Down
12 changes: 6 additions & 6 deletions llvm/include/llvm/MC/MCSectionWasm.h
Expand Up @@ -37,17 +37,17 @@ class MCSectionWasm final : public MCSection {
// The offset of the MC function/data section in the wasm code/data section.
// For data relocations the offset is relative to start of the data payload
// itself and does not include the size of the section header.
uint64_t SectionOffset;
uint64_t SectionOffset = 0;

// For data sections, this is the offset of the corresponding wasm data
// For data sections, this is the index of of the corresponding wasm data
// segment
uint64_t MemoryOffset;
uint32_t SegmentIndex = 0;

friend class MCContext;
MCSectionWasm(StringRef Section, SectionKind K, const MCSymbolWasm *group,
unsigned UniqueID, MCSymbol *Begin)
: MCSection(SV_Wasm, K, Begin), SectionName(Section), UniqueID(UniqueID),
Group(group), SectionOffset(0) {}
Group(group) {}

void setSectionName(StringRef Name) { SectionName = Name; }

Expand Down Expand Up @@ -77,8 +77,8 @@ class MCSectionWasm final : public MCSection {
uint64_t getSectionOffset() const { return SectionOffset; }
void setSectionOffset(uint64_t Offset) { SectionOffset = Offset; }

uint32_t getMemoryOffset() const { return MemoryOffset; }
void setMemoryOffset(uint32_t Offset) { MemoryOffset = Offset; }
uint32_t getSegmentIndex() const { return SegmentIndex; }
void setSegmentIndex(uint32_t Index) { SegmentIndex = Index; }

static bool classof(const MCSection *S) { return S->getVariant() == SV_Wasm; }
};
Expand Down
21 changes: 18 additions & 3 deletions llvm/include/llvm/MC/MCSymbolWasm.h
Expand Up @@ -15,15 +15,17 @@
namespace llvm {

class MCSymbolWasm : public MCSymbol {
bool IsFunction = false;
wasm::WasmSymbolType Type = wasm::WASM_SYMBOL_TYPE_DATA;
bool IsWeak = false;
bool IsHidden = false;
bool IsComdat = false;
std::string ModuleName;
SmallVector<wasm::ValType, 1> Returns;
SmallVector<wasm::ValType, 4> Params;
wasm::WasmGlobalType GlobalType;
bool ParamsSet = false;
bool ReturnsSet = false;
bool GlobalTypeSet = false;

/// An expression describing how to calculate the size of a symbol. If a
/// symbol has no size this field will be NULL.
Expand All @@ -40,8 +42,11 @@ class MCSymbolWasm : public MCSymbol {
const MCExpr *getSize() const { return SymbolSize; }
void setSize(const MCExpr *SS) { SymbolSize = SS; }

bool isFunction() const { return IsFunction; }
void setIsFunction(bool isFunc) { IsFunction = isFunc; }
bool isFunction() const { return Type == wasm::WASM_SYMBOL_TYPE_FUNCTION; }
bool isData() const { return Type == wasm::WASM_SYMBOL_TYPE_DATA; }
bool isGlobal() const { return Type == wasm::WASM_SYMBOL_TYPE_GLOBAL; }
wasm::WasmSymbolType getType() const { return Type; }
void setType(wasm::WasmSymbolType type) { Type = type; }

bool isWeak() const { return IsWeak; }
void setWeak(bool isWeak) { IsWeak = isWeak; }
Expand Down Expand Up @@ -74,6 +79,16 @@ class MCSymbolWasm : public MCSymbol {
ParamsSet = true;
Params = std::move(Pars);
}

const wasm::WasmGlobalType &getGlobalType() const {
assert(GlobalTypeSet);
return GlobalType;
}

void setGlobalType(wasm::WasmGlobalType GT) {
GlobalTypeSet = true;
GlobalType = GT;
}
};

} // end namespace llvm
Expand Down
81 changes: 37 additions & 44 deletions llvm/include/llvm/Object/Wasm.h
Expand Up @@ -34,48 +34,30 @@ namespace object {

class WasmSymbol {
public:
enum class SymbolType {
FUNCTION_IMPORT,
FUNCTION_EXPORT,
GLOBAL_IMPORT,
GLOBAL_EXPORT,
};

WasmSymbol(StringRef Name, SymbolType Type, uint32_t ElementIndex,
uint32_t FunctionType = 0)
: Name(Name), Type(Type), ElementIndex(ElementIndex),
FunctionType(FunctionType) {}

StringRef Name;
SymbolType Type;
uint32_t Flags = 0;

// Index into either the function or global index space.
uint32_t ElementIndex;

// For function, the type index
uint32_t FunctionType;

// Symbols can be both exported and imported (in the case of the weakly
// defined symbol). In this the import index is stored as AltIndex.
uint32_t AltIndex = 0;
bool HasAltIndex = false;

void setAltIndex(uint32_t Index) {
HasAltIndex = true;
AltIndex = Index;
}
WasmSymbol(const wasm::WasmSymbolInfo &Info,
const wasm::WasmSignature *FunctionType,
const wasm::WasmGlobalType *GlobalType)
: Info(Info), FunctionType(FunctionType), GlobalType(GlobalType) {}

const wasm::WasmSymbolInfo &Info;
const wasm::WasmSignature *FunctionType;
const wasm::WasmGlobalType *GlobalType;

bool isTypeFunction() const {
return Type == SymbolType::FUNCTION_IMPORT ||
Type == SymbolType::FUNCTION_EXPORT;
return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION;
}

bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; }

bool isTypeGlobal() const {
return Type == SymbolType::GLOBAL_IMPORT ||
Type == SymbolType::GLOBAL_EXPORT;
return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL;
}

bool isDefined() const { return !isUndefined(); }

bool isUndefined() const {
return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0;
}

bool isBindingWeak() const {
return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK;
Expand All @@ -90,20 +72,27 @@ class WasmSymbol {
}

unsigned getBinding() const {
return Flags & wasm::WASM_SYMBOL_BINDING_MASK;
return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK;
}

bool isHidden() const {
return getVisibility() == wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
}

unsigned getVisibility() const {
return Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK;
return Info.Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK;
}

void print(raw_ostream &Out) const {
Out << "Name=" << Name << ", Type=" << static_cast<int>(Type)
<< ", Flags=" << Flags << " ElemIndex=" << ElementIndex;
Out << "Name=" << Info.Name << ", Kind=" << Info.Kind
<< ", Flags=" << Info.Flags;
if (!isTypeData()) {
Out << ", ElemIndex=" << Info.ElementIndex;
} else if (isDefined()) {
Out << ", Segment=" << Info.DataRef.Segment;
Out << ", Offset=" << Info.DataRef.Offset;
Out << ", Size=" << Info.DataRef.Size;
}
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Expand Down Expand Up @@ -154,6 +143,8 @@ class WasmObjectFile : public ObjectFile {
ArrayRef<StringRef> comdats() const { return Comdats; }
ArrayRef<wasm::WasmFunctionName> debugNames() const { return DebugNames; }
uint32_t startFunction() const { return StartFunction; }
uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }

void moveSymbolNext(DataRefImpl &Symb) const override;

Expand Down Expand Up @@ -210,7 +201,11 @@ class WasmObjectFile : public ObjectFile {
private:
bool isValidFunctionIndex(uint32_t Index) const;
bool isDefinedFunctionIndex(uint32_t Index) const;
wasm::WasmFunction& getDefinedFunction(uint32_t Index);
bool isValidGlobalIndex(uint32_t Index) const;
bool isDefinedGlobalIndex(uint32_t Index) const;
bool isValidFunctionSymbolIndex(uint32_t Index) const;
wasm::WasmFunction &getDefinedFunction(uint32_t Index);
wasm::WasmGlobal &getDefinedGlobal(uint32_t Index);

const WasmSection &getWasmSection(DataRefImpl Ref) const;
const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
Expand Down Expand Up @@ -239,12 +234,11 @@ class WasmObjectFile : public ObjectFile {
// Custom section types
Error parseNameSection(const uint8_t *Ptr, const uint8_t *End);
Error parseLinkingSection(const uint8_t *Ptr, const uint8_t *End);
Error parseLinkingSectionSymtab(const uint8_t *&Ptr, const uint8_t *End);
Error parseLinkingSectionComdat(const uint8_t *&Ptr, const uint8_t *End);
Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
const uint8_t *End);

void populateSymbolTable();

wasm::WasmObjectHeader Header;
std::vector<WasmSection> Sections;
std::vector<wasm::WasmSignature> Signatures;
Expand All @@ -267,8 +261,7 @@ class WasmObjectFile : public ObjectFile {
uint32_t NumImportedFunctions = 0;
uint32_t CodeSection = 0;
uint32_t DataSection = 0;

StringMap<uint32_t> SymbolMap;
uint32_t GlobalSection = 0;
};

} // end namespace object
Expand Down
15 changes: 13 additions & 2 deletions llvm/include/llvm/ObjectYAML/WasmYAML.h
Expand Up @@ -35,6 +35,7 @@ LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportKind)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, Opcode)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, RelocType)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, SymbolFlags)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, SymbolKind)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, SegmentFlags)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, LimitFlags)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ComdatKind)
Expand Down Expand Up @@ -130,13 +131,19 @@ struct Signature {
};

struct SymbolInfo {
uint32_t Index;
StringRef Name;
SymbolKind Kind;
SymbolFlags Flags;
union {
uint32_t ElementIndex;
wasm::WasmDataReference DataRef;
};
};

struct InitFunction {
uint32_t Priority;
uint32_t FunctionIndex;
uint32_t Symbol;
};

struct ComdatEntry {
Expand Down Expand Up @@ -189,7 +196,7 @@ struct LinkingSection : CustomSection {
}

uint32_t DataSize;
std::vector<SymbolInfo> SymbolInfos;
std::vector<SymbolInfo> SymbolTable;
std::vector<SegmentInfo> SegmentInfos;
std::vector<InitFunction> InitFunctions;
std::vector<Comdat> Comdats;
Expand Down Expand Up @@ -368,6 +375,10 @@ template <> struct ScalarBitSetTraits<WasmYAML::SymbolFlags> {
static void bitset(IO &IO, WasmYAML::SymbolFlags &Value);
};

template <> struct ScalarEnumerationTraits<WasmYAML::SymbolKind> {
static void enumeration(IO &IO, WasmYAML::SymbolKind &Kind);
};

template <> struct ScalarBitSetTraits<WasmYAML::SegmentFlags> {
static void bitset(IO &IO, WasmYAML::SegmentFlags &Value);
};
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/MC/MCWasmStreamer.cpp
Expand Up @@ -113,11 +113,11 @@ bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
break;

case MCSA_ELF_TypeFunction:
Symbol->setIsFunction(true);
Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
break;

case MCSA_ELF_TypeObject:
Symbol->setIsFunction(false);
Symbol->setType(wasm::WASM_SYMBOL_TYPE_DATA);
break;

default:
Expand Down

0 comments on commit 6c899ba

Please sign in to comment.