[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