[llvm] r272049 - [yaml] Add a ScalarTraits for mapping endian aware types.
Zachary Turner via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 7 12:32:09 PDT 2016
Author: zturner
Date: Tue Jun 7 14:32:09 2016
New Revision: 272049
URL: http://llvm.org/viewvc/llvm-project?rev=272049&view=rev
Log:
[yaml] Add a ScalarTraits for mapping endian aware types.
This allows mapping of any endian-aware type whose underlying
type (e.g. uint32_t) provides a ScalarTraits specialization.
Reviewed by: majnemer
Differential Revision: http://reviews.llvm.org/D21057
Modified:
llvm/trunk/include/llvm/Support/YAMLTraits.h
llvm/trunk/unittests/Support/YAMLIOTest.cpp
Modified: llvm/trunk/include/llvm/Support/YAMLTraits.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/YAMLTraits.h?rev=272049&r1=272048&r2=272049&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/YAMLTraits.h (original)
+++ llvm/trunk/include/llvm/Support/YAMLTraits.h Tue Jun 7 14:32:09 2016
@@ -17,6 +17,7 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/YAMLParser.h"
@@ -856,6 +857,32 @@ struct ScalarTraits<double> {
static bool mustQuote(StringRef) { return false; }
};
+// For endian types, we just use the existing ScalarTraits for the underlying
+// type. This way endian aware types are supported whenever a ScalarTraits
+// is defined for the underlying type.
+template <typename value_type, support::endianness endian, size_t alignment>
+struct ScalarTraits<support::detail::packed_endian_specific_integral<
+ value_type, endian, alignment>> {
+ typedef support::detail::packed_endian_specific_integral<value_type, endian,
+ alignment>
+ endian_type;
+
+ static void output(const endian_type &E, void *Ctx,
+ llvm::raw_ostream &Stream) {
+ ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream);
+ }
+ static StringRef input(StringRef Str, void *Ctx, endian_type &E) {
+ value_type V;
+ auto R = ScalarTraits<value_type>::input(Str, Ctx, V);
+ E = static_cast<endian_type>(V);
+ return R;
+ }
+
+ static bool mustQuote(StringRef Str) {
+ return ScalarTraits<value_type>::mustQuote(Str);
+ }
+};
+
// Utility for use within MappingTraits<>::mapping() method
// to [de]normalize an object for use with YAML conversion.
template <typename TNorm, typename TFinal>
Modified: llvm/trunk/unittests/Support/YAMLIOTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/YAMLIOTest.cpp?rev=272049&r1=272048&r2=272049&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/YAMLIOTest.cpp (original)
+++ llvm/trunk/unittests/Support/YAMLIOTest.cpp Tue Jun 7 14:32:09 2016
@@ -9,6 +9,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/YAMLTraits.h"
#include "gtest/gtest.h"
@@ -388,6 +389,111 @@ TEST(YAMLIO, TestReadWriteBuiltInTypes)
}
}
+//===----------------------------------------------------------------------===//
+// Test endian-aware types
+//===----------------------------------------------------------------------===//
+
+struct EndianTypes {
+ typedef llvm::support::detail::packed_endian_specific_integral<
+ float, llvm::support::little, llvm::support::unaligned>
+ ulittle_float;
+ typedef llvm::support::detail::packed_endian_specific_integral<
+ double, llvm::support::little, llvm::support::unaligned>
+ ulittle_double;
+
+ llvm::support::ulittle64_t u64;
+ llvm::support::ulittle32_t u32;
+ llvm::support::ulittle16_t u16;
+ llvm::support::little64_t s64;
+ llvm::support::little32_t s32;
+ llvm::support::little16_t s16;
+ ulittle_float f;
+ ulittle_double d;
+};
+
+namespace llvm {
+namespace yaml {
+template <> struct MappingTraits<EndianTypes> {
+ static void mapping(IO &io, EndianTypes &et) {
+ io.mapRequired("u64", et.u64);
+ io.mapRequired("u32", et.u32);
+ io.mapRequired("u16", et.u16);
+ io.mapRequired("s64", et.s64);
+ io.mapRequired("s32", et.s32);
+ io.mapRequired("s16", et.s16);
+ io.mapRequired("f", et.f);
+ io.mapRequired("d", et.d);
+ }
+};
+}
+}
+
+//
+// Test the reading of all endian scalar conversions
+//
+TEST(YAMLIO, TestReadEndianTypes) {
+ EndianTypes map;
+ Input yin("---\n"
+ "u64: 5000000000\n"
+ "u32: 4000000000\n"
+ "u16: 65000\n"
+ "s64: -5000000000\n"
+ "s32: -2000000000\n"
+ "s16: -32000\n"
+ "f: 3.25\n"
+ "d: -2.8625\n"
+ "...\n");
+ yin >> map;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(map.u64, 5000000000ULL);
+ EXPECT_EQ(map.u32, 4000000000U);
+ EXPECT_EQ(map.u16, 65000);
+ EXPECT_EQ(map.s64, -5000000000LL);
+ EXPECT_EQ(map.s32, -2000000000L);
+ EXPECT_EQ(map.s16, -32000);
+ EXPECT_EQ(map.f, 3.25f);
+ EXPECT_EQ(map.d, -2.8625);
+}
+
+//
+// Test writing then reading back all endian-aware scalar types
+//
+TEST(YAMLIO, TestReadWriteEndianTypes) {
+ std::string intermediate;
+ {
+ EndianTypes map;
+ map.u64 = 6000000000ULL;
+ map.u32 = 3000000000U;
+ map.u16 = 50000;
+ map.s64 = -6000000000LL;
+ map.s32 = -2000000000;
+ map.s16 = -32000;
+ map.f = 3.25f;
+ map.d = -2.8625;
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << map;
+ }
+
+ {
+ Input yin(intermediate);
+ EndianTypes map;
+ yin >> map;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(map.u64, 6000000000ULL);
+ EXPECT_EQ(map.u32, 3000000000U);
+ EXPECT_EQ(map.u16, 50000);
+ EXPECT_EQ(map.s64, -6000000000LL);
+ EXPECT_EQ(map.s32, -2000000000L);
+ EXPECT_EQ(map.s16, -32000);
+ EXPECT_EQ(map.f, 3.25f);
+ EXPECT_EQ(map.d, -2.8625);
+ }
+}
+
struct StringTypes {
llvm::StringRef str1;
llvm::StringRef str2;
More information about the llvm-commits
mailing list