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
|
#pragma once
#include "../core/slang-dictionary.h"
#include "../core/slang-smart-pointer.h"
#include "../core/slang-string-slice-pool.h"
#include "../core/slang-string.h"
#include <optional>
#include <spirv/unified1/NonSemanticShaderDebugInfo100.h>
#include <spirv/unified1/spirv.h>
namespace Slang
{
using SpvWord = uint32_t;
class DiagnosticSink;
class SourceView;
struct SPIRVCoreGrammarInfo : public RefObject
{
static RefPtr<SPIRVCoreGrammarInfo> loadFromJSON(SourceView& source, DiagnosticSink& sink);
static RefPtr<SPIRVCoreGrammarInfo>& getEmbeddedVersion();
static inline void freeEmbeddedGrammerInfo() { getEmbeddedVersion() = nullptr; }
template<typename K, typename T>
struct Lookup
{
std::optional<T> lookup(const K& name) const
{
T ret;
if (embedded ? embedded(name, ret) : dict.tryGetValue(name, ret))
return ret;
else
return std::nullopt;
}
bool (*embedded)(const K&, T&) = nullptr;
Dictionary<K, T> dict;
};
struct OperandKind
{
uint8_t index;
SLANG_COMPONENTWISE_HASHABLE_1;
SLANG_COMPONENTWISE_EQUALITY_1(OperandKind);
};
struct QualifiedEnumName
{
OperandKind kind;
UnownedStringSlice name;
SLANG_COMPONENTWISE_HASHABLE_2;
SLANG_COMPONENTWISE_EQUALITY_2(QualifiedEnumName);
};
struct QualifiedEnumValue
{
OperandKind kind;
SpvWord value;
SLANG_COMPONENTWISE_HASHABLE_2;
SLANG_COMPONENTWISE_EQUALITY_2(QualifiedEnumValue);
};
struct OpInfo
{
enum Class
{
// Unrecognized instructions go in here
Other,
// Adding to this? Don't forget to update the embedding generator
Miscellaneous,
Debug,
Annotation,
Extension,
ModeSetting,
TypeDeclaration,
ConstantCreation,
Memory,
Function,
Image,
Conversion,
Composite,
Arithmetic,
Bit,
Relational_and_Logical,
Derivative,
ControlFlow,
Atomic,
Primitive,
Barrier,
Group,
DeviceSideEnqueue,
Pipe,
NonUniform,
Reserved,
};
constexpr static int8_t kNoResultTypeId = -1;
constexpr static int8_t kNoResultId = -1;
Class class_;
// -1 or 0
int8_t resultTypeIndex = kNoResultTypeId;
// -1 or 0 or 1
int8_t resultIdIndex = kNoResultId;
// The range of valid operand counts for this instruction,
// including any result type and id. Multi-word operands count as a
// single operand.
uint16_t minOperandCount;
uint16_t maxOperandCount;
// when looking up an operand type, clamp to this number-1 to
// account for variable length operands at the end
uint16_t numOperandTypes;
const OperandKind* operandTypes;
};
//
// Our tables:
//
// Instruction name to opcode
Lookup<UnownedStringSlice, SpvOp> opcodes;
// Capability name to value
Lookup<UnownedStringSlice, SpvCapability> capabilities;
// String-qualified enum name (one with the type prefix) to value
Lookup<UnownedStringSlice, SpvWord> allEnumsWithTypePrefix;
// kind * enum name to value
Lookup<QualifiedEnumName, SpvWord> allEnums;
// kine * enum value to unqualified name
Lookup<QualifiedEnumValue, UnownedStringSlice> allEnumNames;
// Any other information on instructions
Lookup<SpvOp, OpInfo> opInfos;
// Opcode to instruction name
Lookup<SpvOp, UnownedStringSlice> opNames;
// Operand kind string to numeric id
Lookup<UnownedStringSlice, OperandKind> operandKinds;
// Operand kind id to string
Lookup<OperandKind, UnownedStringSlice> operandKindNames;
// Operand kind to the "un-id" version of itself, for example IdMemorySemantics to
// MemorySemantics
Lookup<OperandKind, OperandKind> operandKindUnderneathIds;
private:
// If this is loaded from JSON, we keep the strings around instead of
// copying them as dictionary keys
StringSlicePool strings = StringSlicePool(StringSlicePool::Style::Empty);
List<OperandKind> operandTypesStorage;
};
} // namespace Slang
|