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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
|
// slang-serialize-ir-types.h
#ifndef SLANG_SERIALIZE_IR_TYPES_H_INCLUDED
#define SLANG_SERIALIZE_IR_TYPES_H_INCLUDED
#include "../compiler-core/slang-name.h"
#include "../compiler-core/slang-source-loc.h"
#include "../core/slang-array-view.h"
#include "../core/slang-riff.h"
#include "../core/slang-string-slice-pool.h"
#include "slang-ir.h"
#include "slang-serialize-source-loc.h"
#include "slang-serialize-types.h"
namespace Slang
{
// Pre-declare
class Name;
struct IRSerialBinary
{
/* NOTE! All FourCC that can be compressed must start with capital 'S', because compressed
version is the same FourCC with the 'S' replaced with 's' */
static const FourCC::RawValue kInstFourCc = SLANG_FOUR_CC('S', 'L', 'i', 'n');
static const FourCC::RawValue kChildRunFourCc = SLANG_FOUR_CC('S', 'L', 'c', 'r');
static const FourCC::RawValue kExternalOperandsFourCc = SLANG_FOUR_CC('S', 'L', 'e', 'o');
static const FourCC::RawValue kUInt32RawSourceLocFourCc = SLANG_FOUR_CC('S', 'r', 's', '4');
/// Debug information is held elsewhere, but if this optional section exists, it maps
/// instructions to locs
static const FourCC::RawValue kDebugSourceLocRunFourCc = SLANG_FOUR_CC('S', 'd', 's', 'r');
};
struct IRSerialData
{
typedef IRSerialData ThisType;
typedef SerialStringData::StringIndex StringIndex;
enum class InstIndex : uint32_t;
enum class ArrayIndex : uint32_t;
enum class RawSourceLoc : SourceLoc::RawValue; ///< This is just to copy over source loc data
///< (ie not strictly serialize)
typedef uint32_t SizeType;
/// A run of instructions
struct InstRun
{
typedef InstRun ThisType;
SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const
{
return m_parentIndex == rhs.m_parentIndex && m_startInstIndex == rhs.m_startInstIndex &&
m_numChildren == rhs.m_numChildren;
}
SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
InstIndex m_parentIndex; ///< The parent instruction
InstIndex m_startInstIndex; ///< The index to the first instruction
SizeType m_numChildren; ///< The number of children
};
struct SourceLocRun
{
typedef SourceLocRun ThisType;
bool operator==(const ThisType& rhs) const
{
return m_sourceLoc == rhs.m_sourceLoc && m_startInstIndex == rhs.m_startInstIndex &&
m_numInst == rhs.m_numInst;
}
bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
bool operator<(const ThisType& rhs) const { return m_sourceLoc < rhs.m_sourceLoc; }
SerialSourceLocData::SourceLoc m_sourceLoc; ///< The source location
InstIndex m_startInstIndex; ///< The index to the first instruction
SizeType m_numInst; ///< The number of children
};
struct PayloadInfo
{
uint8_t m_numOperands;
uint8_t m_numStrings;
};
// Instruction...
// We can store SourceLoc values separately. Just store per index information.
// Parent information is stored in m_childRuns
// Decoration information is stored in m_decorationRuns
struct Inst
{
typedef Inst ThisType;
enum
{
kMaxOperands = 2, ///< Maximum number of operands that can be held in an instruction
///< (otherwise held 'externally')
};
// NOTE! Can't change order or list without changing appropriate s_payloadInfos
enum class PayloadType : uint8_t
{
// First 3 must be in this order so a cast from 0-2 is directly represented as number of
// operands
Empty, ///< Has no payload (or operands)
Operand_1, ///< 1 Operand
Operand_2, ///< 2 Operands
OperandAndUInt32, ///< 1 Operand and a single UInt32
OperandExternal, ///< Operands are held externally
String_1, ///< 1 String
String_2, ///< 2 Strings
UInt32, ///< Holds an unsigned 32 bit integral (might represent a type)
Float64,
Int64,
CountOf,
};
/// Get the number of operands
SLANG_FORCE_INLINE int getNumOperands() const;
bool operator==(const ThisType& rhs) const;
SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
uint16_t m_op; ///< For now one of IROp
PayloadType m_payloadType; ///< The type of payload
uint8_t m_pad0; ///< Not currently used
InstIndex m_resultTypeIndex; //< 0 if has no type. The result type of this instruction
struct ExternalOperandPayload
{
ArrayIndex m_arrayIndex; ///< Index into the m_externalOperands table
SizeType m_size; ///< The amount of entries in that table
};
struct OperandAndUInt32
{
InstIndex m_operand;
uint32_t m_uint32;
};
union Payload
{
double m_float64;
int64_t m_int64;
uint32_t m_uint32; ///< Unsigned integral value
IRFloatingPointValue m_float; ///< Floating point value
IRIntegerValue m_int; ///< Integral value
InstIndex
m_operands[kMaxOperands]; ///< For items that 2 or less operands it can use this.
StringIndex m_stringIndices[kMaxOperands];
ExternalOperandPayload
m_externalOperand; ///< Operands are stored in an an index of an operand array
OperandAndUInt32 m_operandAndUInt32;
};
Payload m_payload;
};
/// Clear to initial state
void clear();
/// Get the operands of an instruction
SLANG_FORCE_INLINE int getOperands(const Inst& inst, const InstIndex** operandsOut) const;
/// ==
bool operator==(const ThisType& rhs) const;
SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
/// Calculate the amount of memory used by this IRSerialData
size_t calcSizeInBytes() const;
/// Ctor
IRSerialData();
List<Inst> m_insts; ///< The instructions
List<RawSourceLoc> m_rawSourceLocs; ///< A source location per instruction (saved without
///< modification from IRInst)
List<InstRun>
m_childRuns; ///< Holds the information about children that belong to an instruction
List<InstIndex> m_externalOperands; ///< Holds external operands (for instructions with more
///< than kNumOperands)
List<char> m_stringTable; ///< All strings. Indexed into by StringIndex
List<SourceLocRun> m_debugSourceLocRuns; ///< Runs of instructions that use a source loc
static const PayloadInfo s_payloadInfos[int(Inst::PayloadType::CountOf)];
};
// --------------------------------------------------------------------------
SLANG_FORCE_INLINE int IRSerialData::Inst::getNumOperands() const
{
return (m_payloadType == PayloadType::OperandExternal)
? m_payload.m_externalOperand.m_size
: s_payloadInfos[int(m_payloadType)].m_numOperands;
}
// --------------------------------------------------------------------------
SLANG_FORCE_INLINE bool IRSerialData::Inst::operator==(const ThisType& rhs) const
{
if (m_op == rhs.m_op && m_payloadType == rhs.m_payloadType &&
m_resultTypeIndex == rhs.m_resultTypeIndex)
{
switch (m_payloadType)
{
case PayloadType::Empty:
{
return true;
}
case PayloadType::Operand_1:
case PayloadType::String_1:
case PayloadType::UInt32:
{
return m_payload.m_operands[0] == rhs.m_payload.m_operands[0];
}
case PayloadType::OperandAndUInt32:
case PayloadType::OperandExternal:
case PayloadType::Operand_2:
case PayloadType::String_2:
{
return m_payload.m_operands[0] == rhs.m_payload.m_operands[0] &&
m_payload.m_operands[1] == rhs.m_payload.m_operands[1];
}
case PayloadType::Float64:
case PayloadType::Int64:
{
return m_payload.m_int64 == rhs.m_payload.m_int64;
}
default:
break;
}
}
return false;
}
// --------------------------------------------------------------------------
SLANG_FORCE_INLINE int IRSerialData::getOperands(const Inst& inst, const InstIndex** operandsOut)
const
{
if (inst.m_payloadType == Inst::PayloadType::OperandExternal)
{
*operandsOut =
m_externalOperands.begin() + int(inst.m_payload.m_externalOperand.m_arrayIndex);
return int(inst.m_payload.m_externalOperand.m_size);
}
else
{
*operandsOut = inst.m_payload.m_operands;
return s_payloadInfos[int(inst.m_payloadType)].m_numOperands;
}
}
} // namespace Slang
#endif
|