xref: /aosp_15_r20/external/angle/third_party/spirv-headers/src/tools/buildHeaders/jsonToSpirv.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 // Copyright (c) 2014-2024 The Khronos Group Inc.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and/or associated documentation files (the "Materials"),
5 // to deal in the Materials without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Materials, and to permit persons to whom the
8 // Materials are furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Materials.
12 //
13 // MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
14 // STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
15 // HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
16 //
17 // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
23 // IN THE MATERIALS.
24 
25 #pragma once
26 #ifndef JSON_TO_SPIRV
27 #define JSON_TO_SPIRV
28 
29 #include <algorithm>
30 #include <string>
31 #include <vector>
32 #include <assert.h>
33 
34 namespace spv {
35 
36     // Reads the file in the given |path|. Returns true and the contents of the
37 // file on success; otherwise, returns false and an empty string.
38 std::pair<bool, std::string> ReadFile(const std::string& path);
39 
40 // Fill in all the parameters
41 void jsonToSpirv(const std::string& jsonPath, bool buildingHeaders);
42 
43 // For parameterizing operands.
44 // The ordering here affects the printing order in the SPIR-V specification.
45 // Please add new operand classes at the end.
46 enum OperandClass {
47     OperandNone,
48     OperandId,
49     OperandVariableIds,
50     OperandOptionalLiteral,
51     OperandOptionalLiteralString,
52     OperandOptionalLiteralStrings,
53     OperandVariableLiterals,
54     OperandVariableIdLiteral,
55     OperandVariableLiteralId,
56     OperandAnySizeLiteralNumber,
57     OperandLiteralNumber,
58     OperandLiteralString,
59     OperandSource,
60     OperandExecutionModel,
61     OperandAddressing,
62     OperandMemory,
63     OperandExecutionMode,
64     OperandStorage,
65     OperandDimensionality,
66     OperandSamplerAddressingMode,
67     OperandSamplerFilterMode,
68     OperandSamplerImageFormat,
69     OperandImageChannelOrder,
70     OperandImageChannelDataType,
71     OperandImageOperands,
72     OperandFPFastMath,
73     OperandFPRoundingMode,
74     OperandLinkageType,
75     OperandAccessQualifier,
76     OperandFuncParamAttr,
77     OperandDecoration,
78     OperandBuiltIn,
79     OperandSelect,
80     OperandLoop,
81     OperandFunction,
82     OperandMemorySemantics,
83     OperandMemoryOperands,
84     OperandScope,
85     OperandGroupOperation,
86     OperandKernelEnqueueFlags,
87     OperandKernelProfilingInfo,
88     OperandCapability,
89     OperandRayFlags,
90     OperandRayQueryIntersection,
91     OperandRayQueryCommittedIntersectionType,
92     OperandRayQueryCandidateIntersectionType,
93     OperandFragmentShadingRate,
94     OperandFPDenormMode,
95     OperandFPOperationMode,
96     OperandQuantizationModes,
97     OperandOverflowModes,
98     OperandPackedVectorFormat,
99     OperandCooperativeMatrixOperands,
100     OperandCooperativeMatrixLayout,
101     OperandCooperativeMatrixUse,
102     OperandCooperativeMatrixReduce,
103     OperandTensorClampMode,
104     OperandTensorAddressingOperands,
105     OperandInitializationModeQualifier,
106     OperandHostAccessQualifier,
107     OperandLoadCacheControl,
108     OperandStoreCacheControl,
109     OperandNamedMaximumNumberOfRegisters,
110     OperandRawAccessChainOperands,
111     OperandFPEncoding,
112 
113     OperandOpcode,
114 
115     OperandCount
116 };
117 
118 // For direct representation of the JSON grammar "instruction_printing_class".
119 struct PrintingClass {
120     std::string tag;
121     std::string heading;
122 };
123 using PrintingClasses = std::vector<PrintingClass>;
124 
125 // Any specific enum can have a set of capabilities that allow it:
126 typedef std::vector<std::string> EnumCaps;
127 
128 // A set of extensions.
129 typedef std::vector<std::string> Extensions;
130 
131 // A set of aliases.
132 typedef std::vector<std::string> Aliases;
133 
134 // Parameterize a set of operands with their OperandClass(es) and descriptions.
135 class OperandParameters {
136 public:
OperandParameters()137     OperandParameters() { }
138     void push(OperandClass oc, const std::string& d, bool opt = false)
139     {
140         opClass.push_back(oc);
141         desc.push_back(d);
142         optional.push_back(opt);
143     }
144     void setOptional();
getClass(int op)145     OperandClass getClass(int op) const { return opClass[op]; }
getDesc(int op)146     const char* getDesc(int op) const { return desc[op].c_str(); }
isOptional(int op)147     bool isOptional(int op) const { return optional[op]; }
getNum()148     int getNum() const { return (int)opClass.size(); }
149 
150 protected:
151     std::vector<OperandClass> opClass;
152     std::vector<std::string> desc;
153     std::vector<bool> optional;
154 };
155 
156 // An ordered sequence of EValue.  We'll preserve the order found in the
157 // JSON file.  You can look up a value by enum or by name.  If there are
158 // duplicate values, then take the first.  We assume names are unique.
159 // The EValue must have an unsigned |value| field and a string |name| field.
160 template <typename EValue>
161 class EnumValuesContainer {
162 public:
163     using ContainerType = std::vector<EValue>;
164     using iterator = typename ContainerType::iterator;
165     using const_iterator = typename ContainerType::const_iterator;
166 
EnumValuesContainer()167     EnumValuesContainer() {}
168 
169     // Constructs an EValue in place as a new element at the end of the
170     // sequence.
171     template <typename... Args>
emplace_back(Args &&...args)172     void emplace_back(Args&&... args) {
173         values.emplace_back(std::forward<Args>(args)...);
174     }
175 
176     // Returns the first EValue in the sequence with the given value.
177     // More than one EValue might have the same value.
178     EValue& operator[](unsigned value) {
179         auto where = std::find_if(begin(), end(), [&value](const EValue& e) {
180            return value == e.value;
181         });
182         assert((where != end()) && "Could not find enum in the enum list");
183         return *where;
184     }
185     // gets *all* entries for the value, including the first one
gatherAliases(unsigned value,std::vector<EValue * > & aliases)186     void gatherAliases(unsigned value, std::vector<EValue*>& aliases) {
187         std::for_each(begin(), end(), [&](EValue& e) {
188             if (value == e.value)
189                 aliases.push_back(&e);});
190     }
191     // Returns the EValue with the given name.  We assume uniqueness
192     // by name.
at(std::string name)193     EValue& at(std::string name) {
194         auto where = std::find_if(begin(), end(), [&name](const EValue& e) {
195            return name == e.name;
196         });
197         assert((where != end()) && "Could not find name in the enum list");
198         return *where;
199     }
200 
begin()201     iterator begin() { return values.begin(); }
end()202     iterator end() { return values.end(); }
back()203     EValue& back() { return values.back(); }
204 
205 private:
206     ContainerType values;
207 };
208 
209 // A single enumerant value.  Corresponds to a row in an enumeration table
210 // in the spec.
211 class EnumValue {
212 public:
EnumValue()213     EnumValue() : value(0), desc(nullptr) {}
EnumValue(unsigned int the_value,const std::string & the_name,Aliases && the_aliases,EnumCaps && the_caps,const std::string & the_firstVersion,const std::string & the_lastVersion,Extensions && the_extensions,OperandParameters && the_operands)214     EnumValue(unsigned int the_value, const std::string& the_name, Aliases&& the_aliases, EnumCaps&& the_caps,
215         const std::string& the_firstVersion, const std::string& the_lastVersion,
216         Extensions&& the_extensions, OperandParameters&& the_operands) :
217       value(the_value), name(the_name), aliases(std::move(the_aliases)), capabilities(std::move(the_caps)),
218       firstVersion(std::move(the_firstVersion)), lastVersion(std::move(the_lastVersion)),
219       extensions(std::move(the_extensions)), operands(std::move(the_operands)), desc(nullptr) { }
220 
hasAliases()221     bool hasAliases() const { return !aliases.empty(); }
222 
223     // For ValueEnum, the value from the JSON file.
224     // For BitEnum, the index of the bit position represented by this mask.
225     // (That is, what you shift 1 by to get the mask.)
226     unsigned value;
227     std::string name;
228     Aliases aliases;
229     EnumCaps capabilities;
230     std::string firstVersion;
231     std::string lastVersion;
232     // A feature only be enabled by certain extensions.
233     // An empty list means the feature does not require an extension.
234     // Normally, only Capability enums are enabled by extension.  In turn,
235     // other enums and instructions are enabled by those capabilities.
236     Extensions extensions;
237     OperandParameters operands;
238     const char* desc;
239 
240     // Returns true if this enum is valid, in isolation.
241     // Otherwise emits a diagnostic to std::cerr and returns false.
242     bool IsValid(OperandClass oc, const std::string& context) const;
243 };
244 
245 using EnumValues = EnumValuesContainer<EnumValue>;
246 
247 // Parameterize a set of enumerants that form an enum
248 class EnumDefinition {
249 public:
EnumDefinition()250     EnumDefinition() :
251         desc(0), bitmask(false), enumValues(nullptr) { }
252     void set(const std::string& enumName, EnumValues* enumValuesArg, bool mask = false)
253     {
254         codeName = enumName;
255         bitmask = mask;
256         enumValues = enumValuesArg;
257     }
258     // Returns the first EnumValue in the sequence with the given value.
259     // More than one EnumValue might have the same value.  Only valid
260     // if enumValues has been populated.
261     EnumValue& operator[](unsigned value) {
262         assert(enumValues != nullptr);
263         return (*enumValues)[value];
264     }
265     // Returns the name of the first EnumValue with the given value.
266     // Assumes enumValues has been populated.
getName(unsigned value)267     const char* getName(unsigned value) {
268         return (*this)[value].name.c_str();
269     }
270 
271     using iterator = EnumValues::iterator;
begin()272     iterator begin() { return enumValues->begin(); }
end()273     iterator end() { return enumValues->end(); }
274 
275     std::string codeName; // name to use when declaring headers for code
276     const char* desc;
277     bool bitmask;  // true if these enumerants combine into a bitmask
278     EnumValues* enumValues; // parameters for each individual enumerant
279 };
280 
281 // Parameterize an instruction's logical format, including its known set of operands,
282 // per OperandParameters above.
283 class InstructionValue : public EnumValue {
284 public:
InstructionValue(EnumValue && e,const std::string & printClass,bool has_type,bool has_result)285     InstructionValue(EnumValue&& e, const std::string& printClass, bool has_type, bool has_result)
286      : EnumValue(std::move(e)),
287        printingClass(printClass),
288        opDesc("TBD."),
289        typePresent(has_type),
290        resultPresent(has_result) { }
InstructionValue(const InstructionValue & v)291     InstructionValue(const InstructionValue& v)
292     {
293         *this = v;
294     }
295 
hasResult()296     bool hasResult() const { return resultPresent != 0; }
hasType()297     bool hasType()   const { return typePresent != 0; }
298 
299     std::string printingClass;
300     const char* opDesc;
301 
302 protected:
303     int typePresent   : 1;
304     int resultPresent : 1;
305 };
306 
307 using InstructionValues = EnumValuesContainer<InstructionValue>;
308 
309 // Parameterization info for all instructions.
310 extern InstructionValues InstructionDesc;
311 extern PrintingClasses InstructionPrintingClasses;
312 
313 // These hold definitions of the enumerants used for operands.
314 // This is indexed by OperandClass, but not including OperandOpcode.
315 extern EnumDefinition OperandClassParams[];
316 
317 };  // end namespace spv
318 
319 #endif // JSON_TO_SPIRV
320