size_t paramIndex = 0;
assert(firstInst < inst && "Invalid instruction pointer");
while (firstInst != --inst) {
- spvCheck(
- SpvOpFunction != inst->opcode && SpvOpFunctionParameter != inst->opcode,
- DIAG(0) << "OpFunctionParameter is not preceded by OpFunction or "
- "OpFunctionParameter sequence.";
- return false);
+ spvCheck(SpvOpFunction != inst->opcode &&
+ SpvOpFunctionParameter != inst->opcode &&
+ SpvOpLine != inst->opcode && SpvOpNoLine != inst->opcode,
+ DIAG(0) << "OpFunctionParameter is not preceded by OpFunction or "
+ "OpFunctionParameter sequence.";
+ return false);
if (SpvOpFunction == inst->opcode) {
break;
- } else {
+ } else if (SpvOpFunctionParameter == inst->opcode) {
paramIndex++;
}
}
auto functionType = usedefs_.FindDef(inst->words[4]);
assert(functionType.first);
+ if (paramIndex >= functionType.second.words.size() - 3) {
+ DIAG(0) << "Too many OpFunctionParameters for " << inst->words[2]
+ << ": expected " << functionType.second.words.size() - 3
+ << " based on the function's type";
+ return false;
+ }
auto paramType = usedefs_.FindDef(functionType.second.words[paramIndex + 3]);
assert(paramType.first);
spvCheck(resultType.second.id != paramType.second.id,
// Validation tests for Logical Layout
-#include "gmock/gmock.h"
-#include "source/diagnostic.h"
-#include "UnitSPIRV.h"
-#include "ValidateFixtures.h"
-
#include <functional>
#include <sstream>
#include <string>
#include <utility>
+#include "gmock/gmock.h"
+
+#include "UnitSPIRV.h"
+#include "ValidateFixtures.h"
+#include "source/diagnostic.h"
+
using std::function;
using std::ostream;
using std::ostream_iterator;
ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
}
+using ValidateOpFunctionParameter =
+ spvtest::ValidateBase<int, SPV_VALIDATE_LAYOUT_BIT | SPV_VALIDATE_ID_BIT>;
+
+TEST_F(ValidateOpFunctionParameter, OpLineBetweenParameters) {
+ const auto s = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+%foo_frag = OpString "foo.frag"
+%i32 = OpTypeInt 32 1
+%tf = OpTypeFunction %i32 %i32 %i32
+%c = OpConstant %i32 123
+%f = OpFunction %i32 None %tf
+OpLine %foo_frag 1 1
+%p1 = OpFunctionParameter %i32
+OpNoLine
+%p2 = OpFunctionParameter %i32
+%l = OpLabel
+OpReturnValue %c
+OpFunctionEnd
+)";
+ CompileSuccessfully(s);
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateOpFunctionParameter, TooManyParameters) {
+ const auto s = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+%i32 = OpTypeInt 32 1
+%tf = OpTypeFunction %i32 %i32 %i32
+%c = OpConstant %i32 123
+%f = OpFunction %i32 None %tf
+%p1 = OpFunctionParameter %i32
+%p2 = OpFunctionParameter %i32
+%xp3 = OpFunctionParameter %i32
+%xp4 = OpFunctionParameter %i32
+%xp5 = OpFunctionParameter %i32
+%xp6 = OpFunctionParameter %i32
+%xp7 = OpFunctionParameter %i32
+%l = OpLabel
+OpReturnValue %c
+OpFunctionEnd
+)";
+ CompileSuccessfully(s);
+ ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
// TODO(umar): Test optional instructions
}
std::tuple<int, std::tuple<std::string, std::function<spv_result_t(int)>,
std::function<spv_result_t(int)>>>,
SPV_VALIDATE_LAYOUT_BIT>;
+template class spvtest::ValidateBase<int, SPV_VALIDATE_LAYOUT_BIT |
+ SPV_VALIDATE_ID_BIT>;
template class spvtest::ValidateBase<
std::tuple<std::string, std::pair<std::string, std::vector<std::string>>>,