Header generator: Check enumerant ordering
authorDavid Neto <dneto@google.com>
Wed, 20 Jan 2021 02:20:44 +0000 (21:20 -0500)
committerDavid Neto <dneto@google.com>
Wed, 27 Jan 2021 20:46:02 +0000 (15:46 -0500)
In the grammar, enforce ordering rules:
- Instructions must appear in order of their opcode
- Non-instructions: each successive enumerant within a single kind must
  appear in order

- Reorder enumerants Subgroup*MaskKHR enums to satisfy the rule.

include/spirv/unified1/spirv.core.grammar.json
include/spirv/unified1/spirv.cs
include/spirv/unified1/spirv.h
include/spirv/unified1/spirv.hpp
tools/buildHeaders/jsonToSpirv.cpp

index 514965e..51840ec 100644 (file)
           "version" : "1.3"
         },
         {
-          "enumerant" : "SubgroupGeMask",
-          "value" : 4417,
+          "enumerant" : "SubgroupEqMaskKHR",
+          "value" : 4416,
           "capabilities" : [ "SubgroupBallotKHR", "GroupNonUniformBallot" ],
+          "extensions" : [ "SPV_KHR_shader_ballot" ],
           "version" : "1.3"
         },
         {
-          "enumerant" : "SubgroupGtMask",
-          "value" : 4418,
+          "enumerant" : "SubgroupGeMask",
+          "value" : 4417,
           "capabilities" : [ "SubgroupBallotKHR", "GroupNonUniformBallot" ],
           "version" : "1.3"
         },
         {
-          "enumerant" : "SubgroupLeMask",
-          "value" : 4419,
+          "enumerant" : "SubgroupGeMaskKHR",
+          "value" : 4417,
           "capabilities" : [ "SubgroupBallotKHR", "GroupNonUniformBallot" ],
+          "extensions" : [ "SPV_KHR_shader_ballot" ],
           "version" : "1.3"
         },
         {
-          "enumerant" : "SubgroupLtMask",
-          "value" : 4420,
+          "enumerant" : "SubgroupGtMask",
+          "value" : 4418,
           "capabilities" : [ "SubgroupBallotKHR", "GroupNonUniformBallot" ],
           "version" : "1.3"
         },
         {
-          "enumerant" : "SubgroupEqMaskKHR",
-          "value" : 4416,
+          "enumerant" : "SubgroupGtMaskKHR",
+          "value" : 4418,
           "capabilities" : [ "SubgroupBallotKHR", "GroupNonUniformBallot" ],
           "extensions" : [ "SPV_KHR_shader_ballot" ],
           "version" : "1.3"
         },
         {
-          "enumerant" : "SubgroupGeMaskKHR",
-          "value" : 4417,
+          "enumerant" : "SubgroupLeMask",
+          "value" : 4419,
           "capabilities" : [ "SubgroupBallotKHR", "GroupNonUniformBallot" ],
-          "extensions" : [ "SPV_KHR_shader_ballot" ],
           "version" : "1.3"
         },
         {
-          "enumerant" : "SubgroupGtMaskKHR",
-          "value" : 4418,
+          "enumerant" : "SubgroupLeMaskKHR",
+          "value" : 4419,
           "capabilities" : [ "SubgroupBallotKHR", "GroupNonUniformBallot" ],
           "extensions" : [ "SPV_KHR_shader_ballot" ],
           "version" : "1.3"
         },
         {
-          "enumerant" : "SubgroupLeMaskKHR",
-          "value" : 4419,
+          "enumerant" : "SubgroupLtMask",
+          "value" : 4420,
           "capabilities" : [ "SubgroupBallotKHR", "GroupNonUniformBallot" ],
-          "extensions" : [ "SPV_KHR_shader_ballot" ],
           "version" : "1.3"
         },
         {
index 3a07e52..ea1036d 100644 (file)
@@ -1106,14 +1106,16 @@ namespace Spv
             Horizontal4Pixels = 0x00000008,
         }
 
