Skip to content

Commit 7350a52

Browse files
committed
[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 <[email protected]>
1 parent 24d707e commit 7350a52

File tree

6 files changed

+568
-0
lines changed

6 files changed

+568
-0
lines changed

llvm/include/llvm/Support/Base64.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,32 @@ template <class InputBytes> std::string encodeBase64(InputBytes const &Bytes) {
5656

5757
llvm::Error decodeBase64(llvm::StringRef Input, std::vector<char> &Output);
5858

59+
// General-purpose Base64 encoder/decoder class wrapper.
60+
class Base64 {
61+
public:
62+
using byte = uint8_t;
63+
64+
// Get the size of the encoded byte sequence of given size.
65+
static size_t getEncodedSize(size_t SrcSize);
66+
67+
// Encode a byte sequence of given size into an output stream.
68+
// Returns the number of bytes in the encoded result.
69+
static size_t encode(const byte *Src, raw_ostream &Out, size_t SrcSize);
70+
71+
// Get the size of the encoded byte sequence of given size.
72+
static size_t getDecodedSize(size_t SrcSize);
73+
74+
// Decode a sequence of given size into a pre-allocated memory.
75+
// Returns the number of bytes in the decoded result or 0 in case of error.
76+
static Expected<size_t> decode(const char *Src, byte *Dst, size_t SrcSize);
77+
78+
// Allocate minimum required amount of memory and decode a sequence of given
79+
// size into it.
80+
// Returns the decoded result. The size can be obtained via getDecodedSize.
81+
static Expected<std::unique_ptr<byte[]>> decode(const char *Src,
82+
size_t SrcSize);
83+
};
84+
5985
} // end namespace llvm
6086

6187
#endif
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
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

llvm/lib/Support/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ add_llvm_component_library(LLVMSupport
217217
Parallel.cpp
218218
PluginLoader.cpp
219219
PrettyStackTrace.cpp
220+
PropertySetIO.cpp
220221
RandomNumberGenerator.cpp
221222
Regex.cpp
222223
RewriteBuffer.cpp

0 commit comments

Comments
 (0)