Check for valid SPIR-V <id>s by comparing against 0
This change consistently uses if(id != 0) { ... } syntax for choosing
code paths where the SPIR-V <id> is valid. This allows the value()
method to assert that we don't inadvertently use an <id> for an operand
which does not exist. This makes for an elegant syntax when parsing
SPIR-V instructions into structures which store <id>s for operands which
are optional, such as common in image instructions, while catching
mistakes centrally.
Bug: b/205642050
Change-Id: I3e1f1340a56bd3c848fdf3724088660046bf29ed
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/39268
Reviewed-by: Alexis Hétu <sugoi@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/SpirvID.hpp b/src/Pipeline/SpirvID.hpp
index 67ca59d..e90a8cc 100644
--- a/src/Pipeline/SpirvID.hpp
+++ b/src/Pipeline/SpirvID.hpp
@@ -15,6 +15,8 @@
#ifndef sw_ID_hpp
#define sw_ID_hpp
+#include "System/Debug.hpp"
+
#include <cstdint>
#include <unordered_map>
@@ -31,15 +33,16 @@
public:
SpirvID() = default;
inline SpirvID(uint32_t id);
+
inline bool operator==(const SpirvID<T> &rhs) const;
inline bool operator!=(const SpirvID<T> &rhs) const;
inline bool operator<(const SpirvID<T> &rhs) const;
- // value returns the numerical value of the identifier.
+ // Returns the numerical value of the identifier.
inline uint32_t value() const;
private:
- uint32_t id = 0;
+ uint32_t id = 0; // Valid ids are in the range "0 < id < Bound".
};
template<typename T>
@@ -68,6 +71,10 @@
template<typename T>
uint32_t SpirvID<T>::value() const
{
+ // Assert that we don't attempt to use unassigned IDs.
+ // Use if(id != 0) { ... } to avoid invalid code paths.
+ ASSERT(id != 0);
+
return id;
}
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index c56fd38..6239a20 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -207,7 +207,7 @@
case spv::OpLabel:
{
- ASSERT(currentBlock.value() == 0);
+ ASSERT(currentBlock == 0);
currentBlock = Block::ID(insn.word(1));
blockStart = insn;
}
@@ -224,8 +224,8 @@
case spv::OpKill:
case spv::OpUnreachable:
{
- ASSERT(currentBlock.value() != 0);
- ASSERT(currentFunction.value() != 0);
+ ASSERT(currentBlock != 0);
+ ASSERT(currentFunction != 0);
auto blockEnd = insn;
blockEnd++;
diff --git a/src/Pipeline/SpirvShaderControlFlow.cpp b/src/Pipeline/SpirvShaderControlFlow.cpp
index 7893023..754e91d 100644
--- a/src/Pipeline/SpirvShaderControlFlow.cpp
+++ b/src/Pipeline/SpirvShaderControlFlow.cpp
@@ -778,6 +778,7 @@
<< "[label=\"M\" style=dashed color=blue]"
<< std::endl;
}
+
if(block.second.continueTarget != 0)
{
file << " block_" << block.first.value() << " -> "
diff --git a/src/Pipeline/SpirvShaderImage.cpp b/src/Pipeline/SpirvShaderImage.cpp
index d13ed5a..426b087 100644
--- a/src/Pipeline/SpirvShaderImage.cpp
+++ b/src/Pipeline/SpirvShaderImage.cpp
@@ -557,7 +557,7 @@
}
SIMD::Int n = 0;
- if(sampleId.value())
+ if(sampleId != 0)
{
Operand sample(this, state, sampleId);
if(!sample.isConstantZero())
@@ -587,7 +587,7 @@
oobMask |= As<SIMD::Int>(CmpNLT(As<SIMD::UInt>(w), SIMD::UInt(depth)));
}
- if(sampleId.value())
+ if(sampleId != 0)
{
Operand sample(this, state, sampleId);
if(!sample.isConstantZero())