diff options
-rw-r--r-- | examples/cpp-interface/CMakeLists.txt | 8 | ||||
-rw-r--r-- | include/spirv-tools/libspirv.h | 1 | ||||
-rw-r--r-- | source/CMakeLists.txt | 14 | ||||
-rw-r--r-- | source/disassemble.cpp | 45 | ||||
-rw-r--r-- | source/enum_set.h | 2 | ||||
-rw-r--r-- | source/instruction.cpp | 20 | ||||
-rw-r--r-- | source/instruction.h | 4 | ||||
-rw-r--r-- | source/name_mapper.cpp | 12 | ||||
-rw-r--r-- | source/name_mapper.h | 1 | ||||
-rw-r--r-- | source/parsed_operand.cpp | 75 | ||||
-rw-r--r-- | source/parsed_operand.h | 32 | ||||
-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.cpp | 18 | ||||
-rw-r--r-- | source/validate.h | 6 | ||||
-rw-r--r-- | source/validate_cfg.cpp | 8 | ||||
-rw-r--r-- | source/validate_datarules.cpp | 272 | ||||
-rw-r--r-- | source/validate_id.cpp | 281 | ||||
-rw-r--r-- | source/validate_instruction.cpp | 22 | ||||
-rw-r--r-- | source/validate_layout.cpp | 4 | ||||
-rw-r--r-- | test/CMakeLists.txt | 121 | ||||
-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.txt | 34 | ||||
-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.txt | 37 | ||||
-rw-r--r-- | test/val/ValidateID.cpp | 1925 | ||||
-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.cpp | 464 | ||||
-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.cpp | 2557 | ||||
-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.cpp | 78 | ||||
-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>; |