Add Module::ComputeIdBound
authorDavid Neto <dneto@google.com>
Tue, 23 Aug 2016 15:41:28 +0000 (11:41 -0400)
committerDavid Neto <dneto@google.com>
Fri, 26 Aug 2016 20:27:12 +0000 (16:27 -0400)
When IDs change, something should use this utility method
and Module::SetIdBound before writing out the binary.

source/opt/module.cpp
source/opt/module.h
test/opt/test_module.cpp

index 16cb16e..204bd96 100644 (file)
 // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 
 #include "module.h"
+
+#include <algorithm>
+
+#include "operand.h"
 #include "reflect.h"
 
 namespace spvtools {
@@ -117,5 +121,22 @@ void Module::ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const {
   ForEachInst(write_inst, true);
 }
 
+uint32_t Module::ComputeIdBound() const {
+  uint32_t highest = 0;
+
+  ForEachInst(
+      [&highest](const Instruction* inst) {
+        // Use a const-cast just to access begin() and end() for the range-for.
+        for (const auto& operand : *const_cast<Instruction*>(inst)) {
+          if (spvIsIdType(operand.type)) {
+            highest = std::max(highest, operand.words[0]);
+          }
+        }
+      },
+      true /* scan debug line insts as well */);
+
+  return highest + 1;
+}
+
 }  // namespace ir
 }  // namespace spvtools
index 7c359cf..f3d748d 100644 (file)
@@ -133,6 +133,9 @@ class Module {
   // If |skip_nop| is true and this is a OpNop, do nothing.
   void ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const;
 
+  // Returns 1 more than the maximum Id value mentioned in the module.
+  uint32_t ComputeIdBound() const;
+
  private:
   ModuleHeader header_;  // Module header
 
index 700e0f5..7260ccb 100644 (file)
 
 #include <vector>
 
-#include "opt/module.h"
-
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
+#include "opt/libspirv.hpp"
+#include "opt/module.h"
+
 namespace {
 
 using spvtools::ir::Module;
+using ::testing::Eq;
 
 uint32_t GetIdBound(const Module& m) {
   std::vector<uint32_t> binary;
@@ -55,4 +58,33 @@ TEST(ModuleTest, SetIdBound) {
   EXPECT_EQ(102u, GetIdBound(m));
 }
 
+// Returns a module formed by assembling the given text,
+// then loading the result.
+std::unique_ptr<Module> BuildModule(std::string text) {
+  spvtools::SpvTools t(SPV_ENV_UNIVERSAL_1_1);
+  return t.BuildModule(text);
+}
+
+TEST(ModuleTest, ComputeIdBound) {
+  // Emtpy module case.
+  EXPECT_EQ(1u, BuildModule("")->ComputeIdBound());
+  // Sensitive to result id
+  EXPECT_EQ(2u, BuildModule("%void = OpTypeVoid")->ComputeIdBound());
+  // Sensitive to type id
+  EXPECT_EQ(1000u, BuildModule("%a = OpTypeArray !999 3")->ComputeIdBound());
+  // Sensitive to a regular Id parameter
+  EXPECT_EQ(2000u, BuildModule("OpDecorate !1999 0")->ComputeIdBound());
+  // Sensitive to a scope Id parameter.
+  EXPECT_EQ(3000u,
+            BuildModule("%f = OpFunction %void None %fntype %a = OpLabel "
+                        "OpMemoryBarrier !2999 %b\n")
+                ->ComputeIdBound());
+  // Sensitive to a semantics Id parameter
+  EXPECT_EQ(4000u,
+            BuildModule("%f = OpFunction %void None %fntype %a = OpLabel "
+                        "OpMemoryBarrier %b !3999\n")
+                ->ComputeIdBound());
+}
+
 }  // anonymous namespace
+