This commit adds support for WebAssembly's custom-page-sizes proposal to `wasm-ld`. An overview of the proposal can be found [here](https://github.com/WebAssembly/custom-page-sizes/blob/main/proposals/custom-page-sizes/Overview.md). In a sentence, it allows customizing a Wasm memory's page size, enabling Wasm to target environments with less than 64KiB of memory (the default Wasm page size) available for Wasm memories. This commit contains the following: * Adds a `--page-size=N` CLI flag to `wasm-ld` for configuring the linked Wasm binary's linear memory's page size. * When the page size is configured to a non-default value, then the final Wasm binary will use the encodings defined in the custom-page-sizes proposal to declare the linear memory's page size. * Defines a `__wasm_first_page_end` symbol, whose address points to the first page in the Wasm linear memory, a.k.a. is the Wasm memory's page size. This allows writing code that is compatible with any page size, and doesn't require re-compiling its object code. At the same time, because it just lowers to a constant rather than a memory access or something, it enables link-time optimization. * Adds tests for these new features. r? @sbc100 cc @sunfishcode
606 lines
15 KiB
C++
606 lines
15 KiB
C++
//===- WasmYAML.h - Wasm YAMLIO implementation ------------------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// This file declares classes for handling the YAML representation
|
|
/// of wasm binaries.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_OBJECTYAML_WASMYAML_H
|
|
#define LLVM_OBJECTYAML_WASMYAML_H
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/BinaryFormat/Wasm.h"
|
|
#include "llvm/ObjectYAML/YAML.h"
|
|
#include "llvm/Support/Casting.h"
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
namespace llvm {
|
|
namespace WasmYAML {
|
|
|
|
LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionType)
|
|
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ValueType)
|
|
LLVM_YAML_STRONG_TYPEDEF(uint32_t, TableType)
|
|
LLVM_YAML_STRONG_TYPEDEF(uint32_t, SignatureForm)
|
|
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)
|
|
LLVM_YAML_STRONG_TYPEDEF(uint32_t, FeaturePolicyPrefix)
|
|
|
|
struct FileHeader {
|
|
yaml::Hex32 Version;
|
|
};
|
|
|
|
struct Limits {
|
|
LimitFlags Flags;
|
|
yaml::Hex32 Minimum;
|
|
yaml::Hex32 Maximum;
|
|
yaml::Hex32 PageSize;
|
|
};
|
|
|
|
struct Table {
|
|
TableType ElemType;
|
|
Limits TableLimits;
|
|
uint32_t Index;
|
|
};
|
|
|
|
struct Export {
|
|
StringRef Name;
|
|
ExportKind Kind;
|
|
uint32_t Index;
|
|
};
|
|
|
|
struct InitExpr {
|
|
InitExpr() {}
|
|
bool Extended;
|
|
union {
|
|
wasm::WasmInitExprMVP Inst;
|
|
yaml::BinaryRef Body;
|
|
};
|
|
};
|
|
|
|
struct ElemSegment {
|
|
uint32_t Flags;
|
|
uint32_t TableNumber;
|
|
ValueType ElemKind;
|
|
InitExpr Offset;
|
|
std::vector<uint32_t> Functions;
|
|
};
|
|
|
|
struct Global {
|
|
uint32_t Index;
|
|
ValueType Type;
|
|
bool Mutable;
|
|
InitExpr Init;
|
|
};
|
|
|
|
struct Import {
|
|
Import() {}
|
|
StringRef Module;
|
|
StringRef Field;
|
|
ExportKind Kind;
|
|
union {
|
|
uint32_t SigIndex;
|
|
Table TableImport;
|
|
Limits Memory;
|
|
uint32_t TagIndex;
|
|
Global GlobalImport;
|
|
};
|
|
};
|
|
|
|
struct LocalDecl {
|
|
ValueType Type;
|
|
uint32_t Count;
|
|
};
|
|
|
|
struct Function {
|
|
uint32_t Index;
|
|
std::vector<LocalDecl> Locals;
|
|
yaml::BinaryRef Body;
|
|
};
|
|
|
|
struct Relocation {
|
|
RelocType Type;
|
|
uint32_t Index;
|
|
// TODO(wvo): this would strictly be better as Hex64, but that will change
|
|
// all existing obj2yaml output.
|
|
yaml::Hex32 Offset;
|
|
int64_t Addend;
|
|
};
|
|
|
|
struct DataSegment {
|
|
uint32_t SectionOffset;
|
|
uint32_t InitFlags;
|
|
uint32_t MemoryIndex;
|
|
InitExpr Offset;
|
|
yaml::BinaryRef Content;
|
|
};
|
|
|
|
struct NameEntry {
|
|
uint32_t Index;
|
|
StringRef Name;
|
|
};
|
|
|
|
struct ProducerEntry {
|
|
std::string Name;
|
|
std::string Version;
|
|
};
|
|
|
|
struct FeatureEntry {
|
|
FeaturePolicyPrefix Prefix;
|
|
std::string Name;
|
|
};
|
|
|
|
struct SegmentInfo {
|
|
uint32_t Index;
|
|
StringRef Name;
|
|
uint32_t Alignment;
|
|
SegmentFlags Flags;
|
|
};
|
|
|
|
struct Signature {
|
|
uint32_t Index;
|
|
SignatureForm Form = wasm::WASM_TYPE_FUNC;
|
|
std::vector<ValueType> ParamTypes;
|
|
std::vector<ValueType> ReturnTypes;
|
|
};
|
|
|
|
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 Symbol;
|
|
};
|
|
|
|
struct ComdatEntry {
|
|
ComdatKind Kind;
|
|
uint32_t Index;
|
|
};
|
|
|
|
struct Comdat {
|
|
StringRef Name;
|
|
std::vector<ComdatEntry> Entries;
|
|
};
|
|
|
|
struct Section {
|
|
explicit Section(SectionType SecType) : Type(SecType) {}
|
|
virtual ~Section();
|
|
|
|
SectionType Type;
|
|
std::vector<Relocation> Relocations;
|
|
std::optional<uint8_t> HeaderSecSizeEncodingLen;
|
|
};
|
|
|
|
struct CustomSection : Section {
|
|
explicit CustomSection(StringRef Name)
|
|
: Section(wasm::WASM_SEC_CUSTOM), Name(Name) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_CUSTOM;
|
|
}
|
|
|
|
StringRef Name;
|
|
yaml::BinaryRef Payload;
|
|
};
|
|
|
|
struct DylinkImportInfo {
|
|
StringRef Module;
|
|
StringRef Field;
|
|
SymbolFlags Flags;
|
|
};
|
|
|
|
struct DylinkExportInfo {
|
|
StringRef Name;
|
|
SymbolFlags Flags;
|
|
};
|
|
|
|
struct DylinkSection : CustomSection {
|
|
DylinkSection() : CustomSection("dylink.0") {}
|
|
|
|
static bool classof(const Section *S) {
|
|
auto C = dyn_cast<CustomSection>(S);
|
|
return C && C->Name == "dylink.0";
|
|
}
|
|
|
|
uint32_t MemorySize;
|
|
uint32_t MemoryAlignment;
|
|
uint32_t TableSize;
|
|
uint32_t TableAlignment;
|
|
std::vector<StringRef> Needed;
|
|
std::vector<DylinkImportInfo> ImportInfo;
|
|
std::vector<DylinkExportInfo> ExportInfo;
|
|
std::vector<StringRef> RuntimePath;
|
|
};
|
|
|
|
struct NameSection : CustomSection {
|
|
NameSection() : CustomSection("name") {}
|
|
|
|
static bool classof(const Section *S) {
|
|
auto C = dyn_cast<CustomSection>(S);
|
|
return C && C->Name == "name";
|
|
}
|
|
|
|
std::vector<NameEntry> FunctionNames;
|
|
std::vector<NameEntry> GlobalNames;
|
|
std::vector<NameEntry> DataSegmentNames;
|
|
};
|
|
|
|
struct LinkingSection : CustomSection {
|
|
LinkingSection() : CustomSection("linking") {}
|
|
|
|
static bool classof(const Section *S) {
|
|
auto C = dyn_cast<CustomSection>(S);
|
|
return C && C->Name == "linking";
|
|
}
|
|
|
|
uint32_t Version;
|
|
std::vector<SymbolInfo> SymbolTable;
|
|
std::vector<SegmentInfo> SegmentInfos;
|
|
std::vector<InitFunction> InitFunctions;
|
|
std::vector<Comdat> Comdats;
|
|
};
|
|
|
|
struct ProducersSection : CustomSection {
|
|
ProducersSection() : CustomSection("producers") {}
|
|
|
|
static bool classof(const Section *S) {
|
|
auto C = dyn_cast<CustomSection>(S);
|
|
return C && C->Name == "producers";
|
|
}
|
|
|
|
std::vector<ProducerEntry> Languages;
|
|
std::vector<ProducerEntry> Tools;
|
|
std::vector<ProducerEntry> SDKs;
|
|
};
|
|
|
|
struct TargetFeaturesSection : CustomSection {
|
|
TargetFeaturesSection() : CustomSection("target_features") {}
|
|
|
|
static bool classof(const Section *S) {
|
|
auto C = dyn_cast<CustomSection>(S);
|
|
return C && C->Name == "target_features";
|
|
}
|
|
|
|
std::vector<FeatureEntry> Features;
|
|
};
|
|
|
|
struct TypeSection : Section {
|
|
TypeSection() : Section(wasm::WASM_SEC_TYPE) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_TYPE;
|
|
}
|
|
|
|
std::vector<Signature> Signatures;
|
|
};
|
|
|
|
struct ImportSection : Section {
|
|
ImportSection() : Section(wasm::WASM_SEC_IMPORT) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_IMPORT;
|
|
}
|
|
|
|
std::vector<Import> Imports;
|
|
};
|
|
|
|
struct FunctionSection : Section {
|
|
FunctionSection() : Section(wasm::WASM_SEC_FUNCTION) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_FUNCTION;
|
|
}
|
|
|
|
std::vector<uint32_t> FunctionTypes;
|
|
};
|
|
|
|
struct TableSection : Section {
|
|
TableSection() : Section(wasm::WASM_SEC_TABLE) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_TABLE;
|
|
}
|
|
|
|
std::vector<Table> Tables;
|
|
};
|
|
|
|
struct MemorySection : Section {
|
|
MemorySection() : Section(wasm::WASM_SEC_MEMORY) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_MEMORY;
|
|
}
|
|
|
|
std::vector<Limits> Memories;
|
|
};
|
|
|
|
struct TagSection : Section {
|
|
TagSection() : Section(wasm::WASM_SEC_TAG) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_TAG;
|
|
}
|
|
|
|
std::vector<uint32_t> TagTypes;
|
|
};
|
|
|
|
struct GlobalSection : Section {
|
|
GlobalSection() : Section(wasm::WASM_SEC_GLOBAL) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_GLOBAL;
|
|
}
|
|
|
|
std::vector<Global> Globals;
|
|
};
|
|
|
|
struct ExportSection : Section {
|
|
ExportSection() : Section(wasm::WASM_SEC_EXPORT) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_EXPORT;
|
|
}
|
|
|
|
std::vector<Export> Exports;
|
|
};
|
|
|
|
struct StartSection : Section {
|
|
StartSection() : Section(wasm::WASM_SEC_START) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_START;
|
|
}
|
|
|
|
uint32_t StartFunction;
|
|
};
|
|
|
|
struct ElemSection : Section {
|
|
ElemSection() : Section(wasm::WASM_SEC_ELEM) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_ELEM;
|
|
}
|
|
|
|
std::vector<ElemSegment> Segments;
|
|
};
|
|
|
|
struct CodeSection : Section {
|
|
CodeSection() : Section(wasm::WASM_SEC_CODE) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_CODE;
|
|
}
|
|
|
|
std::vector<Function> Functions;
|
|
};
|
|
|
|
struct DataSection : Section {
|
|
DataSection() : Section(wasm::WASM_SEC_DATA) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_DATA;
|
|
}
|
|
|
|
std::vector<DataSegment> Segments;
|
|
};
|
|
|
|
struct DataCountSection : Section {
|
|
DataCountSection() : Section(wasm::WASM_SEC_DATACOUNT) {}
|
|
|
|
static bool classof(const Section *S) {
|
|
return S->Type == wasm::WASM_SEC_DATACOUNT;
|
|
}
|
|
|
|
uint32_t Count;
|
|
};
|
|
|
|
struct Object {
|
|
FileHeader Header;
|
|
std::vector<std::unique_ptr<Section>> Sections;
|
|
};
|
|
|
|
} // end namespace WasmYAML
|
|
} // end namespace llvm
|
|
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::WasmYAML::Section>)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Signature)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ValueType)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Table)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Import)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Export)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ElemSegment)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Limits)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DataSegment)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Global)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Function)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::LocalDecl)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ProducerEntry)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::FeatureEntry)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SegmentInfo)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::InitFunction)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ComdatEntry)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Comdat)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DylinkImportInfo)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DylinkExportInfo)
|
|
|
|
namespace llvm {
|
|
namespace yaml {
|
|
|
|
template <> struct MappingTraits<WasmYAML::FileHeader> {
|
|
static void mapping(IO &IO, WasmYAML::FileHeader &FileHdr);
|
|
};
|
|
|
|
template <> struct MappingTraits<std::unique_ptr<WasmYAML::Section>> {
|
|
static void mapping(IO &IO, std::unique_ptr<WasmYAML::Section> &Section);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::Object> {
|
|
static void mapping(IO &IO, WasmYAML::Object &Object);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::Import> {
|
|
static void mapping(IO &IO, WasmYAML::Import &Import);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::Export> {
|
|
static void mapping(IO &IO, WasmYAML::Export &Export);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::Global> {
|
|
static void mapping(IO &IO, WasmYAML::Global &Global);
|
|
};
|
|
|
|
template <> struct ScalarBitSetTraits<WasmYAML::LimitFlags> {
|
|
static void bitset(IO &IO, WasmYAML::LimitFlags &Value);
|
|
};
|
|
|
|
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);
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<WasmYAML::SectionType> {
|
|
static void enumeration(IO &IO, WasmYAML::SectionType &Type);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::Signature> {
|
|
static void mapping(IO &IO, WasmYAML::Signature &Signature);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::Table> {
|
|
static void mapping(IO &IO, WasmYAML::Table &Table);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::Limits> {
|
|
static void mapping(IO &IO, WasmYAML::Limits &Limits);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::Function> {
|
|
static void mapping(IO &IO, WasmYAML::Function &Function);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::Relocation> {
|
|
static void mapping(IO &IO, WasmYAML::Relocation &Relocation);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::NameEntry> {
|
|
static void mapping(IO &IO, WasmYAML::NameEntry &NameEntry);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::ProducerEntry> {
|
|
static void mapping(IO &IO, WasmYAML::ProducerEntry &ProducerEntry);
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<WasmYAML::FeaturePolicyPrefix> {
|
|
static void enumeration(IO &IO, WasmYAML::FeaturePolicyPrefix &Prefix);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::FeatureEntry> {
|
|
static void mapping(IO &IO, WasmYAML::FeatureEntry &FeatureEntry);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::SegmentInfo> {
|
|
static void mapping(IO &IO, WasmYAML::SegmentInfo &SegmentInfo);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::LocalDecl> {
|
|
static void mapping(IO &IO, WasmYAML::LocalDecl &LocalDecl);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::InitExpr> {
|
|
static void mapping(IO &IO, WasmYAML::InitExpr &Expr);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::DataSegment> {
|
|
static void mapping(IO &IO, WasmYAML::DataSegment &Segment);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::ElemSegment> {
|
|
static void mapping(IO &IO, WasmYAML::ElemSegment &Segment);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::SymbolInfo> {
|
|
static void mapping(IO &IO, WasmYAML::SymbolInfo &Info);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::InitFunction> {
|
|
static void mapping(IO &IO, WasmYAML::InitFunction &Init);
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<WasmYAML::ComdatKind> {
|
|
static void enumeration(IO &IO, WasmYAML::ComdatKind &Kind);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::ComdatEntry> {
|
|
static void mapping(IO &IO, WasmYAML::ComdatEntry &ComdatEntry);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::Comdat> {
|
|
static void mapping(IO &IO, WasmYAML::Comdat &Comdat);
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<WasmYAML::ValueType> {
|
|
static void enumeration(IO &IO, WasmYAML::ValueType &Type);
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<WasmYAML::ExportKind> {
|
|
static void enumeration(IO &IO, WasmYAML::ExportKind &Kind);
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<WasmYAML::TableType> {
|
|
static void enumeration(IO &IO, WasmYAML::TableType &Type);
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<WasmYAML::Opcode> {
|
|
static void enumeration(IO &IO, WasmYAML::Opcode &Opcode);
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<WasmYAML::RelocType> {
|
|
static void enumeration(IO &IO, WasmYAML::RelocType &Kind);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::DylinkImportInfo> {
|
|
static void mapping(IO &IO, WasmYAML::DylinkImportInfo &Info);
|
|
};
|
|
|
|
template <> struct MappingTraits<WasmYAML::DylinkExportInfo> {
|
|
static void mapping(IO &IO, WasmYAML::DylinkExportInfo &Info);
|
|
};
|
|
|
|
} // end namespace yaml
|
|
} // end namespace llvm
|
|
|
|
#endif // LLVM_OBJECTYAML_WASMYAML_H
|