From d7b6362ed749969879b8909effc62df0fd120424 Mon Sep 17 00:00:00 2001 From: David Neto Date: Tue, 23 Aug 2016 11:41:28 -0400 Subject: [PATCH] Add Module::ComputeIdBound When IDs change, something should use this utility method and Module::SetIdBound before writing out the binary. --- source/opt/module.cpp | 21 +++++++++++++++++++++ source/opt/module.h | 3 +++ test/opt/test_module.cpp | 36 ++++++++++++++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/source/opt/module.cpp b/source/opt/module.cpp index 16cb16e8..204bd96f 100644 --- a/source/opt/module.cpp +++ b/source/opt/module.cpp @@ -25,6 +25,10 @@ // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. #include "module.h" + +#include + +#include "operand.h" #include "reflect.h" namespace spvtools { @@ -117,5 +121,22 @@ void Module::ToBinary(std::vector* 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(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 diff --git a/source/opt/module.h b/source/opt/module.h index 7c359cfe..f3d748d2 100644 --- a/source/opt/module.h +++ b/source/opt/module.h @@ -133,6 +133,9 @@ class Module { // If |skip_nop| is true and this is a OpNop, do nothing. void ToBinary(std::vector* 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 diff --git a/test/opt/test_module.cpp b/test/opt/test_module.cpp index 700e0f5b..7260ccb8 100644 --- a/test/opt/test_module.cpp +++ b/test/opt/test_module.cpp @@ -26,13 +26,16 @@ #include -#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 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 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 +