aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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>;