| // Copyright (c) 2014-2019 The Khronos Group Inc. |
| // |
| // Permission is hereby granted, free of charge, to any person obtaining a copy |
| // of this software and/or associated documentation files (the "Materials"), |
| // to deal in the Materials without restriction, including without limitation |
| // the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| // and/or sell copies of the Materials, and to permit persons to whom the |
| // Materials are furnished to do so, subject to the following conditions: |
| // |
| // The above copyright notice and this permission notice shall be included in |
| // all copies or substantial portions of the Materials. |
| // |
| // MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS |
| // STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND |
| // HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ |
| // |
| // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| // FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS |
| // IN THE MATERIALS. |
| |
| #pragma once |
| #ifndef JSON_TO_SPIRV |
| #define JSON_TO_SPIRV |
| |
| #include <algorithm> |
| #include <string> |
| #include <vector> |
| #include <assert.h> |
| |
| namespace spv { |
| |
| // Reads the file in the given |path|. Returns true and the contents of the |
| // file on success; otherwise, returns false and an empty string. |
| std::pair<bool, std::string> ReadFile(const std::string& path); |
| |
| // Fill in all the parameters |
| void jsonToSpirv(const std::string& jsonPath, bool buildingHeaders); |
| |
| // For parameterizing operands. |
| enum OperandClass { |
| OperandNone, |
| OperandId, |
| OperandVariableIds, |
| OperandOptionalLiteral, |
| OperandOptionalLiteralString, |
| OperandOptionalLiteralStrings, |
| OperandVariableLiterals, |
| OperandVariableIdLiteral, |
| OperandVariableLiteralId, |
| OperandLiteralNumber, |
| OperandLiteralString, |
| OperandSource, |
| OperandExecutionModel, |
| OperandAddressing, |
| OperandMemory, |
| OperandExecutionMode, |
| OperandStorage, |
| OperandDimensionality, |
| OperandSamplerAddressingMode, |
| OperandSamplerFilterMode, |
| OperandSamplerImageFormat, |
| OperandImageChannelOrder, |
| OperandImageChannelDataType, |
| OperandImageOperands, |
| OperandFPFastMath, |
| OperandFPRoundingMode, |
| OperandLinkageType, |
| OperandAccessQualifier, |
| OperandFuncParamAttr, |
| OperandDecoration, |
| OperandBuiltIn, |
| OperandSelect, |
| OperandLoop, |
| OperandFunction, |
| OperandMemorySemantics, |
| OperandMemoryOperands, |
| OperandScope, |
| OperandGroupOperation, |
| OperandKernelEnqueueFlags, |
| OperandKernelProfilingInfo, |
| OperandCapability, |
| |
| OperandOpcode, |
| |
| OperandCount |
| }; |
| |
| // For direct representation of the JSON grammar "instruction_printing_class". |
| struct PrintingClass { |
| std::string tag; |
| std::string heading; |
| }; |
| using PrintingClasses = std::vector<PrintingClass>; |
| |
| // Any specific enum can have a set of capabilities that allow it: |
| typedef std::vector<std::string> EnumCaps; |
| |
| // A set of extensions. |
| typedef std::vector<std::string> Extensions; |
| |
| // Parameterize a set of operands with their OperandClass(es) and descriptions. |
| class OperandParameters { |
| public: |
| OperandParameters() { } |
| void push(OperandClass oc, const std::string& d, bool opt = false) |
| { |
| opClass.push_back(oc); |
| desc.push_back(d); |
| optional.push_back(opt); |
| } |
| void setOptional(); |
| OperandClass getClass(int op) const { return opClass[op]; } |
| const char* getDesc(int op) const { return desc[op].c_str(); } |
| bool isOptional(int op) const { return optional[op]; } |
| int getNum() const { return (int)opClass.size(); } |
| |
| protected: |
| std::vector<OperandClass> opClass; |
| std::vector<std::string> desc; |
| std::vector<bool> optional; |
| }; |
| |
| // An ordered sequence of EValue. We'll preserve the order found in the |
| // JSON file. You can look up a value by enum or by name. If there are |
| // duplicate values, then take the first. We assume names are unique. |
| // The EValue must have an unsigned |value| field and a string |name| field. |
| template <typename EValue> |
| class EnumValuesContainer { |
| public: |
| using ContainerType = std::vector<EValue>; |
| using iterator = typename ContainerType::iterator; |
| using const_iterator = typename ContainerType::const_iterator; |
| |
| EnumValuesContainer() {} |
| |
| // Constructs an EValue in place as a new element at the end of the |
| // sequence. |
| template <typename... Args> |
| void emplace_back(Args&&... args) { |
| values.emplace_back(std::forward<Args>(args)...); |
| } |
| |
| // Returns the first EValue in the sequence with the given value. |
| // More than one EValue might have the same value. |
| EValue& operator[](unsigned value) { |
| auto where = std::find_if(begin(), end(), [&value](const EValue& e) { |
| return value == e.value; |
| }); |
| assert((where != end()) && "Could not find enum in the enum list"); |
| return *where; |
| } |
| // gets *all* entries for the value, including the first one |
| void gatherAliases(unsigned value, std::vector<EValue*>& aliases) { |
| std::for_each(begin(), end(), [&](EValue& e) { |
| if (value == e.value) |
| aliases.push_back(&e);}); |
| } |
| // Returns the EValue with the given name. We assume uniqueness |
| // by name. |
| EValue& at(std::string name) { |
| auto where = std::find_if(begin(), end(), [&name](const EValue& e) { |
| return name == e.name; |
| }); |
| assert((where != end()) && "Could not find name in the enum list"); |
| return *where; |
| } |
| |
| iterator begin() { return values.begin(); } |
| iterator end() { return values.end(); } |
| |
| private: |
| ContainerType values; |
| }; |
| |
| // A single enumerant value. Corresponds to a row in an enumeration table |
| // in the spec. |
| class EnumValue { |
| public: |
| 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) : |
| value(the_value), name(the_name), capabilities(std::move(the_caps)), |
| firstVersion(std::move(the_firstVersion)), lastVersion(std::move(the_lastVersion)), |
| extensions(std::move(the_extensions)), operands(std::move(the_operands)), desc(nullptr) { } |
| |
| // For ValueEnum, the value from the JSON file. |
| // For BitEnum, the index of the bit position represented by this mask. |
| // (That is, what you shift 1 by to get the mask.) |
| unsigned value; |
| std::string name; |
| EnumCaps capabilities; |
| std::string firstVersion; |
| std::string lastVersion; |
| // A feature only be enabled by certain extensions. |
| // An empty list means the feature does not require an extension. |
| // Normally, only Capability enums are enabled by extension. In turn, |
| // other enums and instructions are enabled by those capabilities. |
| Extensions extensions; |
| OperandParameters operands; |
| const char* desc; |
| }; |
| |
| using EnumValues = EnumValuesContainer<EnumValue>; |
| |
| // Parameterize a set of enumerants that form an enum |
| class EnumDefinition { |
| public: |
| EnumDefinition() : |
| desc(0), bitmask(false), enumValues(nullptr) { } |
| void set(const std::string& enumName, EnumValues* enumValuesArg, bool mask = false) |
| { |
| codeName = enumName; |
| bitmask = mask; |
| enumValues = enumValuesArg; |
| } |
| // Returns the first EnumValue in the sequence with the given value. |
| // More than one EnumValue might have the same value. Only valid |
| // if enumValues has been populated. |
| EnumValue& operator[](unsigned value) { |
| assert(enumValues != nullptr); |
| return (*enumValues)[value]; |
| } |
| // Returns the name of the first EnumValue with the given value. |
| // Assumes enumValues has been populated. |
| const char* getName(unsigned value) { |
| return (*this)[value].name.c_str(); |
| } |
| |
| using iterator = EnumValues::iterator; |
| iterator begin() { return enumValues->begin(); } |
| iterator end() { return enumValues->end(); } |
| |
| std::string codeName; // name to use when declaring headers for code |
| const char* desc; |
| bool bitmask; // true if these enumerants combine into a bitmask |
| EnumValues* enumValues; // parameters for each individual enumerant |
| }; |
| |
| // Parameterize an instruction's logical format, including its known set of operands, |
| // per OperandParameters above. |
| class InstructionValue : public EnumValue { |
| public: |
| InstructionValue(EnumValue&& e, const std::string& printClass, bool has_type, bool has_result) |
| : EnumValue(std::move(e)), |
| printingClass(printClass), |
| opDesc("TBD"), |
| typePresent(has_type), |
| resultPresent(has_result), |
| alias(this) { } |
| InstructionValue(const InstructionValue& v) |
| { |
| *this = v; |
| alias = this; |
| } |
| |
| bool hasResult() const { return resultPresent != 0; } |
| bool hasType() const { return typePresent != 0; } |
| void setAlias(const InstructionValue& a) { alias = &a; } |
| const InstructionValue& getAlias() const { return *alias; } |
| bool isAlias() const { return alias != this; } |
| |
| std::string printingClass; |
| const char* opDesc; |
| |
| protected: |
| int typePresent : 1; |
| int resultPresent : 1; |
| const InstructionValue* alias; // correct only after discovering the aliases; otherwise points to this |
| }; |
| |
| using InstructionValues = EnumValuesContainer<InstructionValue>; |
| |
| // Parameterization info for all instructions. |
| extern InstructionValues InstructionDesc; |
| extern PrintingClasses InstructionPrintingClasses; |
| |
| // These hold definitions of the enumerants used for operands. |
| // This is indexed by OperandClass, but not including OperandOpcode. |
| extern EnumDefinition OperandClassParams[]; |
| |
| }; // end namespace spv |
| |
| #endif // JSON_TO_SPIRV |