-        public enum FPDenormMode {
-          Preserve = 0,
-          FlushToZero = 1,
+        public enum FPDenormMode
+        {
+            Preserve = 0,
+            FlushToZero = 1,
         }
 
-        public enum FPOperationMode {
-          IEEE = 0,
-          ALT = 1,
+        public enum FPOperationMode
+        {
+            IEEE = 0,
+            ALT = 1,
         }
 
         public enum Op
index 41a650b..6b57050 100644 (file)
@@ -1106,15 +1106,15 @@ typedef enum SpvFragmentShadingRateMask_ {
 } SpvFragmentShadingRateMask;
 
 typedef enum SpvFPDenormMode_ {
-  SpvFPDenormModePreserve = 0,
-  SpvFPDenormModeFlushToZero = 1,
-  SpvFPDenormModeMax = 0x7fffffff,
+    SpvFPDenormModePreserve = 0,
+    SpvFPDenormModeFlushToZero = 1,
+    SpvFPDenormModeMax = 0x7fffffff,
 } SpvFPDenormMode;
 
 typedef enum SpvFPOperationMode_ {
-  SpvFPOperationModeIEEE = 0,
-  SpvFPOperationModeALT = 1,
-  SpvFPOperationModeMax = 0x7fffffff,
+    SpvFPOperationModeIEEE = 0,
+    SpvFPOperationModeALT = 1,
+    SpvFPOperationModeMax = 0x7fffffff,
 } SpvFPOperationMode;
 
 typedef enum SpvOp_ {
index af629ef..03a0e6b 100644 (file)
@@ -1102,15 +1102,15 @@ enum FragmentShadingRateMask {
 };
 
 enum FPDenormMode {
-  FPDenormModePreserve = 0,
-  FPDenormModeFlushToZero = 1,
-  FPDenormModeMax = 0x7fffffff,
+    FPDenormModePreserve = 0,
+    FPDenormModeFlushToZero = 1,
+    FPDenormModeMax = 0x7fffffff,
 };
 
 enum FPOperationMode {
-  FPOperationModeIEEE = 0,
-  FPOperationModeALT = 1,
-  FPOperationModeMax = 0x7fffffff,
+    FPOperationModeIEEE = 0,
+    FPOperationModeALT = 1,
+    FPOperationModeMax = 0x7fffffff,
 };
 
 enum Op {
index e5b1e3e..17d2ea4 100644 (file)
@@ -25,6 +25,7 @@
 #include <assert.h>
 #include <string.h>
 #include <algorithm>
+#include <cstdlib>
 #include <iostream>
 #include <unordered_map>
 #include <unordered_set>
@@ -326,6 +327,8 @@ void jsonToSpirv(const std::string& jsonPath, bool buildingHeaders)
 
     // process the instructions
     const Json::Value insts = root["instructions"];
+    unsigned maxOpcode = 0;
+    bool firstOpcode = true;
     for (const auto& inst : insts) {
         const auto printingClass = inst["class"].asString();
         if (printingClass.size() == 0) {
@@ -341,6 +344,19 @@ void jsonToSpirv(const std::string& jsonPath, bool buildingHeaders)
         }
         const auto opcode = inst["opcode"].asUInt();
         const std::string name = inst["opname"].asString();
+        if (firstOpcode) {
+          maxOpcode = opcode;
+          firstOpcode = false;
+        } else {
+          if (maxOpcode > opcode) {
+            std::cerr << "Error: " << name
+                      << " is out of order. It follows the instruction with opcode " << maxOpcode
+                      << std::endl;
+            std::exit(1);
+          } else {
+            maxOpcode = opcode;
+          }
+        }
         EnumCaps caps = getCaps(inst);
         std::string version = inst["version"].asString();
         std::string lastVersion = inst["lastVersion"].asString();
@@ -384,12 +400,27 @@ void jsonToSpirv(const std::string& jsonPath, bool buildingHeaders)
             return result;
         };
 
+        unsigned maxValue = 0;
+        bool firstValue = true;
         for (const auto& enumerant : source["enumerants"]) {
             unsigned value;
             bool skip_zero_in_bitfield;
             std::tie(value, skip_zero_in_bitfield) = getValue(enumerant);
             if (skip_zero_in_bitfield)
                 continue;
+            if (firstValue) {
+              maxValue = value;
+              firstValue = false;
+            } else {
+              if (maxValue > value) {
+                std::cerr << "Error: " << source["kind"] << " enumerant " << enumerant["enumerant"]
+                          << " is out of order. It has value " <<  value
+                          << " but follows the enumerant with value " << maxValue << std::endl;
+                std::exit(1);
+              } else {
+                maxValue = value;
+              }
+            }
             EnumCaps caps(getCaps(enumerant));
             std::string version = enumerant["version"].asString();
             std::string lastVersion = enumerant["lastVersion"].asString();