summaryrefslogtreecommitdiff
path: root/lib/BinaryFormat
diff options
context:
space:
mode:
Diffstat (limited to 'lib/BinaryFormat')
-rw-r--r--lib/BinaryFormat/AMDGPUMetadataVerifier.cpp324
-rw-r--r--lib/BinaryFormat/CMakeLists.txt4
-rw-r--r--lib/BinaryFormat/Dwarf.cpp40
-rw-r--r--lib/BinaryFormat/Magic.cpp2
-rw-r--r--lib/BinaryFormat/MsgPackReader.cpp255
-rw-r--r--lib/BinaryFormat/MsgPackTypes.cpp303
-rw-r--r--lib/BinaryFormat/MsgPackWriter.cpp209
-rw-r--r--lib/BinaryFormat/Wasm.cpp6
8 files changed, 1136 insertions, 7 deletions
diff --git a/lib/BinaryFormat/AMDGPUMetadataVerifier.cpp b/lib/BinaryFormat/AMDGPUMetadataVerifier.cpp
new file mode 100644
index 000000000000..b789f646b5f6
--- /dev/null
+++ b/lib/BinaryFormat/AMDGPUMetadataVerifier.cpp
@@ -0,0 +1,324 @@
+//===- AMDGPUMetadataVerifier.cpp - MsgPack Types ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Implements a verifier for AMDGPU HSA metadata.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h"
+#include "llvm/Support/AMDGPUMetadata.h"
+
+namespace llvm {
+namespace AMDGPU {
+namespace HSAMD {
+namespace V3 {
+
+bool MetadataVerifier::verifyScalar(
+ msgpack::Node &Node, msgpack::ScalarNode::ScalarKind SKind,
+ function_ref<bool(msgpack::ScalarNode &)> verifyValue) {
+ auto ScalarPtr = dyn_cast<msgpack::ScalarNode>(&Node);
+ if (!ScalarPtr)
+ return false;
+ auto &Scalar = *ScalarPtr;
+ // Do not output extraneous tags for types we know from the spec.
+ Scalar.IgnoreTag = true;
+ if (Scalar.getScalarKind() != SKind) {
+ if (Strict)
+ return false;
+ // If we are not strict, we interpret string values as "implicitly typed"
+ // and attempt to coerce them to the expected type here.
+ if (Scalar.getScalarKind() != msgpack::ScalarNode::SK_String)
+ return false;
+ std::string StringValue = Scalar.getString();
+ Scalar.setScalarKind(SKind);
+ if (Scalar.inputYAML(StringValue) != StringRef())
+ return false;
+ }
+ if (verifyValue)
+ return verifyValue(Scalar);
+ return true;
+}
+
+bool MetadataVerifier::verifyInteger(msgpack::Node &Node) {
+ if (!verifyScalar(Node, msgpack::ScalarNode::SK_UInt))
+ if (!verifyScalar(Node, msgpack::ScalarNode::SK_Int))
+ return false;
+ return true;
+}
+
+bool MetadataVerifier::verifyArray(
+ msgpack::Node &Node, function_ref<bool(msgpack::Node &)> verifyNode,
+ Optional<size_t> Size) {
+ auto ArrayPtr = dyn_cast<msgpack::ArrayNode>(&Node);
+ if (!ArrayPtr)
+ return false;
+ auto &Array = *ArrayPtr;
+ if (Size && Array.size() != *Size)
+ return false;
+ for (auto &Item : Array)
+ if (!verifyNode(*Item.get()))
+ return false;
+
+ return true;
+}
+
+bool MetadataVerifier::verifyEntry(
+ msgpack::MapNode &MapNode, StringRef Key, bool Required,
+ function_ref<bool(msgpack::Node &)> verifyNode) {
+ auto Entry = MapNode.find(Key);
+ if (Entry == MapNode.end())
+ return !Required;
+ return verifyNode(*Entry->second.get());
+}
+
+bool MetadataVerifier::verifyScalarEntry(
+ msgpack::MapNode &MapNode, StringRef Key, bool Required,
+ msgpack::ScalarNode::ScalarKind SKind,
+ function_ref<bool(msgpack::ScalarNode &)> verifyValue) {
+ return verifyEntry(MapNode, Key, Required, [=](msgpack::Node &Node) {
+ return verifyScalar(Node, SKind, verifyValue);
+ });
+}
+
+bool MetadataVerifier::verifyIntegerEntry(msgpack::MapNode &MapNode,
+ StringRef Key, bool Required) {
+ return verifyEntry(MapNode, Key, Required, [this](msgpack::Node &Node) {
+ return verifyInteger(Node);
+ });
+}
+
+bool MetadataVerifier::verifyKernelArgs(msgpack::Node &Node) {
+ auto ArgsMapPtr = dyn_cast<msgpack::MapNode>(&Node);
+ if (!ArgsMapPtr)
+ return false;
+ auto &ArgsMap = *ArgsMapPtr;
+
+ if (!verifyScalarEntry(ArgsMap, ".name", false,
+ msgpack::ScalarNode::SK_String))
+ return false;
+ if (!verifyScalarEntry(ArgsMap, ".type_name", false,
+ msgpack::ScalarNode::SK_String))
+ return false;
+ if (!verifyIntegerEntry(ArgsMap, ".size", true))
+ return false;
+ if (!verifyIntegerEntry(ArgsMap, ".offset", true))
+ return false;
+ if (!verifyScalarEntry(ArgsMap, ".value_kind", true,
+ msgpack::ScalarNode::SK_String,
+ [](msgpack::ScalarNode &SNode) {
+ return StringSwitch<bool>(SNode.getString())
+ .Case("by_value", true)
+ .Case("global_buffer", true)
+ .Case("dynamic_shared_pointer", true)
+ .Case("sampler", true)
+ .Case("image", true)
+ .Case("pipe", true)
+ .Case("queue", true)
+ .Case("hidden_global_offset_x", true)
+ .Case("hidden_global_offset_y", true)
+ .Case("hidden_global_offset_z", true)
+ .Case("hidden_none", true)
+ .Case("hidden_printf_buffer", true)
+ .Case("hidden_default_queue", true)
+ .Case("hidden_completion_action", true)
+ .Default(false);
+ }))
+ return false;
+ if (!verifyScalarEntry(ArgsMap, ".value_type", true,
+ msgpack::ScalarNode::SK_String,
+ [](msgpack::ScalarNode &SNode) {
+ return StringSwitch<bool>(SNode.getString())
+ .Case("struct", true)
+ .Case("i8", true)
+ .Case("u8", true)
+ .Case("i16", true)
+ .Case("u16", true)
+ .Case("f16", true)
+ .Case("i32", true)
+ .Case("u32", true)
+ .Case("f32", true)
+ .Case("i64", true)
+ .Case("u64", true)
+ .Case("f64", true)
+ .Default(false);
+ }))
+ return false;
+ if (!verifyIntegerEntry(ArgsMap, ".pointee_align", false))
+ return false;
+ if (!verifyScalarEntry(ArgsMap, ".address_space", false,
+ msgpack::ScalarNode::SK_String,
+ [](msgpack::ScalarNode &SNode) {
+ return StringSwitch<bool>(SNode.getString())
+ .Case("private", true)
+ .Case("global", true)
+ .Case("constant", true)
+ .Case("local", true)
+ .Case("generic", true)
+ .Case("region", true)
+ .Default(false);
+ }))
+ return false;
+ if (!verifyScalarEntry(ArgsMap, ".access", false,
+ msgpack::ScalarNode::SK_String,
+ [](msgpack::ScalarNode &SNode) {
+ return StringSwitch<bool>(SNode.getString())
+ .Case("read_only", true)
+ .Case("write_only", true)
+ .Case("read_write", true)
+ .Default(false);
+ }))
+ return false;
+ if (!verifyScalarEntry(ArgsMap, ".actual_access", false,
+ msgpack::ScalarNode::SK_String,
+ [](msgpack::ScalarNode &SNode) {
+ return StringSwitch<bool>(SNode.getString())
+ .Case("read_only", true)
+ .Case("write_only", true)
+ .Case("read_write", true)
+ .Default(false);
+ }))
+ return false;
+ if (!verifyScalarEntry(ArgsMap, ".is_const", false,
+ msgpack::ScalarNode::SK_Boolean))
+ return false;
+ if (!verifyScalarEntry(ArgsMap, ".is_restrict", false,
+ msgpack::ScalarNode::SK_Boolean))
+ return false;
+ if (!verifyScalarEntry(ArgsMap, ".is_volatile", false,
+ msgpack::ScalarNode::SK_Boolean))
+ return false;
+ if (!verifyScalarEntry(ArgsMap, ".is_pipe", false,
+ msgpack::ScalarNode::SK_Boolean))
+ return false;
+
+ return true;
+}
+
+bool MetadataVerifier::verifyKernel(msgpack::Node &Node) {
+ auto KernelMapPtr = dyn_cast<msgpack::MapNode>(&Node);
+ if (!KernelMapPtr)
+ return false;
+ auto &KernelMap = *KernelMapPtr;
+
+ if (!verifyScalarEntry(KernelMap, ".name", true,
+ msgpack::ScalarNode::SK_String))
+ return false;
+ if (!verifyScalarEntry(KernelMap, ".symbol", true,
+ msgpack::ScalarNode::SK_String))
+ return false;
+ if (!verifyScalarEntry(KernelMap, ".language", false,
+ msgpack::ScalarNode::SK_String,
+ [](msgpack::ScalarNode &SNode) {
+ return StringSwitch<bool>(SNode.getString())
+ .Case("OpenCL C", true)
+ .Case("OpenCL C++", true)
+ .Case("HCC", true)
+ .Case("HIP", true)
+ .Case("OpenMP", true)
+ .Case("Assembler", true)
+ .Default(false);
+ }))
+ return false;
+ if (!verifyEntry(
+ KernelMap, ".language_version", false, [this](msgpack::Node &Node) {
+ return verifyArray(
+ Node,
+ [this](msgpack::Node &Node) { return verifyInteger(Node); }, 2);
+ }))
+ return false;
+ if (!verifyEntry(KernelMap, ".args", false, [this](msgpack::Node &Node) {
+ return verifyArray(Node, [this](msgpack::Node &Node) {
+ return verifyKernelArgs(Node);
+ });
+ }))
+ return false;
+ if (!verifyEntry(KernelMap, ".reqd_workgroup_size", false,
+ [this](msgpack::Node &Node) {
+ return verifyArray(Node,
+ [this](msgpack::Node &Node) {
+ return verifyInteger(Node);
+ },
+ 3);
+ }))
+ return false;
+ if (!verifyEntry(KernelMap, ".workgroup_size_hint", false,
+ [this](msgpack::Node &Node) {
+ return verifyArray(Node,
+ [this](msgpack::Node &Node) {
+ return verifyInteger(Node);
+ },
+ 3);
+ }))
+ return false;
+ if (!verifyScalarEntry(KernelMap, ".vec_type_hint", false,
+ msgpack::ScalarNode::SK_String))
+ return false;
+ if (!verifyScalarEntry(KernelMap, ".device_enqueue_symbol", false,
+ msgpack::ScalarNode::SK_String))
+ return false;
+ if (!verifyIntegerEntry(KernelMap, ".kernarg_segment_size", true))
+ return false;
+ if (!verifyIntegerEntry(KernelMap, ".group_segment_fixed_size", true))
+ return false;
+ if (!verifyIntegerEntry(KernelMap, ".private_segment_fixed_size", true))
+ return false;
+ if (!verifyIntegerEntry(KernelMap, ".kernarg_segment_align", true))
+ return false;
+ if (!verifyIntegerEntry(KernelMap, ".wavefront_size", true))
+ return false;
+ if (!verifyIntegerEntry(KernelMap, ".sgpr_count", true))
+ return false;
+ if (!verifyIntegerEntry(KernelMap, ".vgpr_count", true))
+ return false;
+ if (!verifyIntegerEntry(KernelMap, ".max_flat_workgroup_size", true))
+ return false;
+ if (!verifyIntegerEntry(KernelMap, ".sgpr_spill_count", false))
+ return false;
+ if (!verifyIntegerEntry(KernelMap, ".vgpr_spill_count", false))
+ return false;
+
+ return true;
+}
+
+bool MetadataVerifier::verify(msgpack::Node &HSAMetadataRoot) {
+ auto RootMapPtr = dyn_cast<msgpack::MapNode>(&HSAMetadataRoot);
+ if (!RootMapPtr)
+ return false;
+ auto &RootMap = *RootMapPtr;
+
+ if (!verifyEntry(
+ RootMap, "amdhsa.version", true, [this](msgpack::Node &Node) {
+ return verifyArray(
+ Node,
+ [this](msgpack::Node &Node) { return verifyInteger(Node); }, 2);
+ }))
+ return false;
+ if (!verifyEntry(
+ RootMap, "amdhsa.printf", false, [this](msgpack::Node &Node) {
+ return verifyArray(Node, [this](msgpack::Node &Node) {
+ return verifyScalar(Node, msgpack::ScalarNode::SK_String);
+ });
+ }))
+ return false;
+ if (!verifyEntry(RootMap, "amdhsa.kernels", true,
+ [this](msgpack::Node &Node) {
+ return verifyArray(Node, [this](msgpack::Node &Node) {
+ return verifyKernel(Node);
+ });
+ }))
+ return false;
+
+ return true;
+}
+
+} // end namespace V3
+} // end namespace HSAMD
+} // end namespace AMDGPU
+} // end namespace llvm
diff --git a/lib/BinaryFormat/CMakeLists.txt b/lib/BinaryFormat/CMakeLists.txt
index 06826010c762..d645279d0ac5 100644
--- a/lib/BinaryFormat/CMakeLists.txt
+++ b/lib/BinaryFormat/CMakeLists.txt
@@ -1,6 +1,10 @@
add_llvm_library(LLVMBinaryFormat
+ AMDGPUMetadataVerifier.cpp
Dwarf.cpp
Magic.cpp
+ MsgPackReader.cpp
+ MsgPackTypes.cpp
+ MsgPackWriter.cpp
Wasm.cpp
ADDITIONAL_HEADER_DIRS
diff --git a/lib/BinaryFormat/Dwarf.cpp b/lib/BinaryFormat/Dwarf.cpp
index 5984de73ae63..46f8056774b7 100644
--- a/lib/BinaryFormat/Dwarf.cpp
+++ b/lib/BinaryFormat/Dwarf.cpp
@@ -13,6 +13,7 @@
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
@@ -300,7 +301,7 @@ StringRef llvm::dwarf::LanguageString(unsigned Language) {
switch (Language) {
default:
return StringRef();
-#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) \
+#define HANDLE_DW_LANG(ID, NAME, LOWER_BOUND, VERSION, VENDOR) \
case DW_LANG_##NAME: \
return "DW_LANG_" #NAME;
#include "llvm/BinaryFormat/Dwarf.def"
@@ -309,7 +310,7 @@ StringRef llvm::dwarf::LanguageString(unsigned Language) {
unsigned llvm::dwarf::getLanguage(StringRef LanguageString) {
return StringSwitch<unsigned>(LanguageString)
-#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) \
+#define HANDLE_DW_LANG(ID, NAME, LOWER_BOUND, VERSION, VENDOR) \
.Case("DW_LANG_" #NAME, DW_LANG_##NAME)
#include "llvm/BinaryFormat/Dwarf.def"
.Default(0);
@@ -319,7 +320,7 @@ unsigned llvm::dwarf::LanguageVersion(dwarf::SourceLanguage Lang) {
switch (Lang) {
default:
return 0;
-#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) \
+#define HANDLE_DW_LANG(ID, NAME, LOWER_BOUND, VERSION, VENDOR) \
case DW_LANG_##NAME: \
return VERSION;
#include "llvm/BinaryFormat/Dwarf.def"
@@ -330,13 +331,24 @@ unsigned llvm::dwarf::LanguageVendor(dwarf::SourceLanguage Lang) {
switch (Lang) {
default:
return 0;
-#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) \
+#define HANDLE_DW_LANG(ID, NAME, LOWER_BOUND, VERSION, VENDOR) \
case DW_LANG_##NAME: \
return DWARF_VENDOR_##VENDOR;
#include "llvm/BinaryFormat/Dwarf.def"
}
}
+Optional<unsigned> llvm::dwarf::LanguageLowerBound(dwarf::SourceLanguage Lang) {
+ switch (Lang) {
+ default:
+ return None;
+#define HANDLE_DW_LANG(ID, NAME, LOWER_BOUND, VERSION, VENDOR) \
+ case DW_LANG_##NAME: \
+ return LOWER_BOUND;
+#include "llvm/BinaryFormat/Dwarf.def"
+ }
+}
+
StringRef llvm::dwarf::CaseString(unsigned Case) {
switch (Case) {
case DW_ID_case_sensitive:
@@ -455,14 +467,32 @@ StringRef llvm::dwarf::RangeListEncodingString(unsigned Encoding) {
}
}
-StringRef llvm::dwarf::CallFrameString(unsigned Encoding) {
+StringRef llvm::dwarf::CallFrameString(unsigned Encoding,
+ Triple::ArchType Arch) {
+ assert(Arch != llvm::Triple::ArchType::UnknownArch);
+#define SELECT_AARCH64 (Arch == llvm::Triple::aarch64_be || Arch == llvm::Triple::aarch64)
+#define SELECT_MIPS64 Arch == llvm::Triple::mips64
+#define SELECT_SPARC (Arch == llvm::Triple::sparc || Arch == llvm::Triple::sparcv9)
+#define SELECT_X86 (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64)
+#define HANDLE_DW_CFA(ID, NAME)
+#define HANDLE_DW_CFA_PRED(ID, NAME, PRED) \
+ if (ID == Encoding && PRED) \
+ return "DW_CFA_" #NAME;
+#include "llvm/BinaryFormat/Dwarf.def"
+
switch (Encoding) {
default:
return StringRef();
+#define HANDLE_DW_CFA_PRED(ID, NAME, PRED)
#define HANDLE_DW_CFA(ID, NAME) \
case DW_CFA_##NAME: \
return "DW_CFA_" #NAME;
#include "llvm/BinaryFormat/Dwarf.def"
+
+#undef SELECT_X86
+#undef SELECT_SPARC
+#undef SELECT_MIPS64
+#undef SELECT_AARCH64
}
}
diff --git a/lib/BinaryFormat/Magic.cpp b/lib/BinaryFormat/Magic.cpp
index 5a339583fca1..78efa6ec87be 100644
--- a/lib/BinaryFormat/Magic.cpp
+++ b/lib/BinaryFormat/Magic.cpp
@@ -206,7 +206,7 @@ file_magic llvm::identify_magic(StringRef Magic) {
}
std::error_code llvm::identify_magic(const Twine &Path, file_magic &Result) {
- auto FileOrError = MemoryBuffer::getFile(Path);
+ auto FileOrError = MemoryBuffer::getFile(Path, -1LL, false);
if (!FileOrError)
return FileOrError.getError();
diff --git a/lib/BinaryFormat/MsgPackReader.cpp b/lib/BinaryFormat/MsgPackReader.cpp
new file mode 100644
index 000000000000..b510fdba9608
--- /dev/null
+++ b/lib/BinaryFormat/MsgPackReader.cpp
@@ -0,0 +1,255 @@
+//===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements a MessagePack reader.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/MsgPackReader.h"
+#include "llvm/BinaryFormat/MsgPack.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::support;
+using namespace msgpack;
+
+Reader::Reader(MemoryBufferRef InputBuffer)
+ : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
+ End(InputBuffer.getBufferEnd()) {}
+
+Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
+
+Expected<bool> Reader::read(Object &Obj) {
+ if (Current == End)
+ return false;
+
+ uint8_t FB = static_cast<uint8_t>(*Current++);
+
+ switch (FB) {
+ case FirstByte::Nil:
+ Obj.Kind = Type::Nil;
+ return true;
+ case FirstByte::True:
+ Obj.Kind = Type::Boolean;
+ Obj.Bool = true;
+ return true;
+ case FirstByte::False:
+ Obj.Kind = Type::Boolean;
+ Obj.Bool = false;
+ return true;
+ case FirstByte::Int8:
+ Obj.Kind = Type::Int;
+ return readInt<int8_t>(Obj);
+ case FirstByte::Int16:
+ Obj.Kind = Type::Int;
+ return readInt<int16_t>(Obj);
+ case FirstByte::Int32:
+ Obj.Kind = Type::Int;
+ return readInt<int32_t>(Obj);
+ case FirstByte::Int64:
+ Obj.Kind = Type::Int;
+ return readInt<int64_t>(Obj);
+ case FirstByte::UInt8:
+ Obj.Kind = Type::UInt;
+ return readUInt<uint8_t>(Obj);
+ case FirstByte::UInt16:
+ Obj.Kind = Type::UInt;
+ return readUInt<uint16_t>(Obj);
+ case FirstByte::UInt32:
+ Obj.Kind = Type::UInt;
+ return readUInt<uint32_t>(Obj);
+ case FirstByte::UInt64:
+ Obj.Kind = Type::UInt;
+ return readUInt<uint64_t>(Obj);
+ case FirstByte::Float32:
+ Obj.Kind = Type::Float;
+ if (sizeof(float) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Float32 with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Float = BitsToFloat(endian::read<uint32_t, Endianness>(Current));
+ Current += sizeof(float);
+ return true;
+ case FirstByte::Float64:
+ Obj.Kind = Type::Float;
+ if (sizeof(double) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Float64 with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Float = BitsToDouble(endian::read<uint64_t, Endianness>(Current));
+ Current += sizeof(double);
+ return true;
+ case FirstByte::Str8:
+ Obj.Kind = Type::String;
+ return readRaw<uint8_t>(Obj);
+ case FirstByte::Str16:
+ Obj.Kind = Type::String;
+ return readRaw<uint16_t>(Obj);
+ case FirstByte::Str32:
+ Obj.Kind = Type::String;
+ return readRaw<uint32_t>(Obj);
+ case FirstByte::Bin8:
+ Obj.Kind = Type::Binary;
+ return readRaw<uint8_t>(Obj);
+ case FirstByte::Bin16:
+ Obj.Kind = Type::Binary;
+ return readRaw<uint16_t>(Obj);
+ case FirstByte::Bin32:
+ Obj.Kind = Type::Binary;
+ return readRaw<uint32_t>(Obj);
+ case FirstByte::Array16:
+ Obj.Kind = Type::Array;
+ return readLength<uint16_t>(Obj);
+ case FirstByte::Array32:
+ Obj.Kind = Type::Array;
+ return readLength<uint32_t>(Obj);
+ case FirstByte::Map16:
+ Obj.Kind = Type::Map;
+ return readLength<uint16_t>(Obj);
+ case FirstByte::Map32:
+ Obj.Kind = Type::Map;
+ return readLength<uint32_t>(Obj);
+ case FirstByte::FixExt1:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext1);
+ case FirstByte::FixExt2:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext2);
+ case FirstByte::FixExt4:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext4);
+ case FirstByte::FixExt8:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext8);
+ case FirstByte::FixExt16:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext16);
+ case FirstByte::Ext8:
+ Obj.Kind = Type::Extension;
+ return readExt<uint8_t>(Obj);
+ case FirstByte::Ext16:
+ Obj.Kind = Type::Extension;
+ return readExt<uint16_t>(Obj);
+ case FirstByte::Ext32:
+ Obj.Kind = Type::Extension;
+ return readExt<uint32_t>(Obj);
+ }
+
+ if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {
+ Obj.Kind = Type::Int;
+ int8_t I;
+ static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes");
+ memcpy(&I, &FB, sizeof(FB));
+ Obj.Int = I;
+ return true;
+ }
+
+ if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {
+ Obj.Kind = Type::UInt;
+ Obj.UInt = FB;
+ return true;
+ }
+
+ if ((FB & FixBitsMask::String) == FixBits::String) {
+ Obj.Kind = Type::String;
+ uint8_t Size = FB & ~FixBitsMask::String;
+ return createRaw(Obj, Size);
+ }
+
+ if ((FB & FixBitsMask::Array) == FixBits::Array) {
+ Obj.Kind = Type::Array;
+ Obj.Length = FB & ~FixBitsMask::Array;
+ return true;
+ }
+
+ if ((FB & FixBitsMask::Map) == FixBits::Map) {
+ Obj.Kind = Type::Map;
+ Obj.Length = FB & ~FixBitsMask::Map;
+ return true;
+ }
+
+ return make_error<StringError>(
+ "Invalid first byte", std::make_error_code(std::errc::invalid_argument));
+}
+
+template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Raw with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ T Size = endian::read<T, Endianness>(Current);
+ Current += sizeof(T);
+ return createRaw(Obj, Size);
+}
+
+template <class T> Expected<bool> Reader::readInt(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Int with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));
+ Current += sizeof(T);
+ return true;
+}
+
+template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Int with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));
+ Current += sizeof(T);
+ return true;
+}
+
+template <class T> Expected<bool> Reader::readLength(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Map/Array with invalid length",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current));
+ Current += sizeof(T);
+ return true;
+}
+
+template <class T> Expected<bool> Reader::readExt(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Ext with invalid length",
+ std::make_error_code(std::errc::invalid_argument));
+ T Size = endian::read<T, Endianness>(Current);
+ Current += sizeof(T);
+ return createExt(Obj, Size);
+}
+
+Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
+ if (Size > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Raw with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Raw = StringRef(Current, Size);
+ Current += Size;
+ return true;
+}
+
+Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
+ if (Current == End)
+ return make_error<StringError>(
+ "Invalid Ext with no type",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Extension.Type = *Current++;
+ if (Size > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Ext with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Extension.Bytes = StringRef(Current, Size);
+ Current += Size;
+ return true;
+}
diff --git a/lib/BinaryFormat/MsgPackTypes.cpp b/lib/BinaryFormat/MsgPackTypes.cpp
new file mode 100644
index 000000000000..4a8f70b10fb8
--- /dev/null
+++ b/lib/BinaryFormat/MsgPackTypes.cpp
@@ -0,0 +1,303 @@
+//===- MsgPackTypes.cpp - MsgPack Types -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Implementation of types representing MessagePack "documents".
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/MsgPackTypes.h"
+#include "llvm/Support/Error.h"
+
+using namespace llvm;
+using namespace msgpack;
+
+namespace llvm {
+namespace msgpack {
+void ScalarNode::anchor() {}
+void ArrayNode::anchor() {}
+void MapNode::anchor() {}
+}
+}
+
+Expected<OptNodePtr> Node::readArray(Reader &MPReader, size_t Length) {
+ auto A = std::make_shared<ArrayNode>();
+ for (size_t I = 0; I < Length; ++I) {
+ auto OptNodeOrErr = Node::read(MPReader);
+ if (auto Err = OptNodeOrErr.takeError())
+ return std::move(Err);
+ if (!*OptNodeOrErr)
+ return make_error<StringError>(
+ "Insufficient array elements",
+ std::make_error_code(std::errc::invalid_argument));
+ A->push_back(std::move(**OptNodeOrErr));
+ }
+ return OptNodePtr(std::move(A));
+}
+
+Expected<OptNodePtr> Node::readMap(Reader &MPReader, size_t Length) {
+ auto M = std::make_shared<MapNode>();
+ for (size_t I = 0; I < Length; ++I) {
+ auto OptKeyOrErr = Node::read(MPReader);
+ if (auto Err = OptKeyOrErr.takeError())
+ return std::move(Err);
+ if (!*OptKeyOrErr)
+ return make_error<StringError>(
+ "Insufficient map elements",
+ std::make_error_code(std::errc::invalid_argument));
+ auto OptValOrErr = Node::read(MPReader);
+ if (auto Err = OptValOrErr.takeError())
+ return std::move(Err);
+ if (!*OptValOrErr)
+ return make_error<StringError>(
+ "Insufficient map elements",
+ std::make_error_code(std::errc::invalid_argument));
+ auto *Key = dyn_cast<ScalarNode>((*OptKeyOrErr)->get());
+ if (!Key)
+ return make_error<StringError>(
+ "Only string map keys are supported",
+ std::make_error_code(std::errc::invalid_argument));
+ if (Key->getScalarKind() != ScalarNode::SK_String)
+ return make_error<StringError>(
+ "Only string map keys are supported",
+ std::make_error_code(std::errc::invalid_argument));
+ M->try_emplace(Key->getString(), std::move(**OptValOrErr));
+ }
+ return OptNodePtr(std::move(M));
+}
+
+Expected<OptNodePtr> Node::read(Reader &MPReader) {
+ Object Obj;
+
+ auto ContinueOrErr = MPReader.read(Obj);
+ if (auto Err = ContinueOrErr.takeError())
+ return std::move(Err);
+ if (!*ContinueOrErr)
+ return None;
+
+ switch (Obj.Kind) {
+ case Type::Int:
+ return OptNodePtr(std::make_shared<ScalarNode>(Obj.Int));
+ case Type::UInt:
+ return OptNodePtr(std::make_shared<ScalarNode>(Obj.UInt));
+ case Type::Nil:
+ return OptNodePtr(std::make_shared<ScalarNode>());
+ case Type::Boolean:
+ return OptNodePtr(std::make_shared<ScalarNode>(Obj.Bool));
+ case Type::Float:
+ return OptNodePtr(std::make_shared<ScalarNode>(Obj.Float));
+ case Type::String:
+ return OptNodePtr(std::make_shared<ScalarNode>(Obj.Raw));
+ case Type::Binary:
+ return OptNodePtr(std::make_shared<ScalarNode>(Obj.Raw));
+ case Type::Array:
+ return Node::readArray(MPReader, Obj.Length);
+ case Type::Map:
+ return Node::readMap(MPReader, Obj.Length);
+ case Type::Extension:
+ return make_error<StringError>(
+ "Extension types are not supported",
+ std::make_error_code(std::errc::invalid_argument));
+ }
+ llvm_unreachable("msgpack::Type not handled");
+}
+
+void ScalarNode::destroy() {
+ switch (SKind) {
+ case SK_String:
+ case SK_Binary:
+ StringValue.~basic_string();
+ break;
+ default:
+ // POD types do not require destruction
+ break;
+ }
+}
+
+ScalarNode::ScalarNode(int64_t IntValue)
+ : Node(NK_Scalar), SKind(SK_Int), IntValue(IntValue) {}
+
+ScalarNode::ScalarNode(int32_t IntValue)
+ : ScalarNode(static_cast<int64_t>(IntValue)) {}
+
+ScalarNode::ScalarNode(uint64_t UIntValue)
+ : Node(NK_Scalar), SKind(SK_UInt), UIntValue(UIntValue) {}
+
+ScalarNode::ScalarNode(uint32_t IntValue)
+ : ScalarNode(static_cast<uint64_t>(IntValue)) {}
+
+ScalarNode::ScalarNode() : Node(NK_Scalar), SKind(SK_Nil) {}
+
+ScalarNode::ScalarNode(bool BoolValue)
+ : Node(NK_Scalar), SKind(SK_Boolean), BoolValue(BoolValue) {}
+
+ScalarNode::ScalarNode(double FloatValue)
+ : Node(NK_Scalar), SKind(SK_Float), BoolValue(FloatValue) {}
+
+ScalarNode::ScalarNode(StringRef StringValue)
+ : Node(NK_Scalar), SKind(SK_String) {
+ new (&this->StringValue) std::string(StringValue);
+}
+
+ScalarNode::ScalarNode(const char *StringValue)
+ : ScalarNode(StringRef(StringValue)) {}
+
+ScalarNode::ScalarNode(std::string &&StringValue)
+ : Node(NK_Scalar), SKind(SK_String) {
+ new (&this->StringValue) std::string(StringValue);
+}
+
+ScalarNode::ScalarNode(MemoryBufferRef BinaryValue)
+ : Node(NK_Scalar), SKind(SK_Binary) {
+ new (&StringValue) std::string(BinaryValue.getBuffer());
+}
+
+ScalarNode::~ScalarNode() { destroy(); }
+
+ScalarNode &ScalarNode::operator=(ScalarNode &&RHS) {
+ destroy();
+ switch (SKind = RHS.SKind) {
+ case SK_Int:
+ IntValue = RHS.IntValue;
+ break;
+ case SK_UInt:
+ UIntValue = RHS.UIntValue;
+ break;
+ case SK_Boolean:
+ BoolValue = RHS.BoolValue;
+ break;
+ case SK_Float:
+ FloatValue = RHS.FloatValue;
+ break;
+ case SK_String:
+ case SK_Binary:
+ new (&StringValue) std::string(std::move(RHS.StringValue));
+ break;
+ case SK_Nil:
+ // pass
+ break;
+ }
+ return *this;
+}
+
+StringRef ScalarNode::inputYAML(StringRef ScalarStr) {
+ switch (SKind) {
+ case SK_Int:
+ return yaml::ScalarTraits<int64_t>::input(ScalarStr, nullptr, IntValue);
+ case SK_UInt:
+ return yaml::ScalarTraits<uint64_t>::input(ScalarStr, nullptr, UIntValue);
+ case SK_Nil:
+ return StringRef();
+ case SK_Boolean:
+ return yaml::ScalarTraits<bool>::input(ScalarStr, nullptr, BoolValue);
+ case SK_Float:
+ return yaml::ScalarTraits<double>::input(ScalarStr, nullptr, FloatValue);
+ case SK_Binary:
+ case SK_String:
+ return yaml::ScalarTraits<std::string>::input(ScalarStr, nullptr,
+ StringValue);
+ }
+ llvm_unreachable("unrecognized ScalarKind");
+}
+
+void ScalarNode::outputYAML(raw_ostream &OS) const {
+ switch (SKind) {
+ case SK_Int:
+ yaml::ScalarTraits<int64_t>::output(IntValue, nullptr, OS);
+ break;
+ case SK_UInt:
+ yaml::ScalarTraits<uint64_t>::output(UIntValue, nullptr, OS);
+ break;
+ case SK_Nil:
+ yaml::ScalarTraits<StringRef>::output("", nullptr, OS);
+ break;
+ case SK_Boolean:
+ yaml::ScalarTraits<bool>::output(BoolValue, nullptr, OS);
+ break;
+ case SK_Float:
+ yaml::ScalarTraits<double>::output(FloatValue, nullptr, OS);
+ break;
+ case SK_Binary:
+ case SK_String:
+ yaml::ScalarTraits<std::string>::output(StringValue, nullptr, OS);
+ break;
+ }
+}
+
+yaml::QuotingType ScalarNode::mustQuoteYAML(StringRef ScalarStr) const {
+ switch (SKind) {
+ case SK_Int:
+ return yaml::ScalarTraits<int64_t>::mustQuote(ScalarStr);
+ case SK_UInt:
+ return yaml::ScalarTraits<uint64_t>::mustQuote(ScalarStr);
+ case SK_Nil:
+ return yaml::ScalarTraits<StringRef>::mustQuote(ScalarStr);
+ case SK_Boolean:
+ return yaml::ScalarTraits<bool>::mustQuote(ScalarStr);
+ case SK_Float:
+ return yaml::ScalarTraits<double>::mustQuote(ScalarStr);
+ case SK_Binary:
+ case SK_String:
+ return yaml::ScalarTraits<std::string>::mustQuote(ScalarStr);
+ }
+ llvm_unreachable("unrecognized ScalarKind");
+}
+
+const char *ScalarNode::IntTag = "!int";
+const char *ScalarNode::NilTag = "!nil";
+const char *ScalarNode::BooleanTag = "!bool";
+const char *ScalarNode::FloatTag = "!float";
+const char *ScalarNode::StringTag = "!str";
+const char *ScalarNode::BinaryTag = "!bin";
+
+StringRef ScalarNode::getYAMLTag() const {
+ switch (SKind) {
+ case SK_Int:
+ return IntTag;
+ case SK_UInt:
+ return IntTag;
+ case SK_Nil:
+ return NilTag;
+ case SK_Boolean:
+ return BooleanTag;
+ case SK_Float:
+ return FloatTag;
+ case SK_String:
+ return StringTag;
+ case SK_Binary:
+ return BinaryTag;
+ }
+ llvm_unreachable("unrecognized ScalarKind");
+}
+
+void ScalarNode::write(Writer &MPWriter) {
+ switch (SKind) {
+ case SK_Int:
+ MPWriter.write(IntValue);
+ break;
+ case SK_UInt:
+ MPWriter.write(UIntValue);
+ break;
+ case SK_Nil:
+ MPWriter.writeNil();
+ break;
+ case SK_Boolean:
+ MPWriter.write(BoolValue);
+ break;
+ case SK_Float:
+ MPWriter.write(FloatValue);
+ break;
+ case SK_String:
+ MPWriter.write(StringValue);
+ break;
+ case SK_Binary:
+ MPWriter.write(MemoryBufferRef(StringValue, ""));
+ break;
+ }
+}
diff --git a/lib/BinaryFormat/MsgPackWriter.cpp b/lib/BinaryFormat/MsgPackWriter.cpp
new file mode 100644
index 000000000000..d024bb0fcdb2
--- /dev/null
+++ b/lib/BinaryFormat/MsgPackWriter.cpp
@@ -0,0 +1,209 @@
+//===- MsgPackWriter.cpp - Simple MsgPack writer ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements a MessagePack writer.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/MsgPackWriter.h"
+#include "llvm/BinaryFormat/MsgPack.h"
+
+using namespace llvm;
+using namespace msgpack;
+
+Writer::Writer(raw_ostream &OS, bool Compatible)
+ : EW(OS, Endianness), Compatible(Compatible) {}
+
+void Writer::writeNil() { EW.write(FirstByte::Nil); }
+
+void Writer::write(bool b) { EW.write(b ? FirstByte::True : FirstByte::False); }
+
+void Writer::write(int64_t i) {
+ if (i >= 0) {
+ write(static_cast<uint64_t>(i));
+ return;
+ }
+
+ if (i >= FixMin::NegativeInt) {
+ EW.write(static_cast<int8_t>(i));
+ return;
+ }
+
+ if (i >= INT8_MIN) {
+ EW.write(FirstByte::Int8);
+ EW.write(static_cast<int8_t>(i));
+ return;
+ }
+
+ if (i >= INT16_MIN) {
+ EW.write(FirstByte::Int16);
+ EW.write(static_cast<int16_t>(i));
+ return;
+ }
+
+ if (i >= INT32_MIN) {
+ EW.write(FirstByte::Int32);
+ EW.write(static_cast<int32_t>(i));
+ return;
+ }
+
+ EW.write(FirstByte::Int64);
+ EW.write(i);
+}
+
+void Writer::write(uint64_t u) {
+ if (u <= FixMax::PositiveInt) {
+ EW.write(static_cast<uint8_t>(u));
+ return;
+ }
+
+ if (u <= UINT8_MAX) {
+ EW.write(FirstByte::UInt8);
+ EW.write(static_cast<uint8_t>(u));
+ return;
+ }
+
+ if (u <= UINT16_MAX) {
+ EW.write(FirstByte::UInt16);
+ EW.write(static_cast<uint16_t>(u));
+ return;
+ }
+
+ if (u <= UINT32_MAX) {
+ EW.write(FirstByte::UInt32);
+ EW.write(static_cast<uint32_t>(u));
+ return;
+ }
+
+ EW.write(FirstByte::UInt64);
+ EW.write(u);
+}
+
+void Writer::write(double d) {
+ // If no loss of precision, encode as a Float32.
+ double a = std::fabs(d);
+ if (a >= std::numeric_limits<float>::min() &&
+ a <= std::numeric_limits<float>::max()) {
+ EW.write(FirstByte::Float32);
+ EW.write(static_cast<float>(d));
+ } else {
+ EW.write(FirstByte::Float64);
+ EW.write(d);
+ }
+}
+
+void Writer::write(StringRef s) {
+ size_t Size = s.size();
+
+ if (Size <= FixMax::String)
+ EW.write(static_cast<uint8_t>(FixBits::String | Size));
+ else if (!Compatible && Size <= UINT8_MAX) {
+ EW.write(FirstByte::Str8);
+ EW.write(static_cast<uint8_t>(Size));
+ } else if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Str16);
+ EW.write(static_cast<uint16_t>(Size));
+ } else {
+ assert(Size <= UINT32_MAX && "String object too long to be encoded");
+ EW.write(FirstByte::Str32);
+ EW.write(static_cast<uint32_t>(Size));
+ }
+
+ EW.OS << s;
+}
+
+void Writer::write(MemoryBufferRef Buffer) {
+ assert(!Compatible && "Attempt to write Bin format in compatible mode");
+
+ size_t Size = Buffer.getBufferSize();
+
+ if (Size <= UINT8_MAX) {
+ EW.write(FirstByte::Bin8);
+ EW.write(static_cast<uint8_t>(Size));
+ } else if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Bin16);
+ EW.write(static_cast<uint16_t>(Size));
+ } else {
+ assert(Size <= UINT32_MAX && "Binary object too long to be encoded");
+ EW.write(FirstByte::Bin32);
+ EW.write(static_cast<uint32_t>(Size));
+ }
+
+ EW.OS.write(Buffer.getBufferStart(), Size);
+}
+
+void Writer::writeArraySize(uint32_t Size) {
+ if (Size <= FixMax::Array) {
+ EW.write(static_cast<uint8_t>(FixBits::Array | Size));
+ return;
+ }
+
+ if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Array16);
+ EW.write(static_cast<uint16_t>(Size));
+ return;
+ }
+
+ EW.write(FirstByte::Array32);
+ EW.write(Size);
+}
+
+void Writer::writeMapSize(uint32_t Size) {
+ if (Size <= FixMax::Map) {
+ EW.write(static_cast<uint8_t>(FixBits::Map | Size));
+ return;
+ }
+
+ if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Map16);
+ EW.write(static_cast<uint16_t>(Size));
+ return;
+ }
+
+ EW.write(FirstByte::Map32);
+ EW.write(Size);
+}
+
+void Writer::writeExt(int8_t Type, MemoryBufferRef Buffer) {
+ size_t Size = Buffer.getBufferSize();
+
+ switch (Size) {
+ case FixLen::Ext1:
+ EW.write(FirstByte::FixExt1);
+ break;
+ case FixLen::Ext2:
+ EW.write(FirstByte::FixExt2);
+ break;
+ case FixLen::Ext4:
+ EW.write(FirstByte::FixExt4);
+ break;
+ case FixLen::Ext8:
+ EW.write(FirstByte::FixExt8);
+ break;
+ case FixLen::Ext16:
+ EW.write(FirstByte::FixExt16);
+ break;
+ default:
+ if (Size <= UINT8_MAX) {
+ EW.write(FirstByte::Ext8);
+ EW.write(static_cast<uint8_t>(Size));
+ } else if (Size <= UINT16_MAX) {
+ EW.write(FirstByte::Ext16);
+ EW.write(static_cast<uint16_t>(Size));
+ } else {
+ assert(Size <= UINT32_MAX && "Ext size too large to be encoded");
+ EW.write(FirstByte::Ext32);
+ EW.write(static_cast<uint32_t>(Size));
+ }
+ }
+
+ EW.write(Type);
+ EW.OS.write(Buffer.getBufferStart(), Size);
+}
diff --git a/lib/BinaryFormat/Wasm.cpp b/lib/BinaryFormat/Wasm.cpp
index 35360d0ae4f0..94d40bf02a39 100644
--- a/lib/BinaryFormat/Wasm.cpp
+++ b/lib/BinaryFormat/Wasm.cpp
@@ -19,13 +19,17 @@ std::string llvm::wasm::toString(wasm::WasmSymbolType type) {
return "WASM_SYMBOL_TYPE_DATA";
case wasm::WASM_SYMBOL_TYPE_SECTION:
return "WASM_SYMBOL_TYPE_SECTION";
+ case wasm::WASM_SYMBOL_TYPE_EVENT:
+ return "WASM_SYMBOL_TYPE_EVENT";
}
llvm_unreachable("unknown symbol type");
}
std::string llvm::wasm::relocTypetoString(uint32_t type) {
switch (type) {
-#define WASM_RELOC(NAME, VALUE) case VALUE: return #NAME;
+#define WASM_RELOC(NAME, VALUE) \
+ case VALUE: \
+ return #NAME;
#include "llvm/BinaryFormat/WasmRelocs.def"
#undef WASM_RELOC
default: