xref: /aosp_15_r20/external/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsonToSpirv.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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     OperandInitializationModeQualifier,
103     OperandHostAccessQualifier,
104     OperandLoadCacheControl,
105     OperandStoreCacheControl,
106     OperandNamedMaximumNumberOfRegisters,
107     OperandRawAccessChainOperands,
108 
109     OperandOpcode,
110 
111     OperandCount
112 };
113 
114 // For direct representation of the JSON grammar "instruction_printing_class".
115 struct PrintingClass {
116     std::string tag;
117     std::string heading;
118 };
119 using PrintingClasses = std::vector<PrintingClass>;
120 
121 // Any specific enum can have a set of capabilities that allow it:
122 typedef std::vector<std::string> EnumCaps;
123 
124 // A set of extensions.
125 typedef std::vector<std::string> Extensions;
126 
127 // Parameterize a set of operands with their OperandClass(es) and descriptions.
128 class OperandParameters {
129 public:
OperandParameters()130     OperandParameters() { }
131     void push(OperandClass oc, const std::string& d, bool opt = false)
132     {
133         opClass.push_back(oc);
134         desc.push_back(d);
135         optional.push_back(opt);
136     }
137     void setOptional();
getClass(int op)138     OperandClass getClass(int op) const { return opClass[op]; }
getDesc(int op)139     const char* getDesc(int op) const { return desc[op].c_str(); }
isOptional(int op)140     bool isOptional(int op) const { return optional[op]; }
getNum()141     int getNum() const { return (int)opClass.size(); }
142 
143 protected:
144     std::vector<OperandClass> opClass;
145     std::vector<std::string> desc;
146     std::vector<bool> optional;
147 };
148 
149 // An ordered sequence of EValue.  We'll preserve the order found in the
150 // JSON file.  You can look up a value by enum or by name.  If there are
151 // duplicate values, then take the first.  We assume names are unique.
152 // The EValue must have an unsigned |value| field and a string |name| field.
153 template <typename EValue>
154 class EnumValuesContainer {
155 public:
156     using ContainerType = std::vector<EValue>;
157     using iterator = typename ContainerType::iterator;
158     using const_iterator = typename ContainerType::const_iterator;
159 
EnumValuesContainer()160     EnumValuesContainer() {}
161 
162     // Constructs an EValue in place as a new element at the end of the
163     // sequence.
164     template <typename... Args>
emplace_back(Args &&...args)165     void emplace_back(Args&&... args) {
166         values.emplace_back(std::forward<Args>(args)...);
167     }
168 
169     // Returns the first EValue in the sequence with the given value.
170     // More than one EValue might have the same value.
171     EValue& operator[](unsigned value) {
172         auto where = std::find_if(begin(), end(), [&value](const EValue& e) {
173            return value == e.value;
174         });
175         assert((where != end()) && "Could not find enum in the enum list");
176         return *where;
177     }
178     // gets *all* entries for the value, including the first one
gatherAliases(unsigned value,std::vector<EValue * > & aliases)179     void gatherAliases(unsigned value, std::vector<EValue*>& aliases) {
180         std::for_each(begin(), end(), [&](EValue& e) {
181             if (value == e.value)
182                 aliases.push_back(&e);});
183     }
184     // Returns the EValue with the given name.  We assume uniqueness
185     // by name.
at(std::string name)186     EValue& at(std::string name) {
187         auto where = std::find_if(begin(), end(), [&name](const EValue& e) {
188            return name == e.name;
189         });
190         assert((where != end()) && "Could not find name in the enum list");
191         return *where;
192     }
193 
begin()194     iterator begin() { return values.begin(); }
end()195     iterator end() { return values.end(); }
back()196     EValue& back() { return values.back(); }
197 
198 private:
199     ContainerType values;
200 };
201 
202 // A single enumerant value.  Corresponds to a row in an enumeration table
203 // in the spec.
204 class EnumValue {
205 public:
EnumValue()206     EnumValue() : value(0), desc(nullptr) {}
EnumValue(unsigned int the_value,const std::string & the_name,EnumCaps && the_caps,const std::string & the_firstVersion,const std::string & the_lastVersion,Extensions && the_extensions,OperandParameters && the_operands)207     EnumValue(unsigned int the_value, const std::string& the_name, EnumCaps&& the_caps,
208         const std::string& the_firstVersion, const std::string& the_lastVersion,
209         Extensions&& the_extensions, OperandParameters&& the_operands) :
210       value(the_value), name(the_name), capabilities(std::move(the_caps)),
211       firstVersion(std::move(the_firstVersion)), lastVersion(std::move(the_lastVersion)),
212       extensions(std::move(the_extensions)), operands(std::move(the_operands)), desc(nullptr) { }
213 
214     // For ValueEnum, the value from the JSON file.
215     // For BitEnum, the index of the bit position represented by this mask.
216     // (That is, what you shift 1 by to get the mask.)
217     unsigned value;
218     std::string name;
219     EnumCaps capabilities;
220     std::string firstVersion;
221     std::string lastVersion;
222     // A feature only be enabled by certain extensions.
223     // An empty list means the feature does not require an extension.
224     // Normally, only Capability enums are enabled by extension.  In turn,
225     // other enums and instructions are enabled by those capabilities.
226     Extensions extensions;
227     OperandParameters operands;
228     const char* desc;
229 
230     // Returns true if this enum is valid, in isolation.
231     // Otherwise emits a diagnostic to std::cerr and returns false.
232     bool IsValid(OperandClass oc, const std::string& context) const;
233 };
234 
235 using EnumValues = EnumValuesContainer<EnumValue>;
236 
237 // Parameterize a set of enumerants that form an enum
238 class EnumDefinition {
239 public:
EnumDefinition()240     EnumDefinition() :
241         desc(0), bitmask(false), enumValues(nullptr) { }
242     void set(const std::string& enumName, EnumValues* enumValuesArg, bool mask = false)
243     {
244         codeName = enumName;
245         bitmask = mask;
246         enumValues = enumValuesArg;
247     }
248     // Returns the first EnumValue in the sequence with the given value.
249     // More than one EnumValue might have the same value.  Only valid
250     // if enumValues has been populated.
251     EnumValue& operator[](unsigned value) {
252         assert(enumValues != nullptr);
253         return (*enumValues)[value];
254     }
255     // Returns the name of the first EnumValue with the given value.
256     // Assumes enumValues has been populated.
getName(unsigned value)257     const char* getName(unsigned value) {
258         return (*this)[value].name.c_str();
259     }
260 
261     using iterator = EnumValues::iterator;
begin()262     iterator begin() { return enumValues->begin(); }
end()263     iterator end() { return enumValues->end(); }
264 
265     std::string codeName; // name to use when declaring headers for code
266     const char* desc;
267     bool bitmask;  // true if these enumerants combine into a bitmask
268     EnumValues* enumValues; // parameters for each individual enumerant
269 };
270 
271 // Parameterize an instruction's logical format, including its known set of operands,
272 // per OperandParameters above.
273 class InstructionValue : public EnumValue {
274 public:
InstructionValue(EnumValue && e,const std::string & printClass,bool has_type,bool has_result)275     InstructionValue(EnumValue&& e, const std::string& printClass, bool has_type, bool has_result)
276      : EnumValue(std::move(e)),
277        printingClass(printClass),
278        opDesc("TBD"),
279        typePresent(has_type),
280        resultPresent(has_result),
281        alias(this) { }
InstructionValue(const InstructionValue & v)282     InstructionValue(const InstructionValue& v)
283     {
284         *this = v;
285         alias = this;
286     }
287 
hasResult()288     bool hasResult() const { return resultPresent != 0; }
hasType()289     bool hasType()   const { return typePresent != 0; }
setAlias(const InstructionValue & a)290     void setAlias(const InstructionValue& a) { alias = &a; }
getAlias()291     const InstructionValue& getAlias() const { return *alias; }
isAlias()292     bool isAlias() const { return alias != this; }
293 
294     std::string printingClass;
295     const char* opDesc;
296 
297 protected:
298     int typePresent   : 1;
299     int resultPresent : 1;
300     const InstructionValue* alias;    // correct only after discovering the aliases; otherwise points to this
301 };
302 
303 using InstructionValues = EnumValuesContainer<InstructionValue>;
304 
305 // Parameterization info for all instructions.
306 extern InstructionValues InstructionDesc;
307 extern PrintingClasses InstructionPrintingClasses;
308 
309 // These hold definitions of the enumerants used for operands.
310 // This is indexed by OperandClass, but not including OperandOpcode.
311 extern EnumDefinition OperandClassParams[];
312 
313 };  // end namespace spv
314 
315 #endif // JSON_TO_SPIRV
316