[llvm] [SYCL][LLVM] Adding property set I/O library for SYCL (PR #110771)

Arvind Sudarsanam via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 14 18:12:32 PDT 2024


https://github.com/asudarsa updated https://github.com/llvm/llvm-project/pull/110771

>From 7350a52b10cded8efda062feb27fe00f61a0e1cb Mon Sep 17 00:00:00 2001
From: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
Date: Fri, 27 Sep 2024 13:08:02 -0700
Subject: [PATCH 01/13] [SYCL][LLVM] Adding property set I/O library for SYCL

SYCL objects are normally associated with properties that provide additional information about those objects. This information should be preserved during compilation and made available to the SYCL runtime via property sets.
This PR provides an implementation of a simple library which allows to construct and serialize/de-serialize a sequence of typed property sets, where each property is a <name,typed value> pair.

PropertyValue set format:
   '['<PropertyValue set name>']'
   <property name>=<property type>'|'<property value>
   <property name>=<property type>'|'<property value>
   ...
   '['<PropertyValue set name>']'
   <property name>=<property type>'|'<property value>
where
   <PropertyValue set name>, <property name> are strings
   <property type> - string representation of the property type
   <property value> - string representation of the property value.

For example:
[Staff/Ages]
person1=1|20
person2=1|25
[Staff/Experience]
person1=1|1
person2=1|2
person3=1|12

This library will be used in the SYCL offloading compilation flow to pass information about specialization constants, etc, to the SYCL runtime.

Signed-off-by: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
---
 llvm/include/llvm/Support/Base64.h           |  26 ++
 llvm/include/llvm/Support/PropertySetIO.h    | 256 +++++++++++++++++++
 llvm/lib/Support/CMakeLists.txt              |   1 +
 llvm/lib/Support/PropertySetIO.cpp           | 212 +++++++++++++++
 llvm/unittests/Support/CMakeLists.txt        |   1 +
 llvm/unittests/Support/PropertySetIOTest.cpp |  72 ++++++
 6 files changed, 568 insertions(+)
 create mode 100644 llvm/include/llvm/Support/PropertySetIO.h
 create mode 100644 llvm/lib/Support/PropertySetIO.cpp
 create mode 100644 llvm/unittests/Support/PropertySetIOTest.cpp

diff --git a/llvm/include/llvm/Support/Base64.h b/llvm/include/llvm/Support/Base64.h
index 3d96884749b32f..91317ffeca4170 100644
--- a/llvm/include/llvm/Support/Base64.h
+++ b/llvm/include/llvm/Support/Base64.h
@@ -56,6 +56,32 @@ template <class InputBytes> std::string encodeBase64(InputBytes const &Bytes) {
 
 llvm::Error decodeBase64(llvm::StringRef Input, std::vector<char> &Output);
 
+// General-purpose Base64 encoder/decoder class wrapper.
+class Base64 {
+public:
+  using byte = uint8_t;
+
+  // Get the size of the encoded byte sequence of given size.
+  static size_t getEncodedSize(size_t SrcSize);
+
+  // Encode a byte sequence of given size into an output stream.
+  // Returns the number of bytes in the encoded result.
+  static size_t encode(const byte *Src, raw_ostream &Out, size_t SrcSize);
+
+  // Get the size of the encoded byte sequence of given size.
+  static size_t getDecodedSize(size_t SrcSize);
+
+  // Decode a sequence of given size into a pre-allocated memory.
+  // Returns the number of bytes in the decoded result or 0 in case of error.
+  static Expected<size_t> decode(const char *Src, byte *Dst, size_t SrcSize);
+
+  // Allocate minimum required amount of memory and decode a sequence of given
+  // size into it.
+  // Returns the decoded result. The size can be obtained via getDecodedSize.
+  static Expected<std::unique_ptr<byte[]>> decode(const char *Src,
+                                                  size_t SrcSize);
+};
+
 } // end namespace llvm
 
 #endif
diff --git a/llvm/include/llvm/Support/PropertySetIO.h b/llvm/include/llvm/Support/PropertySetIO.h
new file mode 100644
index 00000000000000..9f02cfd31f54ec
--- /dev/null
+++ b/llvm/include/llvm/Support/PropertySetIO.h
@@ -0,0 +1,256 @@
+//==-- PropertySetIO.h -- models a sequence of property sets and their I/O -==//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// Models a sequence of property sets and their input and output operations.
+// TODO use Yaml as I/O engine.
+// PropertyValue set format:
+//   '['<PropertyValue set name>']'
+//   <property name>=<property type>'|'<property value>
+//   <property name>=<property type>'|'<property value>
+//   ...
+//   '['<PropertyValue set name>']'
+//   <property name>=<property type>'|'<property value>
+// where
+//   <PropertyValue set name>, <property name> are strings
+//   <property type> - string representation of the property type
+//   <property value> - string representation of the property value.
+//
+// For example:
+// [Staff/Ages]
+// person1=1|20
+// person2=1|25
+// [Staff/Experience]
+// person1=1|1
+// person2=1|2
+// person3=1|12
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_PROPERTYSETIO_H
+#define LLVM_SUPPORT_PROPERTYSETIO_H
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/xxhash.h"
+
+namespace llvm {
+namespace util {
+
+// Represents a property value. PropertyValue name is stored in the encompassing
+// container.
+class PropertyValue {
+public:
+  // Type of the size of the value. Value size gets serialized along with the
+  // value data in some cases for later reading at runtime, so size_t is not
+  // suitable as its size varies.
+  using SizeTy = uint64_t;
+  using byte = uint8_t;
+
+  // Defines supported property types
+  enum Type { first = 0, NONE = first, UINT32, BYTE_ARRAY, last = BYTE_ARRAY };
+
+  // Translates C++ type to the corresponding type tag.
+  template <typename T> static Type getTypeTag();
+
+  // Casts from int value to a type tag.
+  static Expected<Type> getTypeTag(int T) {
+    if (T < first || T > last)
+      return createStringError(std::error_code(), "bad property type ", T);
+    return static_cast<Type>(T);
+  }
+
+  ~PropertyValue() {
+    if ((getType() == BYTE_ARRAY) && Val.ByteArrayVal)
+      delete[] Val.ByteArrayVal;
+  }
+
+  PropertyValue() = default;
+  PropertyValue(Type T) : Ty(T) {}
+
+  PropertyValue(uint32_t Val) : Ty(UINT32), Val({Val}) {}
+  PropertyValue(const byte *Data, SizeTy DataBitSize);
+  template <typename C, typename T = typename C::value_type>
+  PropertyValue(const C &Data)
+      : PropertyValue(reinterpret_cast<const byte *>(Data.data()),
+                      Data.size() * sizeof(T) * /* bits in one byte */ 8) {}
+  PropertyValue(const llvm::StringRef &Str)
+      : PropertyValue(reinterpret_cast<const byte *>(Str.data()),
+                      Str.size() * sizeof(char) * /* bits in one byte */ 8) {}
+  PropertyValue(const PropertyValue &P);
+  PropertyValue(PropertyValue &&P);
+
+  PropertyValue &operator=(PropertyValue &&P);
+
+  PropertyValue &operator=(const PropertyValue &P);
+
+  // get property value as unsigned 32-bit integer
+  uint32_t asUint32() const {
+    if (Ty != UINT32)
+      llvm_unreachable("must be UINT32 value");
+    return Val.UInt32Val;
+  }
+
+  // Get raw data size in bits.
+  SizeTy getByteArraySizeInBits() const {
+    if (Ty != BYTE_ARRAY)
+      llvm_unreachable("must be BYTE_ARRAY value");
+    SizeTy Res = 0;
+
+    for (size_t I = 0; I < sizeof(SizeTy); ++I)
+      Res |= (SizeTy)Val.ByteArrayVal[I] << (8 * I);
+    return Res;
+  }
+
+  // Get byte array data size in bytes.
+  SizeTy getByteArraySize() const {
+    SizeTy SizeInBits = getByteArraySizeInBits();
+    constexpr unsigned int MASK = 0x7;
+    return ((SizeInBits + MASK) & ~MASK) / 8;
+  }
+
+  // Get byte array data size in bytes, including the leading bytes encoding the
+  // size.
+  SizeTy getRawByteArraySize() const {
+    return getByteArraySize() + sizeof(SizeTy);
+  }
+
+  // Get byte array data including the leading bytes encoding the size.
+  const byte *asRawByteArray() const {
+    if (Ty != BYTE_ARRAY)
+      llvm_unreachable("must be BYTE_ARRAY value");
+    return Val.ByteArrayVal;
+  }
+
+  // Get byte array data excluding the leading bytes encoding the size.
+  const byte *asByteArray() const {
+    if (Ty != BYTE_ARRAY)
+      llvm_unreachable("must be BYTE_ARRAY value");
+    return Val.ByteArrayVal + sizeof(SizeTy);
+  }
+
+  bool isValid() const { return getType() != NONE; }
+
+  // set property value; the 'T' type must be convertible to a property type tag
+  template <typename T> void set(T V) {
+    if (getTypeTag<T>() != Ty)
+      llvm_unreachable("invalid type tag for this operation");
+    getValueRef<T>() = V;
+  }
+
+  Type getType() const { return Ty; }
+
+  SizeTy size() const {
+    switch (Ty) {
+    case UINT32:
+      return sizeof(Val.UInt32Val);
+    case BYTE_ARRAY:
+      return getRawByteArraySize();
+    default:
+      llvm_unreachable_internal("unsupported property type");
+    }
+  }
+
+private:
+  template <typename T> T &getValueRef();
+  void copy(const PropertyValue &P);
+
+  Type Ty = NONE;
+  // TODO: replace this union with std::variant when uplifting to C++17
+  union {
+    uint32_t UInt32Val;
+    // Holds first sizeof(size_t) bytes of size followed by actual raw data.
+    byte *ByteArrayVal;
+  } Val;
+};
+
+/// Structure for specialization of DenseMap in PropertySetRegistry.
+struct PropertySetKeyInfo {
+  static unsigned getHashValue(const SmallString<16> &K) { return xxHash64(K); }
+
+  static SmallString<16> getEmptyKey() { return SmallString<16>(""); }
+
+  static SmallString<16> getTombstoneKey() { return SmallString<16>("_"); }
+
+  static bool isEqual(StringRef L, StringRef R) { return L == R; }
+};
+
+using PropertyMapTy = DenseMap<SmallString<16>, unsigned, PropertySetKeyInfo>;
+/// A property set. Preserves insertion order when iterating elements.
+using PropertySet = MapVector<SmallString<16>, PropertyValue, PropertyMapTy>;
+
+/// A registry of property sets. Maps a property set name to its
+/// content.
+///
+/// The order of keys is preserved and corresponds to the order of insertion.
+class PropertySetRegistry {
+public:
+  using MapTy = MapVector<SmallString<16>, PropertySet, PropertyMapTy>;
+
+  // Specific property category names used by tools.
+  static constexpr char SYCL_SPECIALIZATION_CONSTANTS[] =
+      "SYCL/specialization constants";
+  static constexpr char SYCL_SPEC_CONSTANTS_DEFAULT_VALUES[] =
+      "SYCL/specialization constants default values";
+  static constexpr char SYCL_DEVICELIB_REQ_MASK[] = "SYCL/devicelib req mask";
+  static constexpr char SYCL_KERNEL_PARAM_OPT_INFO[] = "SYCL/kernel param opt";
+  static constexpr char SYCL_PROGRAM_METADATA[] = "SYCL/program metadata";
+  static constexpr char SYCL_MISC_PROP[] = "SYCL/misc properties";
+  static constexpr char SYCL_ASSERT_USED[] = "SYCL/assert used";
+  static constexpr char SYCL_EXPORTED_SYMBOLS[] = "SYCL/exported symbols";
+  static constexpr char SYCL_IMPORTED_SYMBOLS[] = "SYCL/imported symbols";
+  static constexpr char SYCL_DEVICE_GLOBALS[] = "SYCL/device globals";
+  static constexpr char SYCL_DEVICE_REQUIREMENTS[] = "SYCL/device requirements";
+  static constexpr char SYCL_HOST_PIPES[] = "SYCL/host pipes";
+  static constexpr char SYCL_VIRTUAL_FUNCTIONS[] = "SYCL/virtual functions";
+
+  /// Function for bulk addition of an entire property set in the given
+  /// \p Category .
+  template <typename MapTy> void add(StringRef Category, const MapTy &Props) {
+    assert(PropSetMap.find(Category) == PropSetMap.end() &&
+           "category already added");
+    auto &PropSet = PropSetMap[Category];
+
+    for (const auto &Prop : Props)
+      PropSet.insert_or_assign(Prop.first, PropertyValue(Prop.second));
+  }
+
+  /// Adds the given \p PropVal with the given \p PropName into the given \p
+  /// Category .
+  template <typename T>
+  void add(StringRef Category, StringRef PropName, const T &PropVal) {
+    auto &PropSet = PropSetMap[Category];
+    PropSet.insert({PropName, PropertyValue(PropVal)});
+  }
+
+  /// Parses from the given \p Buf a property set registry.
+  static Expected<std::unique_ptr<PropertySetRegistry>>
+  read(const MemoryBuffer *Buf);
+
+  /// Dumps the property set registry to the given \p Out stream.
+  void write(raw_ostream &Out) const;
+
+  MapTy::const_iterator begin() const { return PropSetMap.begin(); }
+  MapTy::const_iterator end() const { return PropSetMap.end(); }
+
+  /// Retrieves a property set with given \p Name .
+  PropertySet &operator[](StringRef Name) { return PropSetMap[Name]; }
+  /// Constant access to the underlying map.
+  const MapTy &getPropSets() const { return PropSetMap; }
+
+private:
+  MapTy PropSetMap;
+};
+
+} // namespace util
+
+} // namespace llvm
+
+#endif // #define LLVM_SUPPORT_PROPERTYSETIO_H
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 97188b0672f032..0a4d86bfca5121 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -217,6 +217,7 @@ add_llvm_component_library(LLVMSupport
   Parallel.cpp
   PluginLoader.cpp
   PrettyStackTrace.cpp
+  PropertySetIO.cpp  
   RandomNumberGenerator.cpp
   Regex.cpp
   RewriteBuffer.cpp
diff --git a/llvm/lib/Support/PropertySetIO.cpp b/llvm/lib/Support/PropertySetIO.cpp
new file mode 100644
index 00000000000000..2fe7cac00fb144
--- /dev/null
+++ b/llvm/lib/Support/PropertySetIO.cpp
@@ -0,0 +1,212 @@
+//==- PropertySetIO.cpp - models a sequence of property sets and their I/O -==//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/PropertySetIO.h"
+
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Base64.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/LineIterator.h"
+
+#include <memory>
+#include <string>
+
+using namespace llvm::util;
+using namespace llvm;
+
+namespace {
+
+using byte = Base64::byte;
+
+::llvm::Error makeError(const Twine &Msg) {
+  return createStringError(std::error_code{}, Msg);
+}
+
+} // anonymous namespace
+
+Expected<std::unique_ptr<PropertySetRegistry>>
+PropertySetRegistry::read(const MemoryBuffer *Buf) {
+  auto Res = std::make_unique<PropertySetRegistry>();
+  PropertySet *CurPropSet = nullptr;
+
+  for (line_iterator LI(*Buf); !LI.is_at_end(); LI++) {
+    // see if this line starts a new property set
+    if (LI->starts_with("[")) {
+      // yes - parse the category (property name)
+      auto EndPos = LI->rfind(']');
+      if (EndPos == StringRef::npos)
+        return makeError("invalid line: " + *LI);
+      StringRef Category = LI->substr(1, EndPos - 1);
+      CurPropSet = &(*Res)[Category];
+      continue;
+    }
+    if (!CurPropSet)
+      return makeError("property category missing");
+    // parse name and type+value
+    auto Parts = LI->split('=');
+
+    if (Parts.first.empty() || Parts.second.empty())
+      return makeError("invalid property line: " + *LI);
+    auto TypeVal = Parts.second.split('|');
+
+    if (TypeVal.first.empty() || TypeVal.second.empty())
+      return makeError("invalid property value: " + Parts.second);
+    APInt Tint;
+
+    // parse type
+    if (TypeVal.first.getAsInteger(10, Tint))
+      return makeError("invalid property type: " + TypeVal.first);
+    Expected<PropertyValue::Type> Ttag =
+        PropertyValue::getTypeTag(static_cast<int>(Tint.getSExtValue()));
+    StringRef Val = TypeVal.second;
+
+    if (!Ttag)
+      return Ttag.takeError();
+    PropertyValue Prop(Ttag.get());
+
+    // parse value depending on its type
+    switch (Ttag.get()) {
+    case PropertyValue::Type::UINT32: {
+      APInt ValV;
+      if (Val.getAsInteger(10, ValV))
+        return createStringError(std::error_code{},
+                                 "invalid property value: ", Val.data());
+      Prop.set(static_cast<uint32_t>(ValV.getZExtValue()));
+      break;
+    }
+    case PropertyValue::Type::BYTE_ARRAY: {
+      Expected<std::unique_ptr<byte[]>> DecArr =
+          Base64::decode(Val.data(), Val.size());
+      if (!DecArr)
+        return DecArr.takeError();
+      Prop.set(DecArr.get().release());
+      break;
+    }
+    default:
+      return createStringError(std::error_code{},
+                               "unsupported property type: ", Ttag.get());
+    }
+    (*CurPropSet)[Parts.first] = std::move(Prop);
+  }
+  if (!CurPropSet)
+    return makeError("invalid property set registry");
+
+  return Expected<std::unique_ptr<PropertySetRegistry>>(std::move(Res));
+}
+
+namespace llvm {
+// output a property to a stream
+raw_ostream &operator<<(raw_ostream &Out, const PropertyValue &Prop) {
+  Out << static_cast<int>(Prop.getType()) << "|";
+  switch (Prop.getType()) {
+  case PropertyValue::Type::UINT32:
+    Out << Prop.asUint32();
+    break;
+  case PropertyValue::Type::BYTE_ARRAY: {
+    util::PropertyValue::SizeTy Size = Prop.getRawByteArraySize();
+    Base64::encode(Prop.asRawByteArray(), Out, (size_t)Size);
+    break;
+  }
+  default:
+    llvm_unreachable(
+        ("unsupported property type: " + utostr(Prop.getType())).c_str());
+  }
+  return Out;
+}
+} // namespace llvm
+
+void PropertySetRegistry::write(raw_ostream &Out) const {
+  for (const auto &PropSet : PropSetMap) {
+    Out << "[" << PropSet.first << "]\n";
+
+    for (const auto &Props : PropSet.second) {
+      Out << Props.first << "=" << Props.second << "\n";
+    }
+  }
+}
+
+namespace llvm {
+namespace util {
+
+template <> uint32_t &PropertyValue::getValueRef<uint32_t>() {
+  return Val.UInt32Val;
+}
+
+template <> byte *&PropertyValue::getValueRef<byte *>() {
+  return Val.ByteArrayVal;
+}
+
+template <> PropertyValue::Type PropertyValue::getTypeTag<uint32_t>() {
+  return UINT32;
+}
+
+template <> PropertyValue::Type PropertyValue::getTypeTag<byte *>() {
+  return BYTE_ARRAY;
+}
+
+PropertyValue::PropertyValue(const byte *Data, SizeTy DataBitSize) {
+  constexpr int ByteSizeInBits = 8;
+  Ty = BYTE_ARRAY;
+  SizeTy DataSize = (DataBitSize + (ByteSizeInBits - 1)) / ByteSizeInBits;
+  constexpr size_t SizeFieldSize = sizeof(SizeTy);
+
+  // Allocate space for size and data.
+  Val.ByteArrayVal = new byte[SizeFieldSize + DataSize];
+
+  // Write the size into first bytes.
+  for (size_t I = 0; I < SizeFieldSize; ++I) {
+    Val.ByteArrayVal[I] = (byte)DataBitSize;
+    DataBitSize >>= ByteSizeInBits;
+  }
+  // Append data.
+  std::memcpy(Val.ByteArrayVal + SizeFieldSize, Data, DataSize);
+}
+
+PropertyValue::PropertyValue(const PropertyValue &P) { *this = P; }
+
+PropertyValue::PropertyValue(PropertyValue &&P) { *this = std::move(P); }
+
+PropertyValue &PropertyValue::operator=(PropertyValue &&P) {
+  copy(P);
+
+  if (P.getType() == BYTE_ARRAY)
+    P.Val.ByteArrayVal = nullptr;
+  P.Ty = NONE;
+  return *this;
+}
+
+PropertyValue &PropertyValue::operator=(const PropertyValue &P) {
+  if (P.getType() == BYTE_ARRAY)
+    *this = PropertyValue(P.asByteArray(), P.getByteArraySizeInBits());
+  else
+    copy(P);
+  return *this;
+}
+
+void PropertyValue::copy(const PropertyValue &P) {
+  Ty = P.Ty;
+  Val = P.Val;
+}
+
+constexpr char PropertySetRegistry::SYCL_SPECIALIZATION_CONSTANTS[];
+constexpr char PropertySetRegistry::SYCL_DEVICELIB_REQ_MASK[];
+constexpr char PropertySetRegistry::SYCL_SPEC_CONSTANTS_DEFAULT_VALUES[];
+constexpr char PropertySetRegistry::SYCL_KERNEL_PARAM_OPT_INFO[];
+constexpr char PropertySetRegistry::SYCL_PROGRAM_METADATA[];
+constexpr char PropertySetRegistry::SYCL_MISC_PROP[];
+constexpr char PropertySetRegistry::SYCL_ASSERT_USED[];
+constexpr char PropertySetRegistry::SYCL_EXPORTED_SYMBOLS[];
+constexpr char PropertySetRegistry::SYCL_IMPORTED_SYMBOLS[];
+constexpr char PropertySetRegistry::SYCL_DEVICE_GLOBALS[];
+constexpr char PropertySetRegistry::SYCL_DEVICE_REQUIREMENTS[];
+constexpr char PropertySetRegistry::SYCL_HOST_PIPES[];
+constexpr char PropertySetRegistry::SYCL_VIRTUAL_FUNCTIONS[];
+
+} // namespace util
+} // namespace llvm
diff --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt
index d64f89847aa8e7..0261ecdd7ea0bd 100644
--- a/llvm/unittests/Support/CMakeLists.txt
+++ b/llvm/unittests/Support/CMakeLists.txt
@@ -69,6 +69,7 @@ add_llvm_unittest(SupportTests
   PerThreadBumpPtrAllocatorTest.cpp
   ProcessTest.cpp
   ProgramTest.cpp
+  PropertySetIOTest.cpp
   RegexTest.cpp
   ReverseIterationTest.cpp
   ReplaceFileTest.cpp
diff --git a/llvm/unittests/Support/PropertySetIOTest.cpp b/llvm/unittests/Support/PropertySetIOTest.cpp
new file mode 100644
index 00000000000000..74ade9f9dcc219
--- /dev/null
+++ b/llvm/unittests/Support/PropertySetIOTest.cpp
@@ -0,0 +1,72 @@
+//===- llvm/unittest/Support/PropertySetIO.cpp - Property set I/O tests ---===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/PropertySetIO.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::util;
+
+namespace {
+
+TEST(PropertySet, IntValuesIO) {
+  // '1' in '1|20' means 'integer property'
+  auto Content = "[Staff/Ages]\n"
+                 "person1=1|20\n"
+                 "person2=1|25\n"
+                 "[Staff/Experience]\n"
+                 "person1=1|1\n"
+                 "person2=1|2\n"
+                 "person3=1|12\n";
+  auto MemBuf = MemoryBuffer::getMemBuffer(Content);
+  // Parse a property set registry
+  auto PropSetsPtr = PropertySetRegistry::read(MemBuf.get());
+
+  if (!PropSetsPtr)
+    FAIL() << "PropertySetRegistry::read failed\n";
+
+  std::string Serialized;
+  {
+    llvm::raw_string_ostream OS(Serialized);
+    // Serialize
+    PropSetsPtr->get()->write(OS);
+  }
+  // Check that the original and the serialized version are equal
+  ASSERT_EQ(Serialized, Content);
+}
+
+TEST(PropertySet, ByteArrayValuesIO) {
+  // '2' in '2|...' means 'byte array property', Base64-encoded
+  // encodes the following byte arrays:
+  //   { 8, 0, 0, 0, 0, 0, 0, 0, 0x1 };
+  //   { 40, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0x7F, 0xFF, 0x70 };
+  // first 8 bytes are the size in bits (40) of what follows (5 bytes).
+
+  auto Content = "[Opt/Param]\n"
+                 "kernel1=2|IAAAAAAAAAQA\n"
+                 "kernel2=2|oAAAAAAAAAw///3/wB\n";
+  auto MemBuf = MemoryBuffer::getMemBuffer(Content);
+  // Parse a property set registry
+  auto PropSetsPtr = PropertySetRegistry::read(MemBuf.get());
+
+  if (!PropSetsPtr)
+    FAIL() << "PropertySetRegistry::read failed\n";
+
+  std::string Serialized;
+  {
+    llvm::raw_string_ostream OS(Serialized);
+    // Serialize
+    PropSetsPtr->get()->write(OS);
+  }
+  // Check that the original and the serialized version are equal
+  ASSERT_EQ(Serialized, Content);
+}
+} // namespace

>From 526633fe54188134d77e033c512fafbab11ff4ba Mon Sep 17 00:00:00 2001
From: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
Date: Tue, 1 Oct 2024 18:38:35 -0700
Subject: [PATCH 02/13] Move from union to variant

Signed-off-by: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
---
 llvm/include/llvm/Support/Base64.h        |  2 +-
 llvm/include/llvm/Support/PropertySetIO.h | 33 ++++++++++++-----------
 llvm/lib/Support/PropertySetIO.cpp        | 21 +++++++++------
 3 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/llvm/include/llvm/Support/Base64.h b/llvm/include/llvm/Support/Base64.h
index 91317ffeca4170..4bd15873ad5621 100644
--- a/llvm/include/llvm/Support/Base64.h
+++ b/llvm/include/llvm/Support/Base64.h
@@ -59,7 +59,7 @@ llvm::Error decodeBase64(llvm::StringRef Input, std::vector<char> &Output);
 // General-purpose Base64 encoder/decoder class wrapper.
 class Base64 {
 public:
-  using byte = uint8_t;
+  using byte = std::byte;
 
   // Get the size of the encoded byte sequence of given size.
   static size_t getEncodedSize(size_t SrcSize);
diff --git a/llvm/include/llvm/Support/PropertySetIO.h b/llvm/include/llvm/Support/PropertySetIO.h
index 9f02cfd31f54ec..40775dd79dbea1 100644
--- a/llvm/include/llvm/Support/PropertySetIO.h
+++ b/llvm/include/llvm/Support/PropertySetIO.h
@@ -40,6 +40,7 @@
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/xxhash.h"
+#include <variant>
 
 namespace llvm {
 namespace util {
@@ -52,7 +53,7 @@ class PropertyValue {
   // value data in some cases for later reading at runtime, so size_t is not
   // suitable as its size varies.
   using SizeTy = uint64_t;
-  using byte = uint8_t;
+  using byte = std::byte;
 
   // Defines supported property types
   enum Type { first = 0, NONE = first, UINT32, BYTE_ARRAY, last = BYTE_ARRAY };
@@ -68,8 +69,10 @@ class PropertyValue {
   }
 
   ~PropertyValue() {
-    if ((getType() == BYTE_ARRAY) && Val.ByteArrayVal)
-      delete[] Val.ByteArrayVal;
+    if (std::holds_alternative<byte *>(Val)) {
+      byte *ByteArrayVal = std::get<byte *>(Val);
+      delete ByteArrayVal;
+    }
   }
 
   PropertyValue() = default;
@@ -95,7 +98,7 @@ class PropertyValue {
   uint32_t asUint32() const {
     if (Ty != UINT32)
       llvm_unreachable("must be UINT32 value");
-    return Val.UInt32Val;
+    return std::get<uint32_t>(Val);
   }
 
   // Get raw data size in bits.
@@ -104,8 +107,10 @@ class PropertyValue {
       llvm_unreachable("must be BYTE_ARRAY value");
     SizeTy Res = 0;
 
-    for (size_t I = 0; I < sizeof(SizeTy); ++I)
-      Res |= (SizeTy)Val.ByteArrayVal[I] << (8 * I);
+    for (size_t I = 0; I < sizeof(SizeTy); ++I) {
+      auto ByteArrayVal = std::get<byte *>(Val);
+      Res |= (SizeTy)ByteArrayVal[I] << (8 * I);
+    }
     return Res;
   }
 
@@ -126,14 +131,17 @@ class PropertyValue {
   const byte *asRawByteArray() const {
     if (Ty != BYTE_ARRAY)
       llvm_unreachable("must be BYTE_ARRAY value");
-    return Val.ByteArrayVal;
+    auto &ByteArrayVal = std::get<byte *>(Val);
+    return ByteArrayVal;
   }
 
   // Get byte array data excluding the leading bytes encoding the size.
   const byte *asByteArray() const {
     if (Ty != BYTE_ARRAY)
       llvm_unreachable("must be BYTE_ARRAY value");
-    return Val.ByteArrayVal + sizeof(SizeTy);
+
+    auto ByteArrayVal = std::get<byte *>(Val);
+    return ByteArrayVal + sizeof(SizeTy);
   }
 
   bool isValid() const { return getType() != NONE; }
@@ -150,7 +158,7 @@ class PropertyValue {
   SizeTy size() const {
     switch (Ty) {
     case UINT32:
-      return sizeof(Val.UInt32Val);
+      return sizeof(std::get<uint32_t>(Val));
     case BYTE_ARRAY:
       return getRawByteArraySize();
     default:
@@ -163,12 +171,7 @@ class PropertyValue {
   void copy(const PropertyValue &P);
 
   Type Ty = NONE;
-  // TODO: replace this union with std::variant when uplifting to C++17
-  union {
-    uint32_t UInt32Val;
-    // Holds first sizeof(size_t) bytes of size followed by actual raw data.
-    byte *ByteArrayVal;
-  } Val;
+  std::variant<uint32_t, byte *> Val;
 };
 
 /// Structure for specialization of DenseMap in PropertySetRegistry.
diff --git a/llvm/lib/Support/PropertySetIO.cpp b/llvm/lib/Support/PropertySetIO.cpp
index 2fe7cac00fb144..7566f422719746 100644
--- a/llvm/lib/Support/PropertySetIO.cpp
+++ b/llvm/lib/Support/PropertySetIO.cpp
@@ -22,7 +22,7 @@ using namespace llvm;
 
 namespace {
 
-using byte = Base64::byte;
+using byte = std::byte;
 
 ::llvm::Error makeError(const Twine &Msg) {
   return createStringError(std::error_code{}, Msg);
@@ -135,11 +135,12 @@ namespace llvm {
 namespace util {
 
 template <> uint32_t &PropertyValue::getValueRef<uint32_t>() {
-  return Val.UInt32Val;
+  return std::get<uint32_t>(Val);
 }
 
 template <> byte *&PropertyValue::getValueRef<byte *>() {
-  return Val.ByteArrayVal;
+  auto &ByteArrayVal = std::get<byte *>(Val);
+  return ByteArrayVal;
 }
 
 template <> PropertyValue::Type PropertyValue::getTypeTag<uint32_t>() {
@@ -157,15 +158,17 @@ PropertyValue::PropertyValue(const byte *Data, SizeTy DataBitSize) {
   constexpr size_t SizeFieldSize = sizeof(SizeTy);
 
   // Allocate space for size and data.
-  Val.ByteArrayVal = new byte[SizeFieldSize + DataSize];
+  Val = new byte[SizeFieldSize + DataSize];
 
   // Write the size into first bytes.
   for (size_t I = 0; I < SizeFieldSize; ++I) {
-    Val.ByteArrayVal[I] = (byte)DataBitSize;
+    auto ByteArrayVal = std::get<byte *>(Val);
+    ByteArrayVal[I] = (byte)DataBitSize;
     DataBitSize >>= ByteSizeInBits;
   }
   // Append data.
-  std::memcpy(Val.ByteArrayVal + SizeFieldSize, Data, DataSize);
+  auto ByteArrayVal = std::get<byte *>(Val);
+  std::memcpy(ByteArrayVal + SizeFieldSize, Data, DataSize);
 }
 
 PropertyValue::PropertyValue(const PropertyValue &P) { *this = P; }
@@ -175,8 +178,10 @@ PropertyValue::PropertyValue(PropertyValue &&P) { *this = std::move(P); }
 PropertyValue &PropertyValue::operator=(PropertyValue &&P) {
   copy(P);
 
-  if (P.getType() == BYTE_ARRAY)
-    P.Val.ByteArrayVal = nullptr;
+  if (P.getType() == BYTE_ARRAY) {
+    auto &ByteArrayVal = std::get<byte *>(P.Val);
+    ByteArrayVal = nullptr;
+  }
   P.Ty = NONE;
   return *this;
 }

>From 944841adade9d218b875ad4a6f4a3d8c5f5717ce Mon Sep 17 00:00:00 2001
From: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
Date: Wed, 2 Oct 2024 10:26:16 -0700
Subject: [PATCH 03/13] Add missing implementation of encode/decode functions

Signed-off-by: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
---
 llvm/lib/Support/Base64.cpp | 177 ++++++++++++++++++++++++++++++++++++
 1 file changed, 177 insertions(+)

diff --git a/llvm/lib/Support/Base64.cpp b/llvm/lib/Support/Base64.cpp
index 5dab5795497812..5409ca68449da9 100644
--- a/llvm/lib/Support/Base64.cpp
+++ b/llvm/lib/Support/Base64.cpp
@@ -90,3 +90,180 @@ llvm::Error llvm::decodeBase64(llvm::StringRef Input,
   }
   return Error::success();
 }
+
+using namespace llvm;
+
+namespace {
+
+using byte = std::byte;
+
+::llvm::Error makeError(const Twine &Msg) {
+  return createStringError(std::error_code{}, Msg);
+}
+
+class Base64Impl {
+private:
+  static constexpr char EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                          "abcdefghijklmnopqrstuvwxyz"
+                                          "0123456789+/";
+
+  static_assert(sizeof(EncodingTable) == 65, "");
+
+  // Compose an index into the encoder table from two bytes and the number of
+  // significant bits in the lower byte until the byte boundary.
+  static inline int composeInd(byte ByteLo, byte ByteHi, int BitsLo) {
+    int Res = (int)((ByteHi << BitsLo) | (ByteLo >> (8 - BitsLo))) & 0x3F;
+    return Res;
+  }
+
+  // Decode a single character.
+  static inline int decode(char Ch) {
+    if (Ch >= 'A' && Ch <= 'Z') // 0..25
+      return Ch - 'A';
+    else if (Ch >= 'a' && Ch <= 'z') // 26..51
+      return Ch - 'a' + 26;
+    else if (Ch >= '0' && Ch <= '9') // 52..61
+      return Ch - '0' + 52;
+    else if (Ch == '+') // 62
+      return 62;
+    else if (Ch == '/') // 63
+      return 63;
+    return -1;
+  }
+
+  // Decode a quadruple of characters.
+  static inline Expected<bool> decode4(const char *Src, byte *Dst) {
+    int BadCh = -1;
+
+    for (auto I = 0; I < 4; ++I) {
+      char Ch = Src[I];
+      int Byte = decode(Ch);
+
+      if (Byte < 0) {
+        BadCh = Ch;
+        break;
+      }
+      Dst[I] = (byte)Byte;
+    }
+    if (BadCh == -1)
+      return true;
+    return makeError("invalid char in Base64Impl encoding: 0x" + Twine(BadCh));
+  }
+
+public:
+  static size_t getEncodedSize(size_t SrcSize) {
+    constexpr int ByteSizeInBits = 8;
+    constexpr int EncBitsPerChar = 6;
+    return (SrcSize * ByteSizeInBits + (EncBitsPerChar - 1)) / EncBitsPerChar;
+  }
+
+  static size_t encode(const byte *Src, raw_ostream &Out, size_t SrcSize) {
+    size_t Off = 0;
+
+    // encode full byte triples
+    for (size_t TriB = 0; TriB < SrcSize / 3; ++TriB) {
+      Off = TriB * 3;
+      byte Byte0 = Src[Off++];
+      byte Byte1 = Src[Off++];
+      byte Byte2 = Src[Off++];
+
+      Out << EncodingTable[(int)Byte0 & 0x3F];
+      Out << EncodingTable[composeInd(Byte0, Byte1, 2)];
+      Out << EncodingTable[composeInd(Byte1, Byte2, 4)];
+      Out << EncodingTable[(int)(Byte2 >> 2) & 0x3F];
+    }
+    // encode the remainder
+    int RemBytes = SrcSize - Off;
+
+    if (RemBytes > 0) {
+      byte Byte0 = Src[Off + 0];
+      Out << EncodingTable[(int)Byte0 & 0x3F];
+
+      if (RemBytes > 1) {
+        byte Byte1 = Src[Off + 1];
+        Out << EncodingTable[composeInd(Byte0, Byte1, 2)];
+        Out << EncodingTable[(int)(Byte1 >> 4) & 0x3F];
+      } else {
+        Out << EncodingTable[(int)(Byte0 >> 6) & 0x3F];
+      }
+    }
+    return getEncodedSize(SrcSize);
+  }
+
+  static size_t getDecodedSize(size_t SrcSize) { return (SrcSize * 3 + 3) / 4; }
+
+  static Expected<size_t> decode(const char *Src, byte *Dst, size_t SrcSize) {
+    size_t SrcOff = 0;
+    size_t DstOff = 0;
+
+    // decode full quads
+    for (size_t Qch = 0; Qch < SrcSize / 4; ++Qch, SrcOff += 4, DstOff += 3) {
+      byte Ch[4];
+      Expected<bool> TrRes = decode4(Src + SrcOff, Ch);
+
+      if (!TrRes)
+        return TrRes.takeError();
+      // each quad of chars produces three bytes of output
+      Dst[DstOff + 0] = Ch[0] | (Ch[1] << 6);
+      Dst[DstOff + 1] = (Ch[1] >> 2) | (Ch[2] << 4);
+      Dst[DstOff + 2] = (Ch[2] >> 4) | (Ch[3] << 2);
+    }
+    auto RemChars = SrcSize - SrcOff;
+
+    if (RemChars == 0)
+      return DstOff;
+    // decode the remainder; variants:
+    // 2 chars remain - produces single byte
+    // 3 chars remain - produces two bytes
+
+    if (RemChars != 2 && RemChars != 3)
+      return makeError("invalid encoded sequence length");
+
+    int Ch0 = decode(Src[SrcOff++]);
+    int Ch1 = decode(Src[SrcOff++]);
+    int Ch2 = RemChars == 3 ? decode(Src[SrcOff]) : 0;
+
+    if (Ch0 < 0 || Ch1 < 0 || Ch2 < 0)
+      return makeError("invalid characters in the encoded sequence remainder");
+    Dst[DstOff++] = (byte)Ch0 | (byte)((Ch1 << 6));
+
+    if (RemChars == 3)
+      Dst[DstOff++] = (byte)(Ch1 >> 2) | (byte)(Ch2 << 4);
+    return DstOff;
+  }
+
+  static Expected<std::unique_ptr<byte[]>> decode(const char *Src,
+                                                  size_t SrcSize) {
+    size_t DstSize = getDecodedSize(SrcSize);
+    std::unique_ptr<byte[]> Dst(new byte[DstSize]);
+    Expected<size_t> Res = decode(Src, Dst.get(), SrcSize);
+    if (!Res)
+      return Res.takeError();
+    return Expected<std::unique_ptr<byte[]>>(std::move(Dst));
+  }
+};
+
+constexpr char Base64Impl::EncodingTable[];
+
+} // anonymous namespace
+
+size_t Base64::getEncodedSize(size_t SrcSize) {
+  return Base64Impl::getEncodedSize(SrcSize);
+}
+
+size_t Base64::encode(const byte *Src, raw_ostream &Out, size_t SrcSize) {
+  return Base64Impl::encode(Src, Out, SrcSize);
+}
+
+size_t Base64::getDecodedSize(size_t SrcSize) {
+  return Base64Impl::getDecodedSize(SrcSize);
+}
+
+Expected<size_t> Base64::decode(const char *Src, byte *Dst, size_t SrcSize) {
+  return Base64Impl::decode(Src, Dst, SrcSize);
+}
+
+Expected<std::unique_ptr<byte[]>> Base64::decode(const char *Src,
+                                                 size_t SrcSize) {
+  return Base64Impl::decode(Src, SrcSize);
+}
\ No newline at end of file

>From f528b64996f1e1d3d5689f323090739e7342734e Mon Sep 17 00:00:00 2001
From: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
Date: Thu, 3 Oct 2024 04:39:45 -0700
Subject: [PATCH 04/13] More changes due to shift from Union to std::variant

Signed-off-by: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
---
 llvm/include/llvm/Support/PropertySetIO.h | 3 +--
 llvm/lib/Support/PropertySetIO.cpp        | 9 ---------
 2 files changed, 1 insertion(+), 11 deletions(-)

diff --git a/llvm/include/llvm/Support/PropertySetIO.h b/llvm/include/llvm/Support/PropertySetIO.h
index 40775dd79dbea1..8b59098245d314 100644
--- a/llvm/include/llvm/Support/PropertySetIO.h
+++ b/llvm/include/llvm/Support/PropertySetIO.h
@@ -150,7 +150,7 @@ class PropertyValue {
   template <typename T> void set(T V) {
     if (getTypeTag<T>() != Ty)
       llvm_unreachable("invalid type tag for this operation");
-    getValueRef<T>() = V;
+    Val = V;
   }
 
   Type getType() const { return Ty; }
@@ -167,7 +167,6 @@ class PropertyValue {
   }
 
 private:
-  template <typename T> T &getValueRef();
   void copy(const PropertyValue &P);
 
   Type Ty = NONE;
diff --git a/llvm/lib/Support/PropertySetIO.cpp b/llvm/lib/Support/PropertySetIO.cpp
index 7566f422719746..856c6ef957743d 100644
--- a/llvm/lib/Support/PropertySetIO.cpp
+++ b/llvm/lib/Support/PropertySetIO.cpp
@@ -134,15 +134,6 @@ void PropertySetRegistry::write(raw_ostream &Out) const {
 namespace llvm {
 namespace util {
 
-template <> uint32_t &PropertyValue::getValueRef<uint32_t>() {
-  return std::get<uint32_t>(Val);
-}
-
-template <> byte *&PropertyValue::getValueRef<byte *>() {
-  auto &ByteArrayVal = std::get<byte *>(Val);
-  return ByteArrayVal;
-}
-
 template <> PropertyValue::Type PropertyValue::getTypeTag<uint32_t>() {
   return UINT32;
 }

>From 0b4ad716189c3fcfb6e77d299d12c11a3784af0b Mon Sep 17 00:00:00 2001
From: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
Date: Thu, 3 Oct 2024 09:14:15 -0700
Subject: [PATCH 05/13] Address review comments

Signed-off-by: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
---
 llvm/include/llvm/Support/PropertySetIO.h    | 15 ++++++------
 llvm/lib/Support/Base64.cpp                  | 20 ++++++++--------
 llvm/lib/Support/PropertySetIO.cpp           | 24 +++++++++-----------
 llvm/unittests/Support/PropertySetIOTest.cpp |  6 ++---
 4 files changed, 31 insertions(+), 34 deletions(-)

diff --git a/llvm/include/llvm/Support/PropertySetIO.h b/llvm/include/llvm/Support/PropertySetIO.h
index 8b59098245d314..4fa3e745e9aa7b 100644
--- a/llvm/include/llvm/Support/PropertySetIO.h
+++ b/llvm/include/llvm/Support/PropertySetIO.h
@@ -6,7 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 // Models a sequence of property sets and their input and output operations.
-// TODO use Yaml as I/O engine.
 // PropertyValue set format:
 //   '['<PropertyValue set name>']'
 //   <property name>=<property type>'|'<property value>
@@ -83,7 +82,7 @@ class PropertyValue {
   template <typename C, typename T = typename C::value_type>
   PropertyValue(const C &Data)
       : PropertyValue(reinterpret_cast<const byte *>(Data.data()),
-                      Data.size() * sizeof(T) * /* bits in one byte */ 8) {}
+                      Data.size() * sizeof(T) * CHAR_BIT) {}
   PropertyValue(const llvm::StringRef &Str)
       : PropertyValue(reinterpret_cast<const byte *>(Str.data()),
                       Str.size() * sizeof(char) * /* bits in one byte */ 8) {}
@@ -94,7 +93,7 @@ class PropertyValue {
 
   PropertyValue &operator=(const PropertyValue &P);
 
-  // get property value as unsigned 32-bit integer
+  // Get property value as unsigned 32-bit integer
   uint32_t asUint32() const {
     if (Ty != UINT32)
       llvm_unreachable("must be UINT32 value");
@@ -131,7 +130,7 @@ class PropertyValue {
   const byte *asRawByteArray() const {
     if (Ty != BYTE_ARRAY)
       llvm_unreachable("must be BYTE_ARRAY value");
-    auto &ByteArrayVal = std::get<byte *>(Val);
+    auto *ByteArrayVal = std::get<byte *>(Val);
     return ByteArrayVal;
   }
 
@@ -146,7 +145,7 @@ class PropertyValue {
 
   bool isValid() const { return getType() != NONE; }
 
-  // set property value; the 'T' type must be convertible to a property type tag
+  // Set property value; the 'T' type must be convertible to a property type tag
   template <typename T> void set(T V) {
     if (getTypeTag<T>() != Ty)
       llvm_unreachable("invalid type tag for this operation");
@@ -158,7 +157,7 @@ class PropertyValue {
   SizeTy size() const {
     switch (Ty) {
     case UINT32:
-      return sizeof(std::get<uint32_t>(Val));
+      return sizeof(uint32_t);
     case BYTE_ARRAY:
       return getRawByteArraySize();
     default:
@@ -220,8 +219,8 @@ class PropertySetRegistry {
            "category already added");
     auto &PropSet = PropSetMap[Category];
 
-    for (const auto &Prop : Props)
-      PropSet.insert_or_assign(Prop.first, PropertyValue(Prop.second));
+    for (const auto &[PropName, PropVal] : Props)
+      PropSet.insert_or_assign(PropName, PropertyValue(PropVal));
   }
 
   /// Adds the given \p PropVal with the given \p PropName into the given \p
diff --git a/llvm/lib/Support/Base64.cpp b/llvm/lib/Support/Base64.cpp
index 5409ca68449da9..e27faa062eed8f 100644
--- a/llvm/lib/Support/Base64.cpp
+++ b/llvm/lib/Support/Base64.cpp
@@ -120,13 +120,13 @@ class Base64Impl {
   static inline int decode(char Ch) {
     if (Ch >= 'A' && Ch <= 'Z') // 0..25
       return Ch - 'A';
-    else if (Ch >= 'a' && Ch <= 'z') // 26..51
+    if (Ch >= 'a' && Ch <= 'z') // 26..51
       return Ch - 'a' + 26;
-    else if (Ch >= '0' && Ch <= '9') // 52..61
+    if (Ch >= '0' && Ch <= '9') // 52..61
       return Ch - '0' + 52;
-    else if (Ch == '+') // 62
+    if (Ch == '+') // 62
       return 62;
-    else if (Ch == '/') // 63
+    if (Ch == '/') // 63
       return 63;
     return -1;
   }
@@ -160,7 +160,7 @@ class Base64Impl {
   static size_t encode(const byte *Src, raw_ostream &Out, size_t SrcSize) {
     size_t Off = 0;
 
-    // encode full byte triples
+    // Encode full byte triples
     for (size_t TriB = 0; TriB < SrcSize / 3; ++TriB) {
       Off = TriB * 3;
       byte Byte0 = Src[Off++];
@@ -172,7 +172,7 @@ class Base64Impl {
       Out << EncodingTable[composeInd(Byte1, Byte2, 4)];
       Out << EncodingTable[(int)(Byte2 >> 2) & 0x3F];
     }
-    // encode the remainder
+    // Encode the remainder
     int RemBytes = SrcSize - Off;
 
     if (RemBytes > 0) {
@@ -196,14 +196,14 @@ class Base64Impl {
     size_t SrcOff = 0;
     size_t DstOff = 0;
 
-    // decode full quads
+    // Decode full quads.
     for (size_t Qch = 0; Qch < SrcSize / 4; ++Qch, SrcOff += 4, DstOff += 3) {
       byte Ch[4];
       Expected<bool> TrRes = decode4(Src + SrcOff, Ch);
 
       if (!TrRes)
         return TrRes.takeError();
-      // each quad of chars produces three bytes of output
+      // Each quad of chars produces three bytes of output.
       Dst[DstOff + 0] = Ch[0] | (Ch[1] << 6);
       Dst[DstOff + 1] = (Ch[1] >> 2) | (Ch[2] << 4);
       Dst[DstOff + 2] = (Ch[2] >> 4) | (Ch[3] << 2);
@@ -212,7 +212,7 @@ class Base64Impl {
 
     if (RemChars == 0)
       return DstOff;
-    // decode the remainder; variants:
+    // Decode the remainder; variants:
     // 2 chars remain - produces single byte
     // 3 chars remain - produces two bytes
 
@@ -266,4 +266,4 @@ Expected<size_t> Base64::decode(const char *Src, byte *Dst, size_t SrcSize) {
 Expected<std::unique_ptr<byte[]>> Base64::decode(const char *Src,
                                                  size_t SrcSize) {
   return Base64Impl::decode(Src, SrcSize);
-}
\ No newline at end of file
+}
diff --git a/llvm/lib/Support/PropertySetIO.cpp b/llvm/lib/Support/PropertySetIO.cpp
index 856c6ef957743d..4da235429e810a 100644
--- a/llvm/lib/Support/PropertySetIO.cpp
+++ b/llvm/lib/Support/PropertySetIO.cpp
@@ -36,9 +36,9 @@ PropertySetRegistry::read(const MemoryBuffer *Buf) {
   PropertySet *CurPropSet = nullptr;
 
   for (line_iterator LI(*Buf); !LI.is_at_end(); LI++) {
-    // see if this line starts a new property set
+    // See if this line starts a new property set
     if (LI->starts_with("[")) {
-      // yes - parse the category (property name)
+      // Parse the category (property name)
       auto EndPos = LI->rfind(']');
       if (EndPos == StringRef::npos)
         return makeError("invalid line: " + *LI);
@@ -48,7 +48,7 @@ PropertySetRegistry::read(const MemoryBuffer *Buf) {
     }
     if (!CurPropSet)
       return makeError("property category missing");
-    // parse name and type+value
+    // Parse name and type+value
     auto Parts = LI->split('=');
 
     if (Parts.first.empty() || Parts.second.empty())
@@ -59,7 +59,7 @@ PropertySetRegistry::read(const MemoryBuffer *Buf) {
       return makeError("invalid property value: " + Parts.second);
     APInt Tint;
 
-    // parse type
+    // Parse type
     if (TypeVal.first.getAsInteger(10, Tint))
       return makeError("invalid property type: " + TypeVal.first);
     Expected<PropertyValue::Type> Ttag =
@@ -70,7 +70,7 @@ PropertySetRegistry::read(const MemoryBuffer *Buf) {
       return Ttag.takeError();
     PropertyValue Prop(Ttag.get());
 
-    // parse value depending on its type
+    // Parse value depending on its type
     switch (Ttag.get()) {
     case PropertyValue::Type::UINT32: {
       APInt ValV;
@@ -101,9 +101,9 @@ PropertySetRegistry::read(const MemoryBuffer *Buf) {
 }
 
 namespace llvm {
-// output a property to a stream
+// Output a property to a stream
 raw_ostream &operator<<(raw_ostream &Out, const PropertyValue &Prop) {
-  Out << static_cast<int>(Prop.getType()) << "|";
+  Out << static_cast<int>(Prop.getType()) << '|';
   switch (Prop.getType()) {
   case PropertyValue::Type::UINT32:
     Out << Prop.asUint32();
@@ -123,11 +123,10 @@ raw_ostream &operator<<(raw_ostream &Out, const PropertyValue &Prop) {
 
 void PropertySetRegistry::write(raw_ostream &Out) const {
   for (const auto &PropSet : PropSetMap) {
-    Out << "[" << PropSet.first << "]\n";
+    Out << '[' << PropSet.first << "]\n";
 
-    for (const auto &Props : PropSet.second) {
-      Out << Props.first << "=" << Props.second << "\n";
-    }
+    for (const auto &Props : PropSet.second)
+      Out << Props.first << '=' << Props.second << '\n';
   }
 }
 
@@ -142,9 +141,8 @@ template <> PropertyValue::Type PropertyValue::getTypeTag<byte *>() {
   return BYTE_ARRAY;
 }
 
-PropertyValue::PropertyValue(const byte *Data, SizeTy DataBitSize) {
+PropertyValue::PropertyValue(const byte *Data, SizeTy DataBitSize) : Ty(BYTE_ARRAY) {
   constexpr int ByteSizeInBits = 8;
-  Ty = BYTE_ARRAY;
   SizeTy DataSize = (DataBitSize + (ByteSizeInBits - 1)) / ByteSizeInBits;
   constexpr size_t SizeFieldSize = sizeof(SizeTy);
 
diff --git a/llvm/unittests/Support/PropertySetIOTest.cpp b/llvm/unittests/Support/PropertySetIOTest.cpp
index 74ade9f9dcc219..8fb09d43a04741 100644
--- a/llvm/unittests/Support/PropertySetIOTest.cpp
+++ b/llvm/unittests/Support/PropertySetIOTest.cpp
@@ -1,4 +1,4 @@
-//===- llvm/unittest/Support/PropertySetIO.cpp - Property set I/O tests ---===//
+//=- llvm/unittest/Support/PropertySetIOTest.cpp - Property set I/O tests ---=//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -40,7 +40,7 @@ TEST(PropertySet, IntValuesIO) {
     PropSetsPtr->get()->write(OS);
   }
   // Check that the original and the serialized version are equal
-  ASSERT_EQ(Serialized, Content);
+  EXPECT_EQ(Serialized, Content);
 }
 
 TEST(PropertySet, ByteArrayValuesIO) {
@@ -67,6 +67,6 @@ TEST(PropertySet, ByteArrayValuesIO) {
     PropSetsPtr->get()->write(OS);
   }
   // Check that the original and the serialized version are equal
-  ASSERT_EQ(Serialized, Content);
+  EXPECT_EQ(Serialized, Content);
 }
 } // namespace

>From cd9874ab74aacaf52ac2bbf785b0bed765d45450 Mon Sep 17 00:00:00 2001
From: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
Date: Thu, 3 Oct 2024 09:30:40 -0700
Subject: [PATCH 06/13] Fix clang format issue

Signed-off-by: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
---
 llvm/lib/Support/PropertySetIO.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Support/PropertySetIO.cpp b/llvm/lib/Support/PropertySetIO.cpp
index 4da235429e810a..0bb17a9eadedec 100644
--- a/llvm/lib/Support/PropertySetIO.cpp
+++ b/llvm/lib/Support/PropertySetIO.cpp
@@ -141,7 +141,8 @@ template <> PropertyValue::Type PropertyValue::getTypeTag<byte *>() {
   return BYTE_ARRAY;
 }
 
-PropertyValue::PropertyValue(const byte *Data, SizeTy DataBitSize) : Ty(BYTE_ARRAY) {
+PropertyValue::PropertyValue(const byte *Data, SizeTy DataBitSize)
+    : Ty(BYTE_ARRAY) {
   constexpr int ByteSizeInBits = 8;
   SizeTy DataSize = (DataBitSize + (ByteSizeInBits - 1)) / ByteSizeInBits;
   constexpr size_t SizeFieldSize = sizeof(SizeTy);

>From de198063cd419f1eb3a1fea18226bb5b25272139 Mon Sep 17 00:00:00 2001
From: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
Date: Wed, 9 Oct 2024 12:21:50 -0700
Subject: [PATCH 07/13] Remove changes to Base64 implementation and use
 existing implementation

Signed-off-by: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
---
 llvm/include/llvm/Support/Base64.h           |  26 ---
 llvm/include/llvm/Support/PropertySetIO.h    |  50 ++++--
 llvm/lib/Support/Base64.cpp                  | 177 -------------------
 llvm/lib/Support/PropertySetIO.cpp           |  36 ++--
 llvm/unittests/Support/PropertySetIOTest.cpp |   2 +-
 5 files changed, 50 insertions(+), 241 deletions(-)

diff --git a/llvm/include/llvm/Support/Base64.h b/llvm/include/llvm/Support/Base64.h
index 4bd15873ad5621..3d96884749b32f 100644
--- a/llvm/include/llvm/Support/Base64.h
+++ b/llvm/include/llvm/Support/Base64.h
@@ -56,32 +56,6 @@ template <class InputBytes> std::string encodeBase64(InputBytes const &Bytes) {
 
 llvm::Error decodeBase64(llvm::StringRef Input, std::vector<char> &Output);
 
-// General-purpose Base64 encoder/decoder class wrapper.
-class Base64 {
-public:
-  using byte = std::byte;
-
-  // Get the size of the encoded byte sequence of given size.
-  static size_t getEncodedSize(size_t SrcSize);
-
-  // Encode a byte sequence of given size into an output stream.
-  // Returns the number of bytes in the encoded result.
-  static size_t encode(const byte *Src, raw_ostream &Out, size_t SrcSize);
-
-  // Get the size of the encoded byte sequence of given size.
-  static size_t getDecodedSize(size_t SrcSize);
-
-  // Decode a sequence of given size into a pre-allocated memory.
-  // Returns the number of bytes in the decoded result or 0 in case of error.
-  static Expected<size_t> decode(const char *Src, byte *Dst, size_t SrcSize);
-
-  // Allocate minimum required amount of memory and decode a sequence of given
-  // size into it.
-  // Returns the decoded result. The size can be obtained via getDecodedSize.
-  static Expected<std::unique_ptr<byte[]>> decode(const char *Src,
-                                                  size_t SrcSize);
-};
-
 } // end namespace llvm
 
 #endif
diff --git a/llvm/include/llvm/Support/PropertySetIO.h b/llvm/include/llvm/Support/PropertySetIO.h
index 4fa3e745e9aa7b..963bbcd33e6516 100644
--- a/llvm/include/llvm/Support/PropertySetIO.h
+++ b/llvm/include/llvm/Support/PropertySetIO.h
@@ -52,7 +52,6 @@ class PropertyValue {
   // value data in some cases for later reading at runtime, so size_t is not
   // suitable as its size varies.
   using SizeTy = uint64_t;
-  using byte = std::byte;
 
   // Defines supported property types
   enum Type { first = 0, NONE = first, UINT32, BYTE_ARRAY, last = BYTE_ARRAY };
@@ -67,24 +66,19 @@ class PropertyValue {
     return static_cast<Type>(T);
   }
 
-  ~PropertyValue() {
-    if (std::holds_alternative<byte *>(Val)) {
-      byte *ByteArrayVal = std::get<byte *>(Val);
-      delete ByteArrayVal;
-    }
-  }
+  ~PropertyValue() {}
 
   PropertyValue() = default;
   PropertyValue(Type T) : Ty(T) {}
 
   PropertyValue(uint32_t Val) : Ty(UINT32), Val({Val}) {}
-  PropertyValue(const byte *Data, SizeTy DataBitSize);
+  PropertyValue(const std::byte *Data, SizeTy DataBitSize);
   template <typename C, typename T = typename C::value_type>
   PropertyValue(const C &Data)
-      : PropertyValue(reinterpret_cast<const byte *>(Data.data()),
+      : PropertyValue(reinterpret_cast<const std::byte *>(Data.data()),
                       Data.size() * sizeof(T) * CHAR_BIT) {}
   PropertyValue(const llvm::StringRef &Str)
-      : PropertyValue(reinterpret_cast<const byte *>(Str.data()),
+      : PropertyValue(reinterpret_cast<const std::byte *>(Str.data()),
                       Str.size() * sizeof(char) * /* bits in one byte */ 8) {}
   PropertyValue(const PropertyValue &P);
   PropertyValue(PropertyValue &&P);
@@ -107,7 +101,7 @@ class PropertyValue {
     SizeTy Res = 0;
 
     for (size_t I = 0; I < sizeof(SizeTy); ++I) {
-      auto ByteArrayVal = std::get<byte *>(Val);
+      auto ByteArrayVal = std::get<std::byte *>(Val);
       Res |= (SizeTy)ByteArrayVal[I] << (8 * I);
     }
     return Res;
@@ -127,31 +121,51 @@ class PropertyValue {
   }
 
   // Get byte array data including the leading bytes encoding the size.
-  const byte *asRawByteArray() const {
+  const std::byte *asRawByteArray() const {
     if (Ty != BYTE_ARRAY)
       llvm_unreachable("must be BYTE_ARRAY value");
-    auto *ByteArrayVal = std::get<byte *>(Val);
+    auto *ByteArrayVal = std::get<std::byte *>(Val);
     return ByteArrayVal;
   }
 
   // Get byte array data excluding the leading bytes encoding the size.
-  const byte *asByteArray() const {
+  const std::byte *asByteArray() const {
     if (Ty != BYTE_ARRAY)
       llvm_unreachable("must be BYTE_ARRAY value");
 
-    auto ByteArrayVal = std::get<byte *>(Val);
+    auto ByteArrayVal = std::get<std::byte *>(Val);
     return ByteArrayVal + sizeof(SizeTy);
   }
 
   bool isValid() const { return getType() != NONE; }
 
   // Set property value; the 'T' type must be convertible to a property type tag
-  template <typename T> void set(T V) {
-    if (getTypeTag<T>() != Ty)
+  void set(uint32_t V) {
+    if (Ty != UINT32)
       llvm_unreachable("invalid type tag for this operation");
     Val = V;
   }
 
+  // Set property value; the 'T' type must be convertible to a property type tag
+  void set(std::byte *V, int DataSize) {
+    if (Ty != BYTE_ARRAY)
+      llvm_unreachable("invalid type tag for this operation");
+    size_t DataBitSize = DataSize * CHAR_BIT;
+    constexpr size_t SizeFieldSize = sizeof(SizeTy);
+    // Allocate space for size and data.
+    Val = new std::byte[SizeFieldSize + DataSize];
+
+    // Write the size into first bytes.
+    for (size_t I = 0; I < SizeFieldSize; ++I) {
+      auto ByteArrayVal = std::get<std::byte *>(Val);
+      ByteArrayVal[I] = (std::byte)DataBitSize;
+      DataBitSize >>= CHAR_BIT;
+    }
+    // Append data.
+    auto ByteArrayVal = std::get<std::byte *>(Val);
+    std::memcpy(ByteArrayVal + SizeFieldSize, V, DataSize);
+  }
+
   Type getType() const { return Ty; }
 
   SizeTy size() const {
@@ -169,7 +183,7 @@ class PropertyValue {
   void copy(const PropertyValue &P);
 
   Type Ty = NONE;
-  std::variant<uint32_t, byte *> Val;
+  std::variant<uint32_t, std::byte *> Val;
 };
 
 /// Structure for specialization of DenseMap in PropertySetRegistry.
diff --git a/llvm/lib/Support/Base64.cpp b/llvm/lib/Support/Base64.cpp
index e27faa062eed8f..5dab5795497812 100644
--- a/llvm/lib/Support/Base64.cpp
+++ b/llvm/lib/Support/Base64.cpp
@@ -90,180 +90,3 @@ llvm::Error llvm::decodeBase64(llvm::StringRef Input,
   }
   return Error::success();
 }
-
-using namespace llvm;
-
-namespace {
-
-using byte = std::byte;
-
-::llvm::Error makeError(const Twine &Msg) {
-  return createStringError(std::error_code{}, Msg);
-}
-
-class Base64Impl {
-private:
-  static constexpr char EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                                          "abcdefghijklmnopqrstuvwxyz"
-                                          "0123456789+/";
-
-  static_assert(sizeof(EncodingTable) == 65, "");
-
-  // Compose an index into the encoder table from two bytes and the number of
-  // significant bits in the lower byte until the byte boundary.
-  static inline int composeInd(byte ByteLo, byte ByteHi, int BitsLo) {
-    int Res = (int)((ByteHi << BitsLo) | (ByteLo >> (8 - BitsLo))) & 0x3F;
-    return Res;
-  }
-
-  // Decode a single character.
-  static inline int decode(char Ch) {
-    if (Ch >= 'A' && Ch <= 'Z') // 0..25
-      return Ch - 'A';
-    if (Ch >= 'a' && Ch <= 'z') // 26..51
-      return Ch - 'a' + 26;
-    if (Ch >= '0' && Ch <= '9') // 52..61
-      return Ch - '0' + 52;
-    if (Ch == '+') // 62
-      return 62;
-    if (Ch == '/') // 63
-      return 63;
-    return -1;
-  }
-
-  // Decode a quadruple of characters.
-  static inline Expected<bool> decode4(const char *Src, byte *Dst) {
-    int BadCh = -1;
-
-    for (auto I = 0; I < 4; ++I) {
-      char Ch = Src[I];
-      int Byte = decode(Ch);
-
-      if (Byte < 0) {
-        BadCh = Ch;
-        break;
-      }
-      Dst[I] = (byte)Byte;
-    }
-    if (BadCh == -1)
-      return true;
-    return makeError("invalid char in Base64Impl encoding: 0x" + Twine(BadCh));
-  }
-
-public:
-  static size_t getEncodedSize(size_t SrcSize) {
-    constexpr int ByteSizeInBits = 8;
-    constexpr int EncBitsPerChar = 6;
-    return (SrcSize * ByteSizeInBits + (EncBitsPerChar - 1)) / EncBitsPerChar;
-  }
-
-  static size_t encode(const byte *Src, raw_ostream &Out, size_t SrcSize) {
-    size_t Off = 0;
-
-    // Encode full byte triples
-    for (size_t TriB = 0; TriB < SrcSize / 3; ++TriB) {
-      Off = TriB * 3;
-      byte Byte0 = Src[Off++];
-      byte Byte1 = Src[Off++];
-      byte Byte2 = Src[Off++];
-
-      Out << EncodingTable[(int)Byte0 & 0x3F];
-      Out << EncodingTable[composeInd(Byte0, Byte1, 2)];
-      Out << EncodingTable[composeInd(Byte1, Byte2, 4)];
-      Out << EncodingTable[(int)(Byte2 >> 2) & 0x3F];
-    }
-    // Encode the remainder
-    int RemBytes = SrcSize - Off;
-
-    if (RemBytes > 0) {
-      byte Byte0 = Src[Off + 0];
-      Out << EncodingTable[(int)Byte0 & 0x3F];
-
-      if (RemBytes > 1) {
-        byte Byte1 = Src[Off + 1];
-        Out << EncodingTable[composeInd(Byte0, Byte1, 2)];
-        Out << EncodingTable[(int)(Byte1 >> 4) & 0x3F];
-      } else {
-        Out << EncodingTable[(int)(Byte0 >> 6) & 0x3F];
-      }
-    }
-    return getEncodedSize(SrcSize);
-  }
-
-  static size_t getDecodedSize(size_t SrcSize) { return (SrcSize * 3 + 3) / 4; }
-
-  static Expected<size_t> decode(const char *Src, byte *Dst, size_t SrcSize) {
-    size_t SrcOff = 0;
-    size_t DstOff = 0;
-
-    // Decode full quads.
-    for (size_t Qch = 0; Qch < SrcSize / 4; ++Qch, SrcOff += 4, DstOff += 3) {
-      byte Ch[4];
-      Expected<bool> TrRes = decode4(Src + SrcOff, Ch);
-
-      if (!TrRes)
-        return TrRes.takeError();
-      // Each quad of chars produces three bytes of output.
-      Dst[DstOff + 0] = Ch[0] | (Ch[1] << 6);
-      Dst[DstOff + 1] = (Ch[1] >> 2) | (Ch[2] << 4);
-      Dst[DstOff + 2] = (Ch[2] >> 4) | (Ch[3] << 2);
-    }
-    auto RemChars = SrcSize - SrcOff;
-
-    if (RemChars == 0)
-      return DstOff;
-    // Decode the remainder; variants:
-    // 2 chars remain - produces single byte
-    // 3 chars remain - produces two bytes
-
-    if (RemChars != 2 && RemChars != 3)
-      return makeError("invalid encoded sequence length");
-
-    int Ch0 = decode(Src[SrcOff++]);
-    int Ch1 = decode(Src[SrcOff++]);
-    int Ch2 = RemChars == 3 ? decode(Src[SrcOff]) : 0;
-
-    if (Ch0 < 0 || Ch1 < 0 || Ch2 < 0)
-      return makeError("invalid characters in the encoded sequence remainder");
-    Dst[DstOff++] = (byte)Ch0 | (byte)((Ch1 << 6));
-
-    if (RemChars == 3)
-      Dst[DstOff++] = (byte)(Ch1 >> 2) | (byte)(Ch2 << 4);
-    return DstOff;
-  }
-
-  static Expected<std::unique_ptr<byte[]>> decode(const char *Src,
-                                                  size_t SrcSize) {
-    size_t DstSize = getDecodedSize(SrcSize);
-    std::unique_ptr<byte[]> Dst(new byte[DstSize]);
-    Expected<size_t> Res = decode(Src, Dst.get(), SrcSize);
-    if (!Res)
-      return Res.takeError();
-    return Expected<std::unique_ptr<byte[]>>(std::move(Dst));
-  }
-};
-
-constexpr char Base64Impl::EncodingTable[];
-
-} // anonymous namespace
-
-size_t Base64::getEncodedSize(size_t SrcSize) {
-  return Base64Impl::getEncodedSize(SrcSize);
-}
-
-size_t Base64::encode(const byte *Src, raw_ostream &Out, size_t SrcSize) {
-  return Base64Impl::encode(Src, Out, SrcSize);
-}
-
-size_t Base64::getDecodedSize(size_t SrcSize) {
-  return Base64Impl::getDecodedSize(SrcSize);
-}
-
-Expected<size_t> Base64::decode(const char *Src, byte *Dst, size_t SrcSize) {
-  return Base64Impl::decode(Src, Dst, SrcSize);
-}
-
-Expected<std::unique_ptr<byte[]>> Base64::decode(const char *Src,
-                                                 size_t SrcSize) {
-  return Base64Impl::decode(Src, SrcSize);
-}
diff --git a/llvm/lib/Support/PropertySetIO.cpp b/llvm/lib/Support/PropertySetIO.cpp
index 0bb17a9eadedec..661ee6d9fb3243 100644
--- a/llvm/lib/Support/PropertySetIO.cpp
+++ b/llvm/lib/Support/PropertySetIO.cpp
@@ -22,8 +22,6 @@ using namespace llvm;
 
 namespace {
 
-using byte = std::byte;
-
 ::llvm::Error makeError(const Twine &Msg) {
   return createStringError(std::error_code{}, Msg);
 }
@@ -78,14 +76,14 @@ PropertySetRegistry::read(const MemoryBuffer *Buf) {
         return createStringError(std::error_code{},
                                  "invalid property value: ", Val.data());
       Prop.set(static_cast<uint32_t>(ValV.getZExtValue()));
+      llvm::errs() << "ARV: read int done\n";
       break;
     }
     case PropertyValue::Type::BYTE_ARRAY: {
-      Expected<std::unique_ptr<byte[]>> DecArr =
-          Base64::decode(Val.data(), Val.size());
-      if (!DecArr)
-        return DecArr.takeError();
-      Prop.set(DecArr.get().release());
+      std::vector<char> Output;
+      if (Error Err = decodeBase64(Val, Output))
+        return std::move(Err);
+      Prop.set(reinterpret_cast<std::byte *>(Output.data()), Output.size());
       break;
     }
     default:
@@ -109,8 +107,10 @@ raw_ostream &operator<<(raw_ostream &Out, const PropertyValue &Prop) {
     Out << Prop.asUint32();
     break;
   case PropertyValue::Type::BYTE_ARRAY: {
-    util::PropertyValue::SizeTy Size = Prop.getRawByteArraySize();
-    Base64::encode(Prop.asRawByteArray(), Out, (size_t)Size);
+    auto PropArr = Prop.asByteArray();
+    std::vector<std::byte> V(PropArr, PropArr + Prop.getByteArraySize() /
+                                                    sizeof(std::byte));
+    Out << encodeBase64(V);
     break;
   }
   default:
@@ -137,27 +137,27 @@ template <> PropertyValue::Type PropertyValue::getTypeTag<uint32_t>() {
   return UINT32;
 }
 
-template <> PropertyValue::Type PropertyValue::getTypeTag<byte *>() {
+template <> PropertyValue::Type PropertyValue::getTypeTag<std::byte *>() {
   return BYTE_ARRAY;
 }
 
-PropertyValue::PropertyValue(const byte *Data, SizeTy DataBitSize)
+PropertyValue::PropertyValue(const std::byte *Data, SizeTy DataBitSize)
     : Ty(BYTE_ARRAY) {
   constexpr int ByteSizeInBits = 8;
   SizeTy DataSize = (DataBitSize + (ByteSizeInBits - 1)) / ByteSizeInBits;
   constexpr size_t SizeFieldSize = sizeof(SizeTy);
 
   // Allocate space for size and data.
-  Val = new byte[SizeFieldSize + DataSize];
+  Val = new std::byte[SizeFieldSize + DataSize];
 
   // Write the size into first bytes.
   for (size_t I = 0; I < SizeFieldSize; ++I) {
-    auto ByteArrayVal = std::get<byte *>(Val);
-    ByteArrayVal[I] = (byte)DataBitSize;
+    auto ByteArrayVal = std::get<std::byte *>(Val);
+    ByteArrayVal[I] = (std::byte)DataBitSize;
     DataBitSize >>= ByteSizeInBits;
   }
   // Append data.
-  auto ByteArrayVal = std::get<byte *>(Val);
+  auto ByteArrayVal = std::get<std::byte *>(Val);
   std::memcpy(ByteArrayVal + SizeFieldSize, Data, DataSize);
 }
 
@@ -168,10 +168,8 @@ PropertyValue::PropertyValue(PropertyValue &&P) { *this = std::move(P); }
 PropertyValue &PropertyValue::operator=(PropertyValue &&P) {
   copy(P);
 
-  if (P.getType() == BYTE_ARRAY) {
-    auto &ByteArrayVal = std::get<byte *>(P.Val);
-    ByteArrayVal = nullptr;
-  }
+  if (P.getType() == BYTE_ARRAY)
+    P.Val = nullptr;
   P.Ty = NONE;
   return *this;
 }
diff --git a/llvm/unittests/Support/PropertySetIOTest.cpp b/llvm/unittests/Support/PropertySetIOTest.cpp
index 8fb09d43a04741..7083827c2b207f 100644
--- a/llvm/unittests/Support/PropertySetIOTest.cpp
+++ b/llvm/unittests/Support/PropertySetIOTest.cpp
@@ -52,7 +52,7 @@ TEST(PropertySet, ByteArrayValuesIO) {
 
   auto Content = "[Opt/Param]\n"
                  "kernel1=2|IAAAAAAAAAQA\n"
-                 "kernel2=2|oAAAAAAAAAw///3/wB\n";
+                 "kernel2=2|oAAAAAAAAAAAw///3/wB\n";
   auto MemBuf = MemoryBuffer::getMemBuffer(Content);
   // Parse a property set registry
   auto PropSetsPtr = PropertySetRegistry::read(MemBuf.get());

>From 20a7d75fa6d3c91ea9fdf5638b898e65c76eeefa Mon Sep 17 00:00:00 2001
From: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
Date: Wed, 9 Oct 2024 13:15:34 -0700
Subject: [PATCH 08/13] Add SYCL prefix to PropertySet etc.

Signed-off-by: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
---
 .../{PropertySetIO.h => SYCLPropertySetIO.h}  | 83 ++++++++++---------
 llvm/lib/Support/CMakeLists.txt               |  2 +-
 ...ropertySetIO.cpp => SYCLPropertySetIO.cpp} | 79 +++++++++---------
 llvm/unittests/Support/CMakeLists.txt         |  2 +-
 ...etIOTest.cpp => SYCLPropertySetIOTest.cpp} | 17 ++--
 5 files changed, 95 insertions(+), 88 deletions(-)
 rename llvm/include/llvm/Support/{PropertySetIO.h => SYCLPropertySetIO.h} (76%)
 rename llvm/lib/Support/{PropertySetIO.cpp => SYCLPropertySetIO.cpp} (63%)
 rename llvm/unittests/Support/{PropertySetIOTest.cpp => SYCLPropertySetIOTest.cpp} (80%)

diff --git a/llvm/include/llvm/Support/PropertySetIO.h b/llvm/include/llvm/Support/SYCLPropertySetIO.h
similarity index 76%
rename from llvm/include/llvm/Support/PropertySetIO.h
rename to llvm/include/llvm/Support/SYCLPropertySetIO.h
index 963bbcd33e6516..9bfba2d7992585 100644
--- a/llvm/include/llvm/Support/PropertySetIO.h
+++ b/llvm/include/llvm/Support/SYCLPropertySetIO.h
@@ -1,4 +1,4 @@
-//==-- PropertySetIO.h -- models a sequence of property sets and their I/O -==//
+//=- SYCLPropertySetIO.h -- models a sequence of property sets and their I/O =//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,15 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 // Models a sequence of property sets and their input and output operations.
-// PropertyValue set format:
-//   '['<PropertyValue set name>']'
+// SYCLPropertyValue set format:
+//   '['<SYCLPropertyValue set name>']'
 //   <property name>=<property type>'|'<property value>
 //   <property name>=<property type>'|'<property value>
 //   ...
-//   '['<PropertyValue set name>']'
+//   '['<SYCLPropertyValue set name>']'
 //   <property name>=<property type>'|'<property value>
 // where
-//   <PropertyValue set name>, <property name> are strings
+//   <SYCLPropertyValue set name>, <property name> are strings
 //   <property type> - string representation of the property type
 //   <property value> - string representation of the property value.
 //
@@ -29,8 +29,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_SUPPORT_PROPERTYSETIO_H
-#define LLVM_SUPPORT_PROPERTYSETIO_H
+#ifndef LLVM_SUPPORT_SYCLPROPERTYSETIO_H
+#define LLVM_SUPPORT_SYCLPROPERTYSETIO_H
 
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallString.h"
@@ -44,9 +44,9 @@
 namespace llvm {
 namespace util {
 
-// Represents a property value. PropertyValue name is stored in the encompassing
-// container.
-class PropertyValue {
+// Represents a SYCL property value. SYCLPropertyValue name is stored in the
+// encompassing container.
+class SYCLPropertyValue {
 public:
   // Type of the size of the value. Value size gets serialized along with the
   // value data in some cases for later reading at runtime, so size_t is not
@@ -66,26 +66,27 @@ class PropertyValue {
     return static_cast<Type>(T);
   }
 
-  ~PropertyValue() {}
+  ~SYCLPropertyValue() {}
 
-  PropertyValue() = default;
-  PropertyValue(Type T) : Ty(T) {}
+  SYCLPropertyValue() = default;
+  SYCLPropertyValue(Type T) : Ty(T) {}
 
-  PropertyValue(uint32_t Val) : Ty(UINT32), Val({Val}) {}
-  PropertyValue(const std::byte *Data, SizeTy DataBitSize);
+  SYCLPropertyValue(uint32_t Val) : Ty(UINT32), Val({Val}) {}
+  SYCLPropertyValue(const std::byte *Data, SizeTy DataBitSize);
   template <typename C, typename T = typename C::value_type>
-  PropertyValue(const C &Data)
-      : PropertyValue(reinterpret_cast<const std::byte *>(Data.data()),
-                      Data.size() * sizeof(T) * CHAR_BIT) {}
-  PropertyValue(const llvm::StringRef &Str)
-      : PropertyValue(reinterpret_cast<const std::byte *>(Str.data()),
-                      Str.size() * sizeof(char) * /* bits in one byte */ 8) {}
-  PropertyValue(const PropertyValue &P);
-  PropertyValue(PropertyValue &&P);
+  SYCLPropertyValue(const C &Data)
+      : SYCLPropertyValue(reinterpret_cast<const std::byte *>(Data.data()),
+                          Data.size() * sizeof(T) * CHAR_BIT) {}
+  SYCLPropertyValue(const llvm::StringRef &Str)
+      : SYCLPropertyValue(reinterpret_cast<const std::byte *>(Str.data()),
+                          Str.size() * sizeof(char) *
+                              /* bits in one byte */ 8) {}
+  SYCLPropertyValue(const SYCLPropertyValue &P);
+  SYCLPropertyValue(SYCLPropertyValue &&P);
 
-  PropertyValue &operator=(PropertyValue &&P);
+  SYCLPropertyValue &operator=(SYCLPropertyValue &&P);
 
-  PropertyValue &operator=(const PropertyValue &P);
+  SYCLPropertyValue &operator=(const SYCLPropertyValue &P);
 
   // Get property value as unsigned 32-bit integer
   uint32_t asUint32() const {
@@ -139,14 +140,14 @@ class PropertyValue {
 
   bool isValid() const { return getType() != NONE; }
 
-  // Set property value; the 'T' type must be convertible to a property type tag
+  // Set property value when data type is UINT32_T
   void set(uint32_t V) {
     if (Ty != UINT32)
       llvm_unreachable("invalid type tag for this operation");
     Val = V;
   }
 
-  // Set property value; the 'T' type must be convertible to a property type tag
+  // Set property value when data type is BYTE_ARRAY
   void set(std::byte *V, int DataSize) {
     if (Ty != BYTE_ARRAY)
       llvm_unreachable("invalid type tag for this operation");
@@ -175,19 +176,19 @@ class PropertyValue {
     case BYTE_ARRAY:
       return getRawByteArraySize();
     default:
-      llvm_unreachable_internal("unsupported property type");
+      llvm_unreachable_internal("unsupported SYCL property type");
     }
   }
 
 private:
-  void copy(const PropertyValue &P);
+  void copy(const SYCLPropertyValue &P);
 
   Type Ty = NONE;
   std::variant<uint32_t, std::byte *> Val;
 };
 
-/// Structure for specialization of DenseMap in PropertySetRegistry.
-struct PropertySetKeyInfo {
+/// Structure for specialization of DenseMap in SYCLPropertySetRegistry.
+struct SYCLPropertySetKeyInfo {
   static unsigned getHashValue(const SmallString<16> &K) { return xxHash64(K); }
 
   static SmallString<16> getEmptyKey() { return SmallString<16>(""); }
@@ -197,17 +198,19 @@ struct PropertySetKeyInfo {
   static bool isEqual(StringRef L, StringRef R) { return L == R; }
 };
 
-using PropertyMapTy = DenseMap<SmallString<16>, unsigned, PropertySetKeyInfo>;
+using SYCLPropertyMapTy =
+    DenseMap<SmallString<16>, unsigned, SYCLPropertySetKeyInfo>;
 /// A property set. Preserves insertion order when iterating elements.
-using PropertySet = MapVector<SmallString<16>, PropertyValue, PropertyMapTy>;
+using SYCLPropertySet =
+    MapVector<SmallString<16>, SYCLPropertyValue, SYCLPropertyMapTy>;
 
 /// A registry of property sets. Maps a property set name to its
 /// content.
 ///
 /// The order of keys is preserved and corresponds to the order of insertion.
-class PropertySetRegistry {
+class SYCLPropertySetRegistry {
 public:
-  using MapTy = MapVector<SmallString<16>, PropertySet, PropertyMapTy>;
+  using MapTy = MapVector<SmallString<16>, SYCLPropertySet, SYCLPropertyMapTy>;
 
   // Specific property category names used by tools.
   static constexpr char SYCL_SPECIALIZATION_CONSTANTS[] =
@@ -234,7 +237,7 @@ class PropertySetRegistry {
     auto &PropSet = PropSetMap[Category];
 
     for (const auto &[PropName, PropVal] : Props)
-      PropSet.insert_or_assign(PropName, PropertyValue(PropVal));
+      PropSet.insert_or_assign(PropName, SYCLPropertyValue(PropVal));
   }
 
   /// Adds the given \p PropVal with the given \p PropName into the given \p
@@ -242,11 +245,11 @@ class PropertySetRegistry {
   template <typename T>
   void add(StringRef Category, StringRef PropName, const T &PropVal) {
     auto &PropSet = PropSetMap[Category];
-    PropSet.insert({PropName, PropertyValue(PropVal)});
+    PropSet.insert({PropName, SYCLPropertyValue(PropVal)});
   }
 
   /// Parses from the given \p Buf a property set registry.
-  static Expected<std::unique_ptr<PropertySetRegistry>>
+  static Expected<std::unique_ptr<SYCLPropertySetRegistry>>
   read(const MemoryBuffer *Buf);
 
   /// Dumps the property set registry to the given \p Out stream.
@@ -256,7 +259,7 @@ class PropertySetRegistry {
   MapTy::const_iterator end() const { return PropSetMap.end(); }
 
   /// Retrieves a property set with given \p Name .
-  PropertySet &operator[](StringRef Name) { return PropSetMap[Name]; }
+  SYCLPropertySet &operator[](StringRef Name) { return PropSetMap[Name]; }
   /// Constant access to the underlying map.
   const MapTy &getPropSets() const { return PropSetMap; }
 
@@ -268,4 +271,4 @@ class PropertySetRegistry {
 
 } // namespace llvm
 
-#endif // #define LLVM_SUPPORT_PROPERTYSETIO_H
+#endif // #define LLVM_SUPPORT_SYCLPROPERTYSETIO_H
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 0a4d86bfca5121..2e277ba0a9818e 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -217,7 +217,7 @@ add_llvm_component_library(LLVMSupport
   Parallel.cpp
   PluginLoader.cpp
   PrettyStackTrace.cpp
-  PropertySetIO.cpp  
+  SYCLPropertySetIO.cpp  
   RandomNumberGenerator.cpp
   Regex.cpp
   RewriteBuffer.cpp
diff --git a/llvm/lib/Support/PropertySetIO.cpp b/llvm/lib/Support/SYCLPropertySetIO.cpp
similarity index 63%
rename from llvm/lib/Support/PropertySetIO.cpp
rename to llvm/lib/Support/SYCLPropertySetIO.cpp
index 661ee6d9fb3243..c8923d266fcec8 100644
--- a/llvm/lib/Support/PropertySetIO.cpp
+++ b/llvm/lib/Support/SYCLPropertySetIO.cpp
@@ -1,4 +1,4 @@
-//==- PropertySetIO.cpp - models a sequence of property sets and their I/O -==//
+//= SYCLPropertySetIO.cpp - models a sequence of property sets and their I/O =//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Support/PropertySetIO.h"
+#include "llvm/Support/SYCLPropertySetIO.h"
 
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/StringExtras.h"
@@ -28,10 +28,10 @@ ::llvm::Error makeError(const Twine &Msg) {
 
 } // anonymous namespace
 
-Expected<std::unique_ptr<PropertySetRegistry>>
-PropertySetRegistry::read(const MemoryBuffer *Buf) {
-  auto Res = std::make_unique<PropertySetRegistry>();
-  PropertySet *CurPropSet = nullptr;
+Expected<std::unique_ptr<SYCLPropertySetRegistry>>
+SYCLPropertySetRegistry::read(const MemoryBuffer *Buf) {
+  auto Res = std::make_unique<SYCLPropertySetRegistry>();
+  SYCLPropertySet *CurPropSet = nullptr;
 
   for (line_iterator LI(*Buf); !LI.is_at_end(); LI++) {
     // See if this line starts a new property set
@@ -60,17 +60,17 @@ PropertySetRegistry::read(const MemoryBuffer *Buf) {
     // Parse type
     if (TypeVal.first.getAsInteger(10, Tint))
       return makeError("invalid property type: " + TypeVal.first);
-    Expected<PropertyValue::Type> Ttag =
-        PropertyValue::getTypeTag(static_cast<int>(Tint.getSExtValue()));
+    Expected<SYCLPropertyValue::Type> Ttag =
+        SYCLPropertyValue::getTypeTag(static_cast<int>(Tint.getSExtValue()));
     StringRef Val = TypeVal.second;
 
     if (!Ttag)
       return Ttag.takeError();
-    PropertyValue Prop(Ttag.get());
+    SYCLPropertyValue Prop(Ttag.get());
 
     // Parse value depending on its type
     switch (Ttag.get()) {
-    case PropertyValue::Type::UINT32: {
+    case SYCLPropertyValue::Type::UINT32: {
       APInt ValV;
       if (Val.getAsInteger(10, ValV))
         return createStringError(std::error_code{},
@@ -79,7 +79,7 @@ PropertySetRegistry::read(const MemoryBuffer *Buf) {
       llvm::errs() << "ARV: read int done\n";
       break;
     }
-    case PropertyValue::Type::BYTE_ARRAY: {
+    case SYCLPropertyValue::Type::BYTE_ARRAY: {
       std::vector<char> Output;
       if (Error Err = decodeBase64(Val, Output))
         return std::move(Err);
@@ -95,18 +95,18 @@ PropertySetRegistry::read(const MemoryBuffer *Buf) {
   if (!CurPropSet)
     return makeError("invalid property set registry");
 
-  return Expected<std::unique_ptr<PropertySetRegistry>>(std::move(Res));
+  return Expected<std::unique_ptr<SYCLPropertySetRegistry>>(std::move(Res));
 }
 
 namespace llvm {
 // Output a property to a stream
-raw_ostream &operator<<(raw_ostream &Out, const PropertyValue &Prop) {
+raw_ostream &operator<<(raw_ostream &Out, const SYCLPropertyValue &Prop) {
   Out << static_cast<int>(Prop.getType()) << '|';
   switch (Prop.getType()) {
-  case PropertyValue::Type::UINT32:
+  case SYCLPropertyValue::Type::UINT32:
     Out << Prop.asUint32();
     break;
-  case PropertyValue::Type::BYTE_ARRAY: {
+  case SYCLPropertyValue::Type::BYTE_ARRAY: {
     auto PropArr = Prop.asByteArray();
     std::vector<std::byte> V(PropArr, PropArr + Prop.getByteArraySize() /
                                                     sizeof(std::byte));
@@ -121,7 +121,7 @@ raw_ostream &operator<<(raw_ostream &Out, const PropertyValue &Prop) {
 }
 } // namespace llvm
 
-void PropertySetRegistry::write(raw_ostream &Out) const {
+void SYCLPropertySetRegistry::write(raw_ostream &Out) const {
   for (const auto &PropSet : PropSetMap) {
     Out << '[' << PropSet.first << "]\n";
 
@@ -133,15 +133,16 @@ void PropertySetRegistry::write(raw_ostream &Out) const {
 namespace llvm {
 namespace util {
 
-template <> PropertyValue::Type PropertyValue::getTypeTag<uint32_t>() {
+template <> SYCLPropertyValue::Type SYCLPropertyValue::getTypeTag<uint32_t>() {
   return UINT32;
 }
 
-template <> PropertyValue::Type PropertyValue::getTypeTag<std::byte *>() {
+template <>
+SYCLPropertyValue::Type SYCLPropertyValue::getTypeTag<std::byte *>() {
   return BYTE_ARRAY;
 }
 
-PropertyValue::PropertyValue(const std::byte *Data, SizeTy DataBitSize)
+SYCLPropertyValue::SYCLPropertyValue(const std::byte *Data, SizeTy DataBitSize)
     : Ty(BYTE_ARRAY) {
   constexpr int ByteSizeInBits = 8;
   SizeTy DataSize = (DataBitSize + (ByteSizeInBits - 1)) / ByteSizeInBits;
@@ -161,11 +162,13 @@ PropertyValue::PropertyValue(const std::byte *Data, SizeTy DataBitSize)
   std::memcpy(ByteArrayVal + SizeFieldSize, Data, DataSize);
 }
 
-PropertyValue::PropertyValue(const PropertyValue &P) { *this = P; }
+SYCLPropertyValue::SYCLPropertyValue(const SYCLPropertyValue &P) { *this = P; }
 
-PropertyValue::PropertyValue(PropertyValue &&P) { *this = std::move(P); }
+SYCLPropertyValue::SYCLPropertyValue(SYCLPropertyValue &&P) {
+  *this = std::move(P);
+}
 
-PropertyValue &PropertyValue::operator=(PropertyValue &&P) {
+SYCLPropertyValue &SYCLPropertyValue::operator=(SYCLPropertyValue &&P) {
   copy(P);
 
   if (P.getType() == BYTE_ARRAY)
@@ -174,32 +177,32 @@ PropertyValue &PropertyValue::operator=(PropertyValue &&P) {
   return *this;
 }
 
-PropertyValue &PropertyValue::operator=(const PropertyValue &P) {
+SYCLPropertyValue &SYCLPropertyValue::operator=(const SYCLPropertyValue &P) {
   if (P.getType() == BYTE_ARRAY)
-    *this = PropertyValue(P.asByteArray(), P.getByteArraySizeInBits());
+    *this = SYCLPropertyValue(P.asByteArray(), P.getByteArraySizeInBits());
   else
     copy(P);
   return *this;
 }
 
-void PropertyValue::copy(const PropertyValue &P) {
+void SYCLPropertyValue::copy(const SYCLPropertyValue &P) {
   Ty = P.Ty;
   Val = P.Val;
 }
 
-constexpr char PropertySetRegistry::SYCL_SPECIALIZATION_CONSTANTS[];
-constexpr char PropertySetRegistry::SYCL_DEVICELIB_REQ_MASK[];
-constexpr char PropertySetRegistry::SYCL_SPEC_CONSTANTS_DEFAULT_VALUES[];
-constexpr char PropertySetRegistry::SYCL_KERNEL_PARAM_OPT_INFO[];
-constexpr char PropertySetRegistry::SYCL_PROGRAM_METADATA[];
-constexpr char PropertySetRegistry::SYCL_MISC_PROP[];
-constexpr char PropertySetRegistry::SYCL_ASSERT_USED[];
-constexpr char PropertySetRegistry::SYCL_EXPORTED_SYMBOLS[];
-constexpr char PropertySetRegistry::SYCL_IMPORTED_SYMBOLS[];
-constexpr char PropertySetRegistry::SYCL_DEVICE_GLOBALS[];
-constexpr char PropertySetRegistry::SYCL_DEVICE_REQUIREMENTS[];
-constexpr char PropertySetRegistry::SYCL_HOST_PIPES[];
-constexpr char PropertySetRegistry::SYCL_VIRTUAL_FUNCTIONS[];
+constexpr char SYCLPropertySetRegistry::SYCL_SPECIALIZATION_CONSTANTS[];
+constexpr char SYCLPropertySetRegistry::SYCL_DEVICELIB_REQ_MASK[];
+constexpr char SYCLPropertySetRegistry::SYCL_SPEC_CONSTANTS_DEFAULT_VALUES[];
+constexpr char SYCLPropertySetRegistry::SYCL_KERNEL_PARAM_OPT_INFO[];
+constexpr char SYCLPropertySetRegistry::SYCL_PROGRAM_METADATA[];
+constexpr char SYCLPropertySetRegistry::SYCL_MISC_PROP[];
+constexpr char SYCLPropertySetRegistry::SYCL_ASSERT_USED[];
+constexpr char SYCLPropertySetRegistry::SYCL_EXPORTED_SYMBOLS[];
+constexpr char SYCLPropertySetRegistry::SYCL_IMPORTED_SYMBOLS[];
+constexpr char SYCLPropertySetRegistry::SYCL_DEVICE_GLOBALS[];
+constexpr char SYCLPropertySetRegistry::SYCL_DEVICE_REQUIREMENTS[];
+constexpr char SYCLPropertySetRegistry::SYCL_HOST_PIPES[];
+constexpr char SYCLPropertySetRegistry::SYCL_VIRTUAL_FUNCTIONS[];
 
 } // namespace util
 } // namespace llvm
diff --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt
index 0261ecdd7ea0bd..61789ef39a6797 100644
--- a/llvm/unittests/Support/CMakeLists.txt
+++ b/llvm/unittests/Support/CMakeLists.txt
@@ -69,7 +69,7 @@ add_llvm_unittest(SupportTests
   PerThreadBumpPtrAllocatorTest.cpp
   ProcessTest.cpp
   ProgramTest.cpp
-  PropertySetIOTest.cpp
+  SYCLPropertySetIOTest.cpp
   RegexTest.cpp
   ReverseIterationTest.cpp
   ReplaceFileTest.cpp
diff --git a/llvm/unittests/Support/PropertySetIOTest.cpp b/llvm/unittests/Support/SYCLPropertySetIOTest.cpp
similarity index 80%
rename from llvm/unittests/Support/PropertySetIOTest.cpp
rename to llvm/unittests/Support/SYCLPropertySetIOTest.cpp
index 7083827c2b207f..cc7ade67526d5b 100644
--- a/llvm/unittests/Support/PropertySetIOTest.cpp
+++ b/llvm/unittests/Support/SYCLPropertySetIOTest.cpp
@@ -1,4 +1,5 @@
-//=- llvm/unittest/Support/PropertySetIOTest.cpp - Property set I/O tests ---=//
+// llvm/unittest/Support/SYCLPropertySetIOTest.cpp - SYCL Property set I/O tests
+// //
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Support/PropertySetIO.h"
+#include "llvm/Support/SYCLPropertySetIO.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -17,7 +18,7 @@ using namespace llvm::util;
 
 namespace {
 
-TEST(PropertySet, IntValuesIO) {
+TEST(SYCLPropertySet, IntValuesIO) {
   // '1' in '1|20' means 'integer property'
   auto Content = "[Staff/Ages]\n"
                  "person1=1|20\n"
@@ -28,10 +29,10 @@ TEST(PropertySet, IntValuesIO) {
                  "person3=1|12\n";
   auto MemBuf = MemoryBuffer::getMemBuffer(Content);
   // Parse a property set registry
-  auto PropSetsPtr = PropertySetRegistry::read(MemBuf.get());
+  auto PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
 
   if (!PropSetsPtr)
-    FAIL() << "PropertySetRegistry::read failed\n";
+    FAIL() << "SYCLPropertySetRegistry::read failed\n";
 
   std::string Serialized;
   {
@@ -43,7 +44,7 @@ TEST(PropertySet, IntValuesIO) {
   EXPECT_EQ(Serialized, Content);
 }
 
-TEST(PropertySet, ByteArrayValuesIO) {
+TEST(SYCLPropertySet, ByteArrayValuesIO) {
   // '2' in '2|...' means 'byte array property', Base64-encoded
   // encodes the following byte arrays:
   //   { 8, 0, 0, 0, 0, 0, 0, 0, 0x1 };
@@ -55,10 +56,10 @@ TEST(PropertySet, ByteArrayValuesIO) {
                  "kernel2=2|oAAAAAAAAAAAw///3/wB\n";
   auto MemBuf = MemoryBuffer::getMemBuffer(Content);
   // Parse a property set registry
-  auto PropSetsPtr = PropertySetRegistry::read(MemBuf.get());
+  auto PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
 
   if (!PropSetsPtr)
-    FAIL() << "PropertySetRegistry::read failed\n";
+    FAIL() << "SYCLPropertySetRegistry::read failed\n";
 
   std::string Serialized;
   {

>From 025503af2ec438c066093279210c271f38dc9cc1 Mon Sep 17 00:00:00 2001
From: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
Date: Wed, 9 Oct 2024 13:52:25 -0700
Subject: [PATCH 09/13] Add tests expected to fail and make sure errors are
 caught

Signed-off-by: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
---
 llvm/lib/Support/SYCLPropertySetIO.cpp        |  1 -
 .../Support/SYCLPropertySetIOTest.cpp         | 70 +++++++++++++++++++
 2 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Support/SYCLPropertySetIO.cpp b/llvm/lib/Support/SYCLPropertySetIO.cpp
index c8923d266fcec8..1ad070ee8f0cf4 100644
--- a/llvm/lib/Support/SYCLPropertySetIO.cpp
+++ b/llvm/lib/Support/SYCLPropertySetIO.cpp
@@ -76,7 +76,6 @@ SYCLPropertySetRegistry::read(const MemoryBuffer *Buf) {
         return createStringError(std::error_code{},
                                  "invalid property value: ", Val.data());
       Prop.set(static_cast<uint32_t>(ValV.getZExtValue()));
-      llvm::errs() << "ARV: read int done\n";
       break;
     }
     case SYCLPropertyValue::Type::BYTE_ARRAY: {
diff --git a/llvm/unittests/Support/SYCLPropertySetIOTest.cpp b/llvm/unittests/Support/SYCLPropertySetIOTest.cpp
index cc7ade67526d5b..3c57dde8dae15a 100644
--- a/llvm/unittests/Support/SYCLPropertySetIOTest.cpp
+++ b/llvm/unittests/Support/SYCLPropertySetIOTest.cpp
@@ -18,6 +18,76 @@ using namespace llvm::util;
 
 namespace {
 
+TEST(SYCLPropertySet, IncorrectValuesIO) {
+  auto Content = "Staff/Ages]\n";
+  auto MemBuf = MemoryBuffer::getMemBuffer(Content);
+  // Parse a property set registry
+  auto PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
+  if (PropSetsPtr)
+    FAIL() << "SYCLPropertySetRegistry::Invalid line error not caught\n";
+
+  Content = "[Staff/Ages\n";
+  MemBuf = MemoryBuffer::getMemBuffer(Content);
+  // Parse a property set registry
+  PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
+  if (PropSetsPtr)
+    FAIL() << "SYCLPropertySetRegistry::Invalid line error not caught\n";
+
+  Content = "[Staff/Ages]\n"
+            "person1=\n";
+  MemBuf = MemoryBuffer::getMemBuffer(Content);
+  // Parse a property set registry
+  PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
+  if (PropSetsPtr)
+    FAIL()
+        << "SYCLPropertySetRegistry::Invalid property line error not caught\n";
+
+  Content = "[Staff/Ages]\n"
+            "person1=|10\n";
+  MemBuf = MemoryBuffer::getMemBuffer(Content);
+  // Parse a property set registry
+  PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
+  if (PropSetsPtr)
+    FAIL()
+        << "SYCLPropertySetRegistry::Invalid property value error not caught\n";
+
+  Content = "[Staff/Ages]\n"
+            "person1=abc|10\n";
+  MemBuf = MemoryBuffer::getMemBuffer(Content);
+  // Parse a property set registry
+  PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
+  if (PropSetsPtr)
+    FAIL()
+        << "SYCLPropertySetRegistry::Invalid property type error not caught\n";
+
+  Content = "[Staff/Ages]\n"
+            "person1=2|10\n";
+  MemBuf = MemoryBuffer::getMemBuffer(Content);
+  // Parse a property set registry
+  PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
+  if (PropSetsPtr)
+    FAIL()
+        << "SYCLPropertySetRegistry::Invalid property value error not caught\n";
+
+  Content = "[Staff/Ages]\n"
+            "person1=2|IAQ\n";
+  MemBuf = MemoryBuffer::getMemBuffer(Content);
+  // Parse a property set registry
+  PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
+  if (PropSetsPtr)
+    FAIL()
+        << "SYCLPropertySetRegistry::Invalid property value error not caught\n";
+
+  Content = "[Staff/Ages]\n"
+            "person1=100|10\n";
+  MemBuf = MemoryBuffer::getMemBuffer(Content);
+  // Parse a property set registry
+  PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
+  if (PropSetsPtr)
+    FAIL()
+        << "SYCLPropertySetRegistry::Invalid property type error not caught\n";
+}
+
 TEST(SYCLPropertySet, IntValuesIO) {
   // '1' in '1|20' means 'integer property'
   auto Content = "[Staff/Ages]\n"

>From 6550bf55494f40f4309923d24b7ce30f42416226 Mon Sep 17 00:00:00 2001
From: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
Date: Wed, 9 Oct 2024 21:06:27 -0700
Subject: [PATCH 10/13] Update test to pass when assertions are turned on

Signed-off-by: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
---
 .../Support/SYCLPropertySetIOTest.cpp         | 39 ++++++++-----------
 1 file changed, 17 insertions(+), 22 deletions(-)

diff --git a/llvm/unittests/Support/SYCLPropertySetIOTest.cpp b/llvm/unittests/Support/SYCLPropertySetIOTest.cpp
index 3c57dde8dae15a..c4272def0b703c 100644
--- a/llvm/unittests/Support/SYCLPropertySetIOTest.cpp
+++ b/llvm/unittests/Support/SYCLPropertySetIOTest.cpp
@@ -10,6 +10,7 @@
 #include "llvm/Support/SYCLPropertySetIO.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Testing/Support/Error.h"
 
 #include "gtest/gtest.h"
 
@@ -23,69 +24,63 @@ TEST(SYCLPropertySet, IncorrectValuesIO) {
   auto MemBuf = MemoryBuffer::getMemBuffer(Content);
   // Parse a property set registry
   auto PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
-  if (PropSetsPtr)
-    FAIL() << "SYCLPropertySetRegistry::Invalid line error not caught\n";
+  EXPECT_THAT_ERROR(std::move(PropSetsPtr.takeError()), Failed())
+      << "Invalid line";
 
   Content = "[Staff/Ages\n";
   MemBuf = MemoryBuffer::getMemBuffer(Content);
   // Parse a property set registry
   PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
-  if (PropSetsPtr)
-    FAIL() << "SYCLPropertySetRegistry::Invalid line error not caught\n";
+  EXPECT_THAT_ERROR(std::move(PropSetsPtr.takeError()), Failed())
+      << "Invalid line";
 
   Content = "[Staff/Ages]\n"
             "person1=\n";
   MemBuf = MemoryBuffer::getMemBuffer(Content);
   // Parse a property set registry
   PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
-  if (PropSetsPtr)
-    FAIL()
-        << "SYCLPropertySetRegistry::Invalid property line error not caught\n";
+  EXPECT_THAT_ERROR(std::move(PropSetsPtr.takeError()), Failed())
+      << "Invalid property line";
 
   Content = "[Staff/Ages]\n"
             "person1=|10\n";
   MemBuf = MemoryBuffer::getMemBuffer(Content);
   // Parse a property set registry
   PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
-  if (PropSetsPtr)
-    FAIL()
-        << "SYCLPropertySetRegistry::Invalid property value error not caught\n";
+  EXPECT_THAT_ERROR(std::move(PropSetsPtr.takeError()), Failed())
+      << "Invalid property value";
 
   Content = "[Staff/Ages]\n"
             "person1=abc|10\n";
   MemBuf = MemoryBuffer::getMemBuffer(Content);
   // Parse a property set registry
   PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
-  if (PropSetsPtr)
-    FAIL()
-        << "SYCLPropertySetRegistry::Invalid property type error not caught\n";
+  EXPECT_THAT_ERROR(std::move(PropSetsPtr.takeError()), Failed())
+      << "Invalid property type";
 
   Content = "[Staff/Ages]\n"
             "person1=2|10\n";
   MemBuf = MemoryBuffer::getMemBuffer(Content);
   // Parse a property set registry
   PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
-  if (PropSetsPtr)
-    FAIL()
-        << "SYCLPropertySetRegistry::Invalid property value error not caught\n";
+  EXPECT_THAT_ERROR(std::move(PropSetsPtr.takeError()), Failed())
+      << "Invalid property value";
 
   Content = "[Staff/Ages]\n"
             "person1=2|IAQ\n";
   MemBuf = MemoryBuffer::getMemBuffer(Content);
   // Parse a property set registry
   PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
-  if (PropSetsPtr)
-    FAIL()
-        << "SYCLPropertySetRegistry::Invalid property value error not caught\n";
+  EXPECT_THAT_ERROR(std::move(PropSetsPtr.takeError()), Failed())
+      << "Invalid property value";
 
   Content = "[Staff/Ages]\n"
             "person1=100|10\n";
   MemBuf = MemoryBuffer::getMemBuffer(Content);
   // Parse a property set registry
   PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());
-  if (PropSetsPtr)
-    FAIL()
-        << "SYCLPropertySetRegistry::Invalid property type error not caught\n";
+  EXPECT_THAT_ERROR(std::move(PropSetsPtr.takeError()), Failed())
+      << "Invalid property type";
 }
 
 TEST(SYCLPropertySet, IntValuesIO) {

>From 4de315891600364fe4798361e3177625afc542b8 Mon Sep 17 00:00:00 2001
From: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
Date: Wed, 9 Oct 2024 21:14:42 -0700
Subject: [PATCH 11/13] Replace simple llvm_unreachable with asserts

Signed-off-by: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
---
 llvm/include/llvm/Support/SYCLPropertySetIO.h | 18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/llvm/include/llvm/Support/SYCLPropertySetIO.h b/llvm/include/llvm/Support/SYCLPropertySetIO.h
index 9bfba2d7992585..bd628e8efba23a 100644
--- a/llvm/include/llvm/Support/SYCLPropertySetIO.h
+++ b/llvm/include/llvm/Support/SYCLPropertySetIO.h
@@ -90,15 +90,13 @@ class SYCLPropertyValue {
 
   // Get property value as unsigned 32-bit integer
   uint32_t asUint32() const {
-    if (Ty != UINT32)
-      llvm_unreachable("must be UINT32 value");
+    assert((Ty == UINT32) && "must be UINT32 value");
     return std::get<uint32_t>(Val);
   }
 
   // Get raw data size in bits.
   SizeTy getByteArraySizeInBits() const {
-    if (Ty != BYTE_ARRAY)
-      llvm_unreachable("must be BYTE_ARRAY value");
+    assert((Ty == BYTE_ARRAY) && "must be BYTE_ARRAY value");
     SizeTy Res = 0;
 
     for (size_t I = 0; I < sizeof(SizeTy); ++I) {
@@ -123,16 +121,14 @@ class SYCLPropertyValue {
 
   // Get byte array data including the leading bytes encoding the size.
   const std::byte *asRawByteArray() const {
-    if (Ty != BYTE_ARRAY)
-      llvm_unreachable("must be BYTE_ARRAY value");
+    assert((Ty == BYTE_ARRAY) && "must be BYTE_ARRAY value");
     auto *ByteArrayVal = std::get<std::byte *>(Val);
     return ByteArrayVal;
   }
 
   // Get byte array data excluding the leading bytes encoding the size.
   const std::byte *asByteArray() const {
-    if (Ty != BYTE_ARRAY)
-      llvm_unreachable("must be BYTE_ARRAY value");
+    assert((Ty == BYTE_ARRAY) && "must be BYTE_ARRAY value");
 
     auto ByteArrayVal = std::get<std::byte *>(Val);
     return ByteArrayVal + sizeof(SizeTy);
@@ -142,15 +138,13 @@ class SYCLPropertyValue {
 
   // Set property value when data type is UINT32_T
   void set(uint32_t V) {
-    if (Ty != UINT32)
-      llvm_unreachable("invalid type tag for this operation");
+    assert((Ty == UINT32) && "must be UINT32 value");
     Val = V;
   }
 
   // Set property value when data type is BYTE_ARRAY
   void set(std::byte *V, int DataSize) {
-    if (Ty != BYTE_ARRAY)
-      llvm_unreachable("invalid type tag for this operation");
+    assert((Ty == BYTE_ARRAY) && "must be BYTE_ARRAY value");
     size_t DataBitSize = DataSize * CHAR_BIT;
     constexpr size_t SizeFieldSize = sizeof(SizeTy);
     // Allocate space for size and data.

>From b15e2019efc3524b47219ce7b99e09efa9d0d9be Mon Sep 17 00:00:00 2001
From: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
Date: Mon, 14 Oct 2024 08:06:26 -0700
Subject: [PATCH 12/13] Addressed the following comments:

1. LLVM standard coding violations pointed out.
2. Removed 'Ty' field in the SYCLPropertyValue class and adjusted the code.

Signed-off-by: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
---
 llvm/include/llvm/Support/SYCLPropertySetIO.h |  82 +++++++------
 llvm/lib/Support/SYCLPropertySetIO.cpp        | 109 ++++++------------
 .../Support/SYCLPropertySetIOTest.cpp         |   2 +-
 3 files changed, 83 insertions(+), 110 deletions(-)

diff --git a/llvm/include/llvm/Support/SYCLPropertySetIO.h b/llvm/include/llvm/Support/SYCLPropertySetIO.h
index bd628e8efba23a..b024c5c0b068b6 100644
--- a/llvm/include/llvm/Support/SYCLPropertySetIO.h
+++ b/llvm/include/llvm/Support/SYCLPropertySetIO.h
@@ -54,7 +54,7 @@ class SYCLPropertyValue {
   using SizeTy = uint64_t;
 
   // Defines supported property types
-  enum Type { first = 0, NONE = first, UINT32, BYTE_ARRAY, last = BYTE_ARRAY };
+  enum Type { first = 0, None = first, UInt32, ByteArray, last = ByteArray };
 
   // Translates C++ type to the corresponding type tag.
   template <typename T> static Type getTypeTag();
@@ -69,9 +69,16 @@ class SYCLPropertyValue {
   ~SYCLPropertyValue() {}
 
   SYCLPropertyValue() = default;
-  SYCLPropertyValue(Type T) : Ty(T) {}
 
-  SYCLPropertyValue(uint32_t Val) : Ty(UINT32), Val({Val}) {}
+  SYCLPropertyValue(Type Ty) {
+    if (Ty == UInt32)
+      Val = (uint32_t)0;
+    else if (Ty == ByteArray)
+      Val = (std::byte *)(0);
+    else
+      llvm_unreachable_internal("unsupported SYCL property type");
+  }
+  SYCLPropertyValue(uint32_t Val) : Val({Val}) {}
   SYCLPropertyValue(const std::byte *Data, SizeTy DataBitSize);
   template <typename C, typename T = typename C::value_type>
   SYCLPropertyValue(const C &Data)
@@ -79,8 +86,7 @@ class SYCLPropertyValue {
                           Data.size() * sizeof(T) * CHAR_BIT) {}
   SYCLPropertyValue(const llvm::StringRef &Str)
       : SYCLPropertyValue(reinterpret_cast<const std::byte *>(Str.data()),
-                          Str.size() * sizeof(char) *
-                              /* bits in one byte */ 8) {}
+                          Str.size() * sizeof(char) * CHAR_BIT) {}
   SYCLPropertyValue(const SYCLPropertyValue &P);
   SYCLPropertyValue(SYCLPropertyValue &&P);
 
@@ -90,13 +96,14 @@ class SYCLPropertyValue {
 
   // Get property value as unsigned 32-bit integer
   uint32_t asUint32() const {
-    assert((Ty == UINT32) && "must be UINT32 value");
+    assert(std::holds_alternative<uint32_t>(Val) && "must be a uint32_t value");
     return std::get<uint32_t>(Val);
   }
 
   // Get raw data size in bits.
   SizeTy getByteArraySizeInBits() const {
-    assert((Ty == BYTE_ARRAY) && "must be BYTE_ARRAY value");
+    assert(std::holds_alternative<std::byte *>(Val) &&
+           "must be a byte array value");
     SizeTy Res = 0;
 
     for (size_t I = 0; I < sizeof(SizeTy); ++I) {
@@ -121,30 +128,33 @@ class SYCLPropertyValue {
 
   // Get byte array data including the leading bytes encoding the size.
   const std::byte *asRawByteArray() const {
-    assert((Ty == BYTE_ARRAY) && "must be BYTE_ARRAY value");
+    assert(std::holds_alternative<std::byte *>(Val) &&
+           "must be a byte array value");
     auto *ByteArrayVal = std::get<std::byte *>(Val);
     return ByteArrayVal;
   }
 
   // Get byte array data excluding the leading bytes encoding the size.
   const std::byte *asByteArray() const {
-    assert((Ty == BYTE_ARRAY) && "must be BYTE_ARRAY value");
+    assert(std::holds_alternative<std::byte *>(Val) &&
+           "must be a byte array value");
 
     auto ByteArrayVal = std::get<std::byte *>(Val);
     return ByteArrayVal + sizeof(SizeTy);
   }
 
-  bool isValid() const { return getType() != NONE; }
+  bool isValid() const { return getType() != None; }
 
-  // Set property value when data type is UINT32_T
+  // Set property value when data type is uint32_t
   void set(uint32_t V) {
-    assert((Ty == UINT32) && "must be UINT32 value");
+    assert(std::holds_alternative<uint32_t>(Val) && "must be a uint32_t value");
     Val = V;
   }
 
-  // Set property value when data type is BYTE_ARRAY
+  // Set property value when data type is 'std::byte *'
   void set(std::byte *V, int DataSize) {
-    assert((Ty == BYTE_ARRAY) && "must be BYTE_ARRAY value");
+    assert(std::holds_alternative<std::byte *>(Val) &&
+           "must be a byte array value");
     size_t DataBitSize = DataSize * CHAR_BIT;
     constexpr size_t SizeFieldSize = sizeof(SizeTy);
     // Allocate space for size and data.
@@ -161,23 +171,25 @@ class SYCLPropertyValue {
     std::memcpy(ByteArrayVal + SizeFieldSize, V, DataSize);
   }
 
-  Type getType() const { return Ty; }
+  Type getType() const {
+    if (std::holds_alternative<uint32_t>(Val))
+      return UInt32;
+    if (std::holds_alternative<std::byte *>(Val))
+      return ByteArray;
+    return None;
+  }
 
   SizeTy size() const {
-    switch (Ty) {
-    case UINT32:
+    if (std::holds_alternative<uint32_t>(Val))
       return sizeof(uint32_t);
-    case BYTE_ARRAY:
+    if (std::holds_alternative<std::byte *>(Val))
       return getRawByteArraySize();
-    default:
-      llvm_unreachable_internal("unsupported SYCL property type");
-    }
+    llvm_unreachable_internal("unsupported SYCL property type");
   }
 
 private:
   void copy(const SYCLPropertyValue &P);
 
-  Type Ty = NONE;
   std::variant<uint32_t, std::byte *> Val;
 };
 
@@ -207,21 +219,21 @@ class SYCLPropertySetRegistry {
   using MapTy = MapVector<SmallString<16>, SYCLPropertySet, SYCLPropertyMapTy>;
 
   // Specific property category names used by tools.
-  static constexpr char SYCL_SPECIALIZATION_CONSTANTS[] =
+  static constexpr char SYCLSpecializationConstants[] =
       "SYCL/specialization constants";
-  static constexpr char SYCL_SPEC_CONSTANTS_DEFAULT_VALUES[] =
+  static constexpr char SYCLSpecConstantsDefaultValues[] =
       "SYCL/specialization constants default values";
-  static constexpr char SYCL_DEVICELIB_REQ_MASK[] = "SYCL/devicelib req mask";
-  static constexpr char SYCL_KERNEL_PARAM_OPT_INFO[] = "SYCL/kernel param opt";
-  static constexpr char SYCL_PROGRAM_METADATA[] = "SYCL/program metadata";
-  static constexpr char SYCL_MISC_PROP[] = "SYCL/misc properties";
-  static constexpr char SYCL_ASSERT_USED[] = "SYCL/assert used";
-  static constexpr char SYCL_EXPORTED_SYMBOLS[] = "SYCL/exported symbols";
-  static constexpr char SYCL_IMPORTED_SYMBOLS[] = "SYCL/imported symbols";
-  static constexpr char SYCL_DEVICE_GLOBALS[] = "SYCL/device globals";
-  static constexpr char SYCL_DEVICE_REQUIREMENTS[] = "SYCL/device requirements";
-  static constexpr char SYCL_HOST_PIPES[] = "SYCL/host pipes";
-  static constexpr char SYCL_VIRTUAL_FUNCTIONS[] = "SYCL/virtual functions";
+  static constexpr char SYCLDeviceLibReqMask[] = "SYCL/devicelib req mask";
+  static constexpr char SYCLKernelParamOptInfo[] = "SYCL/kernel param opt";
+  static constexpr char SYCLProgramMetadata[] = "SYCL/program metadata";
+  static constexpr char SYCLMiscProp[] = "SYCL/misc properties";
+  static constexpr char SYCLAssertUsed[] = "SYCL/assert used";
+  static constexpr char SYCLExportedSymbols[] = "SYCL/exported symbols";
+  static constexpr char SYCLImportedSymbols[] = "SYCL/imported symbols";
+  static constexpr char SYCLDeviceGlobals[] = "SYCL/device globals";
+  static constexpr char SYCLDeviceRequirements[] = "SYCL/device requirements";
+  static constexpr char SYCLHostPipes[] = "SYCL/host pipes";
+  static constexpr char SYCLVirtualFunctions[] = "SYCL/virtual functions";
 
   /// Function for bulk addition of an entire property set in the given
   /// \p Category .
diff --git a/llvm/lib/Support/SYCLPropertySetIO.cpp b/llvm/lib/Support/SYCLPropertySetIO.cpp
index 1ad070ee8f0cf4..1888e9dc5cfd52 100644
--- a/llvm/lib/Support/SYCLPropertySetIO.cpp
+++ b/llvm/lib/Support/SYCLPropertySetIO.cpp
@@ -20,14 +20,10 @@
 using namespace llvm::util;
 using namespace llvm;
 
-namespace {
-
-::llvm::Error makeError(const Twine &Msg) {
+static llvm::Error makeError(const Twine &Msg) {
   return createStringError(std::error_code{}, Msg);
 }
 
-} // anonymous namespace
-
 Expected<std::unique_ptr<SYCLPropertySetRegistry>>
 SYCLPropertySetRegistry::read(const MemoryBuffer *Buf) {
   auto Res = std::make_unique<SYCLPropertySetRegistry>();
@@ -37,7 +33,7 @@ SYCLPropertySetRegistry::read(const MemoryBuffer *Buf) {
     // See if this line starts a new property set
     if (LI->starts_with("[")) {
       // Parse the category (property name)
-      auto EndPos = LI->rfind(']');
+      size_t EndPos = LI->rfind(']');
       if (EndPos == StringRef::npos)
         return makeError("invalid line: " + *LI);
       StringRef Category = LI->substr(1, EndPos - 1);
@@ -47,49 +43,46 @@ SYCLPropertySetRegistry::read(const MemoryBuffer *Buf) {
     if (!CurPropSet)
       return makeError("property category missing");
     // Parse name and type+value
-    auto Parts = LI->split('=');
+    auto [PropName, PropTypeAndValue] = LI->split('=');
 
-    if (Parts.first.empty() || Parts.second.empty())
+    if (PropName.empty() || PropTypeAndValue.empty())
       return makeError("invalid property line: " + *LI);
-    auto TypeVal = Parts.second.split('|');
+    auto [PropType, PropVal] = PropTypeAndValue.split('|');
 
-    if (TypeVal.first.empty() || TypeVal.second.empty())
-      return makeError("invalid property value: " + Parts.second);
+    if (PropType.empty() || PropVal.empty())
+      return makeError("invalid property value: " + PropTypeAndValue);
     APInt Tint;
 
     // Parse type
-    if (TypeVal.first.getAsInteger(10, Tint))
-      return makeError("invalid property type: " + TypeVal.first);
+    if (PropType.getAsInteger(10, Tint))
+      return makeError("invalid property type: " + PropType);
     Expected<SYCLPropertyValue::Type> Ttag =
         SYCLPropertyValue::getTypeTag(static_cast<int>(Tint.getSExtValue()));
-    StringRef Val = TypeVal.second;
+    StringRef Val = PropVal;
 
     if (!Ttag)
       return Ttag.takeError();
     SYCLPropertyValue Prop(Ttag.get());
 
     // Parse value depending on its type
-    switch (Ttag.get()) {
-    case SYCLPropertyValue::Type::UINT32: {
+    if (Prop.getType() == SYCLPropertyValue::Type::UInt32) {
       APInt ValV;
       if (Val.getAsInteger(10, ValV))
         return createStringError(std::error_code{},
                                  "invalid property value: ", Val.data());
       Prop.set(static_cast<uint32_t>(ValV.getZExtValue()));
-      break;
-    }
-    case SYCLPropertyValue::Type::BYTE_ARRAY: {
+    } else if (Prop.getType() == SYCLPropertyValue::Type::ByteArray) {
       std::vector<char> Output;
+      // Output resized to maximum output size for base64 decoding
+      Output.resize(((Val.size() + 3) / 4) * 3);
       if (Error Err = decodeBase64(Val, Output))
         return std::move(Err);
       Prop.set(reinterpret_cast<std::byte *>(Output.data()), Output.size());
-      break;
-    }
-    default:
+    } else {
       return createStringError(std::error_code{},
-                               "unsupported property type: ", Ttag.get());
+                               "unsupported property type\n");
     }
-    (*CurPropSet)[Parts.first] = std::move(Prop);
+    (*CurPropSet)[PropName] = std::move(Prop);
   }
   if (!CurPropSet)
     return makeError("invalid property set registry");
@@ -101,50 +94,36 @@ namespace llvm {
 // Output a property to a stream
 raw_ostream &operator<<(raw_ostream &Out, const SYCLPropertyValue &Prop) {
   Out << static_cast<int>(Prop.getType()) << '|';
-  switch (Prop.getType()) {
-  case SYCLPropertyValue::Type::UINT32:
+  if (Prop.getType() == SYCLPropertyValue::Type::UInt32) {
     Out << Prop.asUint32();
-    break;
-  case SYCLPropertyValue::Type::BYTE_ARRAY: {
-    auto PropArr = Prop.asByteArray();
+    return Out;
+  }
+  if (Prop.getType() == SYCLPropertyValue::Type::ByteArray) {
+    const std::byte *PropArr = Prop.asByteArray();
     std::vector<std::byte> V(PropArr, PropArr + Prop.getByteArraySize() /
                                                     sizeof(std::byte));
     Out << encodeBase64(V);
-    break;
-  }
-  default:
-    llvm_unreachable(
-        ("unsupported property type: " + utostr(Prop.getType())).c_str());
+    return Out;
   }
-  return Out;
+  llvm_unreachable("unsupported property type");
 }
 } // namespace llvm
 
 void SYCLPropertySetRegistry::write(raw_ostream &Out) const {
-  for (const auto &PropSet : PropSetMap) {
-    Out << '[' << PropSet.first << "]\n";
+  for (const auto &[PropCategory, Props] : PropSetMap) {
+    Out << '[' << PropCategory << "]\n";
 
-    for (const auto &Props : PropSet.second)
-      Out << Props.first << '=' << Props.second << '\n';
+    for (const auto &[PropName, PropVal] : Props)
+      Out << PropName << '=' << PropVal << '\n';
   }
 }
 
 namespace llvm {
 namespace util {
 
-template <> SYCLPropertyValue::Type SYCLPropertyValue::getTypeTag<uint32_t>() {
-  return UINT32;
-}
-
-template <>
-SYCLPropertyValue::Type SYCLPropertyValue::getTypeTag<std::byte *>() {
-  return BYTE_ARRAY;
-}
-
-SYCLPropertyValue::SYCLPropertyValue(const std::byte *Data, SizeTy DataBitSize)
-    : Ty(BYTE_ARRAY) {
-  constexpr int ByteSizeInBits = 8;
-  SizeTy DataSize = (DataBitSize + (ByteSizeInBits - 1)) / ByteSizeInBits;
+SYCLPropertyValue::SYCLPropertyValue(const std::byte *Data,
+                                     SizeTy DataBitSize) {
+  SizeTy DataSize = (DataBitSize + (CHAR_BIT - 1)) / CHAR_BIT;
   constexpr size_t SizeFieldSize = sizeof(SizeTy);
 
   // Allocate space for size and data.
@@ -154,7 +133,7 @@ SYCLPropertyValue::SYCLPropertyValue(const std::byte *Data, SizeTy DataBitSize)
   for (size_t I = 0; I < SizeFieldSize; ++I) {
     auto ByteArrayVal = std::get<std::byte *>(Val);
     ByteArrayVal[I] = (std::byte)DataBitSize;
-    DataBitSize >>= ByteSizeInBits;
+    DataBitSize >>= CHAR_BIT;
   }
   // Append data.
   auto ByteArrayVal = std::get<std::byte *>(Val);
@@ -170,38 +149,20 @@ SYCLPropertyValue::SYCLPropertyValue(SYCLPropertyValue &&P) {
 SYCLPropertyValue &SYCLPropertyValue::operator=(SYCLPropertyValue &&P) {
   copy(P);
 
-  if (P.getType() == BYTE_ARRAY)
+  if (std::holds_alternative<std::byte *>(Val))
     P.Val = nullptr;
-  P.Ty = NONE;
   return *this;
 }
 
 SYCLPropertyValue &SYCLPropertyValue::operator=(const SYCLPropertyValue &P) {
-  if (P.getType() == BYTE_ARRAY)
+  if (std::holds_alternative<std::byte *>(Val))
     *this = SYCLPropertyValue(P.asByteArray(), P.getByteArraySizeInBits());
   else
     copy(P);
   return *this;
 }
 
-void SYCLPropertyValue::copy(const SYCLPropertyValue &P) {
-  Ty = P.Ty;
-  Val = P.Val;
-}
-
-constexpr char SYCLPropertySetRegistry::SYCL_SPECIALIZATION_CONSTANTS[];
-constexpr char SYCLPropertySetRegistry::SYCL_DEVICELIB_REQ_MASK[];
-constexpr char SYCLPropertySetRegistry::SYCL_SPEC_CONSTANTS_DEFAULT_VALUES[];
-constexpr char SYCLPropertySetRegistry::SYCL_KERNEL_PARAM_OPT_INFO[];
-constexpr char SYCLPropertySetRegistry::SYCL_PROGRAM_METADATA[];
-constexpr char SYCLPropertySetRegistry::SYCL_MISC_PROP[];
-constexpr char SYCLPropertySetRegistry::SYCL_ASSERT_USED[];
-constexpr char SYCLPropertySetRegistry::SYCL_EXPORTED_SYMBOLS[];
-constexpr char SYCLPropertySetRegistry::SYCL_IMPORTED_SYMBOLS[];
-constexpr char SYCLPropertySetRegistry::SYCL_DEVICE_GLOBALS[];
-constexpr char SYCLPropertySetRegistry::SYCL_DEVICE_REQUIREMENTS[];
-constexpr char SYCLPropertySetRegistry::SYCL_HOST_PIPES[];
-constexpr char SYCLPropertySetRegistry::SYCL_VIRTUAL_FUNCTIONS[];
+void SYCLPropertyValue::copy(const SYCLPropertyValue &P) { Val = P.Val; }
 
 } // namespace util
 } // namespace llvm
diff --git a/llvm/unittests/Support/SYCLPropertySetIOTest.cpp b/llvm/unittests/Support/SYCLPropertySetIOTest.cpp
index c4272def0b703c..f30ae13b7b2309 100644
--- a/llvm/unittests/Support/SYCLPropertySetIOTest.cpp
+++ b/llvm/unittests/Support/SYCLPropertySetIOTest.cpp
@@ -59,7 +59,7 @@ TEST(SYCLPropertySet, IncorrectValuesIO) {
       << "Invalid property type";
 
   Content = "[Staff/Ages]\n"
-            "person1=2|10\n";
+            "person1=1|IAQ\n";
   MemBuf = MemoryBuffer::getMemBuffer(Content);
   // Parse a property set registry
   PropSetsPtr = SYCLPropertySetRegistry::read(MemBuf.get());

>From 50de423335bd6298bbbd0b6a60de0c394efd49d5 Mon Sep 17 00:00:00 2001
From: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
Date: Mon, 14 Oct 2024 18:11:37 -0700
Subject: [PATCH 13/13] Avoid memory leak for byte array

Signed-off-by: Arvind Sudarsanam <arvind.sudarsanam at intel.com>
---
 llvm/include/llvm/Support/SYCLPropertySetIO.h | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/Support/SYCLPropertySetIO.h b/llvm/include/llvm/Support/SYCLPropertySetIO.h
index b024c5c0b068b6..219866c56545f8 100644
--- a/llvm/include/llvm/Support/SYCLPropertySetIO.h
+++ b/llvm/include/llvm/Support/SYCLPropertySetIO.h
@@ -66,8 +66,13 @@ class SYCLPropertyValue {
     return static_cast<Type>(T);
   }
 
-  ~SYCLPropertyValue() {}
-
+  ~SYCLPropertyValue() {
+    if (std::holds_alternative<std::byte *>(Val)) {
+      auto ByteArrayVal = std::get<std::byte *>(Val);
+      if (ByteArrayVal)
+        delete[] ByteArrayVal;
+    }
+  }
   SYCLPropertyValue() = default;
 
   SYCLPropertyValue(Type Ty) {



More information about the llvm-commits mailing list