diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/buildHeaders/header.cpp | 57 | ||||
-rw-r--r-- | tools/buildHeaders/jsonToSpirv.cpp | 31 | ||||
-rw-r--r-- | tools/buildHeaders/jsonToSpirv.h | 34 | ||||
-rw-r--r-- | tools/buildHeaders/main.cpp | 2 |
4 files changed, 103 insertions, 21 deletions
diff --git a/tools/buildHeaders/header.cpp b/tools/buildHeaders/header.cpp index 7d5cd98..e1e05d0 100644 --- a/tools/buildHeaders/header.cpp +++ b/tools/buildHeaders/header.cpp @@ -42,6 +42,7 @@ #include <cctype> #include <vector> #include <utility> +#include <set> #include "jsoncpp/dist/json/json.h" @@ -68,9 +69,9 @@ namespace { TPrinter(); static const int DocMagicNumber = 0x07230203; - static const int DocVersion = 0x00010300; - static const int DocRevision = 6; - #define DocRevisionString "6" + static const int DocVersion = 0x00010400; + static const int DocRevision = 1; + #define DocRevisionString "1" static const std::string DocCopyright; static const std::string DocComment1; static const std::string DocComment2; @@ -97,6 +98,7 @@ namespace { virtual void printEpilogue(std::ostream&) const { } virtual void printMeta(std::ostream&) const; virtual void printTypes(std::ostream&) const { } + virtual void printHasResultType(std::ostream&) const { }; virtual std::string escapeComment(const std::string& s) const; @@ -346,7 +348,7 @@ namespace { bool printMax = (style != enumMask && maxEnum.size() > 0); for (const auto& v : sorted) - out << enumFmt(opPrefix, v, style, !printMax && v.first == sorted.back().first); + out << enumFmt(opPrefix, v, style, !printMax && v.second == sorted.back().second); if (printMax) out << maxEnum; @@ -364,6 +366,7 @@ namespace { printTypes(out); printMeta(out); printDefs(out); + printHasResultType(out); printEpilogue(out); } @@ -478,7 +481,7 @@ namespace { } virtual void printEpilogue(std::ostream& out) const override { - out << "#endif // #ifndef spirv_" << headerGuardSuffix() << std::endl; + out << "#endif" << std::endl; } virtual void printTypes(std::ostream& out) const override { @@ -494,6 +497,45 @@ namespace { virtual std::string pre() const { return ""; } // C name prefix virtual std::string headerGuardSuffix() const = 0; + + virtual std::string fmtEnumUse(const std::string& opPrefix, const std::string& name) const { return pre() + name; } + + virtual void printHasResultType(std::ostream& out) const + { + const Json::Value& enums = spvRoot["spv"]["enum"]; + + std::set<unsigned> seenValues; + + for (auto opClass = enums.begin(); opClass != enums.end(); ++opClass) { + const auto opName = (*opClass)["Name"].asString(); + if (opName != "Op") { + continue; + } + + out << "#ifdef SPV_ENABLE_UTILITY_CODE" << std::endl; + out << "inline void " << pre() << "HasResultAndType(" << pre() << opName << " opcode, bool *hasResult, bool *hasResultType) {" << std::endl; + out << " *hasResult = *hasResultType = false;" << std::endl; + out << " switch (opcode) {" << std::endl; + out << " default: /* unknown opcode */ break;" << std::endl; + + for (auto& inst : spv::InstructionDesc) { + + // Filter out duplicate enum values, which would break the switch statement. + // These are probably just extension enums promoted to core. + if (seenValues.find(inst.value) != seenValues.end()) { + continue; + } + seenValues.insert(inst.value); + + std::string name = inst.name; + out << " case " << fmtEnumUse("Op", name) << ": *hasResult = " << (inst.hasResult() ? "true" : "false") << "; *hasResultType = " << (inst.hasType() ? "true" : "false") << "; break;" << std::endl; + } + + out << " }" << std::endl; + out << "}" << std::endl; + out << "#endif /* SPV_ENABLE_UTILITY_CODE */" << std::endl << std::endl; + } + } }; // C printer @@ -552,7 +594,7 @@ namespace { } out << "\n} // end namespace spv\n\n"; - TPrinterCBase::printEpilogue(out); + out << "#endif // #ifndef spirv_" << headerGuardSuffix() << std::endl; } std::string commentBOL() const override { return "// "; } @@ -600,6 +642,9 @@ namespace { return enumFmt(s, v, style, true); } + // Add type prefix for scoped enum + virtual std::string fmtEnumUse(const std::string& opPrefix, const std::string& name) const { return opPrefix + "::" + name; } + std::string headerGuardSuffix() const override { return "HPP"; } }; diff --git a/tools/buildHeaders/jsonToSpirv.cpp b/tools/buildHeaders/jsonToSpirv.cpp index 62b85a8..e6cab48 100644 --- a/tools/buildHeaders/jsonToSpirv.cpp +++ b/tools/buildHeaders/jsonToSpirv.cpp @@ -119,8 +119,7 @@ ClassOptionality ToOperandClassAndOptionality(const std::string& operandKind, co else if (quantifier == "?") return {OperandLiteralString, true}; else { - assert(0 && "this case should not exist"); - return {OperandNone, false}; + return {OperandOptionalLiteralStrings, false}; } } else if (operandKind == "PairLiteralIntegerIdRef") { // Used by OpSwitch in the grammar @@ -198,7 +197,7 @@ ClassOptionality ToOperandClassAndOptionality(const std::string& operandKind, co } else if (operandKind == "FunctionControl") { type = OperandFunction; } else if (operandKind == "MemoryAccess") { - type = OperandMemoryAccess; + type = OperandMemoryOperands; } if (type == OperandNone) { @@ -230,7 +229,21 @@ unsigned int NumberStringToBit(const std::string& str) return bit; } -void jsonToSpirv(const std::string& jsonPath) +bool ExcludeInstruction(unsigned op, bool buildingHeaders) +{ + // Some instructions in the grammar don't need to be reflected + // in the specification. + + if (buildingHeaders) + return false; + + if (op >= 5699 /* OpVmeImageINTEL */ && op <= 5816 /* OpSubgroupAvcSicGetInterRawSadsINTEL */) + return true; + + return false; +} + +void jsonToSpirv(const std::string& jsonPath, bool buildingHeaders) { // only do this once. static bool initialized = false; @@ -288,9 +301,12 @@ void jsonToSpirv(const std::string& jsonPath) const Json::Value insts = root["instructions"]; for (const auto& inst : insts) { const unsigned int opcode = inst["opcode"].asUInt(); + if (ExcludeInstruction(opcode, buildingHeaders)) + continue; const std::string name = inst["opname"].asString(); EnumCaps caps = getCaps(inst); std::string version = inst["version"].asString(); + std::string lastVersion = inst["lastVersion"].asString(); Extensions exts = getExts(inst); OperandParameters operands; bool defResultId = false; @@ -306,7 +322,7 @@ void jsonToSpirv(const std::string& jsonPath) } InstructionDesc.emplace_back( std::move(EnumValue(opcode, name, - std::move(caps), std::move(version), std::move(exts), + std::move(caps), std::move(version), std::move(lastVersion), std::move(exts), std::move(operands))), defTypeId, defResultId); } @@ -339,6 +355,7 @@ void jsonToSpirv(const std::string& jsonPath) continue; EnumCaps caps(getCaps(enumerant)); std::string version = enumerant["version"].asString(); + std::string lastVersion = enumerant["lastVersion"].asString(); Extensions exts(getExts(enumerant)); OperandParameters params; const Json::Value& paramsJson = enumerant["parameters"]; @@ -353,7 +370,7 @@ void jsonToSpirv(const std::string& jsonPath) } dest->emplace_back( value, enumerant["enumerant"].asString(), - std::move(caps), std::move(version), std::move(exts), std::move(params)); + std::move(caps), std::move(version), std::move(lastVersion), std::move(exts), std::move(params)); } }; @@ -421,7 +438,7 @@ void jsonToSpirv(const std::string& jsonPath) } else if (enumName == "Dim") { establishOperandClass(enumName, OperandDimensionality, &DimensionalityParams, operandEnum, category); } else if (enumName == "MemoryAccess") { - establishOperandClass(enumName, OperandMemoryAccess, &MemoryAccessParams, operandEnum, category); + establishOperandClass(enumName, OperandMemoryOperands, &MemoryAccessParams, operandEnum, category); } else if (enumName == "Scope") { establishOperandClass(enumName, OperandScope, &ScopeParams, operandEnum, category); } else if (enumName == "GroupOperation") { diff --git a/tools/buildHeaders/jsonToSpirv.h b/tools/buildHeaders/jsonToSpirv.h index bc63a4d..beec01c 100644 --- a/tools/buildHeaders/jsonToSpirv.h +++ b/tools/buildHeaders/jsonToSpirv.h @@ -38,7 +38,7 @@ namespace spv { std::pair<bool, std::string> ReadFile(const std::string& path); // Fill in all the parameters -void jsonToSpirv(const std::string& jsonPath); +void jsonToSpirv(const std::string& jsonPath, bool buildingHeaders); // For parameterizing operands. enum OperandClass { @@ -47,6 +47,7 @@ enum OperandClass { OperandVariableIds, OperandOptionalLiteral, OperandOptionalLiteralString, + OperandOptionalLiteralStrings, OperandVariableLiterals, OperandVariableIdLiteral, OperandVariableLiteralId, @@ -76,7 +77,7 @@ enum OperandClass { OperandLoop, OperandFunction, OperandMemorySemantics, - OperandMemoryAccess, + OperandMemoryOperands, OperandScope, OperandGroupOperation, OperandKernelEnqueueFlags, @@ -145,6 +146,12 @@ public: 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) { @@ -167,9 +174,11 @@ private: 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_version, - Extensions&& the_extensions, OperandParameters&& the_operands) : - value(the_value), name(the_name), capabilities(std::move(the_caps)), version(std::move(the_version)), + 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. @@ -178,7 +187,8 @@ public: unsigned value; std::string name; EnumCaps capabilities; - std::string version; + 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, @@ -233,10 +243,19 @@ public: opDesc("TBD"), opClass(0), typePresent(has_type), - resultPresent(has_result) {} + 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; } const char* opDesc; int opClass; @@ -244,6 +263,7 @@ public: protected: int typePresent : 1; int resultPresent : 1; + const InstructionValue* alias; // correct only after discovering the aliases; otherwise points to this }; using InstructionValues = EnumValuesContainer<InstructionValue>; diff --git a/tools/buildHeaders/main.cpp b/tools/buildHeaders/main.cpp index 67d676c..7e5f7f8 100644 --- a/tools/buildHeaders/main.cpp +++ b/tools/buildHeaders/main.cpp @@ -119,7 +119,7 @@ int main(int argc, char* argv[]) return 1; } - spv::jsonToSpirv(jsonPath); + spv::jsonToSpirv(jsonPath, (Options & EOptionPrintHeader) != 0); if (Options & EOptionPrintHeader) spv::PrintHeader(Language, std::cout); |