aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Neto <dneto@google.com>2016-11-30 13:48:32 -0500
committerDavid Neto <dneto@google.com>2016-11-30 13:58:40 -0500
commit160da1d4e3a5c5b23facfa3277154a44b73cab59 (patch)
tree999983b1cfece234b7ed8c504bcbf086605183cf
parent1401a61b1e7d1516578171a94edbac33858fb1a2 (diff)
parentbd5b0bfca1bf067563c9e03a7c30c3590189b5c0 (diff)
downloadspirv-tools-master.tar.gz
Merge remote-tracking branch 'aosp/upstream-master' into update-shadercHEADmastermain
Includes the following: bd5b0bf Checks that result IDs are within the ID bound specified in the SPIR-V header f72189c Validation for OpSampledImage instruction. 6fa6a3f Adding validation for OpSpecConstantComposite. 8c414eb Adding validation code for OpTypeStruct. 5c19de2 Skip building example executable when asked c935253 Make friendly number-based names for OpConstant 4f750c0 Extract EmitNumericLiteral from disassembler d062006 Adding validation code for more data rules. 38036a7 Rename validation source files to comply with Google style guide. 2881fe9 Rename validation tests to comply with Google style guide. 6c899a5 Adding validation for vector data rule. 4f57e14 Renaming test files to comply with Google style guide. bf190ec Remove source/instruction.cpp b371439 enum_set: Fix bool performance warning. Test: checkbuild.py on Linux x86; unit tests on Windows Change-Id: I96b8f8d6156f2ee5a5dbf070ea9b5e67ccd5e445
-rw-r--r--examples/cpp-interface/CMakeLists.txt8
-rw-r--r--include/spirv-tools/libspirv.h1
-rw-r--r--source/CMakeLists.txt14
-rw-r--r--source/disassemble.cpp45
-rw-r--r--source/enum_set.h2
-rw-r--r--source/instruction.cpp20
-rw-r--r--source/instruction.h4
-rw-r--r--source/name_mapper.cpp12
-rw-r--r--source/name_mapper.h1
-rw-r--r--source/parsed_operand.cpp75
-rw-r--r--source/parsed_operand.h32
-rw-r--r--source/val/basic_block.cpp (renamed from source/val/BasicBlock.cpp)2
-rw-r--r--source/val/basic_block.h (renamed from source/val/BasicBlock.h)0
-rw-r--r--source/val/construct.cpp (renamed from source/val/Construct.cpp)2
-rw-r--r--source/val/construct.h (renamed from source/val/Construct.h)0
-rw-r--r--source/val/function.cpp (renamed from source/val/Function.cpp)6
-rw-r--r--source/val/function.h (renamed from source/val/Function.h)6
-rw-r--r--source/val/instruction.cpp (renamed from source/val/Instruction.cpp)2
-rw-r--r--source/val/instruction.h (renamed from source/val/Instruction.h)0
-rw-r--r--source/val/validation_state.cpp (renamed from source/val/ValidationState.cpp)50
-rw-r--r--source/val/validation_state.h (renamed from source/val/ValidationState.h)34
-rw-r--r--source/validate.cpp18
-rw-r--r--source/validate.h6
-rw-r--r--source/validate_cfg.cpp8
-rw-r--r--source/validate_datarules.cpp272
-rw-r--r--source/validate_id.cpp281
-rw-r--r--source/validate_instruction.cpp22
-rw-r--r--source/validate_layout.cpp4
-rw-r--r--test/CMakeLists.txt121
-rw-r--r--test/assembly_context_test.cpp (renamed from test/AssemblyContext.cpp)2
-rw-r--r--test/assembly_format_test.cpp (renamed from test/AssemblyFormat.cpp)2
-rw-r--r--test/binary_destroy_test.cpp (renamed from test/BinaryDestroy.cpp)4
-rw-r--r--test/binary_endianness_test.cpp (renamed from test/BinaryEndianness.cpp)2
-rw-r--r--test/binary_header_get_test.cpp (renamed from test/BinaryHeaderGet.cpp)2
-rw-r--r--test/binary_parse_test.cpp (renamed from test/BinaryParse.cpp)4
-rw-r--r--test/binary_to_text.literal_test.cpp (renamed from test/BinaryToText.Literal.cpp)4
-rw-r--r--test/binary_to_text_test.cpp (renamed from test/BinaryToText.cpp)39
-rw-r--r--test/c_interface_test.cpp (renamed from test/c_interface.cpp)0
-rw-r--r--test/capability_set_test.cpp (renamed from test/CapabilitySet.cpp)2
-rw-r--r--test/comment_test.cpp (renamed from test/Comment.cpp)4
-rw-r--r--test/cpp_interface_test.cpp (renamed from test/cpp_interface.cpp)0
-rw-r--r--test/diagnostic_test.cpp (renamed from test/diagnostic.cpp)2
-rw-r--r--test/ext_inst.glsl_test.cpp (renamed from test/ExtInstGLSLstd450.cpp)2
-rw-r--r--test/ext_inst.opencl_test.cpp (renamed from test/ExtInst.OpenCL.std.cpp)4
-rw-r--r--test/fix_word_test.cpp (renamed from test/FixWord.cpp)2
-rw-r--r--test/generator_magic_number_test.cpp (renamed from test/GeneratorMagicNumber.cpp)2
-rw-r--r--test/hex_float_test.cpp (renamed from test/HexFloat.cpp)2
-rw-r--r--test/immediate_int_test.cpp (renamed from test/ImmediateInt.cpp)2
-rw-r--r--test/libspirv_macros_test.cpp (renamed from test/LibspirvMacros.cpp)2
-rw-r--r--test/log_test.cpp (renamed from test/test_log.cpp)4
-rw-r--r--test/name_mapper_test.cpp (renamed from test/NameMapper.cpp)57
-rw-r--r--test/named_id_test.cpp (renamed from test/NamedId.cpp)4
-rw-r--r--test/opcode_make_test.cpp (renamed from test/OpcodeMake.cpp)2
-rw-r--r--test/opcode_require_capabilities_test.cpp (renamed from test/OpcodeRequiresCapabilities.cpp)2
-rw-r--r--test/opcode_split_test.cpp (renamed from test/OpcodeSplit.cpp)2
-rw-r--r--test/opcode_table_get_test.cpp (renamed from test/OpcodeTableGet.cpp)2
-rw-r--r--test/operand_capabilities_test.cpp (renamed from test/OperandCapabilities.cpp)2
-rw-r--r--test/operand_pattern_test.cpp (renamed from test/OperandPattern.cpp)2
-rw-r--r--test/operand_test.cpp (renamed from test/Operand.cpp)2
-rw-r--r--test/opt/CMakeLists.txt34
-rw-r--r--test/opt/assembly_builder_test.cpp (renamed from test/opt/test_assembly_builder.cpp)0
-rw-r--r--test/opt/def_use_test.cpp (renamed from test/opt/test_def_use.cpp)0
-rw-r--r--test/opt/eliminate_dead_const_test.cpp (renamed from test/opt/test_eliminate_dead_const.cpp)16
-rw-r--r--test/opt/fold_spec_const_op_composite_test.cpp (renamed from test/opt/test_fold_spec_const_op_composite.cpp)246
-rw-r--r--test/opt/freeze_spec_const_test.cpp (renamed from test/opt/test_freeze_spec_const.cpp)18
-rw-r--r--test/opt/instruction_test.cpp (renamed from test/opt/test_instruction.cpp)2
-rw-r--r--test/opt/ir_loader_test.cpp (renamed from test/opt/test_ir_loader.cpp)18
-rw-r--r--test/opt/iterator_test.cpp (renamed from test/opt/test_iterator.cpp)0
-rw-r--r--test/opt/line_debug_info_test.cpp (renamed from test/opt/test_line_debug_info.cpp)0
-rw-r--r--test/opt/module_test.cpp (renamed from test/opt/test_module.cpp)0
-rw-r--r--test/opt/pass_manager_test.cpp (renamed from test/opt/test_pass_manager.cpp)0
-rw-r--r--test/opt/set_spec_const_default_value_test.cpp (renamed from test/opt/test_set_spec_const_default_value.cpp)8
-rw-r--r--test/opt/strip_debug_info_test.cpp (renamed from test/opt/test_strip_debug_info.cpp)0
-rw-r--r--test/opt/type_manager_test.cpp (renamed from test/opt/test_type_manager.cpp)0
-rw-r--r--test/opt/types_test.cpp (renamed from test/opt/test_types.cpp)0
-rw-r--r--test/opt/unify_const_test.cpp (renamed from test/opt/test_unify_const.cpp)0
-rw-r--r--test/opt/utils_test.cpp (renamed from test/opt/test_utils.cpp)0
-rw-r--r--test/parse_number_test.cpp (renamed from test/ParseNumber.cpp)0
-rw-r--r--test/software_version_test.cpp (renamed from test/SoftwareVersion.cpp)2
-rw-r--r--test/target_env_test.cpp (renamed from test/TargetEnv.cpp)2
-rw-r--r--test/test_fixture.h (renamed from test/TestFixture.h)2
-rw-r--r--test/text_advance_test.cpp (renamed from test/TextAdvance.cpp)2
-rw-r--r--test/text_destroy_test.cpp (renamed from test/TextDestroy.cpp)2
-rw-r--r--test/text_literal_test.cpp (renamed from test/TextLiteral.cpp)4
-rw-r--r--test/text_start_new_inst_test.cpp (renamed from test/TextStartsNewInst.cpp)2
-rw-r--r--test/text_to_binary.annotation_test.cpp (renamed from test/TextToBinary.Annotation.cpp)4
-rw-r--r--test/text_to_binary.barrier_test.cpp (renamed from test/TextToBinary.Barrier.cpp)4
-rw-r--r--test/text_to_binary.constant_test.cpp (renamed from test/TextToBinary.Constant.cpp)4
-rw-r--r--test/text_to_binary.control_flow_test.cpp (renamed from test/TextToBinary.ControlFlow.cpp)4
-rw-r--r--test/text_to_binary.debug_test.cpp (renamed from test/TextToBinary.Debug.cpp)4
-rw-r--r--test/text_to_binary.device_side_enqueue_test.cpp (renamed from test/TextToBinary.DeviceSideEnqueue.cpp)4
-rw-r--r--test/text_to_binary.extension_test.cpp (renamed from test/TextToBinary.Extension.cpp)4
-rw-r--r--test/text_to_binary.function_test.cpp (renamed from test/TextToBinary.Function.cpp)4
-rw-r--r--test/text_to_binary.group_test.cpp (renamed from test/TextToBinary.Group.cpp)4
-rw-r--r--test/text_to_binary.image_test.cpp (renamed from test/TextToBinary.Image.cpp)4
-rw-r--r--test/text_to_binary.literal_test.cpp (renamed from test/TextToBinary.Literal.cpp)2
-rw-r--r--test/text_to_binary.memory_test.cpp (renamed from test/TextToBinary.Memory.cpp)4
-rw-r--r--test/text_to_binary.misc_test.cpp (renamed from test/TextToBinary.Miscellaneous.cpp)4
-rw-r--r--test/text_to_binary.mode_setting_test.cpp (renamed from test/TextToBinary.ModeSetting.cpp)4
-rw-r--r--test/text_to_binary.pipe_storage_test.cpp (renamed from test/TextToBinary.PipeStorage.cpp)2
-rw-r--r--test/text_to_binary.subgroup_dispatch_test.cpp (renamed from test/TextToBinary.SubgroupDispatch.cpp)4
-rw-r--r--test/text_to_binary.type_declaration_test.cpp (renamed from test/TextToBinary.TypeDeclaration.cpp)4
-rw-r--r--test/text_to_binary_test.cpp (renamed from test/TextToBinary.cpp)4
-rw-r--r--test/text_word_get_test.cpp (renamed from test/TextWordGet.cpp)2
-rw-r--r--test/unit_spirv.cpp (renamed from test/UnitSPIRV.cpp)4
-rw-r--r--test/unit_spirv.h (renamed from test/UnitSPIRV.h)0
-rw-r--r--test/val/CMakeLists.txt37
-rw-r--r--test/val/ValidateID.cpp1925
-rw-r--r--test/val/val_capability_test.cpp (renamed from test/val/Validate.Capability.cpp)27
-rw-r--r--test/val/val_cfg_test.cpp (renamed from test/val/Validate.CFG.cpp)6
-rw-r--r--test/val/val_data_test.cpp464
-rw-r--r--test/val/val_fixtures.cpp (renamed from test/val/ValidateFixtures.cpp)12
-rw-r--r--test/val/val_fixtures.h (renamed from test/val/ValidateFixtures.h)8
-rw-r--r--test/val/val_id_test.cpp2557
-rw-r--r--test/val/val_layout_test.cpp (renamed from test/val/Validate.Layout.cpp)13
-rw-r--r--test/val/val_limits_test.cpp78
-rw-r--r--test/val/val_ssa_test.cpp (renamed from test/val/Validate.SSA.cpp)32
-rw-r--r--test/val/val_state_test.cpp (renamed from test/val/ValidationState.cpp)7
-rw-r--r--test/val/val_storage_test.cpp (renamed from test/val/Validate.Storage.cpp)2
119 files changed, 4402 insertions, 2408 deletions
diff --git a/examples/cpp-interface/CMakeLists.txt b/examples/cpp-interface/CMakeLists.txt
index 4e98dede..14f99376 100644
--- a/examples/cpp-interface/CMakeLists.txt
+++ b/examples/cpp-interface/CMakeLists.txt
@@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-add_executable(spirv-tools-cpp-example main.cpp)
-spvtools_default_compile_options(spirv-tools-cpp-example)
-target_link_libraries(spirv-tools-cpp-example PRIVATE SPIRV-Tools-opt)
+if (NOT ${SPIRV_SKIP_EXECUTABLES})
+ add_executable(spirv-tools-cpp-example main.cpp)
+ spvtools_default_compile_options(spirv-tools-cpp-example)
+ target_link_libraries(spirv-tools-cpp-example PRIVATE SPIRV-Tools-opt)
+endif()
diff --git a/include/spirv-tools/libspirv.h b/include/spirv-tools/libspirv.h
index 84a3b29d..ac63e9be 100644
--- a/include/spirv-tools/libspirv.h
+++ b/include/spirv-tools/libspirv.h
@@ -53,6 +53,7 @@ typedef enum spv_result_t {
SPV_ERROR_INVALID_CFG = -11,
SPV_ERROR_INVALID_LAYOUT = -12,
SPV_ERROR_INVALID_CAPABILITY = -13,
+ SPV_ERROR_INVALID_DATA = -14, // Indicates data rules validation failure.
SPV_FORCE_32_BIT_ENUM(spv_result_t)
} spv_result_t;
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index 0324aea9..78202d3a 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -126,6 +126,7 @@ set(SPIRV_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/name_mapper.h
${CMAKE_CURRENT_SOURCE_DIR}/opcode.h
${CMAKE_CURRENT_SOURCE_DIR}/operand.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/parsed_operand.h
${CMAKE_CURRENT_SOURCE_DIR}/print.h
${CMAKE_CURRENT_SOURCE_DIR}/spirv_constant.h
${CMAKE_CURRENT_SOURCE_DIR}/spirv_definition.h
@@ -142,12 +143,12 @@ set(SPIRV_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/diagnostic.cpp
${CMAKE_CURRENT_SOURCE_DIR}/disassemble.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ext_inst.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/instruction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libspirv.cpp
${CMAKE_CURRENT_SOURCE_DIR}/message.cpp
${CMAKE_CURRENT_SOURCE_DIR}/name_mapper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/opcode.cpp
${CMAKE_CURRENT_SOURCE_DIR}/operand.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/parsed_operand.cpp
${CMAKE_CURRENT_SOURCE_DIR}/print.cpp
${CMAKE_CURRENT_SOURCE_DIR}/software_version.cpp
${CMAKE_CURRENT_SOURCE_DIR}/spirv_endian.cpp
@@ -159,12 +160,13 @@ set(SPIRV_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/validate_cfg.cpp
${CMAKE_CURRENT_SOURCE_DIR}/validate_id.cpp
${CMAKE_CURRENT_SOURCE_DIR}/validate_instruction.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/validate_datarules.cpp
${CMAKE_CURRENT_SOURCE_DIR}/validate_layout.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/val/BasicBlock.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/val/Construct.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/val/Function.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/val/Instruction.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/val/ValidationState.cpp)
+ ${CMAKE_CURRENT_SOURCE_DIR}/val/basic_block.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/val/construct.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/val/function.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/val/instruction.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/val/validation_state.cpp)
# The software_version.cpp file includes build-version.inc.
# Rebuild the software_version.cpp object file if it is older than
diff --git a/source/disassemble.cpp b/source/disassemble.cpp
index 267ed172..cbec78ad 100644
--- a/source/disassemble.cpp
+++ b/source/disassemble.cpp
@@ -28,6 +28,7 @@
#include "ext_inst.h"
#include "name_mapper.h"
#include "opcode.h"
+#include "parsed_operand.h"
#include "print.h"
#include "spirv-tools/libspirv.h"
#include "spirv_constant.h"
@@ -229,48 +230,8 @@ void Disassembler::EmitOperand(const spv_parsed_instruction_t& inst,
case SPV_OPERAND_TYPE_LITERAL_INTEGER:
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER: {
SetRed();
- if (operand.num_words == 1) {
- switch (operand.number_kind) {
- case SPV_NUMBER_SIGNED_INT:
- stream_ << int32_t(word);
- break;
- case SPV_NUMBER_UNSIGNED_INT:
- stream_ << word;
- break;
- case SPV_NUMBER_FLOATING:
- if (operand.number_bit_width == 16) {
- stream_ << spvutils::FloatProxy<spvutils::Float16>(
- uint16_t(word & 0xFFFF));
- } else {
- // Assume 32-bit floats.
- stream_ << spvutils::FloatProxy<float>(word);
- }
- break;
- default:
- assert(false && "Unreachable");
- }
- } else if (operand.num_words == 2) {
- // Multi-word numbers are presented with lower order words first.
- uint64_t bits =
- uint64_t(word) | (uint64_t(inst.words[operand.offset + 1]) << 32);
- switch (operand.number_kind) {
- case SPV_NUMBER_SIGNED_INT:
- stream_ << int64_t(bits);
- break;
- case SPV_NUMBER_UNSIGNED_INT:
- stream_ << bits;
- break;
- case SPV_NUMBER_FLOATING:
- // Assume only 64-bit floats.
- stream_ << spvutils::FloatProxy<double>(bits);
- break;
- default:
- assert(false && "Unreachable");
- }
- } else {
- // TODO(dneto): Support more than 64-bits at a time.
- assert(false && "Unhandled");
- }
+ libspirv::EmitNumericLiteral(&stream_, inst, operand);
+ ResetColor();
} break;
case SPV_OPERAND_TYPE_LITERAL_STRING: {
stream_ << "\"";
diff --git a/source/enum_set.h b/source/enum_set.h
index 2ca62517..6f9be32c 100644
--- a/source/enum_set.h
+++ b/source/enum_set.h
@@ -84,7 +84,7 @@ class EnumSet {
bool Contains(uint32_t word) const {
// We shouldn't call Overflow() since this is a const method.
if (auto bits = AsMask(word)) {
- return mask_ & bits;
+ return (mask_ & bits) != 0;
} else if (auto overflow = overflow_.get()) {
return overflow->find(word) != overflow->end();
}
diff --git a/source/instruction.cpp b/source/instruction.cpp
deleted file mode 100644
index 8436fdca..00000000
--- a/source/instruction.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2015-2016 The Khronos Group Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "instruction.h"
-
-void spvInstructionAddWord(spv_instruction_t* inst, uint32_t value) {
- inst->words.push_back(value);
-}
-
diff --git a/source/instruction.h b/source/instruction.h
index ff735e71..5dd4d139 100644
--- a/source/instruction.h
+++ b/source/instruction.h
@@ -42,6 +42,8 @@ struct spv_instruction_t {
};
// Appends a word to an instruction, without checking for overflow.
-void spvInstructionAddWord(spv_instruction_t* inst, uint32_t value);
+inline void spvInstructionAddWord(spv_instruction_t* inst, uint32_t value) {
+ inst->words.push_back(value);
+}
#endif // LIBSPIRV_INSTRUCTION_H_
diff --git a/source/name_mapper.cpp b/source/name_mapper.cpp
index df632e1f..43412a30 100644
--- a/source/name_mapper.cpp
+++ b/source/name_mapper.cpp
@@ -25,6 +25,8 @@
#include "spirv-tools/libspirv.h"
#include "spirv/1.1/spirv.h"
+#include "parsed_operand.h"
+
namespace {
// Converts a uint32_t to its string decimal representation.
@@ -287,6 +289,16 @@ spv_result_t FriendlyNameMapper::ParseInstruction(
// are a struct and then give the raw Id number.
SaveName(result_id, std::string("_struct_") + to_string(result_id));
break;
+ case SpvOpConstant: {
+ std::ostringstream value;
+ EmitNumericLiteral(&value, inst, inst.operands[2]);
+ auto value_str = value.str();
+ // Use 'n' to signify negative. Other invalid characters will be mapped
+ // to underscore.
+ for (auto& c : value_str)
+ if (c == '-') c = 'n';
+ SaveName(result_id, NameForId(inst.type_id) + "_" + value_str);
+ } break;
default:
// If this instruction otherwise defines an Id, then save a mapping for
// it. This is needed to ensure uniqueness in there is an OpName with
diff --git a/source/name_mapper.h b/source/name_mapper.h
index 89eb93ea..12078b66 100644
--- a/source/name_mapper.h
+++ b/source/name_mapper.h
@@ -57,6 +57,7 @@ NameMapper GetTrivialNameMapper();
// - A struct type maps to "_struct_" followed by the raw Id number. That's
// pretty simplistic, but workable.
// - A built-in variable maps to its GLSL variable name.
+// - Numeric literals in OpConstant map to a human-friendly name.
class FriendlyNameMapper {
public:
// Construct a friendly name mapper, and determine friendly names for each
diff --git a/source/parsed_operand.cpp b/source/parsed_operand.cpp
new file mode 100644
index 00000000..6f3ffe8d
--- /dev/null
+++ b/source/parsed_operand.cpp
@@ -0,0 +1,75 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file contains utility functions for spv_parsed_operand_t.
+
+#include "parsed_operand.h"
+
+#include <cassert>
+#include "util/hex_float.h"
+
+namespace libspirv {
+
+void EmitNumericLiteral(std::ostream* out, const spv_parsed_instruction_t& inst,
+ const spv_parsed_operand_t& operand) {
+ assert(operand.type == SPV_OPERAND_TYPE_LITERAL_INTEGER ||
+ operand.type == SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER);
+ assert(1 <= operand.num_words);
+ assert(operand.num_words <= 2);
+
+ const uint32_t word = inst.words[operand.offset];
+ if (operand.num_words == 1) {
+ switch (operand.number_kind) {
+ case SPV_NUMBER_SIGNED_INT:
+ *out << int32_t(word);
+ break;
+ case SPV_NUMBER_UNSIGNED_INT:
+ *out << word;
+ break;
+ case SPV_NUMBER_FLOATING:
+ if (operand.number_bit_width == 16) {
+ *out << spvutils::FloatProxy<spvutils::Float16>(
+ uint16_t(word & 0xFFFF));
+ } else {
+ // Assume 32-bit floats.
+ *out << spvutils::FloatProxy<float>(word);
+ }
+ break;
+ default:
+ assert(false && "Unreachable");
+ }
+ } else if (operand.num_words == 2) {
+ // Multi-word numbers are presented with lower order words first.
+ uint64_t bits =
+ uint64_t(word) | (uint64_t(inst.words[operand.offset + 1]) << 32);
+ switch (operand.number_kind) {
+ case SPV_NUMBER_SIGNED_INT:
+ *out << int64_t(bits);
+ break;
+ case SPV_NUMBER_UNSIGNED_INT:
+ *out << bits;
+ break;
+ case SPV_NUMBER_FLOATING:
+ // Assume only 64-bit floats.
+ *out << spvutils::FloatProxy<double>(bits);
+ break;
+ default:
+ assert(false && "Unreachable");
+ }
+ } else {
+ // TODO(dneto): Support more than 64-bits at a time.
+ assert(false && "Unhandled");
+ }
+}
+} // namespace libspirv
diff --git a/source/parsed_operand.h b/source/parsed_operand.h
new file mode 100644
index 00000000..8c2fd85c
--- /dev/null
+++ b/source/parsed_operand.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef LIBSPIRV_PARSED_OPERAND_H_
+#define LIBSPIRV_PARSED_OPERAND_H_
+
+#include <ostream>
+#include "spirv-tools/libspirv.h"
+
+namespace libspirv {
+
+// Emits the numeric literal representation of the given instruction operand
+// to the stream. The operand must be of numeric type. If integral it may
+// be up to 64 bits wide. If floating point, then it must be 16, 32, or 64
+// bits wide.
+void EmitNumericLiteral(std::ostream* out, const spv_parsed_instruction_t& inst,
+ const spv_parsed_operand_t& operand);
+
+} // namespace libspirv
+
+#endif // LIBSPIRV_BINARY_H_
diff --git a/source/val/BasicBlock.cpp b/source/val/basic_block.cpp
index 55483b94..0bfc4f12 100644
--- a/source/val/BasicBlock.cpp
+++ b/source/val/basic_block.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "BasicBlock.h"
+#include "val/basic_block.h"
#include <algorithm>
#include <utility>
diff --git a/source/val/BasicBlock.h b/source/val/basic_block.h
index 29d730cb..29d730cb 100644
--- a/source/val/BasicBlock.h
+++ b/source/val/basic_block.h
diff --git a/source/val/Construct.cpp b/source/val/construct.cpp
index da87b4d3..4270063f 100644
--- a/source/val/Construct.cpp
+++ b/source/val/construct.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "val/Construct.h"
+#include "val/construct.h"
#include <cassert>
#include <cstddef>
diff --git a/source/val/Construct.h b/source/val/construct.h
index 09cf9dff..09cf9dff 100644
--- a/source/val/Construct.h
+++ b/source/val/construct.h
diff --git a/source/val/Function.cpp b/source/val/function.cpp
index 223fcb1e..e033bfe8 100644
--- a/source/val/Function.cpp
+++ b/source/val/function.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "val/Function.h"
+#include "val/function.h"
#include <cassert>
@@ -21,8 +21,8 @@
#include <unordered_map>
#include <utility>
-#include "val/BasicBlock.h"
-#include "val/Construct.h"
+#include "val/basic_block.h"
+#include "val/construct.h"
#include "validate.h"
using std::ignore;
diff --git a/source/val/Function.h b/source/val/function.h
index dc5c3242..bd993c79 100644
--- a/source/val/Function.h
+++ b/source/val/function.h
@@ -15,16 +15,16 @@
#ifndef LIBSPIRV_VAL_FUNCTION_H_
#define LIBSPIRV_VAL_FUNCTION_H_
-#include <list>
#include <functional>
+#include <list>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "spirv-tools/libspirv.h"
#include "spirv/1.1/spirv.h"
-#include "val/BasicBlock.h"
-#include "val/Construct.h"
+#include "val/basic_block.h"
+#include "val/construct.h"
namespace libspirv {
diff --git a/source/val/Instruction.cpp b/source/val/instruction.cpp
index 02be245a..56bd37f5 100644
--- a/source/val/Instruction.cpp
+++ b/source/val/instruction.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "val/Instruction.h"
+#include "val/instruction.h"
#include <utility>
diff --git a/source/val/Instruction.h b/source/val/instruction.h
index 1d8fe91a..1d8fe91a 100644
--- a/source/val/Instruction.h
+++ b/source/val/instruction.h
diff --git a/source/val/ValidationState.cpp b/source/val/validation_state.cpp
index 13684160..c69749cb 100644
--- a/source/val/ValidationState.cpp
+++ b/source/val/validation_state.cpp
@@ -12,13 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "val/ValidationState.h"
+#include "val/validation_state.h"
#include <cassert>
-#include "val/BasicBlock.h"
-#include "val/Construct.h"
-#include "val/Function.h"
+#include "val/basic_block.h"
+#include "val/construct.h"
+#include "val/function.h"
using std::deque;
using std::make_pair;
@@ -207,6 +207,15 @@ spv_result_t ValidationState_t::RemoveIfForwardDeclared(uint32_t id) {
return SPV_SUCCESS;
}
+spv_result_t ValidationState_t::RegisterForwardPointer(uint32_t id) {
+ forward_pointer_ids_.insert(id);
+ return SPV_SUCCESS;
+}
+
+bool ValidationState_t::IsForwardPointer(uint32_t id) const {
+ return (forward_pointer_ids_.find(id) != forward_pointer_ids_.end());
+}
+
void ValidationState_t::AssignNameToId(uint32_t id, string name) {
operand_names_[id] = name;
}
@@ -385,5 +394,38 @@ void ValidationState_t::RegisterInstruction(
if (id) {
all_definitions_.insert(make_pair(id, &ordered_instructions_.back()));
}
+
+ // If the instruction is using an OpTypeSampledImage as an operand, it should
+ // be recorded. The validator will ensure that all usages of an
+ // OpTypeSampledImage and its definition are in the same basic block.
+ for (uint16_t i = 0; i < inst.num_operands; ++i) {
+ const spv_parsed_operand_t& operand = inst.operands[i];
+ if (SPV_OPERAND_TYPE_ID == operand.type) {
+ const uint32_t operand_word = inst.words[operand.offset];
+ Instruction* operand_inst = FindDef(operand_word);
+ if (operand_inst && SpvOpSampledImage == operand_inst->opcode()) {
+ RegisterSampledImageConsumer(operand_word, inst.result_id);
+ }
+ }
+ }
}
+
+std::vector<uint32_t> ValidationState_t::getSampledImageConsumers(
+ uint32_t sampled_image_id) const {
+ std::vector<uint32_t> result;
+ auto iter = sampled_image_consumers_.find(sampled_image_id);
+ if (iter != sampled_image_consumers_.end()) {
+ result = iter->second;
+ }
+ return result;
+}
+
+void ValidationState_t::RegisterSampledImageConsumer(uint32_t sampled_image_id,
+ uint32_t consumer_id) {
+ sampled_image_consumers_[sampled_image_id].push_back(consumer_id);
+}
+
+uint32_t ValidationState_t::getIdBound() const { return id_bound_; }
+
+void ValidationState_t::setIdBound(const uint32_t bound) { id_bound_ = bound; }
} /// namespace libspirv
diff --git a/source/val/ValidationState.h b/source/val/validation_state.h
index ff23d05e..7e69a9d0 100644
--- a/source/val/ValidationState.h
+++ b/source/val/validation_state.h
@@ -27,8 +27,8 @@
#include "spirv-tools/libspirv.h"
#include "spirv/1.1/spirv.h"
#include "spirv_definition.h"
-#include "val/Function.h"
-#include "val/Instruction.h"
+#include "val/function.h"
+#include "val/instruction.h"
namespace libspirv {
@@ -64,6 +64,12 @@ class ValidationState_t {
/// Removes a forward declared ID if it has been defined
spv_result_t RemoveIfForwardDeclared(uint32_t id);
+ /// Registers an ID as a forward pointer
+ spv_result_t RegisterForwardPointer(uint32_t id);
+
+ /// Returns whether or not an ID is a forward pointer
+ bool IsForwardPointer(uint32_t id) const;
+
/// Assigns a name to an ID
void AssignNameToId(uint32_t id, std::string name);
@@ -72,6 +78,12 @@ class ValidationState_t {
/// the OpName instruction
std::string getIdName(uint32_t id) const;
+ /// Accessor function for ID bound.
+ uint32_t getIdBound() const;
+
+ /// Mutator function for ID bound.
+ void setIdBound(uint32_t bound);
+
/// Like getIdName but does not display the id if the \p id has a name
std::string getIdOrName(uint32_t id) const;
@@ -173,6 +185,14 @@ class ValidationState_t {
return all_definitions_;
}
+ /// Returns a vector containing the Ids of instructions that consume the given
+ /// SampledImage id.
+ std::vector<uint32_t> getSampledImageConsumers(uint32_t id) const;
+
+ /// Records cons_id as a consumer of sampled_image_id.
+ void RegisterSampledImageConsumer(uint32_t sampled_image_id,
+ uint32_t cons_id);
+
private:
ValidationState_t(const ValidationState_t&);
@@ -184,6 +204,13 @@ class ValidationState_t {
/// IDs which have been forward declared but have not been defined
std::unordered_set<uint32_t> unresolved_forward_ids_;
+ /// IDs that have been declared as forward pointers.
+ std::unordered_set<uint32_t> forward_pointer_ids_;
+
+ /// Stores a vector of instructions that use the result of a given
+ /// OpSampledImage instruction.
+ std::unordered_map<uint32_t, std::vector<uint32_t>> sampled_image_consumers_;
+
/// A map of operand IDs and their names defined by the OpName instruction
std::unordered_map<uint32_t, std::string> operand_names_;
@@ -206,6 +233,9 @@ class ValidationState_t {
/// IDs that are entry points, ie, arguments to OpEntryPoint.
std::vector<uint32_t> entry_points_;
+ /// ID Bound from the Header
+ uint32_t id_bound_;
+
AssemblyGrammar grammar_;
SpvAddressingModel addressing_model_;
diff --git a/source/validate.cpp b/source/validate.cpp
index 71d02352..45ae5a45 100644
--- a/source/validate.cpp
+++ b/source/validate.cpp
@@ -32,9 +32,9 @@
#include "spirv-tools/libspirv.h"
#include "spirv_constant.h"
#include "spirv_endian.h"
-#include "val/Construct.h"
-#include "val/Function.h"
-#include "val/ValidationState.h"
+#include "val/construct.h"
+#include "val/function.h"
+#include "val/validation_state.h"
using std::function;
using std::ostream_iterator;
@@ -47,6 +47,7 @@ using std::vector;
using libspirv::CfgPass;
using libspirv::InstructionPass;
using libspirv::ModuleLayoutPass;
+using libspirv::DataRulesPass;
using libspirv::IdPass;
using libspirv::ValidationState_t;
@@ -68,14 +69,15 @@ spv_result_t spvValidateIDs(const spv_instruction_t* pInsts,
namespace {
// TODO(umar): Validate header
-// TODO(umar): The Id bound should be validated also. But you can only do that
-// after you've seen all the instructions in the module.
// TODO(umar): The binary parser validates the magic word, and the length of the
// header, but nothing else.
spv_result_t setHeader(void* user_data, spv_endianness_t endian, uint32_t magic,
uint32_t version, uint32_t generator, uint32_t id_bound,
uint32_t reserved) {
- (void)user_data;
+ // Record the ID bound so that the validator can ensure no ID is out of bound.
+ ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
+ _.setIdBound(id_bound);
+
(void)endian;
(void)magic;
(void)version;
@@ -122,7 +124,7 @@ spv_result_t ProcessInstruction(void* user_data,
_.entry_points().push_back(inst->words[2]);
DebugInstructionPass(_, inst);
- // TODO(umar): Perform data rules pass
+ if (auto error = DataRulesPass(_, inst)) return error;
if (auto error = IdPass(_, inst)) return error;
if (auto error = ModuleLayoutPass(_, inst)) return error;
if (auto error = CfgPass(_, inst)) return error;
@@ -229,7 +231,7 @@ spv_result_t spvValidateBinary(const spv_const_context context,
auto id_str = ss.str();
return vstate.diag(SPV_ERROR_INVALID_ID)
- << "The following forward referenced IDs have not be defined:\n"
+ << "The following forward referenced IDs have not been defined:\n"
<< id_str.substr(0, id_str.size() - 1);
}
diff --git a/source/validate.h b/source/validate.h
index a19e911a..258b0ebb 100644
--- a/source/validate.h
+++ b/source/validate.h
@@ -141,6 +141,12 @@ spv_result_t CfgPass(ValidationState_t& _,
/// Performs Id and SSA validation of a module
spv_result_t IdPass(ValidationState_t& _, const spv_parsed_instruction_t* inst);
+/// Performs validation of the Data Rules subsection of 2.16.1 Universal
+/// Validation Rules.
+/// TODO(ehsann): add more comments here as more validation code is added.
+spv_result_t DataRulesPass(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst);
+
/// Performs instruction validation.
spv_result_t InstructionPass(ValidationState_t& _,
const spv_parsed_instruction_t* inst);
diff --git a/source/validate_cfg.cpp b/source/validate_cfg.cpp
index 78436975..b01b88d0 100644
--- a/source/validate_cfg.cpp
+++ b/source/validate_cfg.cpp
@@ -26,10 +26,10 @@
#include <utility>
#include <vector>
-#include "val/BasicBlock.h"
-#include "val/Construct.h"
-#include "val/Function.h"
-#include "val/ValidationState.h"
+#include "val/basic_block.h"
+#include "val/construct.h"
+#include "val/function.h"
+#include "val/validation_state.h"
using std::find;
using std::function;
diff --git a/source/validate_datarules.cpp b/source/validate_datarules.cpp
new file mode 100644
index 00000000..3d50328c
--- /dev/null
+++ b/source/validate_datarules.cpp
@@ -0,0 +1,272 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Ensures Data Rules are followed according to the specifications.
+
+#include "validate.h"
+
+#include <cassert>
+#include <sstream>
+#include <string>
+
+#include "diagnostic.h"
+#include "opcode.h"
+#include "operand.h"
+#include "val/instruction.h"
+#include "val/validation_state.h"
+
+using libspirv::CapabilitySet;
+using libspirv::DiagnosticStream;
+using libspirv::ValidationState_t;
+
+namespace {
+
+// Validates that the number of components in the vector is valid.
+// Vector types can only be parameterized as having 2, 3, or 4 components.
+// If the Vector16 capability is added, 8 and 16 components are also allowed.
+spv_result_t ValidateVecNumComponents(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst) {
+ // Operand 2 specifies the number of components in the vector.
+ const uint32_t num_components = inst->words[inst->operands[2].offset];
+ if (num_components == 2 || num_components == 3 || num_components == 4) {
+ return SPV_SUCCESS;
+ }
+ if (num_components == 8 || num_components == 16) {
+ if (_.HasCapability(SpvCapabilityVector16)) {
+ return SPV_SUCCESS;
+ }
+ return _.diag(SPV_ERROR_INVALID_DATA)
+ << "Having " << num_components << " components for "
+ << spvOpcodeString(static_cast<SpvOp>(inst->opcode))
+ << " requires the Vector16 capability";
+ }
+ return _.diag(SPV_ERROR_INVALID_DATA)
+ << "Illegal number of components (" << num_components << ") for "
+ << spvOpcodeString(static_cast<SpvOp>(inst->opcode));
+}
+
+// Validates that the number of bits specifed for a float type is valid.
+// Scalar floating-point types can be parameterized only with 32-bits.
+// Float16 capability allows using a 16-bit OpTypeFloat.
+// Float16Buffer capability allows creation of a 16-bit OpTypeFloat.
+// Float64 capability allows using a 64-bit OpTypeFloat.
+spv_result_t ValidateFloatSize(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst) {
+ // Operand 1 is the number of bits for this float
+ const uint32_t num_bits = inst->words[inst->operands[1].offset];
+ if (num_bits == 32) {
+ return SPV_SUCCESS;
+ }
+ if (num_bits == 16) {
+ if (_.HasCapability(SpvCapabilityFloat16) ||
+ _.HasCapability(SpvCapabilityFloat16Buffer)) {
+ return SPV_SUCCESS;
+ }
+ return _.diag(SPV_ERROR_INVALID_DATA)
+ << "Using a 16-bit floating point "
+ << "type requires the Float16 or Float16Buffer capability.";
+ }
+ if (num_bits == 64) {
+ if (_.HasCapability(SpvCapabilityFloat64)) {
+ return SPV_SUCCESS;
+ }
+ return _.diag(SPV_ERROR_INVALID_DATA)
+ << "Using a 64-bit floating point "
+ << "type requires the Float64 capability.";
+ }
+ return _.diag(SPV_ERROR_INVALID_DATA)
+ << "Invalid number of bits (" << num_bits << ") used for OpTypeFloat.";
+}
+
+// Validates that the number of bits specified for an Int type is valid.
+// Scalar integer types can be parameterized only with 32-bits.
+// Int8, Int16, and Int64 capabilities allow using 8-bit, 16-bit, and 64-bit
+// integers, respectively.
+spv_result_t ValidateIntSize(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst) {
+ // Operand 1 is the number of bits for this integer.
+ const uint32_t num_bits = inst->words[inst->operands[1].offset];
+ if (num_bits == 32) {
+ return SPV_SUCCESS;
+ }
+ if (num_bits == 8) {
+ if (_.HasCapability(SpvCapabilityInt8)) {
+ return SPV_SUCCESS;
+ }
+ return _.diag(SPV_ERROR_INVALID_DATA)
+ << "Using an 8-bit integer type requires the Int8 capability.";
+ }
+ if (num_bits == 16) {
+ if (_.HasCapability(SpvCapabilityInt16)) {
+ return SPV_SUCCESS;
+ }
+ return _.diag(SPV_ERROR_INVALID_DATA)
+ << "Using a 16-bit integer type requires the Int16 capability.";
+ }
+ if (num_bits == 64) {
+ if (_.HasCapability(SpvCapabilityInt64)) {
+ return SPV_SUCCESS;
+ }
+ return _.diag(SPV_ERROR_INVALID_DATA)
+ << "Using a 64-bit integer type requires the Int64 capability.";
+ }
+ return _.diag(SPV_ERROR_INVALID_DATA) << "Invalid number of bits ("
+ << num_bits << ") used for OpTypeInt.";
+}
+
+// Validates that the matrix is parameterized with floating-point types.
+spv_result_t ValidateMatrixColumnType(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst) {
+ // Find the component type of matrix columns (must be vector).
+ // Operand 1 is the <id> of the type specified for matrix columns.
+ auto type_id = inst->words[inst->operands[1].offset];
+ auto col_type_instr = _.FindDef(type_id);
+ if (col_type_instr->opcode() != SpvOpTypeVector) {
+ return _.diag(SPV_ERROR_INVALID_ID)
+ << "Columns in a matrix must be of type vector.";
+ }
+
+ // Trace back once more to find out the type of components in the vector.
+ // Operand 1 is the <id> of the type of data in the vector.
+ auto comp_type_id =
+ col_type_instr->words()[col_type_instr->operands()[1].offset];
+ auto comp_type_instruction = _.FindDef(comp_type_id);
+ if (comp_type_instruction->opcode() != SpvOpTypeFloat) {
+ return _.diag(SPV_ERROR_INVALID_DATA) << "Matrix types can only be "
+ "parameterized with "
+ "floating-point types.";
+ }
+ return SPV_SUCCESS;
+}
+
+// Validates that the matrix has 2,3, or 4 columns.
+spv_result_t ValidateMatrixNumCols(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst) {
+ // Operand 2 is the number of columns in the matrix.
+ const uint32_t num_cols = inst->words[inst->operands[2].offset];
+ if (num_cols != 2 && num_cols != 3 && num_cols != 4) {
+ return _.diag(SPV_ERROR_INVALID_DATA) << "Matrix types can only be "
+ "parameterized as having only 2, "
+ "3, or 4 columns.";
+ }
+ return SPV_SUCCESS;
+}
+
+// Validates that OpSpecConstant specializes to either int or float type.
+spv_result_t ValidateSpecConstNumerical(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst) {
+ // Operand 0 is the <id> of the type that we're specializing to.
+ auto type_id = inst->words[inst->operands[0].offset];
+ auto type_instruction = _.FindDef(type_id);
+ auto type_opcode = type_instruction->opcode();
+ if (type_opcode != SpvOpTypeInt && type_opcode != SpvOpTypeFloat) {
+ return _.diag(SPV_ERROR_INVALID_DATA) << "Specialization constant must be "
+ "an integer or floating-point "
+ "number.";
+ }
+ return SPV_SUCCESS;
+}
+
+// Validates that OpSpecConstantTrue and OpSpecConstantFalse specialize to bool.
+spv_result_t ValidateSpecConstBoolean(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst) {
+ // Find out the type that we're specializing to.
+ auto type_instruction = _.FindDef(inst->type_id);
+ if (type_instruction->opcode() != SpvOpTypeBool) {
+ return _.diag(SPV_ERROR_INVALID_ID) << "Specialization constant must be "
+ "a boolean type.";
+ }
+ return SPV_SUCCESS;
+}
+
+// Records the <id> of the forward pointer to be used for validation.
+spv_result_t ValidateForwardPointer(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst) {
+ // Record the <id> (which is operand 0) to ensure it's used properly.
+ // OpTypeStruct can only include undefined pointers that are
+ // previously declared as a ForwardPointer
+ return (_.RegisterForwardPointer(inst->words[inst->operands[0].offset]));
+}
+
+// Validates that any undefined component of the struct is a forward pointer.
+// It is valid to declare a forward pointer, and use its <id> as one of the
+// components of a struct.
+spv_result_t ValidateStruct(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst) {
+ // Struct components are operands 1, 2, etc.
+ for (unsigned i = 1; i < inst->num_operands; i++) {
+ auto type_id = inst->words[inst->operands[i].offset];
+ auto type_instruction = _.FindDef(type_id);
+ if (type_instruction == nullptr && !_.IsForwardPointer(type_id)) {
+ return _.diag(SPV_ERROR_INVALID_ID)
+ << "Forward reference operands in an OpTypeStruct must first be "
+ "declared using OpTypeForwardPointer.";
+ }
+ }
+ return SPV_SUCCESS;
+}
+
+} // anonymous namespace
+
+namespace libspirv {
+
+// Validates that Data Rules are followed according to the specifications.
+// (Data Rules subsection of 2.16.1 Universal Validation Rules)
+spv_result_t DataRulesPass(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst) {
+ switch (inst->opcode) {
+ case SpvOpTypeVector: {
+ if (auto error = ValidateVecNumComponents(_, inst)) return error;
+ break;
+ }
+ case SpvOpTypeFloat: {
+ if (auto error = ValidateFloatSize(_, inst)) return error;
+ break;
+ }
+ case SpvOpTypeInt: {
+ if (auto error = ValidateIntSize(_, inst)) return error;
+ break;
+ }
+ case SpvOpTypeMatrix: {
+ if (auto error = ValidateMatrixColumnType(_, inst)) return error;
+ if (auto error = ValidateMatrixNumCols(_, inst)) return error;
+ break;
+ }
+ // TODO(ehsan): Add OpSpecConstantComposite validation code.
+ // TODO(ehsan): Add OpSpecConstantOp validation code (if any).
+ case SpvOpSpecConstant: {
+ if (auto error = ValidateSpecConstNumerical(_, inst)) return error;
+ break;
+ }
+ case SpvOpSpecConstantFalse:
+ case SpvOpSpecConstantTrue: {
+ if (auto error = ValidateSpecConstBoolean(_, inst)) return error;
+ break;
+ }
+ case SpvOpTypeForwardPointer: {
+ if (auto error = ValidateForwardPointer(_, inst)) return error;
+ break;
+ }
+ case SpvOpTypeStruct: {
+ if (auto error = ValidateStruct(_, inst)) return error;
+ break;
+ }
+ // TODO(ehsan): add more data rules validation here.
+ default: { break; }
+ }
+
+ return SPV_SUCCESS;
+}
+
+} // namespace libspirv
diff --git a/source/validate_id.cpp b/source/validate_id.cpp
index bd7f2067..a486362f 100644
--- a/source/validate_id.cpp
+++ b/source/validate_id.cpp
@@ -27,8 +27,8 @@
#include "message.h"
#include "opcode.h"
#include "spirv-tools/libspirv.h"
-#include "val/Function.h"
-#include "val/ValidationState.h"
+#include "val/function.h"
+#include "val/validation_state.h"
using libspirv::ValidationState_t;
using std::function;
@@ -355,13 +355,35 @@ bool idUsage::isValid<SpvOpTypeStruct>(const spv_instruction_t* inst,
const spv_opcode_desc) {
for (size_t memberTypeIndex = 2; memberTypeIndex < inst->words.size();
++memberTypeIndex) {
- auto memberType = module_.FindDef(inst->words[memberTypeIndex]);
+ auto memberTypeId = inst->words[memberTypeIndex];
+ auto memberType = module_.FindDef(memberTypeId);
if (!memberType || !spvOpcodeGeneratesType(memberType->opcode())) {
DIAG(memberTypeIndex) << "OpTypeStruct Member Type <id> '"
<< inst->words[memberTypeIndex]
<< "' is not a type.";
return false;
}
+ if (memberType && module_.IsForwardPointer(memberTypeId)) {
+ if (memberType->opcode() != SpvOpTypePointer) {
+ DIAG(memberTypeIndex) << "Found a forward reference to a non-pointer "
+ "type in OpTypeStruct instruction.";
+ return false;
+ }
+ // If we're dealing with a forward pointer:
+ // Find out the type that the pointer is pointing to (must be struct)
+ // word 3 is the <id> of the type being pointed to.
+ auto typePointingTo = module_.FindDef(memberType->words()[3]);
+ if (typePointingTo && typePointingTo->opcode() != SpvOpTypeStruct) {
+ // Forward declared operands of a struct may only point to a struct.
+ DIAG(memberTypeIndex)
+ << "A forward reference operand in an OpTypeStruct must be an "
+ "OpTypePointer that points to an OpTypeStruct. "
+ "Found OpTypePointer that points to Op"
+ << spvOpcodeString(static_cast<SpvOp>(typePointingTo->opcode()))
+ << ".";
+ return false;
+ }
+ }
}
return true;
}
@@ -591,7 +613,8 @@ bool idUsage::isValid<SpvOpConstantComposite>(const spv_instruction_t* inst,
constituentIndex < inst->words.size();
constituentIndex++, memberIndex++) {
auto constituent = module_.FindDef(inst->words[constituentIndex]);
- if (!constituent || !spvOpcodeIsConstantOrUndef(constituent->opcode())) {
+ if (!constituent ||
+ !spvOpcodeIsConstantOrUndef(constituent->opcode())) {
DIAG(constituentIndex) << "OpConstantComposite Constituent <id> '"
<< inst->words[constituentIndex]
<< "' is not a constant or undef.";
@@ -710,11 +733,246 @@ bool idUsage::isValid<SpvOpSpecConstantFalse>(const spv_instruction_t* inst,
return true;
}
-#if 0
template <>
-bool idUsage::isValid<SpvOpSpecConstantComposite>(
- const spv_instruction_t *inst, const spv_opcode_desc opcodeEntry) {}
-#endif
+bool idUsage::isValid<SpvOpSampledImage>(const spv_instruction_t* inst,
+ const spv_opcode_desc) {
+ auto resultTypeIndex = 2;
+ auto resultID = inst->words[resultTypeIndex];
+ auto sampledImageInstr = module_.FindDef(resultID);
+ // We need to validate 2 things:
+ // * All OpSampledImage instructions must be in the same block in which their
+ // Result <id> are consumed.
+ // * Result <id> from OpSampledImage instructions must not appear as operands
+ // to OpPhi instructions or OpSelect instructions, or any instructions other
+ // than the image lookup and query instructions specified to take an operand
+ // whose type is OpTypeSampledImage.
+ std::vector<uint32_t> consumers =
+ module_.getSampledImageConsumers(resultID);
+ if (!consumers.empty()) {
+ for (auto consumer_id : consumers) {
+ auto consumer_instr = module_.FindDef(consumer_id);
+ auto consumer_opcode = consumer_instr->opcode();
+ if (consumer_instr->block() != sampledImageInstr->block()) {
+ DIAG(resultTypeIndex)
+ << "All OpSampledImage instructions must be in the same block in "
+ "which their Result <id> are consumed. OpSampledImage Result "
+ "Type <id> '"
+ << resultID << "' has a consumer in a different basic "
+ "block. The consumer instruction <id> is '"
+ << consumer_id << "'.";
+ return false;
+ }
+ // TODO: The following check is incomplete. We should also check that the
+ // Sampled Image is not used by instructions that should not take
+ // SampledImage as an argument. We could find the list of valid
+ // instructions by scanning for "Sampled Image" in the operand description
+ // field in the grammar file.
+ if (consumer_opcode == SpvOpPhi || consumer_opcode == SpvOpSelect) {
+ DIAG(resultTypeIndex)
+ << "Result <id> from OpSampledImage instruction must not appear as "
+ "operands of Op"
+ << spvOpcodeString(static_cast<SpvOp>(consumer_opcode)) << "."
+ << " Found result <id> '" << resultID << "' as an operand of <id> '"
+ << consumer_id << "'.";
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+template <>
+bool idUsage::isValid<SpvOpSpecConstantComposite>(const spv_instruction_t* inst,
+ const spv_opcode_desc) {
+ // The result type must be a composite type.
+ auto resultTypeIndex = 1;
+ auto resultType = module_.FindDef(inst->words[resultTypeIndex]);
+ if (!resultType || !spvOpcodeIsComposite(resultType->opcode())) {
+ DIAG(resultTypeIndex) << "OpSpecConstantComposite Result Type <id> '"
+ << inst->words[resultTypeIndex]
+ << "' is not a composite type.";
+ return false;
+ }
+ // Validation checks differ based on the type of composite type.
+ auto constituentCount = inst->words.size() - 3;
+ switch (resultType->opcode()) {
+ // For Vectors, the following must be met:
+ // * Number of constituents in the result type and the vector must match.
+ // * All the components of the vector must have the same type (or specialize
+ // to the same type). OpConstant and OpSpecConstant are allowed.
+ // To check that condition, we check each supplied value argument's type
+ // against the element type of the result type.
+ case SpvOpTypeVector: {
+ auto componentCount = resultType->words()[3];
+ if (componentCount != constituentCount) {
+ DIAG(inst->words.size() - 1)
+ << "OpSpecConstantComposite Constituent <id> count does not match "
+ "Result Type <id> '"
+ << resultType->id() << "'s vector component count.";
+ return false;
+ }
+ auto componentType = module_.FindDef(resultType->words()[2]);
+ assert(componentType);
+ for (size_t constituentIndex = 3; constituentIndex < inst->words.size();
+ constituentIndex++) {
+ auto constituent = module_.FindDef(inst->words[constituentIndex]);
+ if (!constituent ||
+ !spvOpcodeIsConstantOrUndef(constituent->opcode())) {
+ DIAG(constituentIndex) << "OpSpecConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "' is not a constant or undef.";
+ return false;
+ }
+ auto constituentResultType = module_.FindDef(constituent->type_id());
+ if (!constituentResultType ||
+ componentType->opcode() != constituentResultType->opcode()) {
+ DIAG(constituentIndex) << "OpSpecConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "'s type does not match Result Type <id> '"
+ << resultType->id()
+ << "'s vector element type.";
+ return false;
+ }
+ }
+ break;
+ }
+ case SpvOpTypeMatrix: {
+ auto columnCount = resultType->words()[3];
+ if (columnCount != constituentCount) {
+ DIAG(inst->words.size() - 1)
+ << "OpSpecConstantComposite Constituent <id> count does not match "
+ "Result Type <id> '"
+ << resultType->id() << "'s matrix column count.";
+ return false;
+ }
+
+ auto columnType = module_.FindDef(resultType->words()[2]);
+ assert(columnType);
+ auto componentCount = columnType->words()[3];
+ auto componentType = module_.FindDef(columnType->words()[2]);
+ assert(componentType);
+
+ for (size_t constituentIndex = 3; constituentIndex < inst->words.size();
+ constituentIndex++) {
+ auto constituent = module_.FindDef(inst->words[constituentIndex]);
+ auto constituentOpCode = constituent->opcode();
+ if (!constituent ||
+ !(SpvOpSpecConstantComposite == constituentOpCode ||
+ SpvOpConstantComposite == constituentOpCode ||
+ SpvOpUndef == constituentOpCode)) {
+ // The message says "... or undef" because the spec does not say
+ // undef is a constant.
+ DIAG(constituentIndex) << "OpSpecConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "' is not a constant composite or undef.";
+ return false;
+ }
+ auto vector = module_.FindDef(constituent->type_id());
+ assert(vector);
+ if (columnType->opcode() != vector->opcode()) {
+ DIAG(constituentIndex) << "OpSpecConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "' type does not match Result Type <id> '"
+ << resultType->id()
+ << "'s matrix column type.";
+ return false;
+ }
+ auto vectorComponentType = module_.FindDef(vector->words()[2]);
+ assert(vectorComponentType);
+ if (componentType->id() != vectorComponentType->id()) {
+ DIAG(constituentIndex)
+ << "OpSpecConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "' component type does not match Result Type <id> '"
+ << resultType->id() << "'s matrix column component type.";
+ return false;
+ }
+ if (componentCount != vector->words()[3]) {
+ DIAG(constituentIndex)
+ << "OpSpecConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "' vector component count does not match Result Type <id> '"
+ << resultType->id() << "'s vector component count.";
+ return false;
+ }
+ }
+ break;
+ }
+ case SpvOpTypeArray: {
+ auto elementType = module_.FindDef(resultType->words()[2]);
+ assert(elementType);
+ auto length = module_.FindDef(resultType->words()[3]);
+ assert(length);
+ if (length->words()[3] != constituentCount) {
+ DIAG(inst->words.size() - 1)
+ << "OpSpecConstantComposite Constituent count does not match "
+ "Result Type <id> '"
+ << resultType->id() << "'s array length.";
+ return false;
+ }
+ for (size_t constituentIndex = 3; constituentIndex < inst->words.size();
+ constituentIndex++) {
+ auto constituent = module_.FindDef(inst->words[constituentIndex]);
+ if (!constituent ||
+ !spvOpcodeIsConstantOrUndef(constituent->opcode())) {
+ DIAG(constituentIndex) << "OpSpecConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "' is not a constant or undef.";
+ return false;
+ }
+ auto constituentType = module_.FindDef(constituent->type_id());
+ assert(constituentType);
+ if (elementType->id() != constituentType->id()) {
+ DIAG(constituentIndex) << "OpSpecConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "'s type does not match Result Type <id> '"
+ << resultType->id()
+ << "'s array element type.";
+ return false;
+ }
+ }
+ break;
+ }
+ case SpvOpTypeStruct: {
+ auto memberCount = resultType->words().size() - 2;
+ if (memberCount != constituentCount) {
+ DIAG(resultTypeIndex) << "OpSpecConstantComposite Constituent <id> '"
+ << inst->words[resultTypeIndex]
+ << "' count does not match Result Type <id> '"
+ << resultType->id() << "'s struct member count.";
+ return false;
+ }
+ for (uint32_t constituentIndex = 3, memberIndex = 2;
+ constituentIndex < inst->words.size();
+ constituentIndex++, memberIndex++) {
+ auto constituent = module_.FindDef(inst->words[constituentIndex]);
+ if (!constituent ||
+ !spvOpcodeIsConstantOrUndef(constituent->opcode())) {
+ DIAG(constituentIndex) << "OpSpecConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "' is not a constant or undef.";
+ return false;
+ }
+ auto constituentType = module_.FindDef(constituent->type_id());
+ assert(constituentType);
+
+ auto memberType = module_.FindDef(resultType->words()[memberIndex]);
+ assert(memberType);
+ if (memberType->id() != constituentType->id()) {
+ DIAG(constituentIndex)
+ << "OpSpecConstantComposite Constituent <id> '"
+ << inst->words[constituentIndex]
+ << "' type does not match the Result Type <id> '"
+ << resultType->id() << "'s member type.";
+ return false;
+ }
+ }
+ break;
+ }
+ default: { assert(0 && "Unreachable!"); } break;
+ }
+ return true;
+}
#if 0
template <>
@@ -2149,7 +2407,8 @@ bool idUsage::isValid(const spv_instruction_t* inst) {
CASE(OpConstantNull)
CASE(OpSpecConstantTrue)
CASE(OpSpecConstantFalse)
- TODO(OpSpecConstantComposite)
+ CASE(OpSpecConstantComposite)
+ CASE(OpSampledImage)
TODO(OpSpecConstantOp)
CASE(OpVariable)
CASE(OpLoad)
@@ -2384,8 +2643,8 @@ function<bool(unsigned)> getCanBeForwardDeclaredFunction(SpvOp opcode) {
// The Invoke parameter.
out = [](unsigned index) { return index == 2; };
break;
- case SpvOpTypeForwardPointer:
- out = [](unsigned index) { return index == 0; };
+ case SpvOpTypeForwardPointer:
+ out = [](unsigned index) { return index == 0; };
break;
default:
out = [](unsigned) { return false; };
diff --git a/source/validate_instruction.cpp b/source/validate_instruction.cpp
index 8160b10e..976980eb 100644
--- a/source/validate_instruction.cpp
+++ b/source/validate_instruction.cpp
@@ -26,8 +26,8 @@
#include "opcode.h"
#include "operand.h"
#include "spirv_definition.h"
-#include "val/Function.h"
-#include "val/ValidationState.h"
+#include "val/function.h"
+#include "val/validation_state.h"
using libspirv::AssemblyGrammar;
using libspirv::CapabilitySet;
@@ -131,6 +131,17 @@ spv_result_t CapCheck(ValidationState_t& _,
return SPV_SUCCESS;
}
+// Checks that the Resuld <id> is within the valid bound.
+spv_result_t LimitCheckIdBound(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst) {
+ if (inst->result_id >= _.getIdBound()) {
+ return _.diag(SPV_ERROR_INVALID_BINARY)
+ << "Result <id> '" << inst->result_id
+ << "' must be less than the ID bound '" << _.getIdBound() << "'.";
+ }
+ return SPV_SUCCESS;
+}
+
spv_result_t InstructionPass(ValidationState_t& _,
const spv_parsed_instruction_t* inst) {
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
@@ -169,6 +180,11 @@ spv_result_t InstructionPass(ValidationState_t& _,
}
}
}
- return CapCheck(_, inst);
+
+ if (auto error = CapCheck(_, inst)) return error;
+ if (auto error = LimitCheckIdBound(_, inst)) return error;
+
+ // All instruction checks have passed.
+ return SPV_SUCCESS;
}
} // namespace libspirv
diff --git a/source/validate_layout.cpp b/source/validate_layout.cpp
index de650b47..b8b55180 100644
--- a/source/validate_layout.cpp
+++ b/source/validate_layout.cpp
@@ -22,8 +22,8 @@
#include "opcode.h"
#include "operand.h"
#include "spirv-tools/libspirv.h"
-#include "val/Function.h"
-#include "val/ValidationState.h"
+#include "val/function.h"
+#include "val/validation_state.h"
using libspirv::ValidationState_t;
using libspirv::kLayoutMemoryModel;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 5ce9d9fc..891828bd 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -62,61 +62,62 @@ function(add_spvtools_unittest)
endfunction()
set(TEST_SOURCES
- ${CMAKE_CURRENT_SOURCE_DIR}/TestFixture.h
- ${CMAKE_CURRENT_SOURCE_DIR}/UnitSPIRV.h
+ test_fixture.h
+ unit_spirv.h
- ${CMAKE_CURRENT_SOURCE_DIR}/AssemblyContext.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/AssemblyFormat.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/BinaryDestroy.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/BinaryEndianness.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/BinaryHeaderGet.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/BinaryParse.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/BinaryToText.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/BinaryToText.Literal.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/CapabilitySet.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/Comment.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/ExtInstGLSLstd450.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/ExtInst.OpenCL.std.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/FixWord.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/GeneratorMagicNumber.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/HexFloat.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/ImmediateInt.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/LibspirvMacros.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/NamedId.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/NameMapper.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/OpcodeMake.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/OpcodeRequiresCapabilities.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/OpcodeSplit.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/OpcodeTableGet.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/OperandCapabilities.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/Operand.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/OperandPattern.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/SoftwareVersion.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TargetEnv.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextAdvance.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextDestroy.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextLiteral.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextStartsNewInst.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.Annotation.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.Barrier.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.Constant.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.ControlFlow.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.Debug.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.DeviceSideEnqueue.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.Extension.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.Function.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.Group.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.Image.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.Literal.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.Memory.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.Miscellaneous.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.ModeSetting.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.PipeStorage.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.TypeDeclaration.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextToBinary.SubgroupDispatch.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TextWordGet.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/UnitSPIRV.cpp
+ assembly_context_test.cpp
+ assembly_format_test.cpp
+ binary_destroy_test.cpp
+ binary_endianness_test.cpp
+ binary_header_get_test.cpp
+ binary_parse_test.cpp
+ binary_to_text_test.cpp
+ binary_to_text.literal_test.cpp
+ capability_set_test.cpp
+ comment_test.cpp
+ ext_inst.glsl_test.cpp
+ ext_inst.opencl_test.cpp
+ fix_word_test.cpp
+ generator_magic_number_test.cpp
+ hex_float_test.cpp
+ immediate_int_test.cpp
+ libspirv_macros_test.cpp
+ named_id_test.cpp
+ name_mapper_test.cpp
+ opcode_make_test.cpp
+ opcode_require_capabilities_test.cpp
+ opcode_split_test.cpp
+ opcode_table_get_test.cpp
+ operand_capabilities_test.cpp
+ operand_test.cpp
+ operand_pattern_test.cpp
+ software_version_test.cpp
+ target_env_test.cpp
+ text_advance_test.cpp
+ text_destroy_test.cpp
+ text_literal_test.cpp
+ text_start_new_inst_test.cpp
+ text_to_binary.annotation_test.cpp
+ text_to_binary.barrier_test.cpp
+ text_to_binary.constant_test.cpp
+ text_to_binary.control_flow_test.cpp
+ text_to_binary_test.cpp
+ text_to_binary.debug_test.cpp
+ text_to_binary.device_side_enqueue_test.cpp
+ text_to_binary.extension_test.cpp
+ text_to_binary.function_test.cpp
+ text_to_binary.group_test.cpp
+ text_to_binary.image_test.cpp
+ text_to_binary.literal_test.cpp
+ text_to_binary.memory_test.cpp
+ text_to_binary.misc_test.cpp
+ text_to_binary.mode_setting_test.cpp
+ text_to_binary.pipe_storage_test.cpp
+ text_to_binary.type_declaration_test.cpp
+ text_to_binary.subgroup_dispatch_test.cpp
+ text_word_get_test.cpp
+
+ unit_spirv.cpp
)
add_spvtools_unittest(
@@ -126,27 +127,27 @@ add_spvtools_unittest(
add_spvtools_unittest(
TARGET diagnostic
- SRCS diagnostic.cpp
+ SRCS diagnostic_test.cpp
LIBS ${SPIRV_TOOLS})
add_spvtools_unittest(
TARGET c_interface
- SRCS c_interface.cpp
+ SRCS c_interface_test.cpp
LIBS ${SPIRV_TOOLS})
add_spvtools_unittest(
TARGET cpp_interface
- SRCS cpp_interface.cpp
- LIBS SPIRV-Tools-opt ${SPIRV_TOOLS})
+ SRCS cpp_interface_test.cpp
+ LIBS SPIRV-Tools-opt)
add_spvtools_unittest(
TARGET parse_number
- SRCS ${CMAKE_CURRENT_SOURCE_DIR}/ParseNumber.cpp
+ SRCS parse_number_test.cpp
LIBS ${SPIRV_TOOLS})
add_spvtools_unittest(
TARGET log
- SRCS test_log.cpp
+ SRCS log_test.cpp
LIBS ${SPIRV_TOOLS})
add_subdirectory(opt)
diff --git a/test/AssemblyContext.cpp b/test/assembly_context_test.cpp
index e5308694..219a76ad 100644
--- a/test/AssemblyContext.cpp
+++ b/test/assembly_context_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include <vector>
#include <gmock/gmock.h>
diff --git a/test/AssemblyFormat.cpp b/test/assembly_format_test.cpp
index 891eee9d..953fb8a3 100644
--- a/test/AssemblyFormat.cpp
+++ b/test/assembly_format_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "TestFixture.h"
+#include "test_fixture.h"
namespace {
diff --git a/test/BinaryDestroy.cpp b/test/binary_destroy_test.cpp
index 9cac3517..2df8379c 100644
--- a/test/BinaryDestroy.cpp
+++ b/test/binary_destroy_test.cpp
@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
namespace {
diff --git a/test/BinaryEndianness.cpp b/test/binary_endianness_test.cpp
index c23115ef..343c17e2 100644
--- a/test/BinaryEndianness.cpp
+++ b/test/binary_endianness_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/BinaryHeaderGet.cpp b/test/binary_header_get_test.cpp
index eed808c3..047d3a02 100644
--- a/test/BinaryHeaderGet.cpp
+++ b/test/binary_header_get_test.cpp
@@ -13,7 +13,7 @@
// limitations under the License.
#include "source/spirv_constant.h"
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/BinaryParse.cpp b/test/binary_parse_test.cpp
index 4ccf84df..138092c7 100644
--- a/test/BinaryParse.cpp
+++ b/test/binary_parse_test.cpp
@@ -16,8 +16,8 @@
#include <string>
#include <vector>
-#include "TestFixture.h"
-#include "UnitSPIRV.h"
+#include "test_fixture.h"
+#include "unit_spirv.h"
#include "gmock/gmock.h"
#include "source/message.h"
#include "source/table.h"
diff --git a/test/BinaryToText.Literal.cpp b/test/binary_to_text.literal_test.cpp
index 67b9678a..9201f4a0 100644
--- a/test/BinaryToText.Literal.cpp
+++ b/test/binary_to_text.literal_test.cpp
@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include "gmock/gmock.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
using ::testing::Eq;
diff --git a/test/BinaryToText.cpp b/test/binary_to_text_test.cpp
index 1d28e9de..09d1abd3 100644
--- a/test/BinaryToText.cpp
+++ b/test/binary_to_text_test.cpp
@@ -12,13 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include <sstream>
#include "gmock/gmock.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "source/spirv_constant.h"
namespace {
@@ -236,6 +236,39 @@ TEST_P(RoundTripInstructionsTest, Sample) {
}
INSTANTIATE_TEST_CASE_P(
+ NumericLiterals, RoundTripInstructionsTest,
+ // This test is independent of environment, so just test the one.
+ Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0),
+ ::testing::ValuesIn(std::vector<std::string>{
+ "%1 = OpTypeInt 12 0\n%2 = OpConstant %1 1867\n",
+ "%1 = OpTypeInt 12 1\n%2 = OpConstant %1 1867\n",
+ "%1 = OpTypeInt 12 1\n%2 = OpConstant %1 -1867\n",
+ "%1 = OpTypeInt 32 0\n%2 = OpConstant %1 1867\n",
+ "%1 = OpTypeInt 32 1\n%2 = OpConstant %1 1867\n",
+ "%1 = OpTypeInt 32 1\n%2 = OpConstant %1 -1867\n",
+ "%1 = OpTypeInt 64 0\n%2 = OpConstant %1 18446744073709551615\n",
+ "%1 = OpTypeInt 64 1\n%2 = OpConstant %1 9223372036854775807\n",
+ "%1 = OpTypeInt 64 1\n%2 = OpConstant %1 -9223372036854775808\n",
+ // 16-bit floats print as hex floats.
+ "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ff4p+16\n",
+ "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.d2cp-10\n",
+ // 32-bit floats
+ "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -3.275\n",
+ "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.8p+128\n", // NaN
+ "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.0002p+128\n", // NaN
+ "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1p+128\n", // Inf
+ "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1p+128\n", // -Inf
+ // 64-bit floats
+ "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -3.275\n",
+ "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.ffffffffffffap-1023\n", // small normal
+ "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.ffffffffffffap-1023\n",
+ "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.8p+1024\n", // NaN
+ "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.0002p+1024\n", // NaN
+ "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1p+1024\n", // Inf
+ "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1p+1024\n", // -Inf
+ })), );
+
+INSTANTIATE_TEST_CASE_P(
MemoryAccessMasks, RoundTripInstructionsTest,
Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
::testing::ValuesIn(std::vector<std::string>{
@@ -402,7 +435,7 @@ OpMemoryModel Logical GLSL450
OpMemoryModel Logical GLSL450
%uint = OpTypeInt 32 0
%_struct_2 = OpTypeStruct %uint %3 %4 %5 %6 %7 %8 %9 %10
-%11 = OpConstant %uint 42
+%uint_42 = OpConstant %uint 42
)";
EXPECT_THAT(EncodeAndDecodeSuccessfully(
input, SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES),
diff --git a/test/c_interface.cpp b/test/c_interface_test.cpp
index 6defbec6..6defbec6 100644
--- a/test/c_interface.cpp
+++ b/test/c_interface_test.cpp
diff --git a/test/CapabilitySet.cpp b/test/capability_set_test.cpp
index aaae54e4..4a0111d1 100644
--- a/test/CapabilitySet.cpp
+++ b/test/capability_set_test.cpp
@@ -16,7 +16,7 @@
#include "gmock/gmock.h"
#include "enum_set.h"
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/Comment.cpp b/test/comment_test.cpp
index d708a113..f60b7918 100644
--- a/test/Comment.cpp
+++ b/test/comment_test.cpp
@@ -13,8 +13,8 @@
// limitations under the License.
#include "gmock/gmock.h"
-#include "TestFixture.h"
-#include "UnitSPIRV.h"
+#include "test_fixture.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/cpp_interface.cpp b/test/cpp_interface_test.cpp
index 141e7a37..141e7a37 100644
--- a/test/cpp_interface.cpp
+++ b/test/cpp_interface_test.cpp
diff --git a/test/diagnostic.cpp b/test/diagnostic_test.cpp
index feb5403b..65af274d 100644
--- a/test/diagnostic.cpp
+++ b/test/diagnostic_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/ExtInstGLSLstd450.cpp b/test/ext_inst.glsl_test.cpp
index d81a4446..8502cfdb 100644
--- a/test/ExtInstGLSLstd450.cpp
+++ b/test/ext_inst.glsl_test.cpp
@@ -15,7 +15,7 @@
#include <algorithm>
#include <vector>
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include "spirv/1.0/GLSL.std.450.h"
namespace {
diff --git a/test/ExtInst.OpenCL.std.cpp b/test/ext_inst.opencl_test.cpp
index df463d36..36854153 100644
--- a/test/ExtInst.OpenCL.std.cpp
+++ b/test/ext_inst.opencl_test.cpp
@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include <gmock/gmock.h>
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "spirv/1.0/OpenCL.std.h"
namespace {
diff --git a/test/FixWord.cpp b/test/fix_word_test.cpp
index e5514e68..45ba6e63 100644
--- a/test/FixWord.cpp
+++ b/test/fix_word_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/GeneratorMagicNumber.cpp b/test/generator_magic_number_test.cpp
index 44278250..c3f30f63 100644
--- a/test/GeneratorMagicNumber.cpp
+++ b/test/generator_magic_number_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include <gmock/gmock.h>
diff --git a/test/HexFloat.cpp b/test/hex_float_test.cpp
index 5b97f4ac..33933df9 100644
--- a/test/HexFloat.cpp
+++ b/test/hex_float_test.cpp
@@ -20,7 +20,9 @@
#include <tuple>
#include <gmock/gmock.h>
+
#include "source/util/hex_float.h"
+#include "unit_spirv.h"
namespace {
using ::testing::Eq;
diff --git a/test/ImmediateInt.cpp b/test/immediate_int_test.cpp
index bc2ff3c6..30a8fb03 100644
--- a/test/ImmediateInt.cpp
+++ b/test/immediate_int_test.cpp
@@ -18,7 +18,7 @@
#include <gmock/gmock.h>
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "source/util/bitutils.h"
namespace {
diff --git a/test/LibspirvMacros.cpp b/test/libspirv_macros_test.cpp
index ce84ceae..5b9b5413 100644
--- a/test/LibspirvMacros.cpp
+++ b/test/libspirv_macros_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/test_log.cpp b/test/log_test.cpp
index fd258b17..f14f77d8 100644
--- a/test/test_log.cpp
+++ b/test/log_test.cpp
@@ -29,7 +29,7 @@ TEST(Log, Unimplemented) {
const spv_position_t&, const char* message) {
++invocation;
EXPECT_EQ(SPV_MSG_INTERNAL_ERROR, level);
- EXPECT_THAT(source, MatchesRegex(".*test_log.cpp$"));
+ EXPECT_THAT(source, MatchesRegex(".*log_test.cpp$"));
EXPECT_STREQ("unimplemented: the-ultimite-feature", message);
};
@@ -43,7 +43,7 @@ TEST(Log, Unreachable) {
const spv_position_t&, const char* message) {
++invocation;
EXPECT_EQ(SPV_MSG_INTERNAL_ERROR, level);
- EXPECT_THAT(source, MatchesRegex(".*test_log.cpp$"));
+ EXPECT_THAT(source, MatchesRegex(".*log_test.cpp$"));
EXPECT_STREQ("unreachable", message);
};
diff --git a/test/NameMapper.cpp b/test/name_mapper_test.cpp
index 7a470f36..c201198e 100644
--- a/test/NameMapper.cpp
+++ b/test/name_mapper_test.cpp
@@ -14,8 +14,8 @@
#include "gmock/gmock.h"
-#include "TestFixture.h"
-#include "UnitSPIRV.h"
+#include "test_fixture.h"
+#include "unit_spirv.h"
#include "source/name_mapper.h"
@@ -282,4 +282,57 @@ INSTANTIATE_TEST_CASE_P(DebugNameOverridesBuiltin, FriendlyNameTest,
"%1 = OpVariable %2 Input",
1, "foo"}}), );
+INSTANTIATE_TEST_CASE_P(
+ SimpleIntegralConstants, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 0", 2, "uint_0"},
+ {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 1", 2, "uint_1"},
+ {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 2", 2, "uint_2"},
+ {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 9", 2, "uint_9"},
+ {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 42", 2, "uint_42"},
+ {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 0", 2, "int_0"},
+ {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 1", 2, "int_1"},
+ {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 2", 2, "int_2"},
+ {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 9", 2, "int_9"},
+ {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 42", 2, "int_42"},
+ {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 -42", 2, "int_n42"},
+ // Exotic bit widths
+ {"%1 = OpTypeInt 33 0 %2 = OpConstant %1 0", 2, "u33_0"},
+ {"%1 = OpTypeInt 33 1 %2 = OpConstant %1 10", 2, "i33_10"},
+ {"%1 = OpTypeInt 33 1 %2 = OpConstant %1 -19", 2, "i33_n19"},
+ }), );
+
+INSTANTIATE_TEST_CASE_P(
+ SimpleFloatConstants, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ff4p+16", 2,
+ "half_0x1_ff4p_16"},
+ {"%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.d2cp-10", 2,
+ "half_n0x1_d2cpn10"},
+ // 32-bit floats
+ {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 -3.275", 2, "float_n3_275"},
+ {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.8p+128", 2,
+ "float_0x1_8p_128"}, // NaN
+ {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.0002p+128", 2,
+ "float_n0x1_0002p_128"}, // NaN
+ {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1p+128", 2,
+ "float_0x1p_128"}, // Inf
+ {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1p+128", 2,
+ "float_n0x1p_128"}, // -Inf
+ // 64-bit floats
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 -3.275", 2, "double_n3_275"},
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.ffffffffffffap-1023", 2,
+ "double_0x1_ffffffffffffapn1023"}, // small normal
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.ffffffffffffap-1023", 2,
+ "double_n0x1_ffffffffffffapn1023"},
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.8p+1024", 2,
+ "double_0x1_8p_1024"}, // NaN
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.0002p+1024", 2,
+ "double_n0x1_0002p_1024"}, // NaN
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1p+1024", 2,
+ "double_0x1p_1024"}, // Inf
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1p+1024", 2,
+ "double_n0x1p_1024"}, // -Inf
+ }), );
+
} // anonymous namespace
diff --git a/test/NamedId.cpp b/test/named_id_test.cpp
index 7ece9c93..68946bb3 100644
--- a/test/NamedId.cpp
+++ b/test/named_id_test.cpp
@@ -14,8 +14,8 @@
#include <vector>
-#include "TestFixture.h"
-#include "UnitSPIRV.h"
+#include "test_fixture.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/OpcodeMake.cpp b/test/opcode_make_test.cpp
index 5794a496..5353b719 100644
--- a/test/OpcodeMake.cpp
+++ b/test/opcode_make_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/OpcodeRequiresCapabilities.cpp b/test/opcode_require_capabilities_test.cpp
index 39de7f9e..31a17366 100644
--- a/test/OpcodeRequiresCapabilities.cpp
+++ b/test/opcode_require_capabilities_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include "enum_set.h"
diff --git a/test/OpcodeSplit.cpp b/test/opcode_split_test.cpp
index 197018f0..f42d903a 100644
--- a/test/OpcodeSplit.cpp
+++ b/test/opcode_split_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/OpcodeTableGet.cpp b/test/opcode_table_get_test.cpp
index 67c46ae0..f2272f07 100644
--- a/test/OpcodeTableGet.cpp
+++ b/test/opcode_table_get_test.cpp
@@ -14,7 +14,7 @@
#include <gmock/gmock.h>
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/OperandCapabilities.cpp b/test/operand_capabilities_test.cpp
index 5673ef77..20a7525c 100644
--- a/test/OperandCapabilities.cpp
+++ b/test/operand_capabilities_test.cpp
@@ -19,7 +19,7 @@
#include "gmock/gmock.h"
#include "enum_set.h"
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/OperandPattern.cpp b/test/operand_pattern_test.cpp
index eee7b6d2..be4fffdc 100644
--- a/test/OperandPattern.cpp
+++ b/test/operand_pattern_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include "gmock/gmock.h"
#include "source/operand.h"
diff --git a/test/Operand.cpp b/test/operand_test.cpp
index b5e48975..a9056a24 100644
--- a/test/Operand.cpp
+++ b/test/operand_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/opt/CMakeLists.txt b/test/opt/CMakeLists.txt
index 6a7d604d..8e987935 100644
--- a/test/opt/CMakeLists.txt
+++ b/test/opt/CMakeLists.txt
@@ -13,88 +13,88 @@
# limitations under the License.
add_spvtools_unittest(TARGET instruction
- SRCS test_instruction.cpp
+ SRCS instruction_test.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET ir_loader
- SRCS test_ir_loader.cpp
+ SRCS ir_loader_test.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_manager
SRCS module_utils.h
- test_pass_manager.cpp
+ pass_manager_test.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_strip_debug_info
- SRCS test_strip_debug_info.cpp pass_utils.cpp
+ SRCS strip_debug_info_test.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_freeze_spec_const
- SRCS test_freeze_spec_const.cpp pass_utils.cpp
+ SRCS freeze_spec_const_test.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_eliminate_dead_const
- SRCS test_eliminate_dead_const.cpp pass_utils.cpp
+ SRCS eliminate_dead_const_test.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_utils
- SRCS test_utils.cpp pass_utils.cpp
+ SRCS utils_test.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET def_use
- SRCS test_def_use.cpp pass_utils.cpp
+ SRCS def_use_test.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET assembly_builder
- SRCS test_assembly_builder.cpp pass_utils.cpp
+ SRCS assembly_builder_test.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET types
- SRCS test_types.cpp
+ SRCS types_test.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET type_manager
- SRCS test_type_manager.cpp
+ SRCS type_manager_test.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET iterator
- SRCS test_iterator.cpp
+ SRCS iterator_test.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET module
SRCS module_utils.h
- test_module.cpp
+ module_test.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_fold_spec_const_op_composite
- SRCS test_fold_spec_const_op_composite.cpp pass_utils.cpp
+ SRCS fold_spec_const_op_composite_test.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_unify_const
- SRCS test_unify_const.cpp
+ SRCS unify_const_test.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_set_spec_const_default_value
- SRCS test_set_spec_const_default_value.cpp pass_utils.cpp
+ SRCS set_spec_const_default_value_test.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET line_debug_info
- SRCS test_line_debug_info.cpp pass_utils.cpp
+ SRCS line_debug_info_test.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt
)
diff --git a/test/opt/test_assembly_builder.cpp b/test/opt/assembly_builder_test.cpp
index 50bb46c1..50bb46c1 100644
--- a/test/opt/test_assembly_builder.cpp
+++ b/test/opt/assembly_builder_test.cpp
diff --git a/test/opt/test_def_use.cpp b/test/opt/def_use_test.cpp
index 0ce7b4ca..0ce7b4ca 100644
--- a/test/opt/test_def_use.cpp
+++ b/test/opt/def_use_test.cpp
diff --git a/test/opt/test_eliminate_dead_const.cpp b/test/opt/eliminate_dead_const_test.cpp
index 490132c4..92247e05 100644
--- a/test/opt/test_eliminate_dead_const.cpp
+++ b/test/opt/eliminate_dead_const_test.cpp
@@ -98,16 +98,16 @@ TEST_F(EliminateDeadConstantBasicTest, BasicNoneDeadConstants) {
"%14 = OpConstantFalse %bool",
"%int = OpTypeInt 32 1",
"%_ptr_Function_int = OpTypePointer Function %int",
- "%17 = OpConstant %int 1",
+ "%int_1 = OpConstant %int 1",
"%uint = OpTypeInt 32 0",
"%_ptr_Function_uint = OpTypePointer Function %uint",
- "%20 = OpConstant %uint 2",
+ "%uint_2 = OpConstant %uint 2",
"%float = OpTypeFloat 32",
"%_ptr_Function_float = OpTypePointer Function %float",
- "%23 = OpConstant %float 3.14",
+ "%float_3_14 = OpConstant %float 3.14",
"%double = OpTypeFloat 64",
"%_ptr_Function_double = OpTypePointer Function %double",
- "%26 = OpConstant %double 3.14159265358979",
+ "%double_3_14159265358979 = OpConstant %double 3.14159265358979",
"%main = OpFunction %void None %10",
"%27 = OpLabel",
"%btv = OpVariable %_ptr_Function_bool Function",
@@ -118,10 +118,10 @@ TEST_F(EliminateDeadConstantBasicTest, BasicNoneDeadConstants) {
"%dv = OpVariable %_ptr_Function_double Function",
"OpStore %btv %13",
"OpStore %bfv %14",
- "OpStore %iv %17",
- "OpStore %uv %20",
- "OpStore %fv %23",
- "OpStore %dv %26",
+ "OpStore %iv %int_1",
+ "OpStore %uv %uint_2",
+ "OpStore %fv %float_3_14",
+ "OpStore %dv %double_3_14159265358979",
"OpReturn",
"OpFunctionEnd",
// clang-format on
diff --git a/test/opt/test_fold_spec_const_op_composite.cpp b/test/opt/fold_spec_const_op_composite_test.cpp
index b84bf268..b9afeee3 100644
--- a/test/opt/test_fold_spec_const_op_composite.cpp
+++ b/test/opt/fold_spec_const_op_composite_test.cpp
@@ -483,15 +483,15 @@ INSTANTIATE_TEST_CASE_P(
},
// expected
{
- "%59 = OpConstant %int 1",
- "%60 = OpConstant %int 1",
- "%spec_int_one_vec = OpConstantComposite %v2int %59 %60",
- "%62 = OpConstant %int 0",
- "%63 = OpConstant %int 0",
- "%spec_int_zero_vec = OpConstantComposite %v2int %62 %63",
- "%65 = OpConstant %int 0",
- "%66 = OpConstant %int 0",
- "%spec_int_from_null = OpConstantComposite %v2int %65 %66",
+ "%int_1 = OpConstant %int 1",
+ "%int_1_0 = OpConstant %int 1",
+ "%spec_int_one_vec = OpConstantComposite %v2int %int_1 %int_1_0",
+ "%int_0 = OpConstant %int 0",
+ "%int_0_0 = OpConstant %int 0",
+ "%spec_int_zero_vec = OpConstantComposite %v2int %int_0 %int_0_0",
+ "%int_0_1 = OpConstant %int 0",
+ "%int_0_2 = OpConstant %int 0",
+ "%spec_int_from_null = OpConstantComposite %v2int %int_0_1 %int_0_2",
},
},
@@ -505,15 +505,15 @@ INSTANTIATE_TEST_CASE_P(
},
// expected
{
- "%59 = OpConstant %int 1",
- "%60 = OpConstant %int 1",
- "%spec_int_one_vec = OpConstantComposite %v2int %59 %60",
- "%62 = OpConstant %int 0",
- "%63 = OpConstant %int 0",
- "%spec_int_zero_vec = OpConstantComposite %v2int %62 %63",
- "%65 = OpConstant %int 0",
- "%66 = OpConstant %int 0",
- "%spec_int_from_null = OpConstantComposite %v2int %65 %66",
+ "%int_1 = OpConstant %int 1",
+ "%int_1_0 = OpConstant %int 1",
+ "%spec_int_one_vec = OpConstantComposite %v2int %int_1 %int_1_0",
+ "%int_0 = OpConstant %int 0",
+ "%int_0_0 = OpConstant %int 0",
+ "%spec_int_zero_vec = OpConstantComposite %v2int %int_0 %int_0_0",
+ "%int_0_1 = OpConstant %int 0",
+ "%int_0_2 = OpConstant %int 0",
+ "%spec_int_from_null = OpConstantComposite %v2int %int_0_1 %int_0_2",
},
},
@@ -527,15 +527,15 @@ INSTANTIATE_TEST_CASE_P(
},
// expected
{
- "%59 = OpConstant %uint 1",
- "%60 = OpConstant %uint 1",
- "%spec_uint_one_vec = OpConstantComposite %v2uint %59 %60",
- "%62 = OpConstant %uint 0",
- "%63 = OpConstant %uint 0",
- "%spec_uint_zero_vec = OpConstantComposite %v2uint %62 %63",
- "%65 = OpConstant %uint 0",
- "%66 = OpConstant %uint 0",
- "%spec_uint_from_null = OpConstantComposite %v2uint %65 %66",
+ "%uint_1 = OpConstant %uint 1",
+ "%uint_1_0 = OpConstant %uint 1",
+ "%spec_uint_one_vec = OpConstantComposite %v2uint %uint_1 %uint_1_0",
+ "%uint_0 = OpConstant %uint 0",
+ "%uint_0_0 = OpConstant %uint 0",
+ "%spec_uint_zero_vec = OpConstantComposite %v2uint %uint_0 %uint_0_0",
+ "%uint_0_1 = OpConstant %uint 0",
+ "%uint_0_2 = OpConstant %uint 0",
+ "%spec_uint_from_null = OpConstantComposite %v2uint %uint_0_1 %uint_0_2",
},
},
@@ -549,15 +549,15 @@ INSTANTIATE_TEST_CASE_P(
},
// expected
{
- "%59 = OpConstant %uint 1",
- "%60 = OpConstant %uint 1",
- "%spec_uint_one_vec = OpConstantComposite %v2uint %59 %60",
- "%62 = OpConstant %uint 0",
- "%63 = OpConstant %uint 0",
- "%spec_uint_zero_vec = OpConstantComposite %v2uint %62 %63",
- "%65 = OpConstant %uint 0",
- "%66 = OpConstant %uint 0",
- "%spec_uint_from_null = OpConstantComposite %v2uint %65 %66",
+ "%uint_1 = OpConstant %uint 1",
+ "%uint_1_0 = OpConstant %uint 1",
+ "%spec_uint_one_vec = OpConstantComposite %v2uint %uint_1 %uint_1_0",
+ "%uint_0 = OpConstant %uint 0",
+ "%uint_0_0 = OpConstant %uint 0",
+ "%spec_uint_zero_vec = OpConstantComposite %v2uint %uint_0 %uint_0_0",
+ "%uint_0_1 = OpConstant %uint 0",
+ "%uint_0_2 = OpConstant %uint 0",
+ "%spec_uint_from_null = OpConstantComposite %v2uint %uint_0_1 %uint_0_2",
},
},
// clang-format on
@@ -834,15 +834,15 @@ INSTANTIATE_TEST_CASE_P(
},
// expected
{
- "%59 = OpConstant %int -1",
- "%60 = OpConstant %int -1",
- "%v2int_minus_1 = OpConstantComposite %v2int %59 %60",
- "%62 = OpConstant %int -2",
- "%63 = OpConstant %int -2",
- "%v2int_minus_2 = OpConstantComposite %v2int %62 %63",
- "%65 = OpConstant %int 0",
- "%66 = OpConstant %int 0",
- "%v2int_neg_null = OpConstantComposite %v2int %65 %66",
+ "%int_n1 = OpConstant %int -1",
+ "%int_n1_0 = OpConstant %int -1",
+ "%v2int_minus_1 = OpConstantComposite %v2int %int_n1 %int_n1_0",
+ "%int_n2 = OpConstant %int -2",
+ "%int_n2_0 = OpConstant %int -2",
+ "%v2int_minus_2 = OpConstantComposite %v2int %int_n2 %int_n2_0",
+ "%int_0 = OpConstant %int 0",
+ "%int_0_0 = OpConstant %int 0",
+ "%v2int_neg_null = OpConstantComposite %v2int %int_0 %int_0_0",
},
},
// vector integer (including null vetors) add, sub, div, mul
@@ -863,37 +863,37 @@ INSTANTIATE_TEST_CASE_P(
},
// expected
{
- "%66 = OpConstant %int 5",
- "%67 = OpConstant %int 5",
- "%spec_v2int_iadd = OpConstantComposite %v2int %66 %67",
- "%69 = OpConstant %int -4",
- "%70 = OpConstant %int -4",
- "%spec_v2int_isub = OpConstantComposite %v2int %69 %70",
- "%72 = OpConstant %int -2",
- "%73 = OpConstant %int -2",
- "%spec_v2int_sdiv = OpConstantComposite %v2int %72 %73",
- "%75 = OpConstant %int -6",
- "%76 = OpConstant %int -6",
- "%spec_v2int_imul = OpConstantComposite %v2int %75 %76",
- "%78 = OpConstant %int -6",
- "%79 = OpConstant %int -6",
- "%spec_v2int_iadd_null = OpConstantComposite %v2int %78 %79",
+ "%int_5 = OpConstant %int 5",
+ "%int_5_0 = OpConstant %int 5",
+ "%spec_v2int_iadd = OpConstantComposite %v2int %int_5 %int_5_0",
+ "%int_n4 = OpConstant %int -4",
+ "%int_n4_0 = OpConstant %int -4",
+ "%spec_v2int_isub = OpConstantComposite %v2int %int_n4 %int_n4_0",
+ "%int_n2 = OpConstant %int -2",
+ "%int_n2_0 = OpConstant %int -2",
+ "%spec_v2int_sdiv = OpConstantComposite %v2int %int_n2 %int_n2_0",
+ "%int_n6 = OpConstant %int -6",
+ "%int_n6_0 = OpConstant %int -6",
+ "%spec_v2int_imul = OpConstantComposite %v2int %int_n6 %int_n6_0",
+ "%int_n6_1 = OpConstant %int -6",
+ "%int_n6_2 = OpConstant %int -6",
+ "%spec_v2int_iadd_null = OpConstantComposite %v2int %int_n6_1 %int_n6_2",
- "%81 = OpConstant %uint 5",
- "%82 = OpConstant %uint 5",
- "%spec_v2uint_iadd = OpConstantComposite %v2uint %81 %82",
- "%84 = OpConstant %uint 4294967292",
- "%85 = OpConstant %uint 4294967292",
- "%spec_v2uint_isub = OpConstantComposite %v2uint %84 %85",
- "%87 = OpConstant %uint 1431655764",
- "%88 = OpConstant %uint 1431655764",
- "%spec_v2uint_udiv = OpConstantComposite %v2uint %87 %88",
- "%90 = OpConstant %uint 2863311528",
- "%91 = OpConstant %uint 2863311528",
- "%spec_v2uint_imul = OpConstantComposite %v2uint %90 %91",
- "%93 = OpConstant %uint 2863311528",
- "%94 = OpConstant %uint 2863311528",
- "%spec_v2uint_isub_null = OpConstantComposite %v2uint %93 %94",
+ "%uint_5 = OpConstant %uint 5",
+ "%uint_5_0 = OpConstant %uint 5",
+ "%spec_v2uint_iadd = OpConstantComposite %v2uint %uint_5 %uint_5_0",
+ "%uint_4294967292 = OpConstant %uint 4294967292",
+ "%uint_4294967292_0 = OpConstant %uint 4294967292",
+ "%spec_v2uint_isub = OpConstantComposite %v2uint %uint_4294967292 %uint_4294967292_0",
+ "%uint_1431655764 = OpConstant %uint 1431655764",
+ "%uint_1431655764_0 = OpConstant %uint 1431655764",
+ "%spec_v2uint_udiv = OpConstantComposite %v2uint %uint_1431655764 %uint_1431655764_0",
+ "%uint_2863311528 = OpConstant %uint 2863311528",
+ "%uint_2863311528_0 = OpConstant %uint 2863311528",
+ "%spec_v2uint_imul = OpConstantComposite %v2uint %uint_2863311528 %uint_2863311528_0",
+ "%uint_2863311528_1 = OpConstant %uint 2863311528",
+ "%uint_2863311528_2 = OpConstant %uint 2863311528",
+ "%spec_v2uint_isub_null = OpConstantComposite %v2uint %uint_2863311528_1 %uint_2863311528_2",
},
},
// vector integer rem, mod
@@ -936,35 +936,35 @@ INSTANTIATE_TEST_CASE_P(
"%v2int_minus_3 = OpConstantComposite %v2int %int_minus_3 %int_minus_3",
// srem
- "%73 = OpConstant %int 1",
- "%74 = OpConstant %int 1",
- "%7_srem_3 = OpConstantComposite %v2int %73 %74",
- "%76 = OpConstant %int -1",
- "%77 = OpConstant %int -1",
- "%minus_7_srem_3 = OpConstantComposite %v2int %76 %77",
- "%79 = OpConstant %int 1",
- "%80 = OpConstant %int 1",
- "%7_srem_minus_3 = OpConstantComposite %v2int %79 %80",
- "%82 = OpConstant %int -1",
- "%83 = OpConstant %int -1",
- "%minus_7_srem_minus_3 = OpConstantComposite %v2int %82 %83",
+ "%int_1 = OpConstant %int 1",
+ "%int_1_0 = OpConstant %int 1",
+ "%7_srem_3 = OpConstantComposite %v2int %int_1 %int_1_0",
+ "%int_n1 = OpConstant %int -1",
+ "%int_n1_0 = OpConstant %int -1",
+ "%minus_7_srem_3 = OpConstantComposite %v2int %int_n1 %int_n1_0",
+ "%int_1_1 = OpConstant %int 1",
+ "%int_1_2 = OpConstant %int 1",
+ "%7_srem_minus_3 = OpConstantComposite %v2int %int_1_1 %int_1_2",
+ "%int_n1_1 = OpConstant %int -1",
+ "%int_n1_2 = OpConstant %int -1",
+ "%minus_7_srem_minus_3 = OpConstantComposite %v2int %int_n1_1 %int_n1_2",
// smod
- "%85 = OpConstant %int 1",
- "%86 = OpConstant %int 1",
- "%7_smod_3 = OpConstantComposite %v2int %85 %86",
- "%88 = OpConstant %int 2",
- "%89 = OpConstant %int 2",
- "%minus_7_smod_3 = OpConstantComposite %v2int %88 %89",
- "%91 = OpConstant %int -2",
- "%92 = OpConstant %int -2",
- "%7_smod_minus_3 = OpConstantComposite %v2int %91 %92",
- "%94 = OpConstant %int -1",
- "%95 = OpConstant %int -1",
- "%minus_7_smod_minus_3 = OpConstantComposite %v2int %94 %95",
+ "%int_1_3 = OpConstant %int 1",
+ "%int_1_4 = OpConstant %int 1",
+ "%7_smod_3 = OpConstantComposite %v2int %int_1_3 %int_1_4",
+ "%int_2 = OpConstant %int 2",
+ "%int_2_0 = OpConstant %int 2",
+ "%minus_7_smod_3 = OpConstantComposite %v2int %int_2 %int_2_0",
+ "%int_n2 = OpConstant %int -2",
+ "%int_n2_0 = OpConstant %int -2",
+ "%7_smod_minus_3 = OpConstantComposite %v2int %int_n2 %int_n2_0",
+ "%int_n1_3 = OpConstant %int -1",
+ "%int_n1_4 = OpConstant %int -1",
+ "%minus_7_smod_minus_3 = OpConstantComposite %v2int %int_n1_3 %int_n1_4",
// umod
- "%97 = OpConstant %uint 1",
- "%98 = OpConstant %uint 1",
- "%7_umod_3 = OpConstantComposite %v2uint %97 %98",
+ "%uint_1 = OpConstant %uint 1",
+ "%uint_1_0 = OpConstant %uint 1",
+ "%7_umod_3 = OpConstantComposite %v2uint %uint_1 %uint_1_0",
},
},
// vector integer bitwise, shift
@@ -983,27 +983,27 @@ INSTANTIATE_TEST_CASE_P(
},
// expected
{
- "%64 = OpConstant %int 2",
- "%65 = OpConstant %int 2",
- "%xor_1_3 = OpConstantComposite %v2int %64 %65",
- "%67 = OpConstant %int 0",
- "%68 = OpConstant %int 0",
- "%and_1_2 = OpConstantComposite %v2int %67 %68",
- "%70 = OpConstant %int 3",
- "%71 = OpConstant %int 3",
- "%or_1_2 = OpConstantComposite %v2int %70 %71",
+ "%int_2 = OpConstant %int 2",
+ "%int_2_0 = OpConstant %int 2",
+ "%xor_1_3 = OpConstantComposite %v2int %int_2 %int_2_0",
+ "%int_0 = OpConstant %int 0",
+ "%int_0_0 = OpConstant %int 0",
+ "%and_1_2 = OpConstantComposite %v2int %int_0 %int_0_0",
+ "%int_3 = OpConstant %int 3",
+ "%int_3_0 = OpConstant %int 3",
+ "%or_1_2 = OpConstantComposite %v2int %int_3 %int_3_0",
"%unsigned_31 = OpConstant %uint 31",
"%v2unsigned_31 = OpConstantComposite %v2uint %unsigned_31 %unsigned_31",
- "%73 = OpConstant %uint 2147483648",
- "%74 = OpConstant %uint 2147483648",
- "%unsigned_left_shift_max = OpConstantComposite %v2uint %73 %74",
- "%76 = OpConstant %uint 1",
- "%77 = OpConstant %uint 1",
- "%unsigned_right_shift_logical = OpConstantComposite %v2uint %76 %77",
- "%79 = OpConstant %int -1",
- "%80 = OpConstant %int -1",
- "%signed_right_shift_arithmetic = OpConstantComposite %v2int %79 %80",
+ "%uint_2147483648 = OpConstant %uint 2147483648",
+ "%uint_2147483648_0 = OpConstant %uint 2147483648",
+ "%unsigned_left_shift_max = OpConstantComposite %v2uint %uint_2147483648 %uint_2147483648_0",
+ "%uint_1 = OpConstant %uint 1",
+ "%uint_1_0 = OpConstant %uint 1",
+ "%unsigned_right_shift_logical = OpConstantComposite %v2uint %uint_1 %uint_1_0",
+ "%int_n1 = OpConstant %int -1",
+ "%int_n1_0 = OpConstant %int -1",
+ "%signed_right_shift_arithmetic = OpConstantComposite %v2int %int_n1 %int_n1_0",
},
},
// Skip folding if any vector operands or components of the operands
@@ -1375,9 +1375,9 @@ INSTANTIATE_TEST_CASE_P(
"%spec_int_19 = OpConstant %int -1",
"%spec_int_20 = OpConstant %int 101",
"%used_vec_a = OpConstantComposite %v2int %spec_int_18 %spec_int_19",
- "%104 = OpConstant %int 10201",
- "%105 = OpConstant %int 1",
- "%used_vec_b = OpConstantComposite %v2int %104 %105",
+ "%int_10201 = OpConstant %int 10201",
+ "%int_1 = OpConstant %int 1",
+ "%used_vec_b = OpConstantComposite %v2int %int_10201 %int_1",
"%spec_int_21 = OpConstant %int 10201",
"%array = OpConstantComposite %type_arr_int_4 %spec_int_20 %spec_int_20 %spec_int_21 %spec_int_21",
"%spec_int_22 = OpSpecConstant %int 123",
diff --git a/test/opt/test_freeze_spec_const.cpp b/test/opt/freeze_spec_const_test.cpp
index 6c094939..0fd0fe4f 100644
--- a/test/opt/test_freeze_spec_const.cpp
+++ b/test/opt/freeze_spec_const_test.cpp
@@ -51,13 +51,13 @@ INSTANTIATE_TEST_CASE_P(
// Type declaration, original spec constant definition, expected frozen
// spec constants.
{"%int = OpTypeInt 32 1", "%2 = OpSpecConstant %int 1",
- "%2 = OpConstant %int 1"},
+ "%int_1 = OpConstant %int 1"},
{"%uint = OpTypeInt 32 0", "%2 = OpSpecConstant %uint 1",
- "%2 = OpConstant %uint 1"},
+ "%uint_1 = OpConstant %uint 1"},
{"%float = OpTypeFloat 32", "%2 = OpSpecConstant %float 3.14",
- "%2 = OpConstant %float 3.14"},
+ "%float_3_14 = OpConstant %float 3.14"},
{"%double = OpTypeFloat 64", "%2 = OpSpecConstant %double 3.1415926",
- "%2 = OpConstant %double 3.1415926"},
+ "%double_3_1415926 = OpConstant %double 3.1415926"},
{"%bool = OpTypeBool", "%2 = OpSpecConstantTrue %bool",
"%2 = OpConstantTrue %bool"},
{"%bool = OpTypeBool", "%2 = OpSpecConstantFalse %bool",
@@ -103,12 +103,16 @@ TEST_F(FreezeSpecConstantValueRemoveDecorationTest,
std::string expected_disassembly = SelectiveJoin(text, [](const char* line) {
return std::string(line).find("SpecId") != std::string::npos;
});
- std::vector<std::pair<const char*, const char*>> opcode_replacement_pairs = {
- {" OpSpecConstant ", " OpConstant "},
+ std::vector<std::pair<const char*, const char*>> replacement_pairs = {
+ {"%3 = OpSpecConstant %int 3", "%int_3 = OpConstant %int 3"},
+ {"%4 = OpSpecConstant %float 3.14",
+ "%float_3_14 = OpConstant %float 3.14"},
+ {"%5 = OpSpecConstant %double 3.14159265358979",
+ "%double_3_14159265358979 = OpConstant %double 3.14159265358979"},
{" OpSpecConstantTrue ", " OpConstantTrue "},
{" OpSpecConstantFalse ", " OpConstantFalse "},
};
- for (auto& p : opcode_replacement_pairs) {
+ for (auto& p : replacement_pairs) {
EXPECT_TRUE(FindAndReplace(&expected_disassembly, p.first, p.second))
<< "text:\n"
<< expected_disassembly << "\n"
diff --git a/test/opt/test_instruction.cpp b/test/opt/instruction_test.cpp
index af6593f5..608229f4 100644
--- a/test/opt/test_instruction.cpp
+++ b/test/opt/instruction_test.cpp
@@ -17,7 +17,7 @@
#include "gmock/gmock.h"
#include "spirv-tools/libspirv.h"
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/opt/test_ir_loader.cpp b/test/opt/ir_loader_test.cpp
index 854115a3..4e40e70c 100644
--- a/test/opt/test_ir_loader.cpp
+++ b/test/opt/ir_loader_test.cpp
@@ -61,14 +61,14 @@ TEST(IrBuilder, RoundTrip) {
"%int = OpTypeInt 32 1\n"
"%_ptr_Function_int = OpTypePointer Function %int\n"
"%12 = OpTypeFunction %int %_ptr_Function_int %_ptr_Function_int\n"
- "%13 = OpConstant %int 1\n"
- "%14 = OpConstant %int 2\n"
+ "%int_1 = OpConstant %int 1\n"
+ "%int_2 = OpConstant %int 2\n"
"%main = OpFunction %void None %9\n"
"%15 = OpLabel\n"
"%param = OpVariable %_ptr_Function_int Function\n"
"%param_0 = OpVariable %_ptr_Function_int Function\n"
- "OpStore %param %13\n"
- "OpStore %param_0 %14\n"
+ "OpStore %param %int_1\n"
+ "OpStore %param_0 %int_2\n"
"%16 = OpFunctionCall %int %add_i1_i1_ %param %param_0\n"
"OpReturn\n"
"OpFunctionEnd\n"
@@ -159,15 +159,15 @@ TEST(IrBuilder, LocalGlobalVariables) {
"%12 = OpTypeFunction %float\n"
"%_ptr_Private_float = OpTypePointer Private %float\n"
"%gv1 = OpVariable %_ptr_Private_float Private\n"
- "%14 = OpConstant %float 10\n"
+ "%float_10 = OpConstant %float 10\n"
"%gv2 = OpVariable %_ptr_Private_float Private\n"
- "%15 = OpConstant %float 100\n"
+ "%float_100 = OpConstant %float 100\n"
"%_ptr_Function_float = OpTypePointer Function %float\n"
"%main = OpFunction %void None %10\n"
"%17 = OpLabel\n"
"%lv1_0 = OpVariable %_ptr_Function_float Function\n"
- "OpStore %gv1 %14\n"
- "OpStore %gv2 %15\n"
+ "OpStore %gv1 %float_10\n"
+ "OpStore %gv2 %float_100\n"
"%18 = OpLoad %float %gv1\n"
"%19 = OpLoad %float %gv2\n"
"%20 = OpFSub %float %18 %19\n"
@@ -204,7 +204,7 @@ TEST(IrBuilder, OpUndefOutsideFunction) {
"%uint = OpTypeInt 32 0\n"
"%float = OpTypeFloat 32\n"
"%4 = OpUndef %int\n"
- "%5 = OpConstant %int 10\n"
+ "%int_10 = OpConstant %int 10\n"
"%6 = OpUndef %uint\n"
"%bool = OpTypeBool\n"
"%8 = OpUndef %float\n"
diff --git a/test/opt/test_iterator.cpp b/test/opt/iterator_test.cpp
index 5afe88c1..5afe88c1 100644
--- a/test/opt/test_iterator.cpp
+++ b/test/opt/iterator_test.cpp
diff --git a/test/opt/test_line_debug_info.cpp b/test/opt/line_debug_info_test.cpp
index 43edc940..43edc940 100644
--- a/test/opt/test_line_debug_info.cpp
+++ b/test/opt/line_debug_info_test.cpp
diff --git a/test/opt/test_module.cpp b/test/opt/module_test.cpp
index 622d920f..622d920f 100644
--- a/test/opt/test_module.cpp
+++ b/test/opt/module_test.cpp
diff --git a/test/opt/test_pass_manager.cpp b/test/opt/pass_manager_test.cpp
index 704aa539..704aa539 100644
--- a/test/opt/test_pass_manager.cpp
+++ b/test/opt/pass_manager_test.cpp
diff --git a/test/opt/test_set_spec_const_default_value.cpp b/test/opt/set_spec_const_default_value_test.cpp
index 0d4a1d22..a6eaab9e 100644
--- a/test/opt/test_set_spec_const_default_value.cpp
+++ b/test/opt/set_spec_const_default_value_test.cpp
@@ -473,13 +473,13 @@ INSTANTIATE_TEST_CASE_P(
// code
"OpDecorate %1 SpecId 100\n"
"%int = OpTypeInt 32 1\n"
- "%1 = OpConstant %int 101\n",
+ "%int_101 = OpConstant %int 101\n",
// default values
SpecIdToValueStrMap{{100, "0x7fffffff"}},
// expected
"OpDecorate %1 SpecId 100\n"
"%int = OpTypeInt 32 1\n"
- "%1 = OpConstant %int 101\n",
+ "%int_101 = OpConstant %int 101\n",
},
// 3. Do nothing when SpecId decoration is not attached to a
// OpSpecConstant{|True|False} instruction.
@@ -527,7 +527,7 @@ INSTANTIATE_TEST_CASE_P(
"%1 = OpDecorationGroup\n"
"OpGroupDecorate %1 %2\n"
"%int = OpTypeInt 32 1\n"
- "%2 = OpConstant %int 100\n",
+ "%int_100 = OpConstant %int 100\n",
// default values
SpecIdToValueStrMap{{100, "0xffffffff"}},
// expected
@@ -535,7 +535,7 @@ INSTANTIATE_TEST_CASE_P(
"%1 = OpDecorationGroup\n"
"OpGroupDecorate %1 %2\n"
"%int = OpTypeInt 32 1\n"
- "%2 = OpConstant %int 100\n",
+ "%int_100 = OpConstant %int 100\n",
},
}));
diff --git a/test/opt/test_strip_debug_info.cpp b/test/opt/strip_debug_info_test.cpp
index 9a56d867..9a56d867 100644
--- a/test/opt/test_strip_debug_info.cpp
+++ b/test/opt/strip_debug_info_test.cpp
diff --git a/test/opt/test_type_manager.cpp b/test/opt/type_manager_test.cpp
index 17eb2a49..17eb2a49 100644
--- a/test/opt/test_type_manager.cpp
+++ b/test/opt/type_manager_test.cpp
diff --git a/test/opt/test_types.cpp b/test/opt/types_test.cpp
index adbc870c..adbc870c 100644
--- a/test/opt/test_types.cpp
+++ b/test/opt/types_test.cpp
diff --git a/test/opt/test_unify_const.cpp b/test/opt/unify_const_test.cpp
index 58132017..58132017 100644
--- a/test/opt/test_unify_const.cpp
+++ b/test/opt/unify_const_test.cpp
diff --git a/test/opt/test_utils.cpp b/test/opt/utils_test.cpp
index 085c5f34..085c5f34 100644
--- a/test/opt/test_utils.cpp
+++ b/test/opt/utils_test.cpp
diff --git a/test/ParseNumber.cpp b/test/parse_number_test.cpp
index 9c8850b4..9c8850b4 100644
--- a/test/ParseNumber.cpp
+++ b/test/parse_number_test.cpp
diff --git a/test/SoftwareVersion.cpp b/test/software_version_test.cpp
index da64e1c5..e1b35044 100644
--- a/test/SoftwareVersion.cpp
+++ b/test/software_version_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include <sstream>
diff --git a/test/TargetEnv.cpp b/test/target_env_test.cpp
index c3d0543a..4df5f943 100644
--- a/test/TargetEnv.cpp
+++ b/test/target_env_test.cpp
@@ -14,7 +14,7 @@
#include <gmock/gmock.h>
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include "source/spirv_target_env.h"
diff --git a/test/TestFixture.h b/test/test_fixture.h
index f3cd1e40..e2948a89 100644
--- a/test/TestFixture.h
+++ b/test/test_fixture.h
@@ -15,7 +15,7 @@
#ifndef LIBSPIRV_TEST_TEST_FIXTURE_H_
#define LIBSPIRV_TEST_TEST_FIXTURE_H_
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace spvtest {
diff --git a/test/TextAdvance.cpp b/test/text_advance_test.cpp
index ec430d61..ffc8dbb2 100644
--- a/test/TextAdvance.cpp
+++ b/test/text_advance_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/TextDestroy.cpp b/test/text_destroy_test.cpp
index 61522f68..c956d72c 100644
--- a/test/TextDestroy.cpp
+++ b/test/text_destroy_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/TextLiteral.cpp b/test/text_literal_test.cpp
index c866bda7..e41a0146 100644
--- a/test/TextLiteral.cpp
+++ b/test/text_literal_test.cpp
@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "gmock/gmock.h"
#include "message.h"
diff --git a/test/TextStartsNewInst.cpp b/test/text_start_new_inst_test.cpp
index c7c6d391..6c3e5541 100644
--- a/test/TextStartsNewInst.cpp
+++ b/test/text_start_new_inst_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include <string>
diff --git a/test/TextToBinary.Annotation.cpp b/test/text_to_binary.annotation_test.cpp
index eb6bbf78..e0fe84e7 100644
--- a/test/TextToBinary.Annotation.cpp
+++ b/test/text_to_binary.annotation_test.cpp
@@ -15,12 +15,12 @@
// Assembler tests for instructions in the "Annotation" section of the
// SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include <sstream>
#include <tuple>
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "gmock/gmock.h"
namespace {
diff --git a/test/TextToBinary.Barrier.cpp b/test/text_to_binary.barrier_test.cpp
index 287ec311..c086caa0 100644
--- a/test/TextToBinary.Barrier.cpp
+++ b/test/text_to_binary.barrier_test.cpp
@@ -15,9 +15,9 @@
// Assembler tests for instructions in the "Barrier Instructions" section
// of the SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "gmock/gmock.h"
namespace {
diff --git a/test/TextToBinary.Constant.cpp b/test/text_to_binary.constant_test.cpp
index b27598ee..d975f1c9 100644
--- a/test/TextToBinary.Constant.cpp
+++ b/test/text_to_binary.constant_test.cpp
@@ -15,12 +15,12 @@
// Assembler tests for instructions in the "Group Instrucions" section of the
// SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include <cstdint>
#include <limits>
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "gmock/gmock.h"
namespace {
diff --git a/test/TextToBinary.ControlFlow.cpp b/test/text_to_binary.control_flow_test.cpp
index eec8ce81..8152bf24 100644
--- a/test/TextToBinary.ControlFlow.cpp
+++ b/test/text_to_binary.control_flow_test.cpp
@@ -19,9 +19,9 @@
#include <tuple>
#include <vector>
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "gmock/gmock.h"
namespace {
diff --git a/test/TextToBinary.Debug.cpp b/test/text_to_binary.debug_test.cpp
index 2be9be7d..cefaaec4 100644
--- a/test/TextToBinary.Debug.cpp
+++ b/test/text_to_binary.debug_test.cpp
@@ -15,11 +15,11 @@
// Assembler tests for instructions in the "Debug" section of the
// SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include <string>
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "gmock/gmock.h"
namespace {
diff --git a/test/TextToBinary.DeviceSideEnqueue.cpp b/test/text_to_binary.device_side_enqueue_test.cpp
index eaa108ed..852eef7a 100644
--- a/test/TextToBinary.DeviceSideEnqueue.cpp
+++ b/test/text_to_binary.device_side_enqueue_test.cpp
@@ -15,10 +15,10 @@
// Assembler tests for instructions in the "Device-Side Enqueue Instructions"
// section of the SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include "gmock/gmock.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
namespace {
using spvtest::MakeInstruction;
diff --git a/test/TextToBinary.Extension.cpp b/test/text_to_binary.extension_test.cpp
index b4508f20..44c9b1bf 100644
--- a/test/TextToBinary.Extension.cpp
+++ b/test/text_to_binary.extension_test.cpp
@@ -15,9 +15,9 @@
// Assembler tests for instructions in the "Extension Instruction" section
// of the SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "gmock/gmock.h"
#include "spirv/1.0/GLSL.std.450.h"
#include "spirv/1.0/OpenCL.std.h"
diff --git a/test/TextToBinary.Function.cpp b/test/text_to_binary.function_test.cpp
index 4246bad9..5f1b72a0 100644
--- a/test/TextToBinary.Function.cpp
+++ b/test/text_to_binary.function_test.cpp
@@ -15,10 +15,10 @@
// Assembler tests for instructions in the "Function" section of the
// SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include "gmock/gmock.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
namespace {
diff --git a/test/TextToBinary.Group.cpp b/test/text_to_binary.group_test.cpp
index fc41646f..6fb57066 100644
--- a/test/TextToBinary.Group.cpp
+++ b/test/text_to_binary.group_test.cpp
@@ -15,10 +15,10 @@
// Assembler tests for instructions in the "Group Instrucions" section of the
// SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include "gmock/gmock.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
namespace {
diff --git a/test/TextToBinary.Image.cpp b/test/text_to_binary.image_test.cpp
index 14f389dd..51dd52ea 100644
--- a/test/TextToBinary.Image.cpp
+++ b/test/text_to_binary.image_test.cpp
@@ -15,10 +15,10 @@
// Assembler tests for instructions in the "Image Instructions" section of
// the SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include "gmock/gmock.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
namespace {
diff --git a/test/TextToBinary.Literal.cpp b/test/text_to_binary.literal_test.cpp
index a4a55e83..46355818 100644
--- a/test/TextToBinary.Literal.cpp
+++ b/test/text_to_binary.literal_test.cpp
@@ -14,7 +14,7 @@
// Assembler tests for literal numbers and literal strings.
-#include "TestFixture.h"
+#include "test_fixture.h"
namespace {
diff --git a/test/TextToBinary.Memory.cpp b/test/text_to_binary.memory_test.cpp
index 9fbde994..2146fce6 100644
--- a/test/TextToBinary.Memory.cpp
+++ b/test/text_to_binary.memory_test.cpp
@@ -15,12 +15,12 @@
// Assembler tests for instructions in the "Memory Instructions" section of
// the SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include <sstream>
#include "gmock/gmock.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
namespace {
diff --git a/test/TextToBinary.Miscellaneous.cpp b/test/text_to_binary.misc_test.cpp
index c5acd940..470bdca4 100644
--- a/test/TextToBinary.Miscellaneous.cpp
+++ b/test/text_to_binary.misc_test.cpp
@@ -15,9 +15,9 @@
// Assembler tests for instructions in the "Miscellaneous" section of the
// SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "gmock/gmock.h"
namespace {
diff --git a/test/TextToBinary.ModeSetting.cpp b/test/text_to_binary.mode_setting_test.cpp
index 8d47010f..27991b2a 100644
--- a/test/TextToBinary.ModeSetting.cpp
+++ b/test/text_to_binary.mode_setting_test.cpp
@@ -15,9 +15,9 @@
// Assembler tests for instructions in the "Mode-Setting" section of the
// SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "gmock/gmock.h"
namespace {
diff --git a/test/TextToBinary.PipeStorage.cpp b/test/text_to_binary.pipe_storage_test.cpp
index 3537d83b..66d13eaf 100644
--- a/test/TextToBinary.PipeStorage.cpp
+++ b/test/text_to_binary.pipe_storage_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "gmock/gmock.h"
namespace {
diff --git a/test/TextToBinary.SubgroupDispatch.cpp b/test/text_to_binary.subgroup_dispatch_test.cpp
index 80f3c7e4..c74f9a6f 100644
--- a/test/TextToBinary.SubgroupDispatch.cpp
+++ b/test/text_to_binary.subgroup_dispatch_test.cpp
@@ -15,9 +15,9 @@
// Assembler tests for instructions in the "Barrier Instructions" section
// of the SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "gmock/gmock.h"
namespace {
diff --git a/test/TextToBinary.TypeDeclaration.cpp b/test/text_to_binary.type_declaration_test.cpp
index 4e548fbe..cc2b1656 100644
--- a/test/TextToBinary.TypeDeclaration.cpp
+++ b/test/text_to_binary.type_declaration_test.cpp
@@ -15,9 +15,9 @@
// Assembler tests for instructions in the "Type-Declaration" section of the
// SPIR-V spec.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
#include "gmock/gmock.h"
namespace {
diff --git a/test/TextToBinary.cpp b/test/text_to_binary_test.cpp
index 4db3ed23..ff7e04e5 100644
--- a/test/TextToBinary.cpp
+++ b/test/text_to_binary_test.cpp
@@ -19,8 +19,8 @@
#include "gmock/gmock.h"
-#include "TestFixture.h"
-#include "UnitSPIRV.h"
+#include "test_fixture.h"
+#include "unit_spirv.h"
#include "source/spirv_constant.h"
#include "source/util/bitutils.h"
#include "source/util/hex_float.h"
diff --git a/test/TextWordGet.cpp b/test/text_word_get_test.cpp
index 3b1e9967..dccc7133 100644
--- a/test/TextWordGet.cpp
+++ b/test/text_word_get_test.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace {
diff --git a/test/UnitSPIRV.cpp b/test/unit_spirv.cpp
index f89df6e1..c2a770a8 100644
--- a/test/UnitSPIRV.cpp
+++ b/test/unit_spirv.cpp
@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
#include "gmock/gmock.h"
-#include "TestFixture.h"
+#include "test_fixture.h"
namespace {
diff --git a/test/UnitSPIRV.h b/test/unit_spirv.h
index 823fd78e..823fd78e 100644
--- a/test/UnitSPIRV.h
+++ b/test/unit_spirv.h
diff --git a/test/val/CMakeLists.txt b/test/val/CMakeLists.txt
index 6518fca8..5ac13025 100644
--- a/test/val/CMakeLists.txt
+++ b/test/val/CMakeLists.txt
@@ -13,52 +13,65 @@
# limitations under the License.
set(VAL_TEST_COMMON_SRCS
- ${CMAKE_CURRENT_SOURCE_DIR}/../TestFixture.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../UnitSPIRV.h
- ${CMAKE_CURRENT_SOURCE_DIR}/../UnitSPIRV.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/ValidateFixtures.h
- ${CMAKE_CURRENT_SOURCE_DIR}/ValidateFixtures.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/../test_fixture.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/../unit_spirv.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/../unit_spirv.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/val_fixtures.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/val_fixtures.cpp
)
add_spvtools_unittest(TARGET val_capability
- SRCS ${CMAKE_CURRENT_SOURCE_DIR}/Validate.Capability.cpp
+ SRCS val_capability_test.cpp
${VAL_TEST_COMMON_SRCS}
LIBS ${SPIRV_TOOLS}
)
add_spvtools_unittest(TARGET val_cfg
- SRCS ${CMAKE_CURRENT_SOURCE_DIR}/Validate.CFG.cpp
+ SRCS val_cfg_test.cpp
${VAL_TEST_COMMON_SRCS}
LIBS ${SPIRV_TOOLS}
)
add_spvtools_unittest(TARGET val_id
- SRCS ${CMAKE_CURRENT_SOURCE_DIR}/ValidateID.cpp
+ SRCS val_id_test.cpp
${VAL_TEST_COMMON_SRCS}
LIBS ${SPIRV_TOOLS}
)
add_spvtools_unittest(TARGET val_layout
- SRCS ${CMAKE_CURRENT_SOURCE_DIR}/Validate.Layout.cpp
+ SRCS val_layout_test.cpp
${VAL_TEST_COMMON_SRCS}
LIBS ${SPIRV_TOOLS}
)
add_spvtools_unittest(TARGET val_ssa
- SRCS ${CMAKE_CURRENT_SOURCE_DIR}/Validate.SSA.cpp
+ SRCS val_ssa_test.cpp
${VAL_TEST_COMMON_SRCS}
LIBS ${SPIRV_TOOLS}
)
add_spvtools_unittest(TARGET val_storage
- SRCS ${CMAKE_CURRENT_SOURCE_DIR}/Validate.Storage.cpp
+ SRCS val_storage_test.cpp
${VAL_TEST_COMMON_SRCS}
LIBS ${SPIRV_TOOLS}
)
add_spvtools_unittest(TARGET val_state
- SRCS ${CMAKE_CURRENT_SOURCE_DIR}/ValidationState.cpp
+ SRCS val_state_test.cpp
${VAL_TEST_COMMON_SRCS}
LIBS ${SPIRV_TOOLS}
)
+
+add_spvtools_unittest(TARGET val_data
+ SRCS val_data_test.cpp
+ ${VAL_TEST_COMMON_SRCS}
+ LIBS ${SPIRV_TOOLS}
+)
+
+add_spvtools_unittest(TARGET val_limits
+ SRCS val_limits_test.cpp
+ ${VAL_TEST_COMMON_SRCS}
+ LIBS ${SPIRV_TOOLS}
+)
+
diff --git a/test/val/ValidateID.cpp b/test/val/ValidateID.cpp
deleted file mode 100644
index 727aa951..00000000
--- a/test/val/ValidateID.cpp
+++ /dev/null
@@ -1,1925 +0,0 @@
-// Copyright (c) 2015-2016 The Khronos Group Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <sstream>
-#include <string>
-
-#include "TestFixture.h"
-
-// NOTE: The tests in this file are ONLY testing ID usage, there for the input
-// SPIR-V does not follow the logical layout rules from the spec in all cases in
-// order to makes the tests smaller. Validation of the whole module is handled
-// in stages, ID validation is only one of these stages. All validation stages
-// are stand alone.
-
-namespace {
-
-using ::testing::ValuesIn;
-using spvtest::ScopedContext;
-using std::ostringstream;
-using std::string;
-using std::vector;
-
-class ValidateID : public ::testing::Test {
- public:
- virtual void TearDown() { spvBinaryDestroy(binary); }
- spv_const_binary get_const_binary() { return spv_const_binary(binary); }
- spv_binary binary;
-};
-
-const char kGLSL450MemoryModel[] = R"(
- OpCapability Shader
- OpCapability Addresses
- OpCapability Pipes
- OpCapability LiteralSampler
- OpCapability DeviceEnqueue
- OpMemoryModel Logical GLSL450
-)";
-
-const char kOpenCLMemoryModel32[] = R"(
- OpCapability Addresses
- OpCapability Linkage
- OpCapability Kernel
-%1 = OpExtInstImport "OpenCL.std"
- OpMemoryModel Physical32 OpenCL
-)";
-
-const char kOpenCLMemoryModel64[] = R"(
- OpCapability Addresses
- OpCapability Linkage
- OpCapability Kernel
- OpCapability Int64
-%1 = OpExtInstImport "OpenCL.std"
- OpMemoryModel Physical64 OpenCL
-)";
-
-// TODO(dekimir): this can be removed by adding a method to ValidateID akin to
-// OpTypeArrayLengthTest::Val().
-#define CHECK(str, expected) \
- spv_diagnostic diagnostic; \
- spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0); \
- std::string shader = std::string(kGLSL450MemoryModel) + str; \
- spv_result_t error = spvTextToBinary(context, shader.c_str(), shader.size(), \
- &binary, &diagnostic); \
- if (error) { \
- spvDiagnosticPrint(diagnostic); \
- spvDiagnosticDestroy(diagnostic); \
- ASSERT_EQ(SPV_SUCCESS, error) << shader; \
- } \
- spv_result_t result = spvValidate(context, get_const_binary(), &diagnostic); \
- if (SPV_SUCCESS != result) { \
- spvDiagnosticPrint(diagnostic); \
- spvDiagnosticDestroy(diagnostic); \
- } \
- ASSERT_EQ(expected, result); \
- spvContextDestroy(context);
-
-#define CHECK_KERNEL(str, expected, bitness) \
- ASSERT_TRUE(bitness == 32 || bitness == 64); \
- spv_diagnostic diagnostic; \
- spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_0); \
- std::string kernel = std::string(bitness == 32 ? kOpenCLMemoryModel32 \
- : kOpenCLMemoryModel64) + \
- str; \
- spv_result_t error = spvTextToBinary(context, kernel.c_str(), kernel.size(), \
- &binary, &diagnostic); \
- if (error) { \
- spvDiagnosticPrint(diagnostic); \
- spvDiagnosticDestroy(diagnostic); \
- ASSERT_EQ(SPV_SUCCESS, error); \
- } \
- spv_result_t result = spvValidate(context, get_const_binary(), &diagnostic); \
- if (SPV_SUCCESS != result) { \
- spvDiagnosticPrint(diagnostic); \
- spvDiagnosticDestroy(diagnostic); \
- } \
- ASSERT_EQ(expected, result); \
- spvContextDestroy(context);
-
-// TODO: OpUndef
-
-TEST_F(ValidateID, OpName) {
- const char* spirv = R"(
- OpName %2 "name"
-%1 = OpTypeInt 32 0
-%2 = OpTypePointer UniformConstant %1
-%3 = OpVariable %2 UniformConstant)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpMemberNameGood) {
- const char* spirv = R"(
- OpMemberName %2 0 "foo"
-%1 = OpTypeInt 32 0
-%2 = OpTypeStruct %1)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpMemberNameTypeBad) {
- const char* spirv = R"(
- OpMemberName %1 0 "foo"
-%1 = OpTypeInt 32 0)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpMemberNameMemberBad) {
- const char* spirv = R"(
- OpMemberName %2 1 "foo"
-%1 = OpTypeInt 32 0
-%2 = OpTypeStruct %1)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpLineGood) {
- const char* spirv = R"(
-%1 = OpString "/path/to/source.file"
- OpLine %1 0 0
-%2 = OpTypeInt 32 0
-%3 = OpTypePointer Input %2
-%4 = OpVariable %3 Input)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpLineFileBad) {
- const char* spirv = R"(
- OpLine %2 0 0
-%2 = OpTypeInt 32 0
-%3 = OpTypePointer Input %2
-%4 = OpVariable %3 Input)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpDecorateGood) {
- const char* spirv = R"(
- OpDecorate %2 GLSLShared
-%1 = OpTypeInt 64 0
-%2 = OpTypeStruct %1 %1)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpDecorateBad) {
- const char* spirv = R"(
-OpDecorate %1 GLSLShared)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpMemberDecorateGood) {
- const char* spirv = R"(
- OpMemberDecorate %2 0 Uniform
-%1 = OpTypeInt 32 0
-%2 = OpTypeStruct %1 %1)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpMemberDecorateBad) {
- const char* spirv = R"(
- OpMemberDecorate %1 0 Uniform
-%1 = OpTypeInt 32 0)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpMemberDecorateMemberBad) {
- const char* spirv = R"(
- OpMemberDecorate %2 3 Uniform
-%1 = OpTypeInt 32 0
-%2 = OpTypeStruct %1 %1)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpGroupDecorateGood) {
- const char* spirv = R"(
-%1 = OpDecorationGroup
- OpDecorate %1 Uniform
- OpDecorate %1 GLSLShared
- OpGroupDecorate %1 %3 %4
-%2 = OpTypeInt 32 0
-%3 = OpConstant %2 42
-%4 = OpConstant %2 23)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpGroupDecorateDecorationGroupBad) {
- const char* spirv = R"(
- OpGroupDecorate %2 %3 %4
-%2 = OpTypeInt 32 0
-%3 = OpConstant %2 42
-%4 = OpConstant %2 23)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpGroupDecorateTargetBad) {
- const char* spirv = R"(
-%1 = OpDecorationGroup
- OpDecorate %1 Uniform
- OpDecorate %1 GLSLShared
- OpGroupDecorate %1 %3
-%2 = OpTypeInt 32 0)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-// TODO: OpGroupMemberDecorate
-// TODO: OpExtInst
-
-TEST_F(ValidateID, OpEntryPointGood) {
- const char* spirv = R"(
- OpEntryPoint GLCompute %3 ""
-%1 = OpTypeVoid
-%2 = OpTypeFunction %1
-%3 = OpFunction %1 None %2
-%4 = OpLabel
- OpReturn
- OpFunctionEnd
-)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpEntryPointFunctionBad) {
- const char* spirv = R"(
- OpEntryPoint GLCompute %1 ""
-%1 = OpTypeVoid)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpEntryPointParameterCountBad) {
- const char* spirv = R"(
- OpEntryPoint GLCompute %3 ""
-%1 = OpTypeVoid
-%2 = OpTypeFunction %1 %1
-%3 = OpFunction %1 None %2
-%4 = OpLabel
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpEntryPointReturnTypeBad) {
- const char* spirv = R"(
- OpEntryPoint GLCompute %3 ""
-%1 = OpTypeInt 32 0
-%2 = OpTypeFunction %1
-%3 = OpFunction %1 None %2
-%4 = OpLabel
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpExecutionModeGood) {
- const char* spirv = R"(
- OpEntryPoint GLCompute %3 ""
- OpExecutionMode %3 LocalSize 1 1 1
-%1 = OpTypeVoid
-%2 = OpTypeFunction %1
-%3 = OpFunction %1 None %2
-%4 = OpLabel
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpExecutionModeEntryPointMissing) {
- const char* spirv = R"(
- OpExecutionMode %3 LocalSize 1 1 1
-%1 = OpTypeVoid
-%2 = OpTypeFunction %1
-%3 = OpFunction %1 None %2
-%4 = OpLabel
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpExecutionModeEntryPointBad) {
- const char* spirv = R"(
- OpEntryPoint GLCompute %3 "" %a
- OpExecutionMode %a LocalSize 1 1 1
-%void = OpTypeVoid
-%ptr = OpTypePointer Input %void
-%a = OpVariable %ptr Input
-%2 = OpTypeFunction %void
-%3 = OpFunction %void None %2
-%4 = OpLabel
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpTypeVectorFloat) {
- const char* spirv = R"(
-%1 = OpTypeFloat 32
-%2 = OpTypeVector %1 4)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpTypeVectorInt) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 1
-%2 = OpTypeVector %1 4)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpTypeVectorUInt) {
- const char* spirv = R"(
-%1 = OpTypeInt 64 0
-%2 = OpTypeVector %1 4)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpTypeVectorBool) {
- const char* spirv = R"(
-%1 = OpTypeBool
-%2 = OpTypeVector %1 4)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpTypeVectorComponentTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeFloat 32
-%2 = OpTypePointer UniformConstant %1
-%3 = OpTypeVector %2 4)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpTypeMatrixGood) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpTypeVector %1 2
-%3 = OpTypeMatrix %2 3)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpTypeMatrixColumnTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpTypeMatrix %1 3)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpTypeSamplerGood) {
- // In Rev31, OpTypeSampler takes no arguments.
- const char* spirv = R"(
-%s = OpTypeSampler)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpTypeArrayGood) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpConstant %1 1
-%3 = OpTypeArray %1 %2)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpTypeArrayElementTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpConstant %1 1
-%3 = OpTypeArray %2 %2)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-// Signed or unsigned.
-enum Signed { kSigned, kUnsigned };
-
-// Creates an assembly snippet declaring OpTypeArray with the given length.
-string MakeArrayLength(const string& len, Signed isSigned, int width) {
- ostringstream ss;
- ss << kGLSL450MemoryModel;
- ss << " %t = OpTypeInt " << width << (isSigned == kSigned ? " 1" : " 0")
- << " %l = OpConstant %t " << len << " %a = OpTypeArray %t %l";
- return ss.str();
-}
-
-// Tests OpTypeArray. Parameter is the width (in bits) of the array-length's
-// type.
-class OpTypeArrayLengthTest
- : public spvtest::TextToBinaryTestBase<::testing::TestWithParam<int>> {
- protected:
- OpTypeArrayLengthTest()
- : position_(spv_position_t{0, 0, 0}),
- diagnostic_(spvDiagnosticCreate(&position_, "")) {}
-
- ~OpTypeArrayLengthTest() { spvDiagnosticDestroy(diagnostic_); }
-
- // Runs spvValidate() on v, printing any errors via spvDiagnosticPrint().
- spv_result_t Val(const SpirvVector& v) {
- spv_const_binary_t cbinary{v.data(), v.size()};
- const auto status =
- spvValidate(ScopedContext().context, &cbinary, &diagnostic_);
- if (status != SPV_SUCCESS) {
- spvDiagnosticPrint(diagnostic_);
- }
- return status;
- }
-
- private:
- spv_position_t position_; // For creating diagnostic_.
- spv_diagnostic diagnostic_;
-};
-
-TEST_P(OpTypeArrayLengthTest, LengthPositive) {
- const int width = GetParam();
- EXPECT_EQ(SPV_SUCCESS,
- Val(CompileSuccessfully(MakeArrayLength("1", kSigned, width))));
- EXPECT_EQ(SPV_SUCCESS,
- Val(CompileSuccessfully(MakeArrayLength("1", kUnsigned, width))));
- EXPECT_EQ(SPV_SUCCESS,
- Val(CompileSuccessfully(MakeArrayLength("2", kSigned, width))));
- EXPECT_EQ(SPV_SUCCESS,
- Val(CompileSuccessfully(MakeArrayLength("2", kUnsigned, width))));
- EXPECT_EQ(SPV_SUCCESS,
- Val(CompileSuccessfully(MakeArrayLength("55", kSigned, width))));
- EXPECT_EQ(SPV_SUCCESS,
- Val(CompileSuccessfully(MakeArrayLength("55", kUnsigned, width))));
- const string fpad(width / 4 - 1, 'F');
- EXPECT_EQ(
- SPV_SUCCESS,
- Val(CompileSuccessfully(MakeArrayLength("0x7" + fpad, kSigned, width))));
- EXPECT_EQ(SPV_SUCCESS, Val(CompileSuccessfully(
- MakeArrayLength("0xF" + fpad, kUnsigned, width))));
-}
-
-TEST_P(OpTypeArrayLengthTest, LengthZero) {
- const int width = GetParam();
- EXPECT_EQ(SPV_ERROR_INVALID_ID,
- Val(CompileSuccessfully(MakeArrayLength("0", kSigned, width))));
- EXPECT_EQ(SPV_ERROR_INVALID_ID,
- Val(CompileSuccessfully(MakeArrayLength("0", kUnsigned, width))));
-}
-
-TEST_P(OpTypeArrayLengthTest, LengthNegative) {
- const int width = GetParam();
- EXPECT_EQ(SPV_ERROR_INVALID_ID,
- Val(CompileSuccessfully(MakeArrayLength("-1", kSigned, width))));
- EXPECT_EQ(SPV_ERROR_INVALID_ID,
- Val(CompileSuccessfully(MakeArrayLength("-2", kSigned, width))));
- EXPECT_EQ(SPV_ERROR_INVALID_ID,
- Val(CompileSuccessfully(MakeArrayLength("-123", kSigned, width))));
- const string neg_max = "0x8" + string(width / 4 - 1, '0');
- EXPECT_EQ(SPV_ERROR_INVALID_ID,
- Val(CompileSuccessfully(MakeArrayLength(neg_max, kSigned, width))));
-}
-
-INSTANTIATE_TEST_CASE_P(Widths, OpTypeArrayLengthTest,
- ValuesIn(vector<int>{8, 16, 32, 48, 64}));
-
-TEST_F(ValidateID, OpTypeArrayLengthNull) {
- const char* spirv = R"(
-%i32 = OpTypeInt 32 1
-%len = OpConstantNull %i32
-%ary = OpTypeArray %i32 %len)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpTypeArrayLengthSpecConst) {
- const char* spirv = R"(
-%i32 = OpTypeInt 32 1
-%len = OpSpecConstant %i32 2
-%ary = OpTypeArray %i32 %len)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpTypeArrayLengthSpecConstOp) {
- const char* spirv = R"(
-%i32 = OpTypeInt 32 1
-%c1 = OpConstant %i32 1
-%c2 = OpConstant %i32 2
-%len = OpSpecConstantOp %i32 IAdd %c1 %c2
-%ary = OpTypeArray %i32 %len)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpTypeRuntimeArrayGood) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpTypeRuntimeArray %1)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpTypeRuntimeArrayBad) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpConstant %1 0
-%3 = OpTypeRuntimeArray %2)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-// TODO: Object of this type can only be created with OpVariable using the
-// Unifrom Storage Class
-
-TEST_F(ValidateID, OpTypeStructGood) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpTypeFloat 64
-%3 = OpTypePointer Input %1
-%4 = OpTypeStruct %1 %2 %3)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpTypeStructMemberTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpTypeFloat 64
-%3 = OpConstant %2 0.0
-%4 = OpTypeStruct %1 %2 %3)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpTypePointerGood) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpTypePointer Input %1)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpTypePointerBad) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpConstant %1 0
-%3 = OpTypePointer Input %2)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpTypeFunctionGood) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeFunction %1)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpTypeFunctionReturnTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpConstant %1 0
-%3 = OpTypeFunction %2)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpTypeFunctionParameterBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpConstant %2 0
-%4 = OpTypeFunction %1 %2 %3)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpTypePipeGood) {
- const char* spirv = R"(
-%1 = OpTypeFloat 32
-%2 = OpTypeVector %1 16
-%3 = OpTypePipe ReadOnly)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpConstantTrueGood) {
- const char* spirv = R"(
-%1 = OpTypeBool
-%2 = OpConstantTrue %1)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpConstantTrueBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpConstantTrue %1)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpConstantFalseGood) {
- const char* spirv = R"(
-%1 = OpTypeBool
-%2 = OpConstantTrue %1)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpConstantFalseBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpConstantFalse %1)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpConstantGood) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpConstant %1 1)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpConstantBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpConstant !1 !0)";
- // The expected failure code is implementation dependent (currently
- // INVALID_BINARY because the binary parser catches these cases) and may
- // change over time, but this must always fail.
- CHECK(spirv, SPV_ERROR_INVALID_BINARY);
-}
-
-TEST_F(ValidateID, OpConstantCompositeVectorGood) {
- const char* spirv = R"(
-%1 = OpTypeFloat 32
-%2 = OpTypeVector %1 4
-%3 = OpConstant %1 3.14
-%4 = OpConstantComposite %2 %3 %3 %3 %3)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpConstantCompositeVectorWithUndefGood) {
- const char* spirv = R"(
-%1 = OpTypeFloat 32
-%2 = OpTypeVector %1 4
-%3 = OpConstant %1 3.14
-%9 = OpUndef %1
-%4 = OpConstantComposite %2 %3 %3 %3 %9)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpConstantCompositeVectorResultTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeFloat 32
-%2 = OpTypeVector %1 4
-%3 = OpConstant %1 3.14
-%4 = OpConstantComposite %1 %3 %3 %3 %3)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpConstantCompositeVectorConstituentTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeFloat 32
-%2 = OpTypeVector %1 4
-%4 = OpTypeInt 32 0
-%3 = OpConstant %1 3.14
-%5 = OpConstant %4 42 ; bad type for constant value
-%6 = OpConstantComposite %2 %3 %5 %3 %3)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpConstantCompositeVectorConstituentUndefTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeFloat 32
-%2 = OpTypeVector %1 4
-%4 = OpTypeInt 32 0
-%3 = OpConstant %1 3.14
-%5 = OpUndef %4 ; bad type for undef value
-%6 = OpConstantComposite %2 %3 %5 %3 %3)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpConstantCompositeMatrixGood) {
- const char* spirv = R"(
- %1 = OpTypeFloat 32
- %2 = OpTypeVector %1 4
- %3 = OpTypeMatrix %2 4
- %4 = OpConstant %1 1.0
- %5 = OpConstant %1 0.0
- %6 = OpConstantComposite %2 %4 %5 %5 %5
- %7 = OpConstantComposite %2 %5 %4 %5 %5
- %8 = OpConstantComposite %2 %5 %5 %4 %5
- %9 = OpConstantComposite %2 %5 %5 %5 %4
-%10 = OpConstantComposite %3 %6 %7 %8 %9)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpConstantCompositeMatrixUndefGood) {
- const char* spirv = R"(
- %1 = OpTypeFloat 32
- %2 = OpTypeVector %1 4
- %3 = OpTypeMatrix %2 4
- %4 = OpConstant %1 1.0
- %5 = OpConstant %1 0.0
- %6 = OpConstantComposite %2 %4 %5 %5 %5
- %7 = OpConstantComposite %2 %5 %4 %5 %5
- %8 = OpConstantComposite %2 %5 %5 %4 %5
- %9 = OpUndef %2
-%10 = OpConstantComposite %3 %6 %7 %8 %9)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpConstantCompositeMatrixConstituentTypeBad) {
- const char* spirv = R"(
- %1 = OpTypeFloat 32
- %2 = OpTypeVector %1 4
-%11 = OpTypeVector %1 3
- %3 = OpTypeMatrix %2 4
- %4 = OpConstant %1 1.0
- %5 = OpConstant %1 0.0
- %6 = OpConstantComposite %2 %4 %5 %5 %5
- %7 = OpConstantComposite %2 %5 %4 %5 %5
- %8 = OpConstantComposite %2 %5 %5 %4 %5
- %9 = OpConstantComposite %11 %5 %5 %5
-%10 = OpConstantComposite %3 %6 %7 %8 %9)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpConstantCompositeMatrixConstituentUndefTypeBad) {
- const char* spirv = R"(
- %1 = OpTypeFloat 32
- %2 = OpTypeVector %1 4
-%11 = OpTypeVector %1 3
- %3 = OpTypeMatrix %2 4
- %4 = OpConstant %1 1.0
- %5 = OpConstant %1 0.0
- %6 = OpConstantComposite %2 %4 %5 %5 %5
- %7 = OpConstantComposite %2 %5 %4 %5 %5
- %8 = OpConstantComposite %2 %5 %5 %4 %5
- %9 = OpUndef %11
-%10 = OpConstantComposite %3 %6 %7 %8 %9)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpConstantCompositeMatrixColumnTypeBad) {
- const char* spirv = R"(
- %1 = OpTypeInt 32 0
- %2 = OpTypeFloat 32
- %3 = OpTypeVector %1 2
- %4 = OpTypeVector %3 2
- %5 = OpTypeMatrix %2 2
- %6 = OpConstant %1 42
- %7 = OpConstant %2 3.14
- %8 = OpConstantComposite %3 %6 %6
- %9 = OpConstantComposite %4 %7 %7
-%10 = OpConstantComposite %5 %8 %9)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpConstantCompositeArrayGood) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpConstant %1 4
-%3 = OpTypeArray %1 %2
-%4 = OpConstantComposite %3 %2 %2 %2 %2)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpConstantCompositeArrayWithUndefGood) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpConstant %1 4
-%9 = OpUndef %1
-%3 = OpTypeArray %1 %2
-%4 = OpConstantComposite %3 %2 %2 %2 %9)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpConstantCompositeArrayConstConstituentBad) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpConstant %1 4
-%3 = OpTypeArray %1 %2
-%4 = OpConstantComposite %3 %2 %2 %2 %1)"; // Uses a type as operand
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpConstantCompositeArrayConstituentTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpConstant %1 4
-%3 = OpTypeArray %1 %2
-%5 = OpTypeFloat 32
-%6 = OpConstant %5 3.14 ; bad type for const value
-%4 = OpConstantComposite %3 %2 %2 %2 %6)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpConstantCompositeArrayConstituentUndefTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpConstant %1 4
-%3 = OpTypeArray %1 %2
-%5 = OpTypeFloat 32
-%6 = OpUndef %5 ; bad type for undef
-%4 = OpConstantComposite %3 %2 %2 %2 %6)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpConstantCompositeStructGood) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpTypeInt 64 1
-%3 = OpTypeStruct %1 %1 %2
-%4 = OpConstant %1 42
-%5 = OpConstant %2 4300000000
-%6 = OpConstantComposite %3 %4 %4 %5)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpConstantCompositeStructUndefGood) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpTypeInt 64 1
-%3 = OpTypeStruct %1 %1 %2
-%4 = OpConstant %1 42
-%5 = OpUndef %2
-%6 = OpConstantComposite %3 %4 %4 %5)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpConstantCompositeStructMemberTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpTypeInt 64 1
-%3 = OpTypeStruct %1 %1 %2
-%4 = OpConstant %1 42
-%5 = OpConstant %2 4300000000
-%6 = OpConstantComposite %3 %4 %5 %4)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpConstantCompositeStructMemberUndefTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 0
-%2 = OpTypeInt 64 1
-%3 = OpTypeStruct %1 %1 %2
-%4 = OpConstant %1 42
-%5 = OpUndef %2
-%6 = OpConstantComposite %3 %4 %5 %4)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpConstantSamplerGood) {
- const char* spirv = R"(
-%float = OpTypeFloat 32
-%samplerType = OpTypeSampler
-%3 = OpConstantSampler %samplerType ClampToEdge 0 Nearest)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpConstantSamplerResultTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeFloat 32
-%2 = OpConstantSampler %1 Clamp 0 Nearest)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpConstantNullGood) {
- const char* spirv = R"(
- %1 = OpTypeBool
- %2 = OpConstantNull %1
- %3 = OpTypeInt 32 0
- %4 = OpConstantNull %3
- %5 = OpTypeFloat 32
- %6 = OpConstantNull %5
- %7 = OpTypePointer UniformConstant %3
- %8 = OpConstantNull %7
- %9 = OpTypeEvent
-%10 = OpConstantNull %9
-%11 = OpTypeDeviceEvent
-%12 = OpConstantNull %11
-%13 = OpTypeReserveId
-%14 = OpConstantNull %13
-%15 = OpTypeQueue
-%16 = OpConstantNull %15
-%17 = OpTypeVector %3 2
-%18 = OpConstantNull %17
-%19 = OpTypeMatrix %17 2
-%20 = OpConstantNull %19
-%25 = OpConstant %3 8
-%21 = OpTypeArray %3 %25
-%22 = OpConstantNull %21
-%23 = OpTypeStruct %3 %5 %1
-%24 = OpConstantNull %23
-%26 = OpTypeArray %17 %25
-%27 = OpConstantNull %26
-%28 = OpTypeStruct %7 %26 %26 %1
-%29 = OpConstantNull %28
-)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpConstantNullBasicBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpConstantNull %1)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpConstantNullArrayBad) {
- const char* spirv = R"(
-%2 = OpTypeInt 32 0
-%3 = OpTypeSampler
-%4 = OpConstant %2 4
-%5 = OpTypeArray %3 %4
-%6 = OpConstantNull %5)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpConstantNullStructBad) {
- const char* spirv = R"(
-%2 = OpTypeSampler
-%3 = OpTypeStruct %2 %2
-%4 = OpConstantNull %3)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpConstantNullRuntimeArrayBad) {
- const char* spirv = R"(
-%bool = OpTypeBool
-%array = OpTypeRuntimeArray %bool
-%null = OpConstantNull %array)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpSpecConstantTrueGood) {
- const char* spirv = R"(
-%1 = OpTypeBool
-%2 = OpSpecConstantTrue %1)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpSpecConstantTrueBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpSpecConstantTrue %1)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpSpecConstantFalseGood) {
- const char* spirv = R"(
-%1 = OpTypeBool
-%2 = OpSpecConstantFalse %1)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpSpecConstantFalseBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpSpecConstantFalse %1)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpSpecConstantGood) {
- const char* spirv = R"(
-%1 = OpTypeFloat 32
-%2 = OpSpecConstant %1 42)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpSpecConstantBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpSpecConstant !1 !4)";
- // The expected failure code is implementation dependent (currently
- // INVALID_BINARY because the binary parser catches these cases) and may
- // change over time, but this must always fail.
- CHECK(spirv, SPV_ERROR_INVALID_BINARY);
-}
-
-// TODO: OpSpecConstantComposite
-// TODO: OpSpecConstantOp
-
-TEST_F(ValidateID, OpVariableGood) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 1
-%2 = OpTypePointer Input %1
-%3 = OpVariable %2 Input)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpVariableInitializerGood) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 1
-%2 = OpTypePointer Input %1
-%3 = OpConstant %1 42
-%4 = OpVariable %2 Input %3)";
- CHECK(spirv, SPV_SUCCESS);
-}
-// TODO: Positive test OpVariable with OpConstantNull of OpTypePointer
-TEST_F(ValidateID, OpVariableResultTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 1
-%2 = OpVariable %1 Input)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpVariableInitializerBad) {
- const char* spirv = R"(
-%1 = OpTypeInt 32 1
-%2 = OpTypePointer Input %1
-%3 = OpVariable %2 Input %2)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpLoadGood) {
- const char* spirv = R"(
- %1 = OpTypeVoid
- %2 = OpTypeInt 32 1
- %3 = OpTypePointer UniformConstant %2
- %4 = OpTypeFunction %1
- %5 = OpVariable %3 UniformConstant
- %6 = OpFunction %1 None %4
- %7 = OpLabel
- %8 = OpLoad %2 %5
- %9 = OpReturn
-%10 = OpFunctionEnd
-)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpLoadResultTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 1
-%3 = OpTypePointer UniformConstant %2
-%4 = OpTypeFunction %1
-%5 = OpVariable %3 UniformConstant
-%6 = OpFunction %1 None %4
-%7 = OpLabel
-%8 = OpLoad %3 %5
- OpReturn
- OpFunctionEnd
-)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpLoadPointerBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 1
-%9 = OpTypeFloat 32
-%3 = OpTypePointer UniformConstant %2
-%4 = OpTypeFunction %1
-%6 = OpFunction %1 None %4
-%7 = OpLabel
-%8 = OpLoad %9 %3
- OpReturn
- OpFunctionEnd
-)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpStoreGood) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 1
-%3 = OpTypePointer UniformConstant %2
-%4 = OpTypeFunction %1
-%5 = OpConstant %2 42
-%6 = OpVariable %3 UniformConstant
-%7 = OpFunction %1 None %4
-%8 = OpLabel
- OpStore %6 %5
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpStorePointerBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 1
-%3 = OpTypePointer UniformConstant %2
-%4 = OpTypeFunction %1
-%5 = OpConstant %2 42
-%6 = OpVariable %3 UniformConstant
-%7 = OpFunction %1 None %4
-%8 = OpLabel
- OpStore %3 %5
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpStoreObjectGood) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 1
-%3 = OpTypePointer UniformConstant %2
-%4 = OpTypeFunction %1
-%5 = OpConstant %2 42
-%6 = OpVariable %3 UniformConstant
-%7 = OpFunction %1 None %4
-%8 = OpLabel
- OpStore %6 %7
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpStoreTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 1
-%9 = OpTypeFloat 32
-%3 = OpTypePointer UniformConstant %2
-%4 = OpTypeFunction %1
-%5 = OpConstant %9 3.14
-%6 = OpVariable %3 UniformConstant
-%7 = OpFunction %1 None %4
-%8 = OpLabel
- OpStore %6 %5
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpStoreVoid) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 1
-%3 = OpTypePointer UniformConstant %2
-%4 = OpTypeFunction %1
-%6 = OpVariable %3 UniformConstant
-%7 = OpFunction %1 None %4
-%8 = OpLabel
-%9 = OpFunctionCall %1 %7
- OpStore %6 %9
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpStoreLabel) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 1
-%3 = OpTypePointer UniformConstant %2
-%4 = OpTypeFunction %1
-%6 = OpVariable %3 UniformConstant
-%7 = OpFunction %1 None %4
-%8 = OpLabel
- OpStore %6 %8
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-// TODO: enable when this bug is fixed:
-// https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404
-TEST_F(ValidateID, DISABLED_OpStoreFunction) {
- const char* spirv = R"(
-%2 = OpTypeInt 32 1
-%3 = OpTypePointer UniformConstant %2
-%4 = OpTypeFunction %2
-%5 = OpConstant %2 123
-%6 = OpVariable %3 UniformConstant
-%7 = OpFunction %2 None %4
-%8 = OpLabel
- OpStore %6 %7
- OpReturnValue %5
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpCopyMemoryGood) {
- const char* spirv = R"(
- %1 = OpTypeVoid
- %2 = OpTypeInt 32 0
- %3 = OpTypePointer UniformConstant %2
- %4 = OpConstant %2 42
- %5 = OpVariable %3 UniformConstant %4
- %6 = OpTypePointer Function %2
- %7 = OpTypeFunction %1
- %8 = OpFunction %1 None %7
- %9 = OpLabel
-%10 = OpVariable %6 Function
- OpCopyMemory %10 %5 None
- OpReturn
- OpFunctionEnd
-)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpCopyMemoryBad) {
- const char* spirv = R"(
- %1 = OpTypeVoid
- %2 = OpTypeInt 32 0
- %3 = OpTypePointer UniformConstant %2
- %4 = OpConstant %2 42
- %5 = OpVariable %3 UniformConstant %4
-%11 = OpTypeFloat 32
- %6 = OpTypePointer Function %11
- %7 = OpTypeFunction %1
- %8 = OpFunction %1 None %7
- %9 = OpLabel
-%10 = OpVariable %6 Function
- OpCopyMemory %10 %5 None
- OpReturn
- OpFunctionEnd
-)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-// TODO: OpCopyMemorySized
-TEST_F(ValidateID, OpCopyMemorySizedGood) {
- const char* spirv = R"(
- %1 = OpTypeVoid
- %2 = OpTypeInt 32 0
- %3 = OpTypePointer UniformConstant %2
- %4 = OpTypePointer Function %2
- %5 = OpConstant %2 4
- %6 = OpVariable %3 UniformConstant %5
- %7 = OpTypeFunction %1
- %8 = OpFunction %1 None %7
- %9 = OpLabel
-%10 = OpVariable %4 Function
- OpCopyMemorySized %10 %6 %5 None
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpCopyMemorySizedTargetBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypePointer UniformConstant %2
-%4 = OpTypePointer Function %2
-%5 = OpConstant %2 4
-%6 = OpVariable %3 UniformConstant %5
-%7 = OpTypeFunction %1
-%8 = OpFunction %1 None %7
-%9 = OpLabel
- OpCopyMemorySized %9 %6 %5 None
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpCopyMemorySizedSourceBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypePointer UniformConstant %2
-%4 = OpTypePointer Function %2
-%5 = OpConstant %2 4
-%6 = OpTypeFunction %1
-%7 = OpFunction %1 None %6
-%8 = OpLabel
-%9 = OpVariable %4 Function
- OpCopyMemorySized %9 %6 %5 None
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpCopyMemorySizedSizeBad) {
- const char* spirv = R"(
- %1 = OpTypeVoid
- %2 = OpTypeInt 32 0
- %3 = OpTypePointer UniformConstant %2
- %4 = OpTypePointer Function %2
- %5 = OpConstant %2 4
- %6 = OpVariable %3 UniformConstant %5
- %7 = OpTypeFunction %1
- %8 = OpFunction %1 None %7
- %9 = OpLabel
-%10 = OpVariable %4 Function
- OpCopyMemorySized %10 %6 %6 None
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpCopyMemorySizedSizeTypeBad) {
- const char* spirv = R"(
- %1 = OpTypeVoid
- %2 = OpTypeInt 32 0
- %3 = OpTypePointer UniformConstant %2
- %4 = OpTypePointer Function %2
- %5 = OpConstant %2 4
- %6 = OpVariable %3 UniformConstant %5
- %7 = OpTypeFunction %1
-%11 = OpTypeFloat 32
-%12 = OpConstant %11 1.0
- %8 = OpFunction %1 None %7
- %9 = OpLabel
-%10 = OpVariable %4 Function
- OpCopyMemorySized %10 %6 %12 None
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-// TODO: OpAccessChain
-// TODO: OpInBoundsAccessChain
-// TODO: OpArrayLength
-// TODO: OpImagePointer
-// TODO: OpGenericPtrMemSemantics
-
-TEST_F(ValidateID, OpFunctionGood) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 1
-%3 = OpTypeFunction %1 %2 %2
-%4 = OpFunction %1 None %3
- OpFunctionEnd)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpFunctionResultTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 1
-%5 = OpConstant %2 42
-%3 = OpTypeFunction %1 %2 %2
-%4 = OpFunction %2 None %3
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpFunctionFunctionTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 1
-%4 = OpFunction %1 None %2
-OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpFunctionParameterGood) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %1 %2
-%4 = OpFunction %1 None %3
-%5 = OpFunctionParameter %2
-%6 = OpLabel
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpFunctionParameterMultipleGood) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %1 %2 %2
-%4 = OpFunction %1 None %3
-%5 = OpFunctionParameter %2
-%6 = OpFunctionParameter %2
-%7 = OpLabel
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpFunctionParameterResultTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %1 %2
-%4 = OpFunction %1 None %3
-%5 = OpFunctionParameter %1
-%6 = OpLabel
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpFunctionCallGood) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %2 %2
-%4 = OpTypeFunction %1
-%5 = OpConstant %2 42 ;21
-
-%6 = OpFunction %2 None %3
-%7 = OpFunctionParameter %2
-%8 = OpLabel
- OpReturnValue %7
- OpFunctionEnd
-
-%10 = OpFunction %1 None %4
-%11 = OpLabel
-%12 = OpFunctionCall %2 %6 %5
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_SUCCESS);
-}
-TEST_F(ValidateID, OpFunctionCallResultTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %2 %2
-%4 = OpTypeFunction %1
-%5 = OpConstant %2 42 ;21
-
-%6 = OpFunction %2 None %3
-%7 = OpFunctionParameter %2
-%8 = OpLabel
-%9 = OpLoad %2 %7
- OpReturnValue %9
- OpFunctionEnd
-
-%10 = OpFunction %1 None %4
-%11 = OpLabel
-%12 = OpFunctionCall %1 %6 %5
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpFunctionCallFunctionBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %2 %2
-%4 = OpTypeFunction %1
-%5 = OpConstant %2 42 ;21
-
-%10 = OpFunction %1 None %4
-%11 = OpLabel
-%12 = OpFunctionCall %2 %5 %5
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-TEST_F(ValidateID, OpFunctionCallArgumentTypeBad) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %2 %2
-%4 = OpTypeFunction %1
-%5 = OpConstant %2 42
-
-%13 = OpTypeFloat 32
-%14 = OpConstant %13 3.14
-
-%6 = OpFunction %2 None %3
-%7 = OpFunctionParameter %2
-%8 = OpLabel
-%9 = OpLoad %2 %7
- OpReturnValue %9
- OpFunctionEnd
-
-%10 = OpFunction %1 None %4
-%11 = OpLabel
-%12 = OpFunctionCall %2 %6 %14
- OpReturn
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-#if 0
-TEST_F(ValidateID, OpFunctionCallArgumentCountBar) {
- const char *spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %2 %2
-%4 = OpTypeFunction %1
-%5 = OpConstant %2 42 ;21
-
-%6 = OpFunction %2 None %3
-%7 = OpFunctionParameter %2
-%8 = OpLabel
-%9 = OpLoad %2 %7
- OpReturnValue %9
- OpFunctionEnd
-
-%10 = OpFunction %1 None %4
-%11 = OpLabel
- OpReturn
-%12 = OpFunctionCall %2 %6 %5
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-#endif
-
-// TODO: OpSampledImage
-// TODO: The many things that changed with how images are used.
-// TODO: OpTextureSample
-// TODO: OpTextureSampleDref
-// TODO: OpTextureSampleLod
-// TODO: OpTextureSampleProj
-// TODO: OpTextureSampleGrad
-// TODO: OpTextureSampleOffset
-// TODO: OpTextureSampleProjLod
-// TODO: OpTextureSampleProjGrad
-// TODO: OpTextureSampleLodOffset
-// TODO: OpTextureSampleProjOffset
-// TODO: OpTextureSampleGradOffset
-// TODO: OpTextureSampleProjLodOffset
-// TODO: OpTextureSampleProjGradOffset
-// TODO: OpTextureFetchTexelLod
-// TODO: OpTextureFetchTexelOffset
-// TODO: OpTextureFetchSample
-// TODO: OpTextureFetchTexel
-// TODO: OpTextureGather
-// TODO: OpTextureGatherOffset
-// TODO: OpTextureGatherOffsets
-// TODO: OpTextureQuerySizeLod
-// TODO: OpTextureQuerySize
-// TODO: OpTextureQueryLevels
-// TODO: OpTextureQuerySamples
-// TODO: OpConvertUToF
-// TODO: OpConvertFToS
-// TODO: OpConvertSToF
-// TODO: OpConvertUToF
-// TODO: OpUConvert
-// TODO: OpSConvert
-// TODO: OpFConvert
-// TODO: OpConvertPtrToU
-// TODO: OpConvertUToPtr
-// TODO: OpPtrCastToGeneric
-// TODO: OpGenericCastToPtr
-// TODO: OpBitcast
-// TODO: OpGenericCastToPtrExplicit
-// TODO: OpSatConvertSToU
-// TODO: OpSatConvertUToS
-// TODO: OpVectorExtractDynamic
-// TODO: OpVectorInsertDynamic
-// TODO: OpVectorShuffle
-// TODO: OpCompositeConstruct
-// TODO: OpCompositeExtract
-// TODO: OpCompositeInsert
-// TODO: OpCopyObject
-// TODO: OpTranspose
-// TODO: OpSNegate
-// TODO: OpFNegate
-// TODO: OpNot
-// TODO: OpIAdd
-// TODO: OpFAdd
-// TODO: OpISub
-// TODO: OpFSub
-// TODO: OpIMul
-// TODO: OpFMul
-// TODO: OpUDiv
-// TODO: OpSDiv
-// TODO: OpFDiv
-// TODO: OpUMod
-// TODO: OpSRem
-// TODO: OpSMod
-// TODO: OpFRem
-// TODO: OpFMod
-// TODO: OpVectorTimesScalar
-// TODO: OpMatrixTimesScalar
-// TODO: OpVectorTimesMatrix
-// TODO: OpMatrixTimesVector
-// TODO: OpMatrixTimesMatrix
-// TODO: OpOuterProduct
-// TODO: OpDot
-// TODO: OpShiftRightLogical
-// TODO: OpShiftRightArithmetic
-// TODO: OpShiftLeftLogical
-// TODO: OpBitwiseOr
-// TODO: OpBitwiseXor
-// TODO: OpBitwiseAnd
-// TODO: OpAny
-// TODO: OpAll
-// TODO: OpIsNan
-// TODO: OpIsInf
-// TODO: OpIsFinite
-// TODO: OpIsNormal
-// TODO: OpSignBitSet
-// TODO: OpLessOrGreater
-// TODO: OpOrdered
-// TODO: OpUnordered
-// TODO: OpLogicalOr
-// TODO: OpLogicalXor
-// TODO: OpLogicalAnd
-// TODO: OpSelect
-// TODO: OpIEqual
-// TODO: OpFOrdEqual
-// TODO: OpFUnordEqual
-// TODO: OpINotEqual
-// TODO: OpFOrdNotEqual
-// TODO: OpFUnordNotEqual
-// TODO: OpULessThan
-// TODO: OpSLessThan
-// TODO: OpFOrdLessThan
-// TODO: OpFUnordLessThan
-// TODO: OpUGreaterThan
-// TODO: OpSGreaterThan
-// TODO: OpFOrdGreaterThan
-// TODO: OpFUnordGreaterThan
-// TODO: OpULessThanEqual
-// TODO: OpSLessThanEqual
-// TODO: OpFOrdLessThanEqual
-// TODO: OpFUnordLessThanEqual
-// TODO: OpUGreaterThanEqual
-// TODO: OpSGreaterThanEqual
-// TODO: OpFOrdGreaterThanEqual
-// TODO: OpFUnordGreaterThanEqual
-// TODO: OpDPdx
-// TODO: OpDPdy
-// TODO: OpFWidth
-// TODO: OpDPdxFine
-// TODO: OpDPdyFine
-// TODO: OpFwidthFine
-// TODO: OpDPdxCoarse
-// TODO: OpDPdyCoarse
-// TODO: OpFwidthCoarse
-// TODO: OpPhi
-// TODO: OpLoopMerge
-// TODO: OpSelectionMerge
-// TODO: OpBranch
-// TODO: OpBranchConditional
-// TODO: OpSwitch
-
-TEST_F(ValidateID, OpReturnValueConstantGood) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %2
-%4 = OpConstant %2 42
-%5 = OpFunction %2 None %3
-%6 = OpLabel
- OpReturnValue %4
- OpFunctionEnd)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpReturnValueVariableGood) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0 ;10
-%3 = OpTypeFunction %2
-%8 = OpTypePointer Function %2 ;18
-%4 = OpConstant %2 42 ;22
-%5 = OpFunction %2 None %3 ;27
-%6 = OpLabel ;29
-%7 = OpVariable %8 Function %4 ;34
-%9 = OpLoad %2 %7
- OpReturnValue %9 ;36
- OpFunctionEnd)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpReturnValueExpressionGood) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %2
-%4 = OpConstant %2 42
-%5 = OpFunction %2 None %3
-%6 = OpLabel
-%7 = OpIAdd %2 %4 %4
- OpReturnValue %7
- OpFunctionEnd)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpReturnValueIsType) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %2
-%5 = OpFunction %2 None %3
-%6 = OpLabel
- OpReturnValue %1
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpReturnValueIsLabel) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %2
-%5 = OpFunction %2 None %3
-%6 = OpLabel
- OpReturnValue %6
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpReturnValueIsVoid) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %1
-%5 = OpFunction %1 None %3
-%6 = OpLabel
-%7 = OpFunctionCall %1 %5
- OpReturnValue %7
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, OpReturnValueIsVariableInPhysical) {
- // It's valid to return a pointer in a physical addressing model.
- const char* spirv = R"(
- OpMemoryModel Physical32 OpenCL
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypePointer Private %2
-%4 = OpTypeFunction %3
-%5 = OpFunction %3 None %4
-%6 = OpLabel
-%7 = OpVariable %3 Function
- OpReturnValue %7
- OpFunctionEnd)";
- CHECK(spirv, SPV_SUCCESS);
-}
-
-TEST_F(ValidateID, OpReturnValueIsVariableInLogical) {
- // It's invalid to return a pointer in a physical addressing model.
- const char* spirv = R"(
- OpMemoryModel Logical GLSL450
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypePointer Private %2
-%4 = OpTypeFunction %3
-%5 = OpFunction %3 None %4
-%6 = OpLabel
-%7 = OpVariable %3 Function
- OpReturnValue %7
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-// TODO: enable when this bug is fixed:
-// https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404
-TEST_F(ValidateID, DISABLED_OpReturnValueIsFunction) {
- const char* spirv = R"(
-%1 = OpTypeVoid
-%2 = OpTypeInt 32 0
-%3 = OpTypeFunction %2
-%5 = OpFunction %2 None %3
-%6 = OpLabel
- OpReturnValue %5
- OpFunctionEnd)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, UndefinedTypeId) {
- const char* spirv = R"(
-%s = OpTypeStruct %i32
-)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, UndefinedIdScope) {
- const char* spirv = R"(
-%u32 = OpTypeInt 32 0
-%memsem = OpConstant %u32 0
-%void = OpTypeVoid
-%void_f = OpTypeFunction %void
-%f = OpFunction %void None %void_f
-%l = OpLabel
- OpMemoryBarrier %undef %memsem
- OpReturn
- OpFunctionEnd
-)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, UndefinedIdMemSem) {
- const char* spirv = R"(
-%u32 = OpTypeInt 32 0
-%scope = OpConstant %u32 0
-%void = OpTypeVoid
-%void_f = OpTypeFunction %void
-%f = OpFunction %void None %void_f
-%l = OpLabel
- OpMemoryBarrier %scope %undef
- OpReturn
- OpFunctionEnd
-)";
- CHECK(spirv, SPV_ERROR_INVALID_ID);
-}
-
-TEST_F(ValidateID, KernelOpEntryPointAndOpInBoundsPtrAccessChainGood) {
- const char* spirv = R"(
- OpEntryPoint Kernel %2 "simple_kernel"
- OpSource OpenCL_C 200000
- OpDecorate %3 BuiltIn GlobalInvocationId
- OpDecorate %3 Constant
- OpDecorate %4 FuncParamAttr NoCapture
- OpDecorate %3 LinkageAttributes "__spirv_GlobalInvocationId" Import
- %5 = OpTypeInt 32 0
- %6 = OpTypeVector %5 3
- %7 = OpTypePointer UniformConstant %6
- %3 = OpVariable %7 UniformConstant
- %8 = OpTypeVoid
- %9 = OpTypeStruct %5
-%10 = OpTypePointer CrossWorkgroup %9
-%11 = OpTypeFunction %8 %10
-%12 = OpConstant %5 0
-%13 = OpTypePointer CrossWorkgroup %5
-%14 = OpConstant %5 42
- %2 = OpFunction %8 None %11
- %4 = OpFunctionParameter %10
-%15 = OpLabel
-%16 = OpLoad %6 %3 Aligned 0
-%17 = OpCompositeExtract %5 %16 0
-%18 = OpInBoundsPtrAccessChain %13 %4 %17 %12
- OpStore %18 %14 Aligned 4
- OpReturn
- OpFunctionEnd)";
- CHECK_KERNEL(spirv, SPV_SUCCESS, 32);
-}
-
-TEST_F(ValidateID, OpPtrAccessChainGood) {
- const char* spirv = R"(
- OpEntryPoint Kernel %2 "another_kernel"
- OpSource OpenCL_C 200000
- OpDecorate %3 BuiltIn GlobalInvocationId
- OpDecorate %3 Constant
- OpDecorate %4 FuncParamAttr NoCapture
- OpDecorate %3 LinkageAttributes "__spirv_GlobalInvocationId" Import
- %5 = OpTypeInt 64 0
- %6 = OpTypeVector %5 3
- %7 = OpTypePointer UniformConstant %6
- %3 = OpVariable %7 UniformConstant
- %8 = OpTypeVoid
- %9 = OpTypeInt 32 0
-%10 = OpTypeStruct %9
-%11 = OpTypePointer CrossWorkgroup %10
-%12 = OpTypeFunction %8 %11
-%13 = OpConstant %5 4294967295
-%14 = OpConstant %9 0
-%15 = OpTypePointer CrossWorkgroup %9
-%16 = OpConstant %9 42
- %2 = OpFunction %8 None %12
- %4 = OpFunctionParameter %11
-%17 = OpLabel
-%18 = OpLoad %6 %3 Aligned 0
-%19 = OpCompositeExtract %5 %18 0
-%20 = OpBitwiseAnd %5 %19 %13
-%21 = OpPtrAccessChain %15 %4 %20 %14
- OpStore %21 %16 Aligned 4
- OpReturn
- OpFunctionEnd)";
- CHECK_KERNEL(spirv, SPV_SUCCESS, 64);
-}
-
-TEST_F(ValidateID, OpLoadBitcastPointerGood) {
- const char* spirv = R"(
-%2 = OpTypeVoid
-%3 = OpTypeInt 32 1
-%4 = OpTypeFloat 32
-%5 = OpTypePointer UniformConstant %3
-%6 = OpTypePointer UniformConstant %4
-%7 = OpVariable %5 UniformConstant
-%8 = OpTypeFunction %2
-%9 = OpFunction %2 None %8
-%10 = OpLabel
-%11 = OpBitcast %6 %7
-%12 = OpLoad %4 %11
- OpReturn
- OpFunctionEnd)";
- CHECK_KERNEL(spirv, SPV_SUCCESS, 64);
-}
-TEST_F(ValidateID, OpLoadBitcastNonPointerBad) {
- const char* spirv = R"(
-%2 = OpTypeVoid
-%3 = OpTypeInt 32 1
-%4 = OpTypeFloat 32
-%5 = OpTypePointer UniformConstant %3
-%6 = OpTypeFunction %2
-%7 = OpVariable %5 UniformConstant
-%8 = OpFunction %2 None %6
-%9 = OpLabel
-%10 = OpLoad %3 %7
-%11 = OpBitcast %4 %10
-%12 = OpLoad %3 %11
- OpReturn
- OpFunctionEnd)";
- CHECK_KERNEL(spirv, SPV_ERROR_INVALID_ID, 64);
-}
-TEST_F(ValidateID, OpStoreBitcastPointerGood) {
- const char* spirv = R"(
-%2 = OpTypeVoid
-%3 = OpTypeInt 32 1
-%4 = OpTypeFloat 32
-%5 = OpTypePointer Function %3
-%6 = OpTypePointer Function %4
-%7 = OpTypeFunction %2
-%8 = OpConstant %3 42
-%9 = OpFunction %2 None %7
-%10 = OpLabel
-%11 = OpVariable %6 Function
-%12 = OpBitcast %5 %11
- OpStore %12 %8
- OpReturn
- OpFunctionEnd)";
- CHECK_KERNEL(spirv, SPV_SUCCESS, 64);
-}
-TEST_F(ValidateID, OpStoreBitcastNonPointerBad) {
- const char* spirv = R"(
-%2 = OpTypeVoid
-%3 = OpTypeInt 32 1
-%4 = OpTypeFloat 32
-%5 = OpTypePointer Function %4
-%6 = OpTypeFunction %2
-%7 = OpConstant %4 42
-%8 = OpFunction %2 None %6
-%9 = OpLabel
-%10 = OpVariable %5 Function
-%11 = OpBitcast %3 %7
- OpStore %11 %7
- OpReturn
- OpFunctionEnd)";
- CHECK_KERNEL(spirv, SPV_ERROR_INVALID_ID, 64);
-}
-
-// TODO: OpLifetimeStart
-// TODO: OpLifetimeStop
-// TODO: OpAtomicInit
-// TODO: OpAtomicLoad
-// TODO: OpAtomicStore
-// TODO: OpAtomicExchange
-// TODO: OpAtomicCompareExchange
-// TODO: OpAtomicCompareExchangeWeak
-// TODO: OpAtomicIIncrement
-// TODO: OpAtomicIDecrement
-// TODO: OpAtomicIAdd
-// TODO: OpAtomicISub
-// TODO: OpAtomicUMin
-// TODO: OpAtomicUMax
-// TODO: OpAtomicAnd
-// TODO: OpAtomicOr
-// TODO: OpAtomicXor
-// TODO: OpAtomicIMin
-// TODO: OpAtomicIMax
-// TODO: OpEmitStreamVertex
-// TODO: OpEndStreamPrimitive
-// TODO: OpAsyncGroupCopy
-// TODO: OpWaitGroupEvents
-// TODO: OpGroupAll
-// TODO: OpGroupAny
-// TODO: OpGroupBroadcast
-// TODO: OpGroupIAdd
-// TODO: OpGroupFAdd
-// TODO: OpGroupFMin
-// TODO: OpGroupUMin
-// TODO: OpGroupSMin
-// TODO: OpGroupFMax
-// TODO: OpGroupUMax
-// TODO: OpGroupSMax
-// TODO: OpEnqueueMarker
-// TODO: OpEnqueueKernel
-// TODO: OpGetKernelNDrangeSubGroupCount
-// TODO: OpGetKernelNDrangeMaxSubGroupSize
-// TODO: OpGetKernelWorkGroupSize
-// TODO: OpGetKernelPreferredWorkGroupSizeMultiple
-// TODO: OpRetainEvent
-// TODO: OpReleaseEvent
-// TODO: OpCreateUserEvent
-// TODO: OpIsValidEvent
-// TODO: OpSetUserEventStatus
-// TODO: OpCaptureEventProfilingInfo
-// TODO: OpGetDefaultQueue
-// TODO: OpBuildNDRange
-// TODO: OpReadPipe
-// TODO: OpWritePipe
-// TODO: OpReservedReadPipe
-// TODO: OpReservedWritePipe
-// TODO: OpReserveReadPipePackets
-// TODO: OpReserveWritePipePackets
-// TODO: OpCommitReadPipe
-// TODO: OpCommitWritePipe
-// TODO: OpIsValidReserveId
-// TODO: OpGetNumPipePackets
-// TODO: OpGetMaxPipePackets
-// TODO: OpGroupReserveReadPipePackets
-// TODO: OpGroupReserveWritePipePackets
-// TODO: OpGroupCommitReadPipe
-// TODO: OpGroupCommitWritePipe
-
-} // anonymous namespace
diff --git a/test/val/Validate.Capability.cpp b/test/val/val_capability_test.cpp
index 5af65d7e..2604187e 100644
--- a/test/val/Validate.Capability.cpp
+++ b/test/val/val_capability_test.cpp
@@ -14,17 +14,18 @@
// Validation tests for Logical Layout
-#include <gmock/gmock.h>
-#include "TestFixture.h"
-#include "UnitSPIRV.h"
-#include "ValidateFixtures.h"
-#include "source/assembly_grammar.h"
-
#include <sstream>
#include <string>
#include <tuple>
#include <utility>
+#include <gmock/gmock.h>
+
+#include "source/assembly_grammar.h"
+#include "test_fixture.h"
+#include "unit_spirv.h"
+#include "val_fixtures.h"
+
namespace {
using spvtest::ScopedContext;
@@ -113,8 +114,8 @@ TEST_F(ValidateCapability, Default) {
OpCapability Kernel
OpCapability Matrix
OpMemoryModel Logical OpenCL
-%intt = OpTypeInt 32 1
-%vec3 = OpTypeVector %intt 3
+%f32 = OpTypeFloat 32
+%vec3 = OpTypeVector %f32 3
%mat33 = OpTypeMatrix %vec3 3
)";
@@ -1097,8 +1098,8 @@ INSTANTIATE_TEST_CASE_P(MatrixOp, ValidateCapability,
ValuesIn(AllCapabilities()),
Values(
make_pair(string(kOpenCLMemoryModel) +
- "%intt = OpTypeInt 32 1\n"
- "%vec3 = OpTypeVector %intt 3\n"
+ "%f32 = OpTypeFloat 32\n"
+ "%vec3 = OpTypeVector %f32 3\n"
"%mat33 = OpTypeMatrix %vec3 3\n", MatrixDependencies()))),);
// clang-format on
@@ -1226,6 +1227,12 @@ OpFunctionEnd
)";
CompileSuccessfully(str);
+
+ // Since we are forcing usage of <id> 64, the "id bound" in the binary header
+ // must be overwritten so that <id> 64 is considered within bound.
+ // ID Bound is at index 3 of the binary. Set it to 65.
+ OverwriteAssembledBinary(3, 65);
+
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
}
diff --git a/test/val/Validate.CFG.cpp b/test/val/val_cfg_test.cpp
index 8fbb0ceb..eb30827e 100644
--- a/test/val/Validate.CFG.cpp
+++ b/test/val/val_cfg_test.cpp
@@ -25,9 +25,9 @@
#include "gmock/gmock.h"
-#include "TestFixture.h"
-#include "UnitSPIRV.h"
-#include "ValidateFixtures.h"
+#include "test_fixture.h"
+#include "unit_spirv.h"
+#include "val_fixtures.h"
#include "source/diagnostic.h"
#include "source/validate.h"
diff --git a/test/val/val_data_test.cpp b/test/val/val_data_test.cpp
new file mode 100644
index 00000000..656abce9
--- /dev/null
+++ b/test/val/val_data_test.cpp
@@ -0,0 +1,464 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Validation tests for Data Rules.
+
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "unit_spirv.h"
+#include "val_fixtures.h"
+
+using ::testing::HasSubstr;
+using ::testing::MatchesRegex;
+
+using std::string;
+using std::pair;
+using std::stringstream;
+
+using ValidateData = spvtest::ValidateBase<pair<string, bool>>;
+
+string header = R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+%1 = OpTypeFloat 32
+)";
+string header_with_addresses = R"(
+ OpCapability Addresses
+ OpCapability Kernel
+ OpCapability GenericPointer
+ OpMemoryModel Physical32 OpenCL
+)";
+string header_with_vec16_cap = R"(
+ OpCapability Shader
+ OpCapability Vector16
+ OpMemoryModel Logical GLSL450
+%1 = OpTypeFloat 32
+)";
+string header_with_int8 = R"(
+ OpCapability Shader
+ OpCapability Int8
+ OpMemoryModel Logical GLSL450
+)";
+string header_with_int16 = R"(
+ OpCapability Shader
+ OpCapability Int16
+ OpMemoryModel Logical GLSL450
+)";
+string header_with_int64 = R"(
+ OpCapability Shader
+ OpCapability Int64
+ OpMemoryModel Logical GLSL450
+)";
+string header_with_float16 = R"(
+ OpCapability Shader
+ OpCapability Float16
+ OpMemoryModel Logical GLSL450
+)";
+string header_with_float16_buffer = R"(
+ OpCapability Shader
+ OpCapability Float16Buffer
+ OpMemoryModel Logical GLSL450
+)";
+string header_with_float64 = R"(
+ OpCapability Shader
+ OpCapability Float64
+ OpMemoryModel Logical GLSL450
+)";
+string invalid_comp_error = "Illegal number of components";
+string missing_cap_error = "requires the Vector16 capability";
+string missing_int8_cap_error = "requires the Int8 capability";
+string missing_int16_cap_error = "requires the Int16 capability";
+string missing_int64_cap_error = "requires the Int64 capability";
+string missing_float16_cap_error =
+ "requires the Float16 or Float16Buffer capability.";
+string missing_float64_cap_error = "requires the Float64 capability";
+string invalid_num_bits_error = "Invalid number of bits";
+
+TEST_F(ValidateData, vec0) {
+ string str = header + "%2 = OpTypeVector %1 0";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
+}
+
+TEST_F(ValidateData, vec1) {
+ string str = header + "%2 = OpTypeVector %1 1";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
+}
+
+TEST_F(ValidateData, vec2) {
+ string str = header + "%2 = OpTypeVector %1 2";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, vec3) {
+ string str = header + "%2 = OpTypeVector %1 3";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, vec4) {
+ string str = header + "%2 = OpTypeVector %1 4";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, vec5) {
+ string str = header + "%2 = OpTypeVector %1 5";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
+}
+
+TEST_F(ValidateData, vec8) {
+ string str = header + "%2 = OpTypeVector %1 8";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_cap_error));
+}
+
+TEST_F(ValidateData, vec8_with_capability) {
+ string str = header_with_vec16_cap + "%2 = OpTypeVector %1 8";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, vec16) {
+ string str = header + "%2 = OpTypeVector %1 16";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_cap_error));
+}
+
+TEST_F(ValidateData, vec16_with_capability) {
+ string str = header_with_vec16_cap + "%2 = OpTypeVector %1 16";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, vec15) {
+ string str = header + "%2 = OpTypeVector %1 15";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
+}
+
+TEST_F(ValidateData, int8_good) {
+ string str = header_with_int8 + "%2 = OpTypeInt 8 1";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, int8_bad) {
+ string str = header + "%2 = OpTypeInt 8 1";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int8_cap_error));
+}
+
+TEST_F(ValidateData, int16_good) {
+ string str = header_with_int16 + "%2 = OpTypeInt 16 1";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, int16_bad) {
+ string str = header + "%2 = OpTypeInt 16 1";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int16_cap_error));
+}
+
+TEST_F(ValidateData, int64_good) {
+ string str = header_with_int64 + "%2 = OpTypeInt 64 1";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, int64_bad) {
+ string str = header + "%2 = OpTypeInt 64 1";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int64_cap_error));
+}
+
+// Number of bits in an integer may be only one of: {8,16,32,64}
+TEST_F(ValidateData, int_invalid_num_bits) {
+ string str = header + "%2 = OpTypeInt 48 1";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_num_bits_error));
+}
+
+TEST_F(ValidateData, float16_good) {
+ string str = header_with_float16 + "%2 = OpTypeFloat 16";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, float16_buffer_good) {
+ string str = header_with_float16_buffer + "%2 = OpTypeFloat 16";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, float16_bad) {
+ string str = header + "%2 = OpTypeFloat 16";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float16_cap_error));
+}
+
+TEST_F(ValidateData, float64_good) {
+ string str = header_with_float64 + "%2 = OpTypeFloat 64";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, float64_bad) {
+ string str = header + "%2 = OpTypeFloat 64";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float64_cap_error));
+}
+
+// Number of bits in a float may be only one of: {16,32,64}
+TEST_F(ValidateData, float_invalid_num_bits) {
+ string str = header + "%2 = OpTypeFloat 48";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_num_bits_error));
+}
+
+TEST_F(ValidateData, matrix_data_type_float) {
+ string str = header + R"(
+%f32 = OpTypeFloat 32
+%vec3 = OpTypeVector %f32 3
+%mat33 = OpTypeMatrix %vec3 3
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, matrix_bad_column_type) {
+ string str = header + R"(
+%f32 = OpTypeFloat 32
+%mat33 = OpTypeMatrix %f32 3
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Columns in a matrix must be of type vector"));
+}
+
+TEST_F(ValidateData, matrix_data_type_int) {
+ string str = header + R"(
+%int32 = OpTypeInt 32 1
+%vec3 = OpTypeVector %int32 3
+%mat33 = OpTypeMatrix %vec3 3
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("can only be parameterized with floating-point types"));
+}
+
+TEST_F(ValidateData, matrix_data_type_bool) {
+ string str = header + R"(
+%boolt = OpTypeBool
+%vec3 = OpTypeVector %boolt 3
+%mat33 = OpTypeMatrix %vec3 3
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("can only be parameterized with floating-point types"));
+}
+
+TEST_F(ValidateData, matrix_with_0_columns) {
+ string str = header + R"(
+%f32 = OpTypeFloat 32
+%vec3 = OpTypeVector %f32 3
+%mat33 = OpTypeMatrix %vec3 0
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
+}
+
+TEST_F(ValidateData, matrix_with_1_column) {
+ string str = header + R"(
+%f32 = OpTypeFloat 32
+%vec3 = OpTypeVector %f32 3
+%mat33 = OpTypeMatrix %vec3 1
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
+}
+
+TEST_F(ValidateData, matrix_with_2_columns) {
+ string str = header + R"(
+%f32 = OpTypeFloat 32
+%vec3 = OpTypeVector %f32 3
+%mat33 = OpTypeMatrix %vec3 2
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, matrix_with_3_columns) {
+ string str = header + R"(
+%f32 = OpTypeFloat 32
+%vec3 = OpTypeVector %f32 3
+%mat33 = OpTypeMatrix %vec3 3
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, matrix_with_4_columns) {
+ string str = header + R"(
+%f32 = OpTypeFloat 32
+%vec3 = OpTypeVector %f32 3
+%mat33 = OpTypeMatrix %vec3 4
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, matrix_with_5_column) {
+ string str = header + R"(
+%f32 = OpTypeFloat 32
+%vec3 = OpTypeVector %f32 3
+%mat33 = OpTypeMatrix %vec3 5
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
+}
+
+TEST_F(ValidateData, specialize_int) {
+ string str = header + R"(
+%i32 = OpTypeInt 32 1
+%len = OpSpecConstant %i32 2)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, specialize_float) {
+ string str = header + R"(
+%f32 = OpTypeFloat 32
+%len = OpSpecConstant %f32 2)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, specialize_boolean) {
+ string str = header + R"(
+%2 = OpTypeBool
+%3 = OpSpecConstantTrue %2
+%4 = OpSpecConstantFalse %2)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateData, specialize_boolean_to_int) {
+ string str = header + R"(
+%2 = OpTypeInt 32 1
+%3 = OpSpecConstantTrue %2
+%4 = OpSpecConstantFalse %2)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Specialization constant must be a boolean"));
+}
+
+TEST_F(ValidateData, missing_forward_pointer_decl) {
+ string str = header_with_addresses + R"(
+%uintt = OpTypeInt 32 0
+%3 = OpTypeStruct %fwd_ptrt %uintt
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("must first be declared using OpTypeForwardPointer"));
+}
+
+TEST_F(ValidateData, forward_pointer_missing_definition) {
+ string str = header_with_addresses + R"(
+OpTypeForwardPointer %_ptr_Generic_struct_A Generic
+%uintt = OpTypeInt 32 0
+%struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("forward referenced IDs have not been defined"));
+}
+
+TEST_F(ValidateData, forward_ref_bad_type) {
+ string str = header_with_addresses + R"(
+OpTypeForwardPointer %_ptr_Generic_struct_A Generic
+%uintt = OpTypeInt 32 0
+%struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
+%_ptr_Generic_struct_A = OpTypeFloat 32
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Found a forward reference to a non-pointer type in "
+ "OpTypeStruct instruction."));
+}
+
+TEST_F(ValidateData, forward_ref_points_to_non_struct) {
+ string str = header_with_addresses + R"(
+OpTypeForwardPointer %_ptr_Generic_struct_A Generic
+%uintt = OpTypeInt 32 0
+%struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
+%_ptr_Generic_struct_A = OpTypePointer Generic %uintt
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("A forward reference operand in an OpTypeStruct must "
+ "be an OpTypePointer that points to an OpTypeStruct. "
+ "Found OpTypePointer that points to OpTypeInt."));
+}
+
+TEST_F(ValidateData, struct_forward_pointer_good) {
+ string str = header_with_addresses + R"(
+OpTypeForwardPointer %_ptr_Generic_struct_A Generic
+%uintt = OpTypeInt 32 0
+%struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
+%struct_C = OpTypeStruct %uintt %struct_B
+%struct_A = OpTypeStruct %uintt %struct_C
+%_ptr_Generic_struct_A = OpTypePointer Generic %struct_C
+)";
+ CompileSuccessfully(str.c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
diff --git a/test/val/ValidateFixtures.cpp b/test/val/val_fixtures.cpp
index 7d0d2062..2db99a89 100644
--- a/test/val/ValidateFixtures.cpp
+++ b/test/val/val_fixtures.cpp
@@ -14,13 +14,13 @@
// Common validation fixtures for unit tests
-#include "ValidateFixtures.h"
+#include "val_fixtures.h"
#include <functional>
#include <tuple>
#include <utility>
-#include "TestFixture.h"
+#include "test_fixture.h"
namespace spvtest {
@@ -54,6 +54,14 @@ void ValidateBase<T>::CompileSuccessfully(std::string code,
}
template <typename T>
+void ValidateBase<T>::OverwriteAssembledBinary(uint32_t index, uint32_t word) {
+ ASSERT_TRUE(index < binary_->wordCount)
+ << "OverwriteAssembledBinary: The given index is larger than the binary "
+ "word count.";
+ binary_->code[index] = word;
+}
+
+template <typename T>
spv_result_t ValidateBase<T>::ValidateInstructions(spv_target_env env) {
return spvValidate(ScopedContext(env).context, get_const_binary(),
&diagnostic_);
diff --git a/test/val/ValidateFixtures.h b/test/val/val_fixtures.h
index 3ec6627d..bb4fe187 100644
--- a/test/val/ValidateFixtures.h
+++ b/test/val/val_fixtures.h
@@ -17,7 +17,7 @@
#ifndef LIBSPIRV_TEST_VALIDATE_FIXTURES_H_
#define LIBSPIRV_TEST_VALIDATE_FIXTURES_H_
-#include "UnitSPIRV.h"
+#include "unit_spirv.h"
namespace spvtest {
@@ -35,6 +35,12 @@ class ValidateBase : public ::testing::Test,
void CompileSuccessfully(std::string code,
spv_target_env env = SPV_ENV_UNIVERSAL_1_0);
+ // Overwrites the word at index 'index' with the given word.
+ // For testing purposes, it is often useful to be able to manipulate the
+ // assembled binary before running the validator on it.
+ // This function overwrites the word at the given index with a new word.
+ void OverwriteAssembledBinary(uint32_t index, uint32_t word);
+
// Performs validation on the SPIR-V code and compares the result of the
// spvValidate function
spv_result_t ValidateInstructions(spv_target_env env = SPV_ENV_UNIVERSAL_1_0);
diff --git a/test/val/val_id_test.cpp b/test/val/val_id_test.cpp
new file mode 100644
index 00000000..5dafa08c
--- /dev/null
+++ b/test/val/val_id_test.cpp
@@ -0,0 +1,2557 @@
+// Copyright (c) 2015-2016 The Khronos Group Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <sstream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "test_fixture.h"
+#include "unit_spirv.h"
+#include "val_fixtures.h"
+
+// NOTE: The tests in this file are ONLY testing ID usage, there for the input
+// SPIR-V does not follow the logical layout rules from the spec in all cases in
+// order to makes the tests smaller. Validation of the whole module is handled
+// in stages, ID validation is only one of these stages. All validation stages
+// are stand alone.
+
+namespace {
+
+using ::testing::ValuesIn;
+using ::testing::HasSubstr;
+using spvtest::ScopedContext;
+using std::ostringstream;
+using std::string;
+using std::vector;
+
+using ValidateIdWithMessage = spvtest::ValidateBase<bool>;
+
+string kGLSL450MemoryModel = R"(
+ OpCapability Shader
+ OpCapability Addresses
+ OpCapability Pipes
+ OpCapability LiteralSampler
+ OpCapability DeviceEnqueue
+ OpCapability Vector16
+ OpCapability Int8
+ OpCapability Int16
+ OpCapability Int64
+ OpCapability Float64
+ OpMemoryModel Logical GLSL450
+)";
+
+string kOpenCLMemoryModel32 = R"(
+ OpCapability Addresses
+ OpCapability Linkage
+ OpCapability Kernel
+%1 = OpExtInstImport "OpenCL.std"
+ OpMemoryModel Physical32 OpenCL
+)";
+
+string kOpenCLMemoryModel64 = R"(
+ OpCapability Addresses
+ OpCapability Linkage
+ OpCapability Kernel
+ OpCapability Int64
+%1 = OpExtInstImport "OpenCL.std"
+ OpMemoryModel Physical64 OpenCL
+)";
+
+string sampledImageSetup = R"(
+ %void = OpTypeVoid
+ %typeFuncVoid = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %image_type = OpTypeImage %float 2D 0 0 0 1 Unknown
+%_ptr_UniformConstant_img = OpTypePointer UniformConstant %image_type
+ %tex = OpVariable %_ptr_UniformConstant_img UniformConstant
+ %sampler_type = OpTypeSampler
+%_ptr_UniformConstant_sam = OpTypePointer UniformConstant %sampler_type
+ %s = OpVariable %_ptr_UniformConstant_sam UniformConstant
+ %sampled_image_type = OpTypeSampledImage %image_type
+ %v2float = OpTypeVector %float 2
+ %float_1 = OpConstant %float 1
+ %float_2 = OpConstant %float 2
+ %const_vec_1_1 = OpConstantComposite %v2float %float_1 %float_1
+ %const_vec_2_2 = OpConstantComposite %v2float %float_2 %float_2
+ %bool_type = OpTypeBool
+ %spec_true = OpSpecConstantTrue %bool_type
+ %main = OpFunction %void None %typeFuncVoid
+ %label_1 = OpLabel
+ %image_inst = OpLoad %image_type %tex
+ %sampler_inst = OpLoad %sampler_type %s
+)";
+
+// TODO: OpUndef
+
+TEST_F(ValidateIdWithMessage, OpName) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpName %2 "name"
+%1 = OpTypeInt 32 0
+%2 = OpTypePointer UniformConstant %1
+%3 = OpVariable %2 UniformConstant)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpMemberNameGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpMemberName %2 0 "foo"
+%1 = OpTypeInt 32 0
+%2 = OpTypeStruct %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpMemberNameTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpMemberName %1 0 "foo"
+%1 = OpTypeInt 32 0)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpMemberNameMemberBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpMemberName %2 1 "foo"
+%1 = OpTypeInt 32 0
+%2 = OpTypeStruct %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpLineGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpString "/path/to/source.file"
+ OpLine %1 0 0
+%2 = OpTypeInt 32 0
+%3 = OpTypePointer Input %2
+%4 = OpVariable %3 Input)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpLineFileBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpLine %2 0 0
+%2 = OpTypeInt 32 0
+%3 = OpTypePointer Input %2
+%4 = OpVariable %3 Input)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpDecorateGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpDecorate %2 GLSLShared
+%1 = OpTypeInt 64 0
+%2 = OpTypeStruct %1 %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpDecorateBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+OpDecorate %1 GLSLShared)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpMemberDecorateGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpMemberDecorate %2 0 Uniform
+%1 = OpTypeInt 32 0
+%2 = OpTypeStruct %1 %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpMemberDecorateBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpMemberDecorate %1 0 Uniform
+%1 = OpTypeInt 32 0)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpMemberDecorateMemberBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpMemberDecorate %2 3 Uniform
+%1 = OpTypeInt 32 0
+%2 = OpTypeStruct %1 %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpGroupDecorateGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpDecorationGroup
+ OpDecorate %1 Uniform
+ OpDecorate %1 GLSLShared
+ OpGroupDecorate %1 %3 %4
+%2 = OpTypeInt 32 0
+%3 = OpConstant %2 42
+%4 = OpConstant %2 23)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpGroupDecorateDecorationGroupBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpGroupDecorate %2 %3 %4
+%2 = OpTypeInt 32 0
+%3 = OpConstant %2 42
+%4 = OpConstant %2 23)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpGroupDecorateTargetBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpDecorationGroup
+ OpDecorate %1 Uniform
+ OpDecorate %1 GLSLShared
+ OpGroupDecorate %1 %3
+%2 = OpTypeInt 32 0)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+// TODO: OpGroupMemberDecorate
+// TODO: OpExtInst
+
+TEST_F(ValidateIdWithMessage, OpEntryPointGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpEntryPoint GLCompute %3 ""
+%1 = OpTypeVoid
+%2 = OpTypeFunction %1
+%3 = OpFunction %1 None %2
+%4 = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpEntryPointFunctionBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpEntryPoint GLCompute %1 ""
+%1 = OpTypeVoid)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpEntryPointParameterCountBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpEntryPoint GLCompute %3 ""
+%1 = OpTypeVoid
+%2 = OpTypeFunction %1 %1
+%3 = OpFunction %1 None %2
+%4 = OpLabel
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpEntryPointReturnTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpEntryPoint GLCompute %3 ""
+%1 = OpTypeInt 32 0
+%2 = OpTypeFunction %1
+%3 = OpFunction %1 None %2
+%4 = OpLabel
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpExecutionModeGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpEntryPoint GLCompute %3 ""
+ OpExecutionMode %3 LocalSize 1 1 1
+%1 = OpTypeVoid
+%2 = OpTypeFunction %1
+%3 = OpFunction %1 None %2
+%4 = OpLabel
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpExecutionModeEntryPointMissing) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpExecutionMode %3 LocalSize 1 1 1
+%1 = OpTypeVoid
+%2 = OpTypeFunction %1
+%3 = OpFunction %1 None %2
+%4 = OpLabel
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpExecutionModeEntryPointBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ OpEntryPoint GLCompute %3 "" %a
+ OpExecutionMode %a LocalSize 1 1 1
+%void = OpTypeVoid
+%ptr = OpTypePointer Input %void
+%a = OpVariable %ptr Input
+%2 = OpTypeFunction %void
+%3 = OpFunction %void None %2
+%4 = OpLabel
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypeVectorFloat) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 4)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypeVectorInt) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 1
+%2 = OpTypeVector %1 4)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypeVectorUInt) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 64 0
+%2 = OpTypeVector %1 4)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypeVectorBool) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeBool
+%2 = OpTypeVector %1 4)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypeVectorComponentTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypePointer UniformConstant %1
+%3 = OpTypeVector %2 4)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypeMatrixGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 2
+%3 = OpTypeMatrix %2 3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpTypeMatrixColumnTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeMatrix %1 3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypeSamplerGood) {
+ // In Rev31, OpTypeSampler takes no arguments.
+ string spirv = kGLSL450MemoryModel + R"(
+%s = OpTypeSampler)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypeArrayGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpConstant %1 1
+%3 = OpTypeArray %1 %2)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypeArrayElementTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpConstant %1 1
+%3 = OpTypeArray %2 %2)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+// Signed or unsigned.
+enum Signed { kSigned, kUnsigned };
+
+// Creates an assembly snippet declaring OpTypeArray with the given length.
+string MakeArrayLength(const string& len, Signed isSigned, int width) {
+ ostringstream ss;
+ ss << kGLSL450MemoryModel;
+ ss << " %t = OpTypeInt " << width << (isSigned == kSigned ? " 1" : " 0")
+ << " %l = OpConstant %t " << len << " %a = OpTypeArray %t %l";
+ return ss.str();
+}
+
+// Tests OpTypeArray. Parameter is the width (in bits) of the array-length's
+// type.
+class OpTypeArrayLengthTest
+ : public spvtest::TextToBinaryTestBase<::testing::TestWithParam<int>> {
+ protected:
+ OpTypeArrayLengthTest()
+ : position_(spv_position_t{0, 0, 0}),
+ diagnostic_(spvDiagnosticCreate(&position_, "")) {}
+
+ ~OpTypeArrayLengthTest() { spvDiagnosticDestroy(diagnostic_); }
+
+ // Runs spvValidate() on v, printing any errors via spvDiagnosticPrint().
+ spv_result_t Val(const SpirvVector& v) {
+ spv_const_binary_t cbinary{v.data(), v.size()};
+ const auto status =
+ spvValidate(ScopedContext().context, &cbinary, &diagnostic_);
+ if (status != SPV_SUCCESS) {
+ spvDiagnosticPrint(diagnostic_);
+ }
+ return status;
+ }
+
+ private:
+ spv_position_t position_; // For creating diagnostic_.
+ spv_diagnostic diagnostic_;
+};
+
+TEST_P(OpTypeArrayLengthTest, LengthPositive) {
+ const int width = GetParam();
+ EXPECT_EQ(SPV_SUCCESS,
+ Val(CompileSuccessfully(MakeArrayLength("1", kSigned, width))));
+ EXPECT_EQ(SPV_SUCCESS,
+ Val(CompileSuccessfully(MakeArrayLength("1", kUnsigned, width))));
+ EXPECT_EQ(SPV_SUCCESS,
+ Val(CompileSuccessfully(MakeArrayLength("2", kSigned, width))));
+ EXPECT_EQ(SPV_SUCCESS,
+ Val(CompileSuccessfully(MakeArrayLength("2", kUnsigned, width))));
+ EXPECT_EQ(SPV_SUCCESS,
+ Val(CompileSuccessfully(MakeArrayLength("55", kSigned, width))));
+ EXPECT_EQ(SPV_SUCCESS,
+ Val(CompileSuccessfully(MakeArrayLength("55", kUnsigned, width))));
+ const string fpad(width / 4 - 1, 'F');
+ EXPECT_EQ(
+ SPV_SUCCESS,
+ Val(CompileSuccessfully(MakeArrayLength("0x7" + fpad, kSigned, width))));
+ EXPECT_EQ(SPV_SUCCESS, Val(CompileSuccessfully(
+ MakeArrayLength("0xF" + fpad, kUnsigned, width))));
+}
+
+TEST_P(OpTypeArrayLengthTest, LengthZero) {
+ const int width = GetParam();
+ EXPECT_EQ(SPV_ERROR_INVALID_ID,
+ Val(CompileSuccessfully(MakeArrayLength("0", kSigned, width))));
+ EXPECT_EQ(SPV_ERROR_INVALID_ID,
+ Val(CompileSuccessfully(MakeArrayLength("0", kUnsigned, width))));
+}
+
+TEST_P(OpTypeArrayLengthTest, LengthNegative) {
+ const int width = GetParam();
+ EXPECT_EQ(SPV_ERROR_INVALID_ID,
+ Val(CompileSuccessfully(MakeArrayLength("-1", kSigned, width))));
+ EXPECT_EQ(SPV_ERROR_INVALID_ID,
+ Val(CompileSuccessfully(MakeArrayLength("-2", kSigned, width))));
+ EXPECT_EQ(SPV_ERROR_INVALID_ID,
+ Val(CompileSuccessfully(MakeArrayLength("-123", kSigned, width))));
+ const string neg_max = "0x8" + string(width / 4 - 1, '0');
+ EXPECT_EQ(SPV_ERROR_INVALID_ID,
+ Val(CompileSuccessfully(MakeArrayLength(neg_max, kSigned, width))));
+}
+
+// The only valid widths for integers are 8, 16, 32, and 64.
+INSTANTIATE_TEST_CASE_P(Widths, OpTypeArrayLengthTest,
+ ValuesIn(vector<int>{8, 16, 32, 64}));
+
+TEST_F(ValidateIdWithMessage, OpTypeArrayLengthNull) {
+ string spirv = kGLSL450MemoryModel + R"(
+%i32 = OpTypeInt 32 1
+%len = OpConstantNull %i32
+%ary = OpTypeArray %i32 %len)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypeArrayLengthSpecConst) {
+ string spirv = kGLSL450MemoryModel + R"(
+%i32 = OpTypeInt 32 1
+%len = OpSpecConstant %i32 2
+%ary = OpTypeArray %i32 %len)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypeArrayLengthSpecConstOp) {
+ string spirv = kGLSL450MemoryModel + R"(
+%i32 = OpTypeInt 32 1
+%c1 = OpConstant %i32 1
+%c2 = OpConstant %i32 2
+%len = OpSpecConstantOp %i32 IAdd %c1 %c2
+%ary = OpTypeArray %i32 %len)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypeRuntimeArrayGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeRuntimeArray %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpTypeRuntimeArrayBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpConstant %1 0
+%3 = OpTypeRuntimeArray %2)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+// TODO: Object of this type can only be created with OpVariable using the
+// Unifrom Storage Class
+
+TEST_F(ValidateIdWithMessage, OpTypeStructGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeFloat 64
+%3 = OpTypePointer Input %1
+%4 = OpTypeStruct %1 %2 %3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpTypeStructMemberTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeFloat 64
+%3 = OpConstant %2 0.0
+%4 = OpTypeStruct %1 %2 %3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypePointerGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypePointer Input %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpTypePointerBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpConstant %1 0
+%3 = OpTypePointer Input %2)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypeFunctionGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeFunction %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpTypeFunctionReturnTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpConstant %1 0
+%3 = OpTypeFunction %2)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpTypeFunctionParameterBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpConstant %2 0
+%4 = OpTypeFunction %1 %2 %3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpTypePipeGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 16
+%3 = OpTypePipe ReadOnly)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpConstantTrueGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeBool
+%2 = OpConstantTrue %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantTrueBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpConstantTrue %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpConstantFalseGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeBool
+%2 = OpConstantTrue %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantFalseBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpConstantFalse %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpConstantGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpConstant %1 1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpConstant !1 !0)";
+ // The expected failure code is implementation dependent (currently
+ // INVALID_BINARY because the binary parser catches these cases) and may
+ // change over time, but this must always fail.
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 4
+%3 = OpConstant %1 3.14
+%4 = OpConstantComposite %2 %3 %3 %3 %3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorWithUndefGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 4
+%3 = OpConstant %1 3.14
+%9 = OpUndef %1
+%4 = OpConstantComposite %2 %3 %3 %3 %9)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorResultTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 4
+%3 = OpConstant %1 3.14
+%4 = OpConstantComposite %1 %3 %3 %3 %3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeVectorConstituentTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 4
+%4 = OpTypeInt 32 0
+%3 = OpConstant %1 3.14
+%5 = OpConstant %4 42 ; bad type for constant value
+%6 = OpConstantComposite %2 %3 %5 %3 %3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage,
+ OpConstantCompositeVectorConstituentUndefTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 4
+%4 = OpTypeInt 32 0
+%3 = OpConstant %1 3.14
+%5 = OpUndef %4 ; bad type for undef value
+%6 = OpConstantComposite %2 %3 %5 %3 %3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeFloat 32
+ %2 = OpTypeVector %1 4
+ %3 = OpTypeMatrix %2 4
+ %4 = OpConstant %1 1.0
+ %5 = OpConstant %1 0.0
+ %6 = OpConstantComposite %2 %4 %5 %5 %5
+ %7 = OpConstantComposite %2 %5 %4 %5 %5
+ %8 = OpConstantComposite %2 %5 %5 %4 %5
+ %9 = OpConstantComposite %2 %5 %5 %5 %4
+%10 = OpConstantComposite %3 %6 %7 %8 %9)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixUndefGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeFloat 32
+ %2 = OpTypeVector %1 4
+ %3 = OpTypeMatrix %2 4
+ %4 = OpConstant %1 1.0
+ %5 = OpConstant %1 0.0
+ %6 = OpConstantComposite %2 %4 %5 %5 %5
+ %7 = OpConstantComposite %2 %5 %4 %5 %5
+ %8 = OpConstantComposite %2 %5 %5 %4 %5
+ %9 = OpUndef %2
+%10 = OpConstantComposite %3 %6 %7 %8 %9)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixConstituentTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeFloat 32
+ %2 = OpTypeVector %1 4
+%11 = OpTypeVector %1 3
+ %3 = OpTypeMatrix %2 4
+ %4 = OpConstant %1 1.0
+ %5 = OpConstant %1 0.0
+ %6 = OpConstantComposite %2 %4 %5 %5 %5
+ %7 = OpConstantComposite %2 %5 %4 %5 %5
+ %8 = OpConstantComposite %2 %5 %5 %4 %5
+ %9 = OpConstantComposite %11 %5 %5 %5
+%10 = OpConstantComposite %3 %6 %7 %8 %9)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage,
+ OpConstantCompositeMatrixConstituentUndefTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeFloat 32
+ %2 = OpTypeVector %1 4
+%11 = OpTypeVector %1 3
+ %3 = OpTypeMatrix %2 4
+ %4 = OpConstant %1 1.0
+ %5 = OpConstant %1 0.0
+ %6 = OpConstantComposite %2 %4 %5 %5 %5
+ %7 = OpConstantComposite %2 %5 %4 %5 %5
+ %8 = OpConstantComposite %2 %5 %5 %4 %5
+ %9 = OpUndef %11
+%10 = OpConstantComposite %3 %6 %7 %8 %9)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeMatrixColumnTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeInt 32 0
+ %2 = OpTypeFloat 32
+ %3 = OpTypeVector %1 2
+ %4 = OpTypeVector %3 2
+ %5 = OpTypeMatrix %2 2
+ %6 = OpConstant %1 42
+ %7 = OpConstant %2 3.14
+ %8 = OpConstantComposite %3 %6 %6
+ %9 = OpConstantComposite %4 %7 %7
+%10 = OpConstantComposite %5 %8 %9)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpConstant %1 4
+%3 = OpTypeArray %1 %2
+%4 = OpConstantComposite %3 %2 %2 %2 %2)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayWithUndefGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpConstant %1 4
+%9 = OpUndef %1
+%3 = OpTypeArray %1 %2
+%4 = OpConstantComposite %3 %2 %2 %2 %9)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstConstituentBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpConstant %1 4
+%3 = OpTypeArray %1 %2
+%4 = OpConstantComposite %3 %2 %2 %2 %1)"; // Uses a type as operand
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstituentTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpConstant %1 4
+%3 = OpTypeArray %1 %2
+%5 = OpTypeFloat 32
+%6 = OpConstant %5 3.14 ; bad type for const value
+%4 = OpConstantComposite %3 %2 %2 %2 %6)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeArrayConstituentUndefTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpConstant %1 4
+%3 = OpTypeArray %1 %2
+%5 = OpTypeFloat 32
+%6 = OpUndef %5 ; bad type for undef
+%4 = OpConstantComposite %3 %2 %2 %2 %6)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeStructGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeInt 64 1
+%3 = OpTypeStruct %1 %1 %2
+%4 = OpConstant %1 42
+%5 = OpConstant %2 4300000000
+%6 = OpConstantComposite %3 %4 %4 %5)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeStructUndefGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeInt 64 1
+%3 = OpTypeStruct %1 %1 %2
+%4 = OpConstant %1 42
+%5 = OpUndef %2
+%6 = OpConstantComposite %3 %4 %4 %5)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantCompositeStructMemberTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeInt 64 1
+%3 = OpTypeStruct %1 %1 %2
+%4 = OpConstant %1 42
+%5 = OpConstant %2 4300000000
+%6 = OpConstantComposite %3 %4 %5 %4)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpConstantCompositeStructMemberUndefTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeInt 64 1
+%3 = OpTypeStruct %1 %1 %2
+%4 = OpConstant %1 42
+%5 = OpUndef %2
+%6 = OpConstantComposite %3 %4 %5 %4)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpConstantSamplerGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%float = OpTypeFloat 32
+%samplerType = OpTypeSampler
+%3 = OpConstantSampler %samplerType ClampToEdge 0 Nearest)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpConstantSamplerResultTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpConstantSampler %1 Clamp 0 Nearest)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpConstantNullGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeBool
+ %2 = OpConstantNull %1
+ %3 = OpTypeInt 32 0
+ %4 = OpConstantNull %3
+ %5 = OpTypeFloat 32
+ %6 = OpConstantNull %5
+ %7 = OpTypePointer UniformConstant %3
+ %8 = OpConstantNull %7
+ %9 = OpTypeEvent
+%10 = OpConstantNull %9
+%11 = OpTypeDeviceEvent
+%12 = OpConstantNull %11
+%13 = OpTypeReserveId
+%14 = OpConstantNull %13
+%15 = OpTypeQueue
+%16 = OpConstantNull %15
+%17 = OpTypeVector %5 2
+%18 = OpConstantNull %17
+%19 = OpTypeMatrix %17 2
+%20 = OpConstantNull %19
+%25 = OpConstant %3 8
+%21 = OpTypeArray %3 %25
+%22 = OpConstantNull %21
+%23 = OpTypeStruct %3 %5 %1
+%24 = OpConstantNull %23
+%26 = OpTypeArray %17 %25
+%27 = OpConstantNull %26
+%28 = OpTypeStruct %7 %26 %26 %1
+%29 = OpConstantNull %28
+)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpConstantNullBasicBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpConstantNull %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpConstantNullArrayBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%2 = OpTypeInt 32 0
+%3 = OpTypeSampler
+%4 = OpConstant %2 4
+%5 = OpTypeArray %3 %4
+%6 = OpConstantNull %5)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpConstantNullStructBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%2 = OpTypeSampler
+%3 = OpTypeStruct %2 %2
+%4 = OpConstantNull %3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpConstantNullRuntimeArrayBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%bool = OpTypeBool
+%array = OpTypeRuntimeArray %bool
+%null = OpConstantNull %array)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpSpecConstantTrueGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeBool
+%2 = OpSpecConstantTrue %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpSpecConstantTrueBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpSpecConstantTrue %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpSpecConstantFalseGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeBool
+%2 = OpSpecConstantFalse %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpSpecConstantFalseBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpSpecConstantFalse %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpSpecConstantGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpSpecConstant %1 42)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpSpecConstantBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpSpecConstant !1 !4)";
+ // The expected failure code is implementation dependent (currently
+ // INVALID_BINARY because the binary parser catches these cases) and may
+ // change over time, but this must always fail.
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
+}
+
+// Valid: SpecConstantComposite specializes to a vector.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 4
+%3 = OpSpecConstant %1 3.14
+%4 = OpConstant %1 3.14
+%5 = OpSpecConstantComposite %2 %3 %3 %4 %4)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+// Valid: Vector of floats and Undefs.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorWithUndefGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 4
+%3 = OpSpecConstant %1 3.14
+%5 = OpConstant %1 3.14
+%9 = OpUndef %1
+%4 = OpSpecConstantComposite %2 %3 %5 %3 %9)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+// Invalid: result type is float.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorResultTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 4
+%3 = OpSpecConstant %1 3.14
+%4 = OpSpecConstantComposite %1 %3 %3 %3 %3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a composite type"));
+}
+
+// Invalid: Vector contains a mix of Int and Float.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorConstituentTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 4
+%4 = OpTypeInt 32 0
+%3 = OpSpecConstant %1 3.14
+%5 = OpConstant %4 42 ; bad type for constant value
+%6 = OpSpecConstantComposite %2 %3 %5 %3 %3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '5's type "
+ "does not match Result Type <id> '2's vector element "
+ "type."));
+}
+
+// Invalid: Constituent is not a constant
+TEST_F(ValidateIdWithMessage,
+ OpSpecConstantCompositeVectorConstituentNotConstantBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 4
+%3 = OpTypeInt 32 0
+%4 = OpSpecConstant %1 3.14
+%6 = OpSpecConstantComposite %2 %3 %4 %4 %4)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '3' is not a "
+ "constant or undef."));
+}
+
+// Invalid: Vector contains a mix of Undef-int and Float.
+TEST_F(ValidateIdWithMessage,
+ OpSpecConstantCompositeVectorConstituentUndefTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 4
+%4 = OpTypeInt 32 0
+%3 = OpSpecConstant %1 3.14
+%5 = OpUndef %4 ; bad type for undef value
+%6 = OpSpecConstantComposite %2 %3 %5 %3 %3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '5's type "
+ "does not match Result Type <id> '2's vector element "
+ "type."));
+}
+
+// Invalid: Vector expects 3 components, but 4 specified.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeVectorNumComponentsBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeFloat 32
+%2 = OpTypeVector %1 3
+%3 = OpConstant %1 3.14
+%5 = OpSpecConstant %1 4.0
+%6 = OpSpecConstantComposite %2 %3 %5 %3 %3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> count does "
+ "not match Result Type <id> '2's vector component "
+ "count."));
+}
+
+// Valid: 4x4 matrix of floats
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeFloat 32
+ %2 = OpTypeVector %1 4
+ %3 = OpTypeMatrix %2 4
+ %4 = OpConstant %1 1.0
+ %5 = OpSpecConstant %1 0.0
+ %6 = OpSpecConstantComposite %2 %4 %5 %5 %5
+ %7 = OpSpecConstantComposite %2 %5 %4 %5 %5
+ %8 = OpSpecConstantComposite %2 %5 %5 %4 %5
+ %9 = OpSpecConstantComposite %2 %5 %5 %5 %4
+%10 = OpSpecConstantComposite %3 %6 %7 %8 %9)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+// Valid: Matrix in which one column is Undef
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixUndefGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeFloat 32
+ %2 = OpTypeVector %1 4
+ %3 = OpTypeMatrix %2 4
+ %4 = OpConstant %1 1.0
+ %5 = OpSpecConstant %1 0.0
+ %6 = OpSpecConstantComposite %2 %4 %5 %5 %5
+ %7 = OpSpecConstantComposite %2 %5 %4 %5 %5
+ %8 = OpSpecConstantComposite %2 %5 %5 %4 %5
+ %9 = OpUndef %2
+%10 = OpSpecConstantComposite %3 %6 %7 %8 %9)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+// Invalid: Matrix in which the sizes of column vectors are not equal.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixConstituentTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeFloat 32
+ %2 = OpTypeVector %1 4
+ %3 = OpTypeVector %1 3
+ %4 = OpTypeMatrix %2 4
+ %5 = OpSpecConstant %1 1.0
+ %6 = OpConstant %1 0.0
+ %7 = OpSpecConstantComposite %2 %5 %6 %6 %6
+ %8 = OpSpecConstantComposite %2 %6 %5 %6 %6
+ %9 = OpSpecConstantComposite %2 %6 %6 %5 %6
+ %10 = OpSpecConstantComposite %3 %6 %6 %6
+%11 = OpSpecConstantComposite %4 %7 %8 %9 %10)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '10' vector "
+ "component count does not match Result Type <id> '4's "
+ "vector component count."));
+}
+
+// Invalid: Matrix type expects 4 columns but only 3 specified.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixNumColsBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeFloat 32
+ %2 = OpTypeVector %1 4
+ %3 = OpTypeMatrix %2 4
+ %4 = OpSpecConstant %1 1.0
+ %5 = OpConstant %1 0.0
+ %6 = OpSpecConstantComposite %2 %4 %5 %5 %5
+ %7 = OpSpecConstantComposite %2 %5 %4 %5 %5
+ %8 = OpSpecConstantComposite %2 %5 %5 %4 %5
+%10 = OpSpecConstantComposite %3 %6 %7 %8)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> count does "
+ "not match Result Type <id> '3's matrix column count."));
+}
+
+// Invalid: Composite contains a non-const/undef component
+TEST_F(ValidateIdWithMessage,
+ OpSpecConstantCompositeMatrixConstituentNotConstBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeFloat 32
+ %2 = OpConstant %1 0.0
+ %3 = OpTypeVector %1 4
+ %4 = OpTypeMatrix %3 4
+ %5 = OpSpecConstantComposite %3 %2 %2 %2 %2
+ %6 = OpSpecConstantComposite %4 %5 %5 %5 %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '1' is not a "
+ "constant composite or undef."));
+}
+
+// Invalid: Composite contains a column that is *not* a vector (it's an array)
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixColTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeFloat 32
+ %2 = OpTypeInt 32 0
+ %3 = OpSpecConstant %2 4
+ %4 = OpConstant %1 0.0
+ %5 = OpTypeVector %1 4
+ %6 = OpTypeArray %2 %3
+ %7 = OpTypeMatrix %5 4
+ %8 = OpSpecConstantComposite %6 %3 %3 %3 %3
+ %9 = OpSpecConstantComposite %5 %4 %4 %4 %4
+ %10 = OpSpecConstantComposite %7 %9 %9 %9 %8)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '8' type "
+ "does not match Result Type <id> '7's matrix column "
+ "type."));
+}
+
+// Invalid: Matrix with an Undef column of the wrong size.
+TEST_F(ValidateIdWithMessage,
+ OpSpecConstantCompositeMatrixConstituentUndefTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeFloat 32
+ %2 = OpTypeVector %1 4
+ %3 = OpTypeVector %1 3
+ %4 = OpTypeMatrix %2 4
+ %5 = OpSpecConstant %1 1.0
+ %6 = OpSpecConstant %1 0.0
+ %7 = OpSpecConstantComposite %2 %5 %6 %6 %6
+ %8 = OpSpecConstantComposite %2 %6 %5 %6 %6
+ %9 = OpSpecConstantComposite %2 %6 %6 %5 %6
+ %10 = OpUndef %3
+ %11 = OpSpecConstantComposite %4 %7 %8 %9 %10)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '10' vector "
+ "component count does not match Result Type <id> '4's "
+ "vector component count."));
+}
+
+// Invalid: Matrix in which some columns are Int and some are Float.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeMatrixColumnTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeInt 32 0
+ %2 = OpTypeFloat 32
+ %3 = OpTypeVector %1 2
+ %4 = OpTypeVector %2 2
+ %5 = OpTypeMatrix %4 2
+ %6 = OpSpecConstant %1 42
+ %7 = OpConstant %2 3.14
+ %8 = OpSpecConstantComposite %3 %6 %6
+ %9 = OpSpecConstantComposite %4 %7 %7
+%10 = OpSpecConstantComposite %5 %8 %9)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '8' "
+ "component type does not match Result Type <id> '5's "
+ "matrix column component type."));
+}
+
+// Valid: Array of integers
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpSpecConstant %1 4
+%5 = OpConstant %1 5
+%3 = OpTypeArray %1 %2
+%6 = OpTypeArray %1 %5
+%4 = OpSpecConstantComposite %3 %2 %2 %2 %2
+%7 = OpSpecConstantComposite %3 %5 %5 %5 %5)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+// Invalid: Expecting an array of 4 components, but 3 specified.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayNumComponentsBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpSpecConstant %1 4
+%3 = OpTypeArray %1 %2
+%4 = OpSpecConstantComposite %3 %2 %2 %2)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent count does not "
+ "match Result Type <id> '3's array length."));
+}
+
+// Valid: Array of Integers and Undef-int
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayWithUndefGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpSpecConstant %1 4
+%9 = OpUndef %1
+%3 = OpTypeArray %1 %2
+%4 = OpSpecConstantComposite %3 %2 %2 %2 %9)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+// Invalid: Array uses a type as operand.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayConstConstituentBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpConstant %1 4
+%3 = OpTypeArray %1 %2
+%4 = OpSpecConstantComposite %3 %2 %2 %2 %1)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '1' is not a "
+ "constant or undef."));
+}
+
+// Invalid: Array has a mix of Int and Float components.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeArrayConstituentTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpConstant %1 4
+%3 = OpTypeArray %1 %2
+%4 = OpTypeFloat 32
+%5 = OpSpecConstant %4 3.14 ; bad type for const value
+%6 = OpSpecConstantComposite %3 %2 %2 %2 %5)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '5's type "
+ "does not match Result Type <id> '3's array element "
+ "type."));
+}
+
+// Invalid: Array has a mix of Int and Undef-float.
+TEST_F(ValidateIdWithMessage,
+ OpSpecConstantCompositeArrayConstituentUndefTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpSpecConstant %1 4
+%3 = OpTypeArray %1 %2
+%5 = OpTypeFloat 32
+%6 = OpUndef %5 ; bad type for undef
+%4 = OpSpecConstantComposite %3 %2 %2 %2 %6)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '5's type "
+ "does not match Result Type <id> '3's array element "
+ "type."));
+}
+
+// Valid: Struct of {Int32,Int32,Int64}.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeInt 64 1
+%3 = OpTypeStruct %1 %1 %2
+%4 = OpConstant %1 42
+%5 = OpSpecConstant %2 4300000000
+%6 = OpSpecConstantComposite %3 %4 %4 %5)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+// Invalid: missing one int32 struct member.
+TEST_F(ValidateIdWithMessage,
+ OpSpecConstantCompositeStructMissingComponentBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%3 = OpTypeStruct %1 %1 %1
+%4 = OpConstant %1 42
+%5 = OpSpecConstant %1 430
+%6 = OpSpecConstantComposite %3 %4 %5)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '2' count "
+ "does not match Result Type <id> '2's struct member "
+ "count."));
+}
+
+// Valid: Struct uses Undef-int64.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructUndefGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeInt 64 1
+%3 = OpTypeStruct %1 %1 %2
+%4 = OpSpecConstant %1 42
+%5 = OpUndef %2
+%6 = OpSpecConstantComposite %3 %4 %4 %5)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+// Invalid: Composite contains non-const/undef component.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructNonConstBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeInt 64 1
+%3 = OpTypeStruct %1 %1 %2
+%4 = OpSpecConstant %1 42
+%5 = OpUndef %2
+%6 = OpSpecConstantComposite %3 %4 %1 %5)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '1' is not a "
+ "constant or undef."));
+}
+
+// Invalid: Struct component type does not match expected specialization type.
+// Second component was expected to be Int32, but got Int64.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructMemberTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeInt 64 1
+%3 = OpTypeStruct %1 %1 %2
+%4 = OpConstant %1 42
+%5 = OpSpecConstant %2 4300000000
+%6 = OpSpecConstantComposite %3 %4 %5 %4)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '5' type "
+ "does not match the Result Type <id> '3's member "
+ "type."));
+}
+
+// Invalid: Undef-int64 used when Int32 was expected.
+TEST_F(ValidateIdWithMessage, OpSpecConstantCompositeStructMemberUndefTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeInt 64 1
+%3 = OpTypeStruct %1 %1 %2
+%4 = OpSpecConstant %1 42
+%5 = OpUndef %2
+%6 = OpSpecConstantComposite %3 %4 %5 %4)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("OpSpecConstantComposite Constituent <id> '5' type "
+ "does not match the Result Type <id> '3's member "
+ "type."));
+}
+
+// TODO: OpSpecConstantOp
+
+TEST_F(ValidateIdWithMessage, OpVariableGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 1
+%2 = OpTypePointer Input %1
+%3 = OpVariable %2 Input)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpVariableInitializerGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 1
+%2 = OpTypePointer Input %1
+%3 = OpConstant %1 42
+%4 = OpVariable %2 Input %3)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+// TODO: Positive test OpVariable with OpConstantNull of OpTypePointer
+TEST_F(ValidateIdWithMessage, OpVariableResultTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 1
+%2 = OpVariable %1 Input)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpVariableInitializerBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeInt 32 1
+%2 = OpTypePointer Input %1
+%3 = OpVariable %2 Input %2)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpLoadGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeVoid
+ %2 = OpTypeInt 32 1
+ %3 = OpTypePointer UniformConstant %2
+ %4 = OpTypeFunction %1
+ %5 = OpVariable %3 UniformConstant
+ %6 = OpFunction %1 None %4
+ %7 = OpLabel
+ %8 = OpLoad %2 %5
+ %9 = OpReturn
+%10 = OpFunctionEnd
+)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpLoadResultTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 1
+%3 = OpTypePointer UniformConstant %2
+%4 = OpTypeFunction %1
+%5 = OpVariable %3 UniformConstant
+%6 = OpFunction %1 None %4
+%7 = OpLabel
+%8 = OpLoad %3 %5
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpLoadPointerBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 1
+%9 = OpTypeFloat 32
+%3 = OpTypePointer UniformConstant %2
+%4 = OpTypeFunction %1
+%6 = OpFunction %1 None %4
+%7 = OpLabel
+%8 = OpLoad %9 %3
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpStoreGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 1
+%3 = OpTypePointer UniformConstant %2
+%4 = OpTypeFunction %1
+%5 = OpConstant %2 42
+%6 = OpVariable %3 UniformConstant
+%7 = OpFunction %1 None %4
+%8 = OpLabel
+ OpStore %6 %5
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpStorePointerBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 1
+%3 = OpTypePointer UniformConstant %2
+%4 = OpTypeFunction %1
+%5 = OpConstant %2 42
+%6 = OpVariable %3 UniformConstant
+%7 = OpFunction %1 None %4
+%8 = OpLabel
+ OpStore %3 %5
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpStoreObjectGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 1
+%3 = OpTypePointer UniformConstant %2
+%4 = OpTypeFunction %1
+%5 = OpConstant %2 42
+%6 = OpVariable %3 UniformConstant
+%7 = OpFunction %1 None %4
+%8 = OpLabel
+ OpStore %6 %7
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpStoreTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 1
+%9 = OpTypeFloat 32
+%3 = OpTypePointer UniformConstant %2
+%4 = OpTypeFunction %1
+%5 = OpConstant %9 3.14
+%6 = OpVariable %3 UniformConstant
+%7 = OpFunction %1 None %4
+%8 = OpLabel
+ OpStore %6 %5
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpStoreVoid) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 1
+%3 = OpTypePointer UniformConstant %2
+%4 = OpTypeFunction %1
+%6 = OpVariable %3 UniformConstant
+%7 = OpFunction %1 None %4
+%8 = OpLabel
+%9 = OpFunctionCall %1 %7
+ OpStore %6 %9
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpStoreLabel) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 1
+%3 = OpTypePointer UniformConstant %2
+%4 = OpTypeFunction %1
+%6 = OpVariable %3 UniformConstant
+%7 = OpFunction %1 None %4
+%8 = OpLabel
+ OpStore %6 %8
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+// TODO: enable when this bug is fixed:
+// https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404
+TEST_F(ValidateIdWithMessage, DISABLED_OpStoreFunction) {
+ string spirv = kGLSL450MemoryModel + R"(
+%2 = OpTypeInt 32 1
+%3 = OpTypePointer UniformConstant %2
+%4 = OpTypeFunction %2
+%5 = OpConstant %2 123
+%6 = OpVariable %3 UniformConstant
+%7 = OpFunction %2 None %4
+%8 = OpLabel
+ OpStore %6 %7
+ OpReturnValue %5
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpCopyMemoryGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeVoid
+ %2 = OpTypeInt 32 0
+ %3 = OpTypePointer UniformConstant %2
+ %4 = OpConstant %2 42
+ %5 = OpVariable %3 UniformConstant %4
+ %6 = OpTypePointer Function %2
+ %7 = OpTypeFunction %1
+ %8 = OpFunction %1 None %7
+ %9 = OpLabel
+%10 = OpVariable %6 Function
+ OpCopyMemory %10 %5 None
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpCopyMemoryBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeVoid
+ %2 = OpTypeInt 32 0
+ %3 = OpTypePointer UniformConstant %2
+ %4 = OpConstant %2 42
+ %5 = OpVariable %3 UniformConstant %4
+%11 = OpTypeFloat 32
+ %6 = OpTypePointer Function %11
+ %7 = OpTypeFunction %1
+ %8 = OpFunction %1 None %7
+ %9 = OpLabel
+%10 = OpVariable %6 Function
+ OpCopyMemory %10 %5 None
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+// TODO: OpCopyMemorySized
+TEST_F(ValidateIdWithMessage, OpCopyMemorySizedGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeVoid
+ %2 = OpTypeInt 32 0
+ %3 = OpTypePointer UniformConstant %2
+ %4 = OpTypePointer Function %2
+ %5 = OpConstant %2 4
+ %6 = OpVariable %3 UniformConstant %5
+ %7 = OpTypeFunction %1
+ %8 = OpFunction %1 None %7
+ %9 = OpLabel
+%10 = OpVariable %4 Function
+ OpCopyMemorySized %10 %6 %5 None
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpCopyMemorySizedTargetBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypePointer UniformConstant %2
+%4 = OpTypePointer Function %2
+%5 = OpConstant %2 4
+%6 = OpVariable %3 UniformConstant %5
+%7 = OpTypeFunction %1
+%8 = OpFunction %1 None %7
+%9 = OpLabel
+ OpCopyMemorySized %9 %6 %5 None
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSourceBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypePointer UniformConstant %2
+%4 = OpTypePointer Function %2
+%5 = OpConstant %2 4
+%6 = OpTypeFunction %1
+%7 = OpFunction %1 None %6
+%8 = OpLabel
+%9 = OpVariable %4 Function
+ OpCopyMemorySized %9 %6 %5 None
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeVoid
+ %2 = OpTypeInt 32 0
+ %3 = OpTypePointer UniformConstant %2
+ %4 = OpTypePointer Function %2
+ %5 = OpConstant %2 4
+ %6 = OpVariable %3 UniformConstant %5
+ %7 = OpTypeFunction %1
+ %8 = OpFunction %1 None %7
+ %9 = OpLabel
+%10 = OpVariable %4 Function
+ OpCopyMemorySized %10 %6 %6 None
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpCopyMemorySizedSizeTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+ %1 = OpTypeVoid
+ %2 = OpTypeInt 32 0
+ %3 = OpTypePointer UniformConstant %2
+ %4 = OpTypePointer Function %2
+ %5 = OpConstant %2 4
+ %6 = OpVariable %3 UniformConstant %5
+ %7 = OpTypeFunction %1
+%11 = OpTypeFloat 32
+%12 = OpConstant %11 1.0
+ %8 = OpFunction %1 None %7
+ %9 = OpLabel
+%10 = OpVariable %4 Function
+ OpCopyMemorySized %10 %6 %12 None
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+// TODO: OpAccessChain
+// TODO: OpInBoundsAccessChain
+// TODO: OpArrayLength
+// TODO: OpImagePointer
+// TODO: OpGenericPtrMemSemantics
+
+TEST_F(ValidateIdWithMessage, OpFunctionGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 1
+%3 = OpTypeFunction %1 %2 %2
+%4 = OpFunction %1 None %3
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpFunctionResultTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 1
+%5 = OpConstant %2 42
+%3 = OpTypeFunction %1 %2 %2
+%4 = OpFunction %2 None %3
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpFunctionFunctionTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 1
+%4 = OpFunction %1 None %2
+OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpFunctionParameterGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %1 %2
+%4 = OpFunction %1 None %3
+%5 = OpFunctionParameter %2
+%6 = OpLabel
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpFunctionParameterMultipleGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %1 %2 %2
+%4 = OpFunction %1 None %3
+%5 = OpFunctionParameter %2
+%6 = OpFunctionParameter %2
+%7 = OpLabel
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpFunctionParameterResultTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %1 %2
+%4 = OpFunction %1 None %3
+%5 = OpFunctionParameter %1
+%6 = OpLabel
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpFunctionCallGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %2 %2
+%4 = OpTypeFunction %1
+%5 = OpConstant %2 42 ;21
+
+%6 = OpFunction %2 None %3
+%7 = OpFunctionParameter %2
+%8 = OpLabel
+ OpReturnValue %7
+ OpFunctionEnd
+
+%10 = OpFunction %1 None %4
+%11 = OpLabel
+%12 = OpFunctionCall %2 %6 %5
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpFunctionCallResultTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %2 %2
+%4 = OpTypeFunction %1
+%5 = OpConstant %2 42 ;21
+
+%6 = OpFunction %2 None %3
+%7 = OpFunctionParameter %2
+%8 = OpLabel
+%9 = OpLoad %2 %7
+ OpReturnValue %9
+ OpFunctionEnd
+
+%10 = OpFunction %1 None %4
+%11 = OpLabel
+%12 = OpFunctionCall %1 %6 %5
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpFunctionCallFunctionBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %2 %2
+%4 = OpTypeFunction %1
+%5 = OpConstant %2 42 ;21
+
+%10 = OpFunction %1 None %4
+%11 = OpLabel
+%12 = OpFunctionCall %2 %5 %5
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpFunctionCallArgumentTypeBad) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %2 %2
+%4 = OpTypeFunction %1
+%5 = OpConstant %2 42
+
+%13 = OpTypeFloat 32
+%14 = OpConstant %13 3.14
+
+%6 = OpFunction %2 None %3
+%7 = OpFunctionParameter %2
+%8 = OpLabel
+%9 = OpLoad %2 %7
+ OpReturnValue %9
+ OpFunctionEnd
+
+%10 = OpFunction %1 None %4
+%11 = OpLabel
+%12 = OpFunctionCall %2 %6 %14
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+// Valid: OpSampledImage result <id> is used in the same block by
+// OpImageSampleImplictLod
+TEST_F(ValidateIdWithMessage, OpSampledImageGood) {
+ string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
+%smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
+%si_lod = OpImageSampleImplicitLod %v4float %smpld_img %const_vec_1_1
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+// Invalid: OpSampledImage result <id> is defined in one block and used in a
+// different block.
+TEST_F(ValidateIdWithMessage, OpSampledImageUsedInDifferentBlockBad) {
+ string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
+%smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
+OpBranch %label_2
+%label_2 = OpLabel
+%si_lod = OpImageSampleImplicitLod %v4float %smpld_img %const_vec_1_1
+OpReturn
+OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("All OpSampledImage instructions must be in the same block in "
+ "which their Result <id> are consumed. OpSampledImage Result "
+ "Type <id> '23' has a consumer in a different basic block. The "
+ "consumer instruction <id> is '25'."));
+}
+
+// Invalid: OpSampledImage result <id> is used by OpSelect
+// Note: According to the Spec, OpSelect parameters must be either a scalar or a
+// vector. Therefore, OpTypeSampledImage is an illegal parameter for OpSelect.
+// However, the OpSelect validation does not catch this today. Therefore, it is
+// caught by the OpSampledImage validation. If the OpSelect validation code is
+// updated, the error message for this test may change.
+TEST_F(ValidateIdWithMessage, OpSampledImageUsedInOpSelectBad) {
+ string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
+%smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
+%select_img = OpSelect %sampled_image_type %spec_true %smpld_img %smpld_img
+OpReturn
+OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Result <id> from OpSampledImage instruction must not "
+ "appear as operands of OpSelect. Found result <id> "
+ "'23' as an operand of <id> '24'."));
+}
+
+// Invalid: OpSampledImage result <id> is used by OpPhi
+TEST_F(ValidateIdWithMessage, OpSampledImageUsedInOpPhiBad) {
+ string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
+%smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
+%phi_result = OpPhi %sampled_image_type %smpld_img %label_1
+OpReturn
+OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Result <id> from OpSampledImage instruction must not "
+ "appear as operands of OpPhi. Found result <id> '23' "
+ "as an operand of <id> '24'."));
+}
+
+#if 0
+TEST_F(ValidateIdWithMessage, OpFunctionCallArgumentCountBar) {
+ const char *spirv = R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %2 %2
+%4 = OpTypeFunction %1
+%5 = OpConstant %2 42 ;21
+
+%6 = OpFunction %2 None %3
+%7 = OpFunctionParameter %2
+%8 = OpLabel
+%9 = OpLoad %2 %7
+ OpReturnValue %9
+ OpFunctionEnd
+
+%10 = OpFunction %1 None %4
+%11 = OpLabel
+ OpReturn
+%12 = OpFunctionCall %2 %6 %5
+ OpFunctionEnd)";
+ CHECK(spirv, SPV_ERROR_INVALID_ID);
+}
+#endif
+
+// TODO: The many things that changed with how images are used.
+// TODO: OpTextureSample
+// TODO: OpTextureSampleDref
+// TODO: OpTextureSampleLod
+// TODO: OpTextureSampleProj
+// TODO: OpTextureSampleGrad
+// TODO: OpTextureSampleOffset
+// TODO: OpTextureSampleProjLod
+// TODO: OpTextureSampleProjGrad
+// TODO: OpTextureSampleLodOffset
+// TODO: OpTextureSampleProjOffset
+// TODO: OpTextureSampleGradOffset
+// TODO: OpTextureSampleProjLodOffset
+// TODO: OpTextureSampleProjGradOffset
+// TODO: OpTextureFetchTexelLod
+// TODO: OpTextureFetchTexelOffset
+// TODO: OpTextureFetchSample
+// TODO: OpTextureFetchTexel
+// TODO: OpTextureGather
+// TODO: OpTextureGatherOffset
+// TODO: OpTextureGatherOffsets
+// TODO: OpTextureQuerySizeLod
+// TODO: OpTextureQuerySize
+// TODO: OpTextureQueryLevels
+// TODO: OpTextureQuerySamples
+// TODO: OpConvertUToF
+// TODO: OpConvertFToS
+// TODO: OpConvertSToF
+// TODO: OpConvertUToF
+// TODO: OpUConvert
+// TODO: OpSConvert
+// TODO: OpFConvert
+// TODO: OpConvertPtrToU
+// TODO: OpConvertUToPtr
+// TODO: OpPtrCastToGeneric
+// TODO: OpGenericCastToPtr
+// TODO: OpBitcast
+// TODO: OpGenericCastToPtrExplicit
+// TODO: OpSatConvertSToU
+// TODO: OpSatConvertUToS
+// TODO: OpVectorExtractDynamic
+// TODO: OpVectorInsertDynamic
+// TODO: OpVectorShuffle
+// TODO: OpCompositeConstruct
+// TODO: OpCompositeExtract
+// TODO: OpCompositeInsert
+// TODO: OpCopyObject
+// TODO: OpTranspose
+// TODO: OpSNegate
+// TODO: OpFNegate
+// TODO: OpNot
+// TODO: OpIAdd
+// TODO: OpFAdd
+// TODO: OpISub
+// TODO: OpFSub
+// TODO: OpIMul
+// TODO: OpFMul
+// TODO: OpUDiv
+// TODO: OpSDiv
+// TODO: OpFDiv
+// TODO: OpUMod
+// TODO: OpSRem
+// TODO: OpSMod
+// TODO: OpFRem
+// TODO: OpFMod
+// TODO: OpVectorTimesScalar
+// TODO: OpMatrixTimesScalar
+// TODO: OpVectorTimesMatrix
+// TODO: OpMatrixTimesVector
+// TODO: OpMatrixTimesMatrix
+// TODO: OpOuterProduct
+// TODO: OpDot
+// TODO: OpShiftRightLogical
+// TODO: OpShiftRightArithmetic
+// TODO: OpShiftLeftLogical
+// TODO: OpBitwiseOr
+// TODO: OpBitwiseXor
+// TODO: OpBitwiseAnd
+// TODO: OpAny
+// TODO: OpAll
+// TODO: OpIsNan
+// TODO: OpIsInf
+// TODO: OpIsFinite
+// TODO: OpIsNormal
+// TODO: OpSignBitSet
+// TODO: OpLessOrGreater
+// TODO: OpOrdered
+// TODO: OpUnordered
+// TODO: OpLogicalOr
+// TODO: OpLogicalXor
+// TODO: OpLogicalAnd
+// TODO: OpSelect
+// TODO: OpIEqual
+// TODO: OpFOrdEqual
+// TODO: OpFUnordEqual
+// TODO: OpINotEqual
+// TODO: OpFOrdNotEqual
+// TODO: OpFUnordNotEqual
+// TODO: OpULessThan
+// TODO: OpSLessThan
+// TODO: OpFOrdLessThan
+// TODO: OpFUnordLessThan
+// TODO: OpUGreaterThan
+// TODO: OpSGreaterThan
+// TODO: OpFOrdGreaterThan
+// TODO: OpFUnordGreaterThan
+// TODO: OpULessThanEqual
+// TODO: OpSLessThanEqual
+// TODO: OpFOrdLessThanEqual
+// TODO: OpFUnordLessThanEqual
+// TODO: OpUGreaterThanEqual
+// TODO: OpSGreaterThanEqual
+// TODO: OpFOrdGreaterThanEqual
+// TODO: OpFUnordGreaterThanEqual
+// TODO: OpDPdx
+// TODO: OpDPdy
+// TODO: OpFWidth
+// TODO: OpDPdxFine
+// TODO: OpDPdyFine
+// TODO: OpFwidthFine
+// TODO: OpDPdxCoarse
+// TODO: OpDPdyCoarse
+// TODO: OpFwidthCoarse
+// TODO: OpPhi
+// TODO: OpLoopMerge
+// TODO: OpSelectionMerge
+// TODO: OpBranch
+// TODO: OpBranchConditional
+// TODO: OpSwitch
+
+TEST_F(ValidateIdWithMessage, OpReturnValueConstantGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %2
+%4 = OpConstant %2 42
+%5 = OpFunction %2 None %3
+%6 = OpLabel
+ OpReturnValue %4
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpReturnValueVariableGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0 ;10
+%3 = OpTypeFunction %2
+%8 = OpTypePointer Function %2 ;18
+%4 = OpConstant %2 42 ;22
+%5 = OpFunction %2 None %3 ;27
+%6 = OpLabel ;29
+%7 = OpVariable %8 Function %4 ;34
+%9 = OpLoad %2 %7
+ OpReturnValue %9 ;36
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpReturnValueExpressionGood) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %2
+%4 = OpConstant %2 42
+%5 = OpFunction %2 None %3
+%6 = OpLabel
+%7 = OpIAdd %2 %4 %4
+ OpReturnValue %7
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpReturnValueIsType) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %2
+%5 = OpFunction %2 None %3
+%6 = OpLabel
+ OpReturnValue %1
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpReturnValueIsLabel) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %2
+%5 = OpFunction %2 None %3
+%6 = OpLabel
+ OpReturnValue %6
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpReturnValueIsVoid) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %1
+%5 = OpFunction %1 None %3
+%6 = OpLabel
+%7 = OpFunctionCall %1 %5
+ OpReturnValue %7
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpReturnValueIsVariableInPhysical) {
+ // It's valid to return a pointer in a physical addressing model.
+ string spirv = kGLSL450MemoryModel + R"(
+ OpMemoryModel Physical32 OpenCL
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypePointer Private %2
+%4 = OpTypeFunction %3
+%5 = OpFunction %3 None %4
+%6 = OpLabel
+%7 = OpVariable %3 Function
+ OpReturnValue %7
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpReturnValueIsVariableInLogical) {
+ // It's invalid to return a pointer in a physical addressing model.
+ string spirv = kGLSL450MemoryModel + R"(
+ OpMemoryModel Logical GLSL450
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypePointer Private %2
+%4 = OpTypeFunction %3
+%5 = OpFunction %3 None %4
+%6 = OpLabel
+%7 = OpVariable %3 Function
+ OpReturnValue %7
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+// TODO: enable when this bug is fixed:
+// https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404
+TEST_F(ValidateIdWithMessage, DISABLED_OpReturnValueIsFunction) {
+ string spirv = kGLSL450MemoryModel + R"(
+%1 = OpTypeVoid
+%2 = OpTypeInt 32 0
+%3 = OpTypeFunction %2
+%5 = OpFunction %2 None %3
+%6 = OpLabel
+ OpReturnValue %5
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, UndefinedTypeId) {
+ string spirv = kGLSL450MemoryModel + R"(
+%s = OpTypeStruct %i32
+)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, UndefinedIdScope) {
+ string spirv = kGLSL450MemoryModel + R"(
+%u32 = OpTypeInt 32 0
+%memsem = OpConstant %u32 0
+%void = OpTypeVoid
+%void_f = OpTypeFunction %void
+%f = OpFunction %void None %void_f
+%l = OpLabel
+ OpMemoryBarrier %undef %memsem
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, UndefinedIdMemSem) {
+ string spirv = kGLSL450MemoryModel + R"(
+%u32 = OpTypeInt 32 0
+%scope = OpConstant %u32 0
+%void = OpTypeVoid
+%void_f = OpTypeFunction %void
+%f = OpFunction %void None %void_f
+%l = OpLabel
+ OpMemoryBarrier %scope %undef
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage,
+ KernelOpEntryPointAndOpInBoundsPtrAccessChainGood) {
+ string spirv = kOpenCLMemoryModel32 + R"(
+ OpEntryPoint Kernel %2 "simple_kernel"
+ OpSource OpenCL_C 200000
+ OpDecorate %3 BuiltIn GlobalInvocationId
+ OpDecorate %3 Constant
+ OpDecorate %4 FuncParamAttr NoCapture
+ OpDecorate %3 LinkageAttributes "__spirv_GlobalInvocationId" Import
+ %5 = OpTypeInt 32 0
+ %6 = OpTypeVector %5 3
+ %7 = OpTypePointer UniformConstant %6
+ %3 = OpVariable %7 UniformConstant
+ %8 = OpTypeVoid
+ %9 = OpTypeStruct %5
+%10 = OpTypePointer CrossWorkgroup %9
+%11 = OpTypeFunction %8 %10
+%12 = OpConstant %5 0
+%13 = OpTypePointer CrossWorkgroup %5
+%14 = OpConstant %5 42
+ %2 = OpFunction %8 None %11
+ %4 = OpFunctionParameter %10
+%15 = OpLabel
+%16 = OpLoad %6 %3 Aligned 0
+%17 = OpCompositeExtract %5 %16 0
+%18 = OpInBoundsPtrAccessChain %13 %4 %17 %12
+ OpStore %18 %14 Aligned 4
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpPtrAccessChainGood) {
+ string spirv = kOpenCLMemoryModel64 + R"(
+ OpEntryPoint Kernel %2 "another_kernel"
+ OpSource OpenCL_C 200000
+ OpDecorate %3 BuiltIn GlobalInvocationId
+ OpDecorate %3 Constant
+ OpDecorate %4 FuncParamAttr NoCapture
+ OpDecorate %3 LinkageAttributes "__spirv_GlobalInvocationId" Import
+ %5 = OpTypeInt 64 0
+ %6 = OpTypeVector %5 3
+ %7 = OpTypePointer UniformConstant %6
+ %3 = OpVariable %7 UniformConstant
+ %8 = OpTypeVoid
+ %9 = OpTypeInt 32 0
+%10 = OpTypeStruct %9
+%11 = OpTypePointer CrossWorkgroup %10
+%12 = OpTypeFunction %8 %11
+%13 = OpConstant %5 4294967295
+%14 = OpConstant %9 0
+%15 = OpTypePointer CrossWorkgroup %9
+%16 = OpConstant %9 42
+ %2 = OpFunction %8 None %12
+ %4 = OpFunctionParameter %11
+%17 = OpLabel
+%18 = OpLoad %6 %3 Aligned 0
+%19 = OpCompositeExtract %5 %18 0
+%20 = OpBitwiseAnd %5 %19 %13
+%21 = OpPtrAccessChain %15 %4 %20 %14
+ OpStore %21 %16 Aligned 4
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateIdWithMessage, OpLoadBitcastPointerGood) {
+ string spirv = kOpenCLMemoryModel64 + R"(
+%2 = OpTypeVoid
+%3 = OpTypeInt 32 1
+%4 = OpTypeFloat 32
+%5 = OpTypePointer UniformConstant %3
+%6 = OpTypePointer UniformConstant %4
+%7 = OpVariable %5 UniformConstant
+%8 = OpTypeFunction %2
+%9 = OpFunction %2 None %8
+%10 = OpLabel
+%11 = OpBitcast %6 %7
+%12 = OpLoad %4 %11
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpLoadBitcastNonPointerBad) {
+ string spirv = kOpenCLMemoryModel64 + R"(
+%2 = OpTypeVoid
+%3 = OpTypeInt 32 1
+%4 = OpTypeFloat 32
+%5 = OpTypePointer UniformConstant %3
+%6 = OpTypeFunction %2
+%7 = OpVariable %5 UniformConstant
+%8 = OpFunction %2 None %6
+%9 = OpLabel
+%10 = OpLoad %3 %7
+%11 = OpBitcast %4 %10
+%12 = OpLoad %3 %11
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpStoreBitcastPointerGood) {
+ string spirv = kOpenCLMemoryModel64 + R"(
+%2 = OpTypeVoid
+%3 = OpTypeInt 32 1
+%4 = OpTypeFloat 32
+%5 = OpTypePointer Function %3
+%6 = OpTypePointer Function %4
+%7 = OpTypeFunction %2
+%8 = OpConstant %3 42
+%9 = OpFunction %2 None %7
+%10 = OpLabel
+%11 = OpVariable %6 Function
+%12 = OpBitcast %5 %11
+ OpStore %12 %8
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+TEST_F(ValidateIdWithMessage, OpStoreBitcastNonPointerBad) {
+ string spirv = kOpenCLMemoryModel64 + R"(
+%2 = OpTypeVoid
+%3 = OpTypeInt 32 1
+%4 = OpTypeFloat 32
+%5 = OpTypePointer Function %4
+%6 = OpTypeFunction %2
+%7 = OpConstant %4 42
+%8 = OpFunction %2 None %6
+%9 = OpLabel
+%10 = OpVariable %5 Function
+%11 = OpBitcast %3 %7
+ OpStore %11 %7
+ OpReturn
+ OpFunctionEnd)";
+ CompileSuccessfully(spirv.c_str());
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+}
+
+// TODO: OpLifetimeStart
+// TODO: OpLifetimeStop
+// TODO: OpAtomicInit
+// TODO: OpAtomicLoad
+// TODO: OpAtomicStore
+// TODO: OpAtomicExchange
+// TODO: OpAtomicCompareExchange
+// TODO: OpAtomicCompareExchangeWeak
+// TODO: OpAtomicIIncrement
+// TODO: OpAtomicIDecrement
+// TODO: OpAtomicIAdd
+// TODO: OpAtomicISub
+// TODO: OpAtomicUMin
+// TODO: OpAtomicUMax
+// TODO: OpAtomicAnd
+// TODO: OpAtomicOr
+// TODO: OpAtomicXor
+// TODO: OpAtomicIMin
+// TODO: OpAtomicIMax
+// TODO: OpEmitStreamVertex
+// TODO: OpEndStreamPrimitive
+// TODO: OpAsyncGroupCopy
+// TODO: OpWaitGroupEvents
+// TODO: OpGroupAll
+// TODO: OpGroupAny
+// TODO: OpGroupBroadcast
+// TODO: OpGroupIAdd
+// TODO: OpGroupFAdd
+// TODO: OpGroupFMin
+// TODO: OpGroupUMin
+// TODO: OpGroupSMin
+// TODO: OpGroupFMax
+// TODO: OpGroupUMax
+// TODO: OpGroupSMax
+// TODO: OpEnqueueMarker
+// TODO: OpEnqueueKernel
+// TODO: OpGetKernelNDrangeSubGroupCount
+// TODO: OpGetKernelNDrangeMaxSubGroupSize
+// TODO: OpGetKernelWorkGroupSize
+// TODO: OpGetKernelPreferredWorkGroupSizeMultiple
+// TODO: OpRetainEvent
+// TODO: OpReleaseEvent
+// TODO: OpCreateUserEvent
+// TODO: OpIsValidEvent
+// TODO: OpSetUserEventStatus
+// TODO: OpCaptureEventProfilingInfo
+// TODO: OpGetDefaultQueue
+// TODO: OpBuildNDRange
+// TODO: OpReadPipe
+// TODO: OpWritePipe
+// TODO: OpReservedReadPipe
+// TODO: OpReservedWritePipe
+// TODO: OpReserveReadPipePackets
+// TODO: OpReserveWritePipePackets
+// TODO: OpCommitReadPipe
+// TODO: OpCommitWritePipe
+// TODO: OpIsValidReserveId
+// TODO: OpGetNumPipePackets
+// TODO: OpGetMaxPipePackets
+// TODO: OpGroupReserveReadPipePackets
+// TODO: OpGroupReserveWritePipePackets
+// TODO: OpGroupCommitReadPipe
+// TODO: OpGroupCommitWritePipe
+
+} // anonymous namespace
diff --git a/test/val/Validate.Layout.cpp b/test/val/val_layout_test.cpp
index a1256ab9..bc49075a 100644
--- a/test/val/Validate.Layout.cpp
+++ b/test/val/val_layout_test.cpp
@@ -20,10 +20,9 @@
#include <utility>
#include "gmock/gmock.h"
-
-#include "UnitSPIRV.h"
-#include "ValidateFixtures.h"
#include "source/diagnostic.h"
+#include "unit_spirv.h"
+#include "val_fixtures.h"
using std::function;
using std::ostream;
@@ -95,8 +94,8 @@ const vector<string>& getInstructions() {
"%floatt = OpTypeFloat 32",
"%voidt = OpTypeVoid",
"%boolt = OpTypeBool",
- "%vec4 = OpTypeVector %intt 4",
- "%vec3 = OpTypeVector %intt 3",
+ "%vec4 = OpTypeVector %floatt 4",
+ "%vec3 = OpTypeVector %floatt 3",
"%mat33 = OpTypeMatrix %vec3 3",
"%mat44 = OpTypeMatrix %vec4 4",
"%struct = OpTypeStruct %intt %mat33",
@@ -150,9 +149,9 @@ INSTANTIATE_TEST_CASE_P(InstructionsOrder,
, make_tuple(string("OpDecorationGroup") , Range<13, 16>() , Range<0, 15>())
, make_tuple(string("OpTypeBool") , Range<17, 30>() , All)
, make_tuple(string("OpTypeVoid") , Range<17, 30>() , Range<0, 25>())
- , make_tuple(string("OpTypeFloat") , Range<17, 30>() , All)
+ , make_tuple(string("OpTypeFloat") , Range<17, 30>() , Range<0,20>())
, make_tuple(string("OpTypeInt") , Range<17, 30>() , Range<0, 20>())
- , make_tuple(string("OpTypeVector %intt 4") , Range<17, 30>() , Range<18, 23>())
+ , make_tuple(string("OpTypeVector %floatt 4") , Range<17, 30>() , Range<19, 23>())
, make_tuple(string("OpTypeMatrix %vec4 4") , Range<17, 30>() , Range<22, kRangeEnd>())
, make_tuple(string("OpTypeStruct") , Range<17, 30>() , Range<24, kRangeEnd>())
, make_tuple(string("%vfunct = OpTypeFunction"), Range<17, 30>() , Range<20, 30>())
diff --git a/test/val/val_limits_test.cpp b/test/val/val_limits_test.cpp
new file mode 100644
index 00000000..97bca1df
--- /dev/null
+++ b/test/val/val_limits_test.cpp
@@ -0,0 +1,78 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Validation tests for Universal Limits. (Section 2.17 of the SPIR-V Spec)
+
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "unit_spirv.h"
+#include "val_fixtures.h"
+
+using ::testing::HasSubstr;
+using ::testing::MatchesRegex;
+
+using std::string;
+
+using ValidateLimits = spvtest::ValidateBase<bool>;
+
+string header = R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+)";
+
+TEST_F(ValidateLimits, idLargerThanBoundBad) {
+ string str = header + R"(
+; %i32 has ID 1
+%i32 = OpTypeInt 32 1
+%c = OpConstant %i32 100
+
+; Fake an instruction with 64 as the result id.
+; !64 = OpConstantNull %i32
+!0x3002e !1 !64
+)";
+
+ CompileSuccessfully(str);
+ ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Result <id> '64' must be less than the ID bound '3'."));
+}
+
+TEST_F(ValidateLimits, idEqualToBoundBad) {
+ string str = header + R"(
+; %i32 has ID 1
+%i32 = OpTypeInt 32 1
+%c = OpConstant %i32 100
+
+; Fake an instruction with 64 as the result id.
+; !64 = OpConstantNull %i32
+!0x3002e !1 !64
+)";
+
+ CompileSuccessfully(str);
+
+ // The largest ID used in this program is 64. Let's overwrite the ID bound in
+ // the header to be 64. This should result in an error because all IDs must
+ // satisfy: 0 < id < bound.
+ OverwriteAssembledBinary(3, 64);
+
+ ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Result <id> '64' must be less than the ID bound '64'."));
+}
+
diff --git a/test/val/Validate.SSA.cpp b/test/val/val_ssa_test.cpp
index 06f56911..09bb9bcf 100644
--- a/test/val/Validate.SSA.cpp
+++ b/test/val/val_ssa_test.cpp
@@ -14,14 +14,14 @@
// Validation tests for SSA
-#include "UnitSPIRV.h"
-#include "ValidateFixtures.h"
-#include "gmock/gmock.h"
-
#include <sstream>
#include <string>
#include <utility>
+#include "gmock/gmock.h"
+#include "unit_spirv.h"
+#include "val_fixtures.h"
+
using ::testing::HasSubstr;
using ::testing::MatchesRegex;
@@ -234,7 +234,8 @@ TEST_F(ValidateSSA, ForwardMemberDecorateGood) {
OpMemoryModel Logical GLSL450
OpMemberDecorate %struct 1 RowMajor
%intt = OpTypeInt 32 1
-%vec3 = OpTypeVector %intt 3
+%f32 = OpTypeFloat 32
+%vec3 = OpTypeVector %f32 3
%mat33 = OpTypeMatrix %vec3 3
%struct = OpTypeStruct %intt %mat33
)";
@@ -249,7 +250,8 @@ TEST_F(ValidateSSA, ForwardMemberDecorateInvalidIdBad) {
OpName %missing "missing"
OpMemberDecorate %missing 1 RowMajor ; Target not defined
%intt = OpTypeInt 32 1
-%vec3 = OpTypeVector %intt 3
+%f32 = OpTypeFloat 32
+%vec3 = OpTypeVector %f32 3
%mat33 = OpTypeMatrix %vec3 3
%struct = OpTypeStruct %intt %mat33
)";
@@ -265,9 +267,9 @@ TEST_F(ValidateSSA, ForwardGroupDecorateGood) {
OpDecorate %dgrp RowMajor
%dgrp = OpDecorationGroup
OpGroupDecorate %dgrp %mat33 %mat44
-%intt = OpTypeInt 32 1
-%vec3 = OpTypeVector %intt 3
-%vec4 = OpTypeVector %intt 4
+%f32 = OpTypeFloat 32
+%vec3 = OpTypeVector %f32 3
+%vec4 = OpTypeVector %f32 4
%mat33 = OpTypeMatrix %vec3 3
%mat44 = OpTypeMatrix %vec4 4
)";
@@ -302,9 +304,9 @@ TEST_F(ValidateSSA, ForwardGroupDecorateMissingTargetBad) {
OpDecorate %dgrp RowMajor
%dgrp = OpDecorationGroup
OpGroupDecorate %dgrp %missing %mat44 ; Target not defined
-%intt = OpTypeInt 32 1
-%vec3 = OpTypeVector %intt 3
-%vec4 = OpTypeVector %intt 4
+%f32 = OpTypeFloat 32
+%vec3 = OpTypeVector %f32 3
+%vec4 = OpTypeVector %f32 4
%mat33 = OpTypeMatrix %vec3 3
%mat44 = OpTypeMatrix %vec4 4
)";
@@ -1241,10 +1243,8 @@ TEST_F(ValidateSSA, PhiVariableDefNotDominatedByParentBlockBad) {
"definition does not dominate its parent .\\[if_false\\]"));
}
-TEST_F(ValidateSSA,
- PhiVariableDefDominatesButNotDefinedInParentBlock) {
- string str = kHeader + "OpName %if_true \"if_true\"\n" +
- kBasicTypes +
+TEST_F(ValidateSSA, PhiVariableDefDominatesButNotDefinedInParentBlock) {
+ string str = kHeader + "OpName %if_true \"if_true\"\n" + kBasicTypes +
R"(
%func = OpFunction %voidt None %vfunct
%entry = OpLabel
diff --git a/test/val/ValidationState.cpp b/test/val/val_state_test.cpp
index 23df7ccc..2e6dafbc 100644
--- a/test/val/ValidationState.cpp
+++ b/test/val/val_state_test.cpp
@@ -15,16 +15,15 @@
// Unit tests for ValidationState_t.
-#include "val/ValidationState.h"
-
#include <vector>
#include "gtest/gtest.h"
#include "spirv/1.1/spirv.h"
#include "enum_set.h"
-#include "val/Construct.h"
-#include "val/Function.h"
+#include "val/construct.h"
+#include "val/function.h"
+#include "val/validation_state.h"
#include "validate.h"
namespace {
diff --git a/test/val/Validate.Storage.cpp b/test/val/val_storage_test.cpp
index 7954eb23..653429f9 100644
--- a/test/val/Validate.Storage.cpp
+++ b/test/val/val_storage_test.cpp
@@ -18,8 +18,8 @@
#include <string>
#include <tuple>
-#include "ValidateFixtures.h"
#include "gmock/gmock.h"
+#include "val_fixtures.h"
using ValidateStorage = spvtest::ValidateBase<std::string>;