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
|
// slang-ir-spirv-legalize.h
#pragma once
#include "../core/slang-basic.h"
#include "spirv/unified1/spirv.h"
namespace Slang
{
struct SPIRVCoreGrammarInfo;
//
// [2.2: Terms]
//
// > Word: 32 bits.
//
// Despite the importance to SPIR-V, the `spirv.h` header doesn't
// define a type for words, so we'll do it here.
/// A SPIR-V word.
typedef uint32_t SpvWord;
/// Represents a parsed Spv ASM from intrinsic definition.
struct SpvSnippet : public RefObject
{
enum class ASMOperandType
{
// Plain SpvWord to inline without modifications.
SpvWord,
// Represents the result type of the intrinsic.
ResultTypeId,
// Represents the result Id of the ASM inst.
ResultId,
// Represents a reference to an intrinsic argument (e.g. `_1`).
ObjectReference,
// Represents a reference to an ASM inst (e.g. `%t`).
InstReference,
// Refer to the GLSL450 Instruction Set.
GLSL450ExtInstSet,
// A select expression based on whether result type is float, e.g.
// `fi(x,y)` selects `x` if resultType is `float`.
FloatIntegerSelection,
// A select expression based on whether result type is float, unsigned
// or signed integer. e.g. `fus(f_opcode, u_opcode, s_opcode)`.
FloatUnsignedSignedSelection,
// Reference to a type defined in `ASMType`.
TypeReference,
// Reference to a Constant defined in `SpvSnippet::constants`.
ConstantReference,
};
struct ASMOperand
{
ASMOperandType type;
// The value of the spv word when type is `SpvWord`, or
// the reference name when type is `ObjectReference`
// (e.g. an argument reference (_1) has `content` == 1).
SpvWord content;
// Additional value contents.
SpvWord content2;
SpvWord content3;
};
enum class ASMType : SpvWord
{
None,
Int,
UInt,
UInt16,
Half,
Float,
Double,
FloatOrDouble, // Float or double type, depending on the result type of the intrinsic.
Float2,
UInt2,
};
struct ASMConstant
{
ASMType type;
SpvWord intValues[4];
float floatValues[4];
HashCode getHashCode() const
{
HashCode result = (HashCode)type;
for (int i = 0; i < 4; i++)
{
switch (type)
{
case ASMType::Half:
case ASMType::Float:
case ASMType::Double:
case ASMType::Float2:
case ASMType::FloatOrDouble:
result = combineHash(result, Slang::getHashCode(floatValues[i]));
break;
default:
result = combineHash(result, Slang::getHashCode(intValues[i]));
break;
}
}
return result;
}
bool operator==(const ASMConstant& other) const
{
if (type != other.type)
return false;
switch (type)
{
case ASMType::Half:
case ASMType::Float:
case ASMType::Double:
case ASMType::FloatOrDouble:
return floatValues[0] == other.floatValues[0];
case ASMType::Float2:
return floatValues[0] == other.floatValues[0] &&
floatValues[1] == other.floatValues[1];
case ASMType::Int:
return intValues[0] == other.intValues[0];
case ASMType::UInt:
case ASMType::UInt16:
return intValues[0] == other.intValues[0];
case ASMType::UInt2:
return intValues[0] == other.intValues[0] && intValues[1] == other.intValues[1];
default:
return false;
}
}
};
struct ASMInst
{
SpvWord opCode = 0;
List<ASMOperand> operands;
};
List<ASMInst> instructions;
HashSet<SpvStorageClass> usedPtrResultTypeStorageClasses;
List<ASMConstant> constants;
SpvStorageClass resultStorageClass = SpvStorageClassMax;
static RefPtr<SpvSnippet> parse(
const SPIRVCoreGrammarInfo& spirvGrammar,
UnownedStringSlice definition);
};
} // namespace Slang
|