1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
|
// slang-serialize-types.h
#ifndef SLANG_SERIALIZE_TYPES_H
#define SLANG_SERIALIZE_TYPES_H
#include "../core/slang-riff.h"
#include "../core/slang-string-slice-pool.h"
#include "../core/slang-array-view.h"
//#include "slang-name.h"
//#include "slang-source-loc.h"
namespace Slang {
// An enumeration of types that can be set
enum class SerialExtraType
{
SourceLocReader,
SourceLocWriter,
CountOf,
};
// Options for IR/AST/Debug serialization
struct SerialOptionFlag
{
typedef uint32_t Type;
enum Enum : Type
{
RawSourceLocation = 0x01, ///< If set will store directly SourceLoc - only useful if current source locs will be identical when read in (typically this is *NOT* the case)
SourceLocation = 0x02, ///< If set will output SourceLoc information, that can be reconstructed when read after being stored.
ASTModule = 0x04, ///< If set will output AST modules - typically required, but potentially not desired (for example with obsfucation)
IRModule = 0x08, ///< If set will output IR modules - typically required
};
};
typedef SerialOptionFlag::Type SerialOptionFlags;
// Compression styles
enum class SerialCompressionType : uint8_t
{
None,
VariableByteLite,
};
struct SerialStringData
{
enum class StringIndex : uint32_t;
///enum class StringOffset : uint32_t; ///< Offset into the m_stringsBuffer
typedef uint32_t SizeType;
static const StringIndex kNullStringIndex = StringIndex(StringSlicePool::kNullHandle);
static const StringIndex kEmptyStringIndex = StringIndex(StringSlicePool::kEmptyHandle);
};
struct SerialStringTableUtil
{
/// Convert a pool into a string table
static void encodeStringTable(const StringSlicePool& pool, List<char>& stringTable);
static void encodeStringTable(const ConstArrayView<UnownedStringSlice>& slices, List<char>& stringTable);
/// Appends the decoded strings into slicesOut
static void appendDecodedStringTable(const char* table, size_t tableSize, List<UnownedStringSlice>& slicesOut);
/// Decodes a string table (and does so such that the indices are compatible with StringSlicePool)
static void decodeStringTable(const char* table, size_t tableSize, List<UnownedStringSlice>& slicesOut);
/// Decodes a string table
static void decodeStringTable(const char* table, size_t tableSize, StringSlicePool& outPool);
/// Produces an index map, from slices to indices in pool
static void calcStringSlicePoolMap(const List<UnownedStringSlice>& slices, StringSlicePool& pool, List<StringSlicePool::Handle>& indexMap);
};
struct SerialParseUtil
{
/// Given text, finds the compression type
static SlangResult parseCompressionType(const UnownedStringSlice& text, SerialCompressionType& outType);
/// Given a compression type, return text
static UnownedStringSlice getText(SerialCompressionType type);
};
struct SerialListUtil
{
template <typename T>
static size_t calcArraySize(const List<T>& list)
{
return list.getCount() * sizeof(T);
}
template <typename T>
static bool isEqual(const List<T>& aIn, const List<T>& bIn)
{
if (&aIn == &bIn)
{
return true;
}
const Index size = aIn.getCount();
if (size != bIn.getCount())
{
return false;
}
const T* a = aIn.begin();
const T* b = bIn.begin();
if (a != b)
{
for (Index i = 0; i < size; ++i)
{
if (a[i] != b[i])
{
return false;
}
}
}
return true;
}
};
// For types/FourCC that work for serializing in general (not just IR).
struct SerialBinary
{
static const FourCC kRiffFourCc = RiffFourCC::kRiff;
/// Container
static const FourCC kContainerFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'c');
/// A string table
static const FourCC kStringTableFourCc = SLANG_FOUR_CC('S', 'L', 's', 't');
/// TranslationUnitList
static const FourCC kModuleListFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'l');
/// An entry point
static const FourCC kEntryPointFourCc = SLANG_FOUR_CC('E', 'P', 'n', 't');
/// Container
static const FourCC kContainerHeaderFourCc = SLANG_FOUR_CC('S', 'c', 'h', 'd');
struct ContainerHeader
{
uint32_t compressionType; ///< Holds the compression type used (if used at all)
};
struct ArrayHeader
{
uint32_t numEntries;
};
struct CompressedArrayHeader
{
uint32_t numEntries; ///< The number of entries
uint32_t numCompressedEntries; ///< The amount of compressed entries
};
};
// Replace first char with 's'
#define SLANG_MAKE_COMPRESSED_FOUR_CC(fourCc) SLANG_FOUR_CC_REPLACE_FIRST_CHAR(fourCc, 's')
struct SerialRiffUtil
{
class ListResizer
{
public:
virtual void* setSize(size_t newSize) = 0;
SLANG_FORCE_INLINE size_t getTypeSize() const { return m_typeSize; }
ListResizer(size_t typeSize) :m_typeSize(typeSize) {}
protected:
size_t m_typeSize;
};
template <typename T>
class ListResizerForType : public ListResizer
{
public:
typedef ListResizer Parent;
SLANG_FORCE_INLINE ListResizerForType(List<T>& list) :
Parent(sizeof(T)),
m_list(list)
{}
virtual void* setSize(size_t newSize) SLANG_OVERRIDE
{
m_list.setCount(UInt(newSize));
return (void*)m_list.begin();
}
protected:
List<T>& m_list;
};
static Result writeArrayChunk(SerialCompressionType compressionType, FourCC chunkId, const void* data, size_t numEntries, size_t typeSize, RiffContainer* container);
template <typename T>
static Result writeArrayChunk(SerialCompressionType compressionType, FourCC chunkId, const List<T>& array, RiffContainer* container)
{
return writeArrayChunk(compressionType, chunkId, array.begin(), size_t(array.getCount()), sizeof(T), container);
}
template <typename T>
static Result writeArrayUncompressedChunk(FourCC chunkId, const List<T>& array, RiffContainer* container)
{
return writeArrayChunk(SerialCompressionType::None, chunkId, array.begin(), size_t(array.getCount()), sizeof(T), container);
}
static Result readArrayChunk(SerialCompressionType compressionType, RiffContainer::DataChunk* dataChunk, ListResizer& listOut);
template <typename T>
static Result readArrayChunk(SerialCompressionType moduleCompressionType, RiffContainer::DataChunk* dataChunk, List<T>& arrayOut)
{
SerialCompressionType compressionType = SerialCompressionType::None;
if (dataChunk->m_fourCC == SLANG_MAKE_COMPRESSED_FOUR_CC(dataChunk->m_fourCC))
{
// If it has compression, use the compression type set in the header
compressionType = moduleCompressionType;
}
ListResizerForType<T> resizer(arrayOut);
return readArrayChunk(compressionType, dataChunk, resizer);
}
template <typename T>
static Result readArrayUncompressedChunk(RiffContainer::DataChunk* chunk, List<T>& arrayOut)
{
ListResizerForType<T> resizer(arrayOut);
return readArrayChunk(SerialCompressionType::None, chunk, resizer);
}
};
} // namespace Slang
#endif
|