|
| 1 | +//==-- PropertySetIO.h -- models a sequence of property sets and their I/O -==// |
| 2 | +// |
| 3 | +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | +// See https://llvm.org/LICENSE.txt for license information. |
| 5 | +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | +// |
| 7 | +//===----------------------------------------------------------------------===// |
| 8 | +// Models a sequence of property sets and their input and output operations. |
| 9 | +// TODO use Yaml as I/O engine. |
| 10 | +// PropertyValue set format: |
| 11 | +// '['<PropertyValue set name>']' |
| 12 | +// <property name>=<property type>'|'<property value> |
| 13 | +// <property name>=<property type>'|'<property value> |
| 14 | +// ... |
| 15 | +// '['<PropertyValue set name>']' |
| 16 | +// <property name>=<property type>'|'<property value> |
| 17 | +// where |
| 18 | +// <PropertyValue set name>, <property name> are strings |
| 19 | +// <property type> - string representation of the property type |
| 20 | +// <property value> - string representation of the property value. |
| 21 | +// |
| 22 | +// For example: |
| 23 | +// [Staff/Ages] |
| 24 | +// person1=1|20 |
| 25 | +// person2=1|25 |
| 26 | +// [Staff/Experience] |
| 27 | +// person1=1|1 |
| 28 | +// person2=1|2 |
| 29 | +// person3=1|12 |
| 30 | +// |
| 31 | +//===----------------------------------------------------------------------===// |
| 32 | + |
| 33 | +#ifndef LLVM_SUPPORT_PROPERTYSETIO_H |
| 34 | +#define LLVM_SUPPORT_PROPERTYSETIO_H |
| 35 | + |
| 36 | +#include "llvm/ADT/MapVector.h" |
| 37 | +#include "llvm/ADT/SmallString.h" |
| 38 | +#include "llvm/ADT/StringRef.h" |
| 39 | +#include "llvm/Support/Error.h" |
| 40 | +#include "llvm/Support/MemoryBuffer.h" |
| 41 | +#include "llvm/Support/raw_ostream.h" |
| 42 | +#include "llvm/Support/xxhash.h" |
| 43 | + |
| 44 | +namespace llvm { |
| 45 | +namespace util { |
| 46 | + |
| 47 | +// Represents a property value. PropertyValue name is stored in the encompassing |
| 48 | +// container. |
| 49 | +class PropertyValue { |
| 50 | +public: |
| 51 | + // Type of the size of the value. Value size gets serialized along with the |
| 52 | + // value data in some cases for later reading at runtime, so size_t is not |
| 53 | + // suitable as its size varies. |
| 54 | + using SizeTy = uint64_t; |
| 55 | + using byte = uint8_t; |
| 56 | + |
| 57 | + // Defines supported property types |
| 58 | + enum Type { first = 0, NONE = first, UINT32, BYTE_ARRAY, last = BYTE_ARRAY }; |
| 59 | + |
| 60 | + // Translates C++ type to the corresponding type tag. |
| 61 | + template <typename T> static Type getTypeTag(); |
| 62 | + |
| 63 | + // Casts from int value to a type tag. |
| 64 | + static Expected<Type> getTypeTag(int T) { |
| 65 | + if (T < first || T > last) |
| 66 | + return createStringError(std::error_code(), "bad property type ", T); |
| 67 | + return static_cast<Type>(T); |
| 68 | + } |
| 69 | + |
| 70 | + ~PropertyValue() { |
| 71 | + if ((getType() == BYTE_ARRAY) && Val.ByteArrayVal) |
| 72 | + delete[] Val.ByteArrayVal; |
| 73 | + } |
| 74 | + |
| 75 | + PropertyValue() = default; |
| 76 | + PropertyValue(Type T) : Ty(T) {} |
| 77 | + |
| 78 | + PropertyValue(uint32_t Val) : Ty(UINT32), Val({Val}) {} |
| 79 | + PropertyValue(const byte *Data, SizeTy DataBitSize); |
| 80 | + template <typename C, typename T = typename C::value_type> |
| 81 | + PropertyValue(const C &Data) |
| 82 | + : PropertyValue(reinterpret_cast<const byte *>(Data.data()), |
| 83 | + Data.size() * sizeof(T) * /* bits in one byte */ 8) {} |
| 84 | + PropertyValue(const llvm::StringRef &Str) |
| 85 | + : PropertyValue(reinterpret_cast<const byte *>(Str.data()), |
| 86 | + Str.size() * sizeof(char) * /* bits in one byte */ 8) {} |
| 87 | + PropertyValue(const PropertyValue &P); |
| 88 | + PropertyValue(PropertyValue &&P); |
| 89 | + |
| 90 | + PropertyValue &operator=(PropertyValue &&P); |
| 91 | + |
| 92 | + PropertyValue &operator=(const PropertyValue &P); |
| 93 | + |
| 94 | + // get property value as unsigned 32-bit integer |
| 95 | + uint32_t asUint32() const { |
| 96 | + if (Ty != UINT32) |
| 97 | + llvm_unreachable("must be UINT32 value"); |
| 98 | + return Val.UInt32Val; |
| 99 | + } |
| 100 | + |
| 101 | + // Get raw data size in bits. |
| 102 | + SizeTy getByteArraySizeInBits() const { |
| 103 | + if (Ty != BYTE_ARRAY) |
| 104 | + llvm_unreachable("must be BYTE_ARRAY value"); |
| 105 | + SizeTy Res = 0; |
| 106 | + |
| 107 | + for (size_t I = 0; I < sizeof(SizeTy); ++I) |
| 108 | + Res |= (SizeTy)Val.ByteArrayVal[I] << (8 * I); |
| 109 | + return Res; |
| 110 | + } |
| 111 | + |
| 112 | + // Get byte array data size in bytes. |
| 113 | + SizeTy getByteArraySize() const { |
| 114 | + SizeTy SizeInBits = getByteArraySizeInBits(); |
| 115 | + constexpr unsigned int MASK = 0x7; |
| 116 | + return ((SizeInBits + MASK) & ~MASK) / 8; |
| 117 | + } |
| 118 | + |
| 119 | + // Get byte array data size in bytes, including the leading bytes encoding the |
| 120 | + // size. |
| 121 | + SizeTy getRawByteArraySize() const { |
| 122 | + return getByteArraySize() + sizeof(SizeTy); |
| 123 | + } |
| 124 | + |
| 125 | + // Get byte array data including the leading bytes encoding the size. |
| 126 | + const byte *asRawByteArray() const { |
| 127 | + if (Ty != BYTE_ARRAY) |
| 128 | + llvm_unreachable("must be BYTE_ARRAY value"); |
| 129 | + return Val.ByteArrayVal; |
| 130 | + } |
| 131 | + |
| 132 | + // Get byte array data excluding the leading bytes encoding the size. |
| 133 | + const byte *asByteArray() const { |
| 134 | + if (Ty != BYTE_ARRAY) |
| 135 | + llvm_unreachable("must be BYTE_ARRAY value"); |
| 136 | + return Val.ByteArrayVal + sizeof(SizeTy); |
| 137 | + } |
| 138 | + |
| 139 | + bool isValid() const { return getType() != NONE; } |
| 140 | + |
| 141 | + // set property value; the 'T' type must be convertible to a property type tag |
| 142 | + template <typename T> void set(T V) { |
| 143 | + if (getTypeTag<T>() != Ty) |
| 144 | + llvm_unreachable("invalid type tag for this operation"); |
| 145 | + getValueRef<T>() = V; |
| 146 | + } |
| 147 | + |
| 148 | + Type getType() const { return Ty; } |
| 149 | + |
| 150 | + SizeTy size() const { |
| 151 | + switch (Ty) { |
| 152 | + case UINT32: |
| 153 | + return sizeof(Val.UInt32Val); |
| 154 | + case BYTE_ARRAY: |
| 155 | + return getRawByteArraySize(); |
| 156 | + default: |
| 157 | + llvm_unreachable_internal("unsupported property type"); |
| 158 | + } |
| 159 | + } |
| 160 | + |
| 161 | +private: |
| 162 | + template <typename T> T &getValueRef(); |
| 163 | + void copy(const PropertyValue &P); |
| 164 | + |
| 165 | + Type Ty = NONE; |
| 166 | + // TODO: replace this union with std::variant when uplifting to C++17 |
| 167 | + union { |
| 168 | + uint32_t UInt32Val; |
| 169 | + // Holds first sizeof(size_t) bytes of size followed by actual raw data. |
| 170 | + byte *ByteArrayVal; |
| 171 | + } Val; |
| 172 | +}; |
| 173 | + |
| 174 | +/// Structure for specialization of DenseMap in PropertySetRegistry. |
| 175 | +struct PropertySetKeyInfo { |
| 176 | + static unsigned getHashValue(const SmallString<16> &K) { return xxHash64(K); } |
| 177 | + |
| 178 | + static SmallString<16> getEmptyKey() { return SmallString<16>(""); } |
| 179 | + |
| 180 | + static SmallString<16> getTombstoneKey() { return SmallString<16>("_"); } |
| 181 | + |
| 182 | + static bool isEqual(StringRef L, StringRef R) { return L == R; } |
| 183 | +}; |
| 184 | + |
| 185 | +using PropertyMapTy = DenseMap<SmallString<16>, unsigned, PropertySetKeyInfo>; |
| 186 | +/// A property set. Preserves insertion order when iterating elements. |
| 187 | +using PropertySet = MapVector<SmallString<16>, PropertyValue, PropertyMapTy>; |
| 188 | + |
| 189 | +/// A registry of property sets. Maps a property set name to its |
| 190 | +/// content. |
| 191 | +/// |
| 192 | +/// The order of keys is preserved and corresponds to the order of insertion. |
| 193 | +class PropertySetRegistry { |
| 194 | +public: |
| 195 | + using MapTy = MapVector<SmallString<16>, PropertySet, PropertyMapTy>; |
| 196 | + |
| 197 | + // Specific property category names used by tools. |
| 198 | + static constexpr char SYCL_SPECIALIZATION_CONSTANTS[] = |
| 199 | + "SYCL/specialization constants"; |
| 200 | + static constexpr char SYCL_SPEC_CONSTANTS_DEFAULT_VALUES[] = |
| 201 | + "SYCL/specialization constants default values"; |
| 202 | + static constexpr char SYCL_DEVICELIB_REQ_MASK[] = "SYCL/devicelib req mask"; |
| 203 | + static constexpr char SYCL_KERNEL_PARAM_OPT_INFO[] = "SYCL/kernel param opt"; |
| 204 | + static constexpr char SYCL_PROGRAM_METADATA[] = "SYCL/program metadata"; |
| 205 | + static constexpr char SYCL_MISC_PROP[] = "SYCL/misc properties"; |
| 206 | + static constexpr char SYCL_ASSERT_USED[] = "SYCL/assert used"; |
| 207 | + static constexpr char SYCL_EXPORTED_SYMBOLS[] = "SYCL/exported symbols"; |
| 208 | + static constexpr char SYCL_IMPORTED_SYMBOLS[] = "SYCL/imported symbols"; |
| 209 | + static constexpr char SYCL_DEVICE_GLOBALS[] = "SYCL/device globals"; |
| 210 | + static constexpr char SYCL_DEVICE_REQUIREMENTS[] = "SYCL/device requirements"; |
| 211 | + static constexpr char SYCL_HOST_PIPES[] = "SYCL/host pipes"; |
| 212 | + static constexpr char SYCL_VIRTUAL_FUNCTIONS[] = "SYCL/virtual functions"; |
| 213 | + |
| 214 | + /// Function for bulk addition of an entire property set in the given |
| 215 | + /// \p Category . |
| 216 | + template <typename MapTy> void add(StringRef Category, const MapTy &Props) { |
| 217 | + assert(PropSetMap.find(Category) == PropSetMap.end() && |
| 218 | + "category already added"); |
| 219 | + auto &PropSet = PropSetMap[Category]; |
| 220 | + |
| 221 | + for (const auto &Prop : Props) |
| 222 | + PropSet.insert_or_assign(Prop.first, PropertyValue(Prop.second)); |
| 223 | + } |
| 224 | + |
| 225 | + /// Adds the given \p PropVal with the given \p PropName into the given \p |
| 226 | + /// Category . |
| 227 | + template <typename T> |
| 228 | + void add(StringRef Category, StringRef PropName, const T &PropVal) { |
| 229 | + auto &PropSet = PropSetMap[Category]; |
| 230 | + PropSet.insert({PropName, PropertyValue(PropVal)}); |
| 231 | + } |
| 232 | + |
| 233 | + /// Parses from the given \p Buf a property set registry. |
| 234 | + static Expected<std::unique_ptr<PropertySetRegistry>> |
| 235 | + read(const MemoryBuffer *Buf); |
| 236 | + |
| 237 | + /// Dumps the property set registry to the given \p Out stream. |
| 238 | + void write(raw_ostream &Out) const; |
| 239 | + |
| 240 | + MapTy::const_iterator begin() const { return PropSetMap.begin(); } |
| 241 | + MapTy::const_iterator end() const { return PropSetMap.end(); } |
| 242 | + |
| 243 | + /// Retrieves a property set with given \p Name . |
| 244 | + PropertySet &operator[](StringRef Name) { return PropSetMap[Name]; } |
| 245 | + /// Constant access to the underlying map. |
| 246 | + const MapTy &getPropSets() const { return PropSetMap; } |
| 247 | + |
| 248 | +private: |
| 249 | + MapTy PropSetMap; |
| 250 | +}; |
| 251 | + |
| 252 | +} // namespace util |
| 253 | + |
| 254 | +} // namespace llvm |
| 255 | + |
| 256 | +#endif // #define LLVM_SUPPORT_PROPERTYSETIO_H |
0 commit comments