• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2014-2019 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 enum OperandClass {
45     OperandNone,
46     OperandId,
47     OperandVariableIds,
48     OperandOptionalLiteral,
49     OperandOptionalLiteralString,
50     OperandOptionalLiteralStrings,
51     OperandVariableLiterals,
52     OperandVariableIdLiteral,
53     OperandVariableLiteralId,
54     OperandLiteralNumber,
55     OperandLiteralString,
56     OperandSource,
57     OperandExecutionModel,
58     OperandAddressing,
59     OperandMemory,
60     OperandExecutionMode,
61     OperandStorage,
62     OperandDimensionality,
63     OperandSamplerAddressingMode,
64     OperandSamplerFilterMode,
65     OperandSamplerImageFormat,
66     OperandImageChannelOrder,
67     OperandImageChannelDataType,
68     OperandImageOperands,
69     OperandFPFastMath,
70     OperandFPRoundingMode,
71     OperandLinkageType,
72     OperandAccessQualifier,
73     OperandFuncParamAttr,
74     OperandDecoration,
75     OperandBuiltIn,
76     OperandSelect,
77     OperandLoop,
78     OperandFunction,
79     OperandMemorySemantics,
80     OperandMemoryOperands,
81     OperandScope,
82 	OperandGroupOperation,
83     OperandKernelEnqueueFlags,
84     OperandKernelProfilingInfo,
85     OperandCapability,
86 
87     OperandOpcode,
88 
89     OperandCount
90 };
91 
92 // Any specific enum can have a set of capabilities that allow it:
93 typedef std::vector<std::string> EnumCaps;
94 
95 // A set of extensions.
96 typedef std::vector<std::string> Extensions;
97 
98 // Parameterize a set of operands with their OperandClass(es) and descriptions.
99 class OperandParameters {
100 public:
OperandParameters()101     OperandParameters() { }
102     void push(OperandClass oc, const std::string& d, bool opt = false)
103     {
104         opClass.push_back(oc);
105         desc.push_back(d);
106         optional.push_back(opt);
107     }
108     void setOptional();
getClass(int op)109     OperandClass getClass(int op) const { return opClass[op]; }
getDesc(int op)110     const char* getDesc(int op) const { return desc[op].c_str(); }
isOptional(int op)111     bool isOptional(int op) const { return optional[op]; }
getNum()112     int getNum() const { return (int)opClass.size(); }
113 
114 protected:
115     std::vector<OperandClass> opClass;
116     std::vector<std::string> desc;
117     std::vector<bool> optional;
118 };
119 
120 // An ordered sequence of EValue.  We'll preserve the order found in the
121 // JSON file.  You can look up a value by enum or by name.  If there are
122 // duplicate values, then take the first.  We assume names are unique.
123 // The EValue must have an unsigned |value| field and a string |name| field.
124 template <typename EValue>
125 class EnumValuesContainer {
126 public:
127     using ContainerType = std::vector<EValue>;
128     using iterator = typename ContainerType::iterator;
129     using const_iterator = typename ContainerType::const_iterator;
130 
EnumValuesContainer()131     EnumValuesContainer() {}
132 
133     // Constructs an EValue in place as a new element at the end of the
134     // sequence.
135     template <typename... Args>
emplace_back(Args &&...args)136     void emplace_back(Args&&... args) {
137         values.emplace_back(std::forward<Args>(args)...);
138     }
139 
140     // Returns the first EValue in the sequence with the given value.
141     // More than one EValue might have the same value.
142     EValue& operator[](unsigned value) {
143         auto where = std::find_if(begin(), end(), [&value](const EValue& e) {
144            return value == e.value;
145         });
146         assert((where != end()) && "Could not find enum in the enum list");
147         return *where;
148     }
149     // gets *all* entries for the value, including the first one
gatherAliases(unsigned value,std::vector<EValue * > & aliases)150     void gatherAliases(unsigned value, std::vector<EValue*>& aliases) {
151         std::for_each(begin(), end(), [&](EValue& e) {
152             if (value == e.value)
153                 aliases.push_back(&e);});
154     }
155     // Returns the EValue with the given name.  We assume uniqueness
156     // by name.
at(std::string name)157     EValue& at(std::string name) {
158         auto where = std::find_if(begin(), end(), [&name](const EValue& e) {
159            return name == e.name;
160         });
161         assert((where != end()) && "Could not find name in the enum list");
162         return *where;
163     }
164 
begin()165     iterator begin() { return values.begin(); }
end()166     iterator end() { return values.end(); }
167 
168 private:
169     ContainerType values;
170 };
171 
172 // A single enumerant value.  Corresponds to a row in an enumeration table
173 // in the spec.
174 class EnumValue {
175 public:
EnumValue()176     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)177     EnumValue(unsigned int the_value, const std::string& the_name, EnumCaps&& the_caps,
178         const std::string& the_firstVersion, const std::string& the_lastVersion,
179         Extensions&& the_extensions, OperandParameters&& the_operands) :
180       value(the_value), name(the_name), capabilities(std::move(the_caps)),
181       firstVersion(std::move(the_firstVersion)), lastVersion(std::move(the_lastVersion)),
182       extensions(std::move(the_extensions)), operands(std::move(the_operands)), desc(nullptr) { }
183 
184     // For ValueEnum, the value from the JSON file.
185     // For BitEnum, the index of the bit position represented by this mask.
186     // (That is, what you shift 1 by to get the mask.)
187     unsigned value;
188     std::string name;
189     EnumCaps capabilities;
190     std::string firstVersion;
191     std::string lastVersion;
192     // A feature only be enabled by certain extensions.
193     // An empty list means the feature does not require an extension.
194     // Normally, only Capability enums are enabled by extension.  In turn,
195     // other enums and instructions are enabled by those capabilities.
196     Extensions extensions;
197     OperandParameters operands;
198     const char* desc;
199 };
200 
201 using EnumValues = EnumValuesContainer<EnumValue>;
202 
203 // Parameterize a set of enumerants that form an enum
204 class EnumDefinition {
205 public:
EnumDefinition()206     EnumDefinition() :
207         desc(0), bitmask(false), enumValues(nullptr) { }
208     void set(const std::string& enumName, EnumValues* enumValuesArg, bool mask = false)
209     {
210         codeName = enumName;
211         bitmask = mask;
212         enumValues = enumValuesArg;
213     }
214     // Returns the first EnumValue in the sequence with the given value.
215     // More than one EnumValue might have the same value.  Only valid
216     // if enumValues has been populated.
217     EnumValue& operator[](unsigned value) {
218         assert(enumValues != nullptr);
219         return (*enumValues)[value];
220     }
221     // Returns the name of the first EnumValue with the given value.
222     // Assumes enumValues has been populated.
getName(unsigned value)223     const char* getName(unsigned value) {
224         return (*this)[value].name.c_str();
225     }
226 
227     using iterator = EnumValues::iterator;
begin()228     iterator begin() { return enumValues->begin(); }
end()229     iterator end() { return enumValues->end(); }
230 
231     std::string codeName; // name to use when declaring headers for code
232     const char* desc;
233     bool bitmask;  // true if these enumerants combine into a bitmask
234     EnumValues* enumValues; // parameters for each individual enumerant
235 };
236 
237 // Parameterize an instruction's logical format, including its known set of operands,
238 // per OperandParameters above.
239 class InstructionValue : public EnumValue {
240 public:
InstructionValue(EnumValue && e,bool has_type,bool has_result)241     InstructionValue(EnumValue&& e, bool has_type, bool has_result)
242      : EnumValue(std::move(e)),
243        opDesc("TBD"),
244        opClass(0),
245        typePresent(has_type),
246        resultPresent(has_result),
247        alias(this) { }
InstructionValue(const InstructionValue & v)248     InstructionValue(const InstructionValue& v)
249     {
250         *this = v;
251         alias = this;
252     }
253 
hasResult()254     bool hasResult() const { return resultPresent != 0; }
hasType()255     bool hasType()   const { return typePresent != 0; }
setAlias(const InstructionValue & a)256     void setAlias(const InstructionValue& a) { alias = &a; }
getAlias()257     const InstructionValue& getAlias() const { return *alias; }
isAlias()258     bool isAlias() const { return alias != this; }
259 
260     const char* opDesc;
261     int opClass;
262 
263 protected:
264     int typePresent   : 1;
265     int resultPresent : 1;
266     const InstructionValue* alias;    // correct only after discovering the aliases; otherwise points to this
267 };
268 
269 using InstructionValues = EnumValuesContainer<InstructionValue>;
270 
271 // Parameterization info for all instructions.
272 extern InstructionValues InstructionDesc;
273 
274 // These hold definitions of the enumerants used for operands.
275 // This is indexed by OperandClass, but not including OperandOpcode.
276 extern EnumDefinition OperandClassParams[];
277 
278 };  // end namespace spv
279 
280 #endif // JSON_TO_SPIRV
281