Add helper methods for obtaining type and result ID
For instructions which define objects, the type ID and result ID are
always the second and third SPIR-V instruction word, respectively.
Bug: b/129000021
Change-Id: I6879251732860b80e1f7780d9078ad7bc9751b4c
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/43691
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 6d38c46..96b67ef 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -26,6 +26,7 @@
#include "Vulkan/VkConfig.h"
#include "Vulkan/VkDescriptorSet.hpp"
+#define SPV_ENABLE_UTILITY_CODE
#include <spirv/unified1/spirv.hpp>
#include <array>
@@ -143,12 +144,22 @@
ControlBarrier,
};
- /* Pseudo-iterator over SPIRV instructions, designed to support range-based-for. */
+ class Type;
+ class Object;
+
+ // Pseudo-iterator over SPIRV instructions, designed to support range-based-for.
class InsnIterator
{
- InsnStore::const_iterator iter;
-
public:
+ InsnIterator(InsnIterator const &other) = default;
+
+ InsnIterator() = default;
+
+ explicit InsnIterator(InsnStore::const_iterator iter)
+ : iter{ iter }
+ {
+ }
+
spv::Op opcode() const
{
return static_cast<spv::Op>(*iter & spv::OpCodeMask);
@@ -176,6 +187,26 @@
return reinterpret_cast<const char *>(wordPointer(n));
}
+ bool hasResultAndType() const
+ {
+ bool hasResult = false, hasResultType = false;
+ spv::HasResultAndType(opcode(), &hasResult, &hasResultType);
+
+ return hasResultType;
+ }
+
+ SpirvID<Type> resultTypeId() const
+ {
+ ASSERT(hasResultAndType());
+ return word(1);
+ }
+
+ SpirvID<Object> resultId() const
+ {
+ ASSERT(hasResultAndType());
+ return word(2);
+ }
+
bool operator==(InsnIterator const &other) const
{
return iter == other.iter;
@@ -204,14 +235,8 @@
return ret;
}
- InsnIterator(InsnIterator const &other) = default;
-
- InsnIterator() = default;
-
- explicit InsnIterator(InsnStore::const_iterator iter)
- : iter{ iter }
- {
- }
+ private:
+ InsnStore::const_iterator iter;
};
/* range-based-for interface */
@@ -247,9 +272,11 @@
using ID = SpirvID<Object>;
spv::Op opcode() const { return definition.opcode(); }
+ Type::ID typeId() const { return definition.resultTypeId(); }
+ Object::ID id() const { return definition.resultId(); }
InsnIterator definition;
- Type::ID type;
+ Type::ID type; // TODO(b/129000021): Eliminate. Use typeId() instead.
std::unique_ptr<uint32_t[]> constantValue = nullptr;
enum class Kind
@@ -1006,7 +1033,12 @@
return SIMD::UInt(constantValue[i]);
}
- SpirvShader::Type::ID const type;
+ SpirvShader::Type::ID const type; // TODO(b/129000021): Eliminate. Use typeId() instead.
+
+ Type::ID typeId() const
+ {
+ return obj.typeId();
+ }
};
Type const &getType(Type::ID id) const
@@ -1016,6 +1048,16 @@
return it->second;
}
+ Type const &getType(const Object &object) const
+ {
+ return getType(object.typeId());
+ }
+
+ Type const &getType(const Operand &operand) const
+ {
+ return getType(operand.typeId());
+ }
+
Object const &getObject(Object::ID id) const
{
auto it = defs.find(id);
@@ -1167,6 +1209,10 @@
// etc).
static bool IsStatement(spv::Op op);
+ // HasTypeAndResult() returns true if the given opcode's instruction
+ // has a result type ID and result ID, i.e. defines an Object.
+ static bool HasTypeAndResult(spv::Op op);
+
// Helper as we often need to take dot products as part of doing other things.
SIMD::Float Dot(unsigned numComponents, Operand const &x, Operand const &y) const;