diff options
Diffstat (limited to '3rdparty/bgfx/3rdparty/spirv-tools/source/val/validate_extensions.cpp')
-rw-r--r-- | 3rdparty/bgfx/3rdparty/spirv-tools/source/val/validate_extensions.cpp | 1074 |
1 files changed, 609 insertions, 465 deletions
diff --git a/3rdparty/bgfx/3rdparty/spirv-tools/source/val/validate_extensions.cpp b/3rdparty/bgfx/3rdparty/spirv-tools/source/val/validate_extensions.cpp index 1f7b95633f8..dccbe14908d 100644 --- a/3rdparty/bgfx/3rdparty/spirv-tools/source/val/validate_extensions.cpp +++ b/3rdparty/bgfx/3rdparty/spirv-tools/source/val/validate_extensions.cpp @@ -20,7 +20,9 @@ #include "spirv/unified1/NonSemanticClspvReflection.h" +#include "NonSemanticShaderDebugInfo100.h" #include "OpenCLDebugInfo100.h" +#include "source/common_debug_info.h" #include "source/diagnostic.h" #include "source/enum_string_mapping.h" #include "source/extensions.h" @@ -45,6 +47,34 @@ uint32_t GetSizeTBitWidth(const ValidationState_t& _) { return 0; } +bool IsIntScalar(ValidationState_t& _, uint32_t id, bool must_len32, + bool must_unsigned) { + auto type = _.FindDef(id); + if (!type || type->opcode() != SpvOpTypeInt) { + return false; + } + + if (must_len32 && type->GetOperandAs<uint32_t>(1) != 32) { + return false; + } + + return !must_unsigned || type->GetOperandAs<uint32_t>(2) == 0; +} + +bool IsUint32Constant(ValidationState_t& _, uint32_t id) { + auto inst = _.FindDef(id); + if (!inst || inst->opcode() != SpvOpConstant) { + return false; + } + + return IsIntScalar(_, inst->type_id(), true, true); +} + +uint32_t GetUint32Constant(ValidationState_t& _, uint32_t id) { + auto inst = _.FindDef(id); + return inst->word(3); +} + // Check that the operand of a debug info instruction |inst| at |word_index| // is a result id of an instruction with |expected_opcode|. spv_result_t ValidateOperandForDebugInfo( @@ -68,6 +98,22 @@ spv_result_t ValidateOperandForDebugInfo( return SPV_SUCCESS; } +// For NonSemantic.Shader.DebugInfo.100 check that the operand of a debug info +// instruction |inst| at |word_index| is a result id of a 32-bit integer +// OpConstant instruction. For OpenCL.DebugInfo.100 the parameter is a literal +// word so cannot be validated. +spv_result_t ValidateUint32ConstantOperandForDebugInfo( + ValidationState_t& _, const std::string& operand_name, + const Instruction* inst, uint32_t word_index, + const std::function<std::string()>& ext_inst_name) { + if (!IsUint32Constant(_, inst->word(word_index))) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": expected operand " << operand_name + << " must be a result id of 32-bit unsigned OpConstant"; + } + return SPV_SUCCESS; +} + #define CHECK_OPERAND(NAME, opcode, index) \ do { \ auto result = ValidateOperandForDebugInfo(_, NAME, opcode, inst, index, \ @@ -75,18 +121,27 @@ spv_result_t ValidateOperandForDebugInfo( if (result != SPV_SUCCESS) return result; \ } while (0) +#define CHECK_CONST_UINT_OPERAND(NAME, index) \ + if (vulkanDebugInfo) { \ + auto result = ValidateUint32ConstantOperandForDebugInfo( \ + _, NAME, inst, index, ext_inst_name); \ + if (result != SPV_SUCCESS) return result; \ + } + // True if the operand of a debug info instruction |inst| at |word_index| // satisifies |expectation| that is given as a function. Otherwise, // returns false. bool DoesDebugInfoOperandMatchExpectation( const ValidationState_t& _, - const std::function<bool(OpenCLDebugInfo100Instructions)>& expectation, + const std::function<bool(CommonDebugInfoInstructions)>& expectation, const Instruction* inst, uint32_t word_index) { if (inst->words().size() <= word_index) return false; auto* debug_inst = _.FindDef(inst->word(word_index)); if (debug_inst->opcode() != SpvOpExtInst || - debug_inst->ext_inst_type() != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 || - !expectation(OpenCLDebugInfo100Instructions(debug_inst->word(4)))) { + (debug_inst->ext_inst_type() != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 && + debug_inst->ext_inst_type() != + SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) || + !expectation(CommonDebugInfoInstructions(debug_inst->word(4)))) { return false; } return true; @@ -97,20 +152,18 @@ bool DoesDebugInfoOperandMatchExpectation( // is |expected_debug_inst|. spv_result_t ValidateDebugInfoOperand( ValidationState_t& _, const std::string& debug_inst_name, - OpenCLDebugInfo100Instructions expected_debug_inst, const Instruction* inst, + CommonDebugInfoInstructions expected_debug_inst, const Instruction* inst, uint32_t word_index, const std::function<std::string()>& ext_inst_name) { - std::function<bool(OpenCLDebugInfo100Instructions)> expectation = - [expected_debug_inst](OpenCLDebugInfo100Instructions dbg_inst) { + std::function<bool(CommonDebugInfoInstructions)> expectation = + [expected_debug_inst](CommonDebugInfoInstructions dbg_inst) { return dbg_inst == expected_debug_inst; }; if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index)) return SPV_SUCCESS; spv_ext_inst_desc desc = nullptr; - _.grammar().lookupExtInst(SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100, - expected_debug_inst, &desc); - if (_.grammar().lookupExtInst(SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100, - expected_debug_inst, &desc) != SPV_SUCCESS || + if (_.grammar().lookupExtInst(inst->ext_inst_type(), expected_debug_inst, + &desc) != SPV_SUCCESS || !desc) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << ext_inst_name() << ": " @@ -134,9 +187,8 @@ spv_result_t ValidateDebugInfoOperand( spv_result_t ValidateOperandBaseType( ValidationState_t& _, const Instruction* inst, uint32_t word_index, const std::function<std::string()>& ext_inst_name) { - return ValidateDebugInfoOperand(_, "Base Type", - OpenCLDebugInfo100DebugTypeBasic, inst, - word_index, ext_inst_name); + return ValidateDebugInfoOperand(_, "Base Type", CommonDebugInfoDebugTypeBasic, + inst, word_index, ext_inst_name); } // Check that the operand of a debug info instruction |inst| at |word_index| @@ -147,12 +199,12 @@ spv_result_t ValidateOperandLexicalScope( ValidationState_t& _, const std::string& debug_inst_name, const Instruction* inst, uint32_t word_index, const std::function<std::string()>& ext_inst_name) { - std::function<bool(OpenCLDebugInfo100Instructions)> expectation = - [](OpenCLDebugInfo100Instructions dbg_inst) { - return dbg_inst == OpenCLDebugInfo100DebugCompilationUnit || - dbg_inst == OpenCLDebugInfo100DebugFunction || - dbg_inst == OpenCLDebugInfo100DebugLexicalBlock || - dbg_inst == OpenCLDebugInfo100DebugTypeComposite; + std::function<bool(CommonDebugInfoInstructions)> expectation = + [](CommonDebugInfoInstructions dbg_inst) { + return dbg_inst == CommonDebugInfoDebugCompilationUnit || + dbg_inst == CommonDebugInfoDebugFunction || + dbg_inst == CommonDebugInfoDebugLexicalBlock || + dbg_inst == CommonDebugInfoDebugTypeComposite; }; if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index)) return SPV_SUCCESS; @@ -171,16 +223,15 @@ spv_result_t ValidateOperandDebugType( const Instruction* inst, uint32_t word_index, const std::function<std::string()>& ext_inst_name, bool allow_template_param) { - std::function<bool(OpenCLDebugInfo100Instructions)> expectation = - [&allow_template_param](OpenCLDebugInfo100Instructions dbg_inst) { + std::function<bool(CommonDebugInfoInstructions)> expectation = + [&allow_template_param](CommonDebugInfoInstructions dbg_inst) { if (allow_template_param && - (dbg_inst == OpenCLDebugInfo100DebugTypeTemplateParameter || - dbg_inst == - OpenCLDebugInfo100DebugTypeTemplateTemplateParameter)) { + (dbg_inst == CommonDebugInfoDebugTypeTemplateParameter || + dbg_inst == CommonDebugInfoDebugTypeTemplateTemplateParameter)) { return true; } - return OpenCLDebugInfo100DebugTypeBasic <= dbg_inst && - dbg_inst <= OpenCLDebugInfo100DebugTypeTemplate; + return CommonDebugInfoDebugTypeBasic <= dbg_inst && + dbg_inst <= CommonDebugInfoDebugTypeTemplate; }; if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index)) return SPV_SUCCESS; @@ -191,28 +242,6 @@ spv_result_t ValidateOperandDebugType( << " is not a valid debug type"; } -bool IsUint32Constant(ValidationState_t& _, uint32_t id) { - auto inst = _.FindDef(id); - if (!inst || inst->opcode() != SpvOpConstant) { - return false; - } - - auto type = _.FindDef(inst->type_id()); - if (!type || type->opcode() != SpvOpTypeInt) { - return false; - } - - if (type->GetOperandAs<uint32_t>(1) != 32) { - return false; - } - - if (type->GetOperandAs<uint32_t>(2) != 0) { - return false; - } - - return true; -} - spv_result_t ValidateClspvReflectionKernel(ValidationState_t& _, const Instruction* inst) { const auto kernel_id = inst->GetOperandAs<uint32_t>(4); @@ -667,18 +696,26 @@ bool IsDebugVariableWithIntScalarType(ValidationState_t& _, const Instruction* inst, uint32_t word_index) { auto* dbg_int_scalar_var = _.FindDef(inst->word(word_index)); - if (OpenCLDebugInfo100Instructions(dbg_int_scalar_var->word(4)) == - OpenCLDebugInfo100DebugLocalVariable || - OpenCLDebugInfo100Instructions(dbg_int_scalar_var->word(4)) == - OpenCLDebugInfo100DebugGlobalVariable) { + if (CommonDebugInfoInstructions(dbg_int_scalar_var->word(4)) == + CommonDebugInfoDebugLocalVariable || + CommonDebugInfoInstructions(dbg_int_scalar_var->word(4)) == + CommonDebugInfoDebugGlobalVariable) { auto* dbg_type = _.FindDef(dbg_int_scalar_var->word(6)); - if (OpenCLDebugInfo100Instructions(dbg_type->word(4)) == - OpenCLDebugInfo100DebugTypeBasic && - (OpenCLDebugInfo100DebugBaseTypeAttributeEncoding(dbg_type->word(7)) == - OpenCLDebugInfo100Signed || - OpenCLDebugInfo100DebugBaseTypeAttributeEncoding(dbg_type->word(7)) == - OpenCLDebugInfo100Unsigned)) { - return true; + if (CommonDebugInfoInstructions(dbg_type->word(4)) == + CommonDebugInfoDebugTypeBasic) { + const spv_ext_inst_type_t ext_inst_type = + spv_ext_inst_type_t(inst->ext_inst_type()); + const bool vulkanDebugInfo = + ext_inst_type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100; + uint32_t encoding = dbg_type->word(7); + if (!vulkanDebugInfo || IsUint32Constant(_, encoding)) { + auto ocl_encoding = OpenCLDebugInfo100DebugBaseTypeAttributeEncoding( + vulkanDebugInfo ? GetUint32Constant(_, encoding) : encoding); + if (ocl_encoding == OpenCLDebugInfo100Signed || + ocl_encoding == OpenCLDebugInfo100Unsigned) { + return true; + } + } } } return false; @@ -2668,7 +2705,9 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) { break; } } - } else if (ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) { + } else if (ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 || + ext_inst_type == + SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) { if (!_.IsVoidType(result_type)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << ext_inst_name() << ": " @@ -2676,447 +2715,552 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) { << "OpTypeVoid"; } - auto num_words = inst->words().size(); + const bool vulkanDebugInfo = + ext_inst_type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100; - const OpenCLDebugInfo100Instructions ext_inst_key = - OpenCLDebugInfo100Instructions(ext_inst_index); - switch (ext_inst_key) { - case OpenCLDebugInfo100DebugInfoNone: - case OpenCLDebugInfo100DebugNoScope: - case OpenCLDebugInfo100DebugOperation: - // The binary parser validates the opcode for DebugInfoNone, - // DebugNoScope, DebugOperation, and the literal values don't need - // further checks. - break; - case OpenCLDebugInfo100DebugCompilationUnit: { - CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); - break; - } - case OpenCLDebugInfo100DebugSource: { - CHECK_OPERAND("File", SpvOpString, 5); - if (num_words == 7) CHECK_OPERAND("Text", SpvOpString, 6); - break; - } - case OpenCLDebugInfo100DebugTypeBasic: { - CHECK_OPERAND("Name", SpvOpString, 5); - CHECK_OPERAND("Size", SpvOpConstant, 6); - // "Encoding" param is already validated by the binary parsing stage. - break; - } - case OpenCLDebugInfo100DebugTypePointer: - case OpenCLDebugInfo100DebugTypeQualifier: { - auto validate_base_type = - ValidateOperandBaseType(_, inst, 5, ext_inst_name); - if (validate_base_type != SPV_SUCCESS) return validate_base_type; - break; - } - case OpenCLDebugInfo100DebugTypeVector: { - auto validate_base_type = - ValidateOperandBaseType(_, inst, 5, ext_inst_name); - if (validate_base_type != SPV_SUCCESS) return validate_base_type; + auto num_words = inst->words().size(); - uint32_t component_count = inst->word(6); - if (!component_count || component_count > 4) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << ext_inst_name() << ": Component Count must be positive " - << "integer less than or equal to 4"; - } - break; - } - case OpenCLDebugInfo100DebugTypeArray: { - auto validate_base_type = ValidateOperandDebugType( - _, "Base Type", inst, 5, ext_inst_name, false); - if (validate_base_type != SPV_SUCCESS) return validate_base_type; - for (uint32_t i = 6; i < num_words; ++i) { - bool invalid = false; - auto* component_count = _.FindDef(inst->word(i)); - if (IsConstIntScalarTypeWith32Or64Bits(_, component_count)) { - // TODO: We need a spec discussion for the bindless array. - if (!component_count->word(3)) { - invalid = true; + // Handle any non-common OpenCL insts, then common + if (ext_inst_type != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 || + OpenCLDebugInfo100Instructions(ext_inst_index) != + OpenCLDebugInfo100DebugModuleINTEL) { + const CommonDebugInfoInstructions ext_inst_key = + CommonDebugInfoInstructions(ext_inst_index); + switch (ext_inst_key) { + case CommonDebugInfoDebugInfoNone: + case CommonDebugInfoDebugNoScope: + break; + // The binary parser validates the opcode for DebugInfoNone, + // DebugNoScope, DebugOperation. We just check the parameters to + // DebugOperation are properly constants for vulkan debug info. + case CommonDebugInfoDebugOperation: { + CHECK_CONST_UINT_OPERAND("Operation", 5); + for (uint32_t i = 6; i < num_words; ++i) { + CHECK_CONST_UINT_OPERAND("Operand", i); + } + break; + } + case CommonDebugInfoDebugCompilationUnit: { + CHECK_CONST_UINT_OPERAND("Version", 5); + CHECK_CONST_UINT_OPERAND("DWARF Version", 6); + CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7); + CHECK_CONST_UINT_OPERAND("Language", 8); + break; + } + case CommonDebugInfoDebugSource: { + CHECK_OPERAND("File", SpvOpString, 5); + if (num_words == 7) CHECK_OPERAND("Text", SpvOpString, 6); + break; + } + case CommonDebugInfoDebugTypeBasic: { + CHECK_OPERAND("Name", SpvOpString, 5); + CHECK_OPERAND("Size", SpvOpConstant, 6); + CHECK_CONST_UINT_OPERAND("Encoding", 7); + break; + } + case CommonDebugInfoDebugTypePointer: { + auto validate_base_type = + ValidateOperandBaseType(_, inst, 5, ext_inst_name); + if (validate_base_type != SPV_SUCCESS) return validate_base_type; + CHECK_CONST_UINT_OPERAND("Storage Class", 6); + CHECK_CONST_UINT_OPERAND("Flags", 7); + break; + } + case CommonDebugInfoDebugTypeQualifier: { + auto validate_base_type = + ValidateOperandBaseType(_, inst, 5, ext_inst_name); + if (validate_base_type != SPV_SUCCESS) return validate_base_type; + CHECK_CONST_UINT_OPERAND("Type Qualifier", 6); + break; + } + case CommonDebugInfoDebugTypeVector: { + auto validate_base_type = + ValidateOperandBaseType(_, inst, 5, ext_inst_name); + if (validate_base_type != SPV_SUCCESS) return validate_base_type; + + CHECK_CONST_UINT_OPERAND("Component Count", 6); + uint32_t component_count = inst->word(6); + if (vulkanDebugInfo) { + uint64_t const_val; + if (!_.GetConstantValUint64(component_count, &const_val)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() + << ": Component Count must be 32-bit integer OpConstant"; } - } else if (component_count->words().size() > 6 && - (OpenCLDebugInfo100Instructions(component_count->word( - 4)) == OpenCLDebugInfo100DebugLocalVariable || - OpenCLDebugInfo100Instructions(component_count->word( - 4)) == OpenCLDebugInfo100DebugGlobalVariable)) { - auto* component_count_type = _.FindDef(component_count->word(6)); - if (component_count_type->words().size() > 7) { - if (OpenCLDebugInfo100Instructions(component_count_type->word( - 4)) != OpenCLDebugInfo100DebugTypeBasic || - OpenCLDebugInfo100DebugBaseTypeAttributeEncoding( - component_count_type->word(7)) != - OpenCLDebugInfo100Unsigned) { + component_count = const_val & 0xffffffff; + } + + if (!component_count || component_count > 4) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": Component Count must be positive " + << "integer less than or equal to 4"; + } + break; + } + case CommonDebugInfoDebugTypeArray: { + auto validate_base_type = ValidateOperandDebugType( + _, "Base Type", inst, 5, ext_inst_name, false); + if (validate_base_type != SPV_SUCCESS) return validate_base_type; + for (uint32_t i = 6; i < num_words; ++i) { + bool invalid = false; + auto* component_count = _.FindDef(inst->word(i)); + if (IsConstIntScalarTypeWith32Or64Bits(_, component_count)) { + // TODO: We need a spec discussion for the bindless array. + if (!component_count->word(3)) { invalid = true; - } else { - // DebugTypeBasic for DebugLocalVariable/DebugGlobalVariable - // must have Unsigned encoding and 32 or 64 as its size in bits. - Instruction* size_in_bits = - _.FindDef(component_count_type->word(6)); - if (!_.IsIntScalarType(size_in_bits->type_id()) || - (size_in_bits->word(3) != 32 && - size_in_bits->word(3) != 64)) { + } + } else if (component_count->words().size() > 6 && + (CommonDebugInfoInstructions(component_count->word(4)) == + CommonDebugInfoDebugLocalVariable || + CommonDebugInfoInstructions(component_count->word(4)) == + CommonDebugInfoDebugGlobalVariable)) { + auto* component_count_type = _.FindDef(component_count->word(6)); + if (component_count_type->words().size() > 7) { + uint32_t encoding = component_count_type->word(7); + if (CommonDebugInfoInstructions(component_count_type->word( + 4)) != CommonDebugInfoDebugTypeBasic || + (vulkanDebugInfo && !IsUint32Constant(_, encoding)) || + OpenCLDebugInfo100DebugBaseTypeAttributeEncoding( + vulkanDebugInfo + ? GetUint32Constant(_, encoding) + : encoding) != OpenCLDebugInfo100Unsigned) { invalid = true; + } else { + // DebugTypeBasic for DebugLocalVariable/DebugGlobalVariable + // must have Unsigned encoding and 32 or 64 as its size in + // bits. + Instruction* size_in_bits = + _.FindDef(component_count_type->word(6)); + if (!_.IsIntScalarType(size_in_bits->type_id()) || + (size_in_bits->word(3) != 32 && + size_in_bits->word(3) != 64)) { + invalid = true; + } } + } else { + invalid = true; } } else { invalid = true; } - } else { - invalid = true; + if (invalid) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": Component Count must be " + << "OpConstant with a 32- or 64-bits integer scalar type " + "or " + << "DebugGlobalVariable or DebugLocalVariable with a 32- " + "or " + << "64-bits unsigned integer scalar type"; + } } - if (invalid) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << ext_inst_name() << ": Component Count must be " - << "OpConstant with a 32- or 64-bits integer scalar type or " - << "DebugGlobalVariable or DebugLocalVariable with a 32- or " - << "64-bits unsigned integer scalar type"; + break; + } + case CommonDebugInfoDebugTypedef: { + CHECK_OPERAND("Name", SpvOpString, 5); + auto validate_base_type = + ValidateOperandBaseType(_, inst, 6, ext_inst_name); + if (validate_base_type != SPV_SUCCESS) return validate_base_type; + CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7); + CHECK_CONST_UINT_OPERAND("Line", 8); + CHECK_CONST_UINT_OPERAND("Column", 9); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + break; + } + case CommonDebugInfoDebugTypeFunction: { + CHECK_CONST_UINT_OPERAND("Flags", 5); + auto* return_type = _.FindDef(inst->word(6)); + // TODO: We need a spec discussion that we have to allow return and + // parameter types of a DebugTypeFunction to have template parameter. + if (return_type->opcode() != SpvOpTypeVoid) { + auto validate_return = ValidateOperandDebugType( + _, "Return Type", inst, 6, ext_inst_name, true); + if (validate_return != SPV_SUCCESS) return validate_return; } + for (uint32_t word_index = 7; word_index < num_words; ++word_index) { + auto validate_param = ValidateOperandDebugType( + _, "Parameter Types", inst, word_index, ext_inst_name, true); + if (validate_param != SPV_SUCCESS) return validate_param; + } + break; } - break; - } - case OpenCLDebugInfo100DebugTypedef: { - CHECK_OPERAND("Name", SpvOpString, 5); - auto validate_base_type = - ValidateOperandBaseType(_, inst, 6, ext_inst_name); - if (validate_base_type != SPV_SUCCESS) return validate_base_type; - CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); - auto validate_parent = - ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); - if (validate_parent != SPV_SUCCESS) return validate_parent; - break; - } - case OpenCLDebugInfo100DebugTypeFunction: { - auto* return_type = _.FindDef(inst->word(6)); - // TODO: We need a spec discussion that we have to allow return and - // parameter types of a DebugTypeFunction to have template parameter. - if (return_type->opcode() != SpvOpTypeVoid) { - auto validate_return = ValidateOperandDebugType( - _, "Return Type", inst, 6, ext_inst_name, true); - if (validate_return != SPV_SUCCESS) return validate_return; - } - for (uint32_t word_index = 7; word_index < num_words; ++word_index) { - auto validate_param = ValidateOperandDebugType( - _, "Parameter Types", inst, word_index, ext_inst_name, true); - if (validate_param != SPV_SUCCESS) return validate_param; - } - break; - } - case OpenCLDebugInfo100DebugTypeEnum: { - CHECK_OPERAND("Name", SpvOpString, 5); - if (!DoesDebugInfoOperandMatchExpectation( - _, - [](OpenCLDebugInfo100Instructions dbg_inst) { - return dbg_inst == OpenCLDebugInfo100DebugInfoNone; - }, - inst, 6)) { - auto validate_underlying_type = ValidateOperandDebugType( - _, "Underlying Types", inst, 6, ext_inst_name, false); - if (validate_underlying_type != SPV_SUCCESS) - return validate_underlying_type; - } - CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); - auto validate_parent = - ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); - if (validate_parent != SPV_SUCCESS) return validate_parent; - CHECK_OPERAND("Size", SpvOpConstant, 11); - auto* size = _.FindDef(inst->word(11)); - if (!_.IsIntScalarType(size->type_id()) || !size->word(3)) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << ext_inst_name() << ": expected operand Size is a " - << "positive integer"; - } - for (uint32_t word_index = 13; word_index + 1 < num_words; - word_index += 2) { - CHECK_OPERAND("Value", SpvOpConstant, word_index); - CHECK_OPERAND("Name", SpvOpString, word_index + 1); - } - break; - } - case OpenCLDebugInfo100DebugTypeComposite: { - CHECK_OPERAND("Name", SpvOpString, 5); - CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); - auto validate_parent = - ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); - if (validate_parent != SPV_SUCCESS) return validate_parent; - CHECK_OPERAND("Linkage Name", SpvOpString, 11); - if (!DoesDebugInfoOperandMatchExpectation( - _, - [](OpenCLDebugInfo100Instructions dbg_inst) { - return dbg_inst == OpenCLDebugInfo100DebugInfoNone; - }, - inst, 12)) { - CHECK_OPERAND("Size", SpvOpConstant, 12); - } - for (uint32_t word_index = 14; word_index < num_words; ++word_index) { + case CommonDebugInfoDebugTypeEnum: { + CHECK_OPERAND("Name", SpvOpString, 5); if (!DoesDebugInfoOperandMatchExpectation( _, - [](OpenCLDebugInfo100Instructions dbg_inst) { - return dbg_inst == OpenCLDebugInfo100DebugTypeMember || - dbg_inst == OpenCLDebugInfo100DebugFunction || - dbg_inst == OpenCLDebugInfo100DebugTypeInheritance; + [](CommonDebugInfoInstructions dbg_inst) { + return dbg_inst == CommonDebugInfoDebugInfoNone; }, - inst, word_index)) { + inst, 6)) { + auto validate_underlying_type = ValidateOperandDebugType( + _, "Underlying Types", inst, 6, ext_inst_name, false); + if (validate_underlying_type != SPV_SUCCESS) + return validate_underlying_type; + } + CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7); + CHECK_CONST_UINT_OPERAND("Line", 8); + CHECK_CONST_UINT_OPERAND("Column", 9); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + CHECK_OPERAND("Size", SpvOpConstant, 11); + auto* size = _.FindDef(inst->word(11)); + if (!_.IsIntScalarType(size->type_id()) || !size->word(3)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) - << ext_inst_name() << ": " - << "expected operand Members " - << "must be DebugTypeMember, DebugFunction, or " - "DebugTypeInheritance"; + << ext_inst_name() << ": expected operand Size is a " + << "positive integer"; } - } - break; - } - case OpenCLDebugInfo100DebugTypeMember: { - CHECK_OPERAND("Name", SpvOpString, 5); - // TODO: We need a spec discussion that we have to allow member types - // to have template parameter. - auto validate_type = - ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name, true); - if (validate_type != SPV_SUCCESS) return validate_type; - CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); - CHECK_DEBUG_OPERAND("Parent", OpenCLDebugInfo100DebugTypeComposite, 10); - CHECK_OPERAND("Offset", SpvOpConstant, 11); - CHECK_OPERAND("Size", SpvOpConstant, 12); - if (num_words == 15) CHECK_OPERAND("Value", SpvOpConstant, 14); - break; - } - case OpenCLDebugInfo100DebugTypeInheritance: { - CHECK_DEBUG_OPERAND("Child", OpenCLDebugInfo100DebugTypeComposite, 5); - auto* debug_inst = _.FindDef(inst->word(5)); - auto composite_type = - OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6)); - if (composite_type != OpenCLDebugInfo100Class && - composite_type != OpenCLDebugInfo100Structure) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << ext_inst_name() << ": " - << "expected operand Child must be class or struct debug type"; - } - CHECK_DEBUG_OPERAND("Parent", OpenCLDebugInfo100DebugTypeComposite, 6); - debug_inst = _.FindDef(inst->word(6)); - composite_type = - OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6)); - if (composite_type != OpenCLDebugInfo100Class && - composite_type != OpenCLDebugInfo100Structure) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << ext_inst_name() << ": " - << "expected operand Parent must be class or struct debug " - "type"; - } - CHECK_OPERAND("Offset", SpvOpConstant, 7); - CHECK_OPERAND("Size", SpvOpConstant, 8); - break; - } - case OpenCLDebugInfo100DebugFunction: { - CHECK_OPERAND("Name", SpvOpString, 5); - auto validate_type = - ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name, false); - if (validate_type != SPV_SUCCESS) return validate_type; - CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); - auto validate_parent = - ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); - if (validate_parent != SPV_SUCCESS) return validate_parent; - CHECK_OPERAND("Linkage Name", SpvOpString, 11); - if (!DoesDebugInfoOperandMatchExpectation( - _, - [](OpenCLDebugInfo100Instructions dbg_inst) { - return dbg_inst == OpenCLDebugInfo100DebugInfoNone; - }, - inst, 14)) { - CHECK_OPERAND("Function", SpvOpFunction, 14); - } - if (num_words == 16) { - CHECK_DEBUG_OPERAND("Declaration", - OpenCLDebugInfo100DebugFunctionDeclaration, 15); - } - break; - } - case OpenCLDebugInfo100DebugFunctionDeclaration: { - CHECK_OPERAND("Name", SpvOpString, 5); - auto validate_type = - ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name, false); - if (validate_type != SPV_SUCCESS) return validate_type; - CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); - auto validate_parent = - ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); - if (validate_parent != SPV_SUCCESS) return validate_parent; - CHECK_OPERAND("Linkage Name", SpvOpString, 11); - break; - } - case OpenCLDebugInfo100DebugLexicalBlock: { - CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 5); - auto validate_parent = - ValidateOperandLexicalScope(_, "Parent", inst, 8, ext_inst_name); - if (validate_parent != SPV_SUCCESS) return validate_parent; - if (num_words == 10) CHECK_OPERAND("Name", SpvOpString, 9); - break; - } - case OpenCLDebugInfo100DebugScope: { - auto validate_scope = - ValidateOperandLexicalScope(_, "Scope", inst, 5, ext_inst_name); - if (validate_scope != SPV_SUCCESS) return validate_scope; - if (num_words == 7) { - CHECK_DEBUG_OPERAND("Inlined At", OpenCLDebugInfo100DebugInlinedAt, - 6); - } - break; - } - case OpenCLDebugInfo100DebugLocalVariable: { - CHECK_OPERAND("Name", SpvOpString, 5); - // TODO: We need a spec discussion that we have to allow local variable - // types to have template parameter. - auto validate_type = - ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name, true); - if (validate_type != SPV_SUCCESS) return validate_type; - CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); - auto validate_parent = - ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); - if (validate_parent != SPV_SUCCESS) return validate_parent; - break; - } - case OpenCLDebugInfo100DebugDeclare: { - CHECK_DEBUG_OPERAND("Local Variable", - OpenCLDebugInfo100DebugLocalVariable, 5); - auto* operand = _.FindDef(inst->word(6)); - if (operand->opcode() != SpvOpVariable && - operand->opcode() != SpvOpFunctionParameter) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << ext_inst_name() << ": " - << "expected operand Variable must be a result id of " - "OpVariable or OpFunctionParameter"; - } - - CHECK_DEBUG_OPERAND("Expression", OpenCLDebugInfo100DebugExpression, 7); - break; - } - case OpenCLDebugInfo100DebugExpression: { - for (uint32_t word_index = 5; word_index < num_words; ++word_index) { - CHECK_DEBUG_OPERAND("Operation", OpenCLDebugInfo100DebugOperation, - word_index); - } - break; - } - case OpenCLDebugInfo100DebugTypeTemplate: { - if (!DoesDebugInfoOperandMatchExpectation( - _, - [](OpenCLDebugInfo100Instructions dbg_inst) { - return dbg_inst == OpenCLDebugInfo100DebugTypeComposite || - dbg_inst == OpenCLDebugInfo100DebugFunction; - }, - inst, 5)) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << ext_inst_name() << ": " - << "expected operand Target must be DebugTypeComposite " - << "or DebugFunction"; - } - for (uint32_t word_index = 6; word_index < num_words; ++word_index) { + CHECK_CONST_UINT_OPERAND("Flags", 12); + for (uint32_t word_index = 13; word_index + 1 < num_words; + word_index += 2) { + CHECK_OPERAND("Value", SpvOpConstant, word_index); + CHECK_OPERAND("Name", SpvOpString, word_index + 1); + } + break; + } + case CommonDebugInfoDebugTypeComposite: { + CHECK_OPERAND("Name", SpvOpString, 5); + CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7); + CHECK_CONST_UINT_OPERAND("Line", 8); + CHECK_CONST_UINT_OPERAND("Column", 9); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + CHECK_OPERAND("Linkage Name", SpvOpString, 11); if (!DoesDebugInfoOperandMatchExpectation( _, - [](OpenCLDebugInfo100Instructions dbg_inst) { - return dbg_inst == - OpenCLDebugInfo100DebugTypeTemplateParameter || - dbg_inst == - OpenCLDebugInfo100DebugTypeTemplateTemplateParameter; + [](CommonDebugInfoInstructions dbg_inst) { + return dbg_inst == CommonDebugInfoDebugInfoNone; }, - inst, word_index)) { + inst, 12)) { + CHECK_OPERAND("Size", SpvOpConstant, 12); + } + CHECK_CONST_UINT_OPERAND("Flags", 13); + for (uint32_t word_index = 14; word_index < num_words; ++word_index) { + if (!DoesDebugInfoOperandMatchExpectation( + _, + [](CommonDebugInfoInstructions dbg_inst) { + return dbg_inst == CommonDebugInfoDebugTypeMember || + dbg_inst == CommonDebugInfoDebugFunction || + dbg_inst == CommonDebugInfoDebugTypeInheritance; + }, + inst, word_index)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand Members " + << "must be DebugTypeMember, DebugFunction, or " + "DebugTypeInheritance"; + } + } + break; + } + case CommonDebugInfoDebugTypeMember: { + CHECK_OPERAND("Name", SpvOpString, 5); + // TODO: We need a spec discussion that we have to allow member types + // to have template parameter. + auto validate_type = + ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name, true); + if (validate_type != SPV_SUCCESS) return validate_type; + CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7); + CHECK_CONST_UINT_OPERAND("Line", 8); + CHECK_CONST_UINT_OPERAND("Column", 9); + // NonSemantic.Shader.DebugInfo doesn't have the Parent operand + if (vulkanDebugInfo) { + CHECK_OPERAND("Offset", SpvOpConstant, 10); + CHECK_OPERAND("Size", SpvOpConstant, 11); + CHECK_CONST_UINT_OPERAND("Flags", 12); + if (num_words == 14) CHECK_OPERAND("Value", SpvOpConstant, 13); + } else { + CHECK_DEBUG_OPERAND("Parent", CommonDebugInfoDebugTypeComposite, + 10); + CHECK_OPERAND("Offset", SpvOpConstant, 11); + CHECK_OPERAND("Size", SpvOpConstant, 12); + CHECK_CONST_UINT_OPERAND("Flags", 13); + if (num_words == 15) CHECK_OPERAND("Value", SpvOpConstant, 14); + } + break; + } + case CommonDebugInfoDebugTypeInheritance: { + CHECK_DEBUG_OPERAND("Child", CommonDebugInfoDebugTypeComposite, 5); + auto* debug_inst = _.FindDef(inst->word(5)); + auto composite_type = + OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6)); + if (composite_type != OpenCLDebugInfo100Class && + composite_type != OpenCLDebugInfo100Structure) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand Child must be class or struct debug " + "type"; + } + CHECK_DEBUG_OPERAND("Parent", CommonDebugInfoDebugTypeComposite, 6); + debug_inst = _.FindDef(inst->word(6)); + composite_type = + OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6)); + if (composite_type != OpenCLDebugInfo100Class && + composite_type != OpenCLDebugInfo100Structure) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << ext_inst_name() << ": " - << "expected operand Parameters must be " - << "DebugTypeTemplateParameter or " - << "DebugTypeTemplateTemplateParameter"; + << "expected operand Parent must be class or struct debug " + "type"; } + CHECK_OPERAND("Offset", SpvOpConstant, 7); + CHECK_OPERAND("Size", SpvOpConstant, 8); + CHECK_CONST_UINT_OPERAND("Flags", 9); + break; + } + case CommonDebugInfoDebugFunction: { + CHECK_OPERAND("Name", SpvOpString, 5); + auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6, + ext_inst_name, false); + if (validate_type != SPV_SUCCESS) return validate_type; + CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7); + CHECK_CONST_UINT_OPERAND("Line", 8); + CHECK_CONST_UINT_OPERAND("Column", 9); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + CHECK_OPERAND("Linkage Name", SpvOpString, 11); + CHECK_CONST_UINT_OPERAND("Flags", 12); + CHECK_CONST_UINT_OPERAND("Scope Line", 13); + // NonSemantic.Shader.DebugInfo.100 doesn't include a reference to the + // OpFunction + if (vulkanDebugInfo) { + if (num_words == 15) { + CHECK_DEBUG_OPERAND("Declaration", + CommonDebugInfoDebugFunctionDeclaration, 14); + } + } else { + if (!DoesDebugInfoOperandMatchExpectation( + _, + [](CommonDebugInfoInstructions dbg_inst) { + return dbg_inst == CommonDebugInfoDebugInfoNone; + }, + inst, 14)) { + CHECK_OPERAND("Function", SpvOpFunction, 14); + } + if (num_words == 16) { + CHECK_DEBUG_OPERAND("Declaration", + CommonDebugInfoDebugFunctionDeclaration, 15); + } + } + break; + } + case CommonDebugInfoDebugFunctionDeclaration: { + CHECK_OPERAND("Name", SpvOpString, 5); + auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6, + ext_inst_name, false); + if (validate_type != SPV_SUCCESS) return validate_type; + CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7); + CHECK_CONST_UINT_OPERAND("Line", 8); + CHECK_CONST_UINT_OPERAND("Column", 9); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + CHECK_OPERAND("Linkage Name", SpvOpString, 11); + CHECK_CONST_UINT_OPERAND("Flags", 12); + break; + } + case CommonDebugInfoDebugLexicalBlock: { + CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 5); + CHECK_CONST_UINT_OPERAND("Line", 6); + CHECK_CONST_UINT_OPERAND("Column", 7); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 8, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + if (num_words == 10) CHECK_OPERAND("Name", SpvOpString, 9); + break; + } + case CommonDebugInfoDebugScope: { + auto validate_scope = + ValidateOperandLexicalScope(_, "Scope", inst, 5, ext_inst_name); + if (validate_scope != SPV_SUCCESS) return validate_scope; + if (num_words == 7) { + CHECK_DEBUG_OPERAND("Inlined At", CommonDebugInfoDebugInlinedAt, 6); + } + break; + } + case CommonDebugInfoDebugLocalVariable: { + CHECK_OPERAND("Name", SpvOpString, 5); + // TODO: We need a spec discussion that we have to allow local + // variable types to have template parameter. + auto validate_type = + ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name, true); + if (validate_type != SPV_SUCCESS) return validate_type; + CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7); + CHECK_CONST_UINT_OPERAND("Line", 8); + CHECK_CONST_UINT_OPERAND("Column", 9); + auto validate_parent = + ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name); + if (validate_parent != SPV_SUCCESS) return validate_parent; + CHECK_CONST_UINT_OPERAND("Flags", 11); + if (num_words == 13) { + CHECK_CONST_UINT_OPERAND("ArgNumber", 12); + } + break; } - break; - } - case OpenCLDebugInfo100DebugTypeTemplateParameter: { - CHECK_OPERAND("Name", SpvOpString, 5); - auto validate_actual_type = ValidateOperandDebugType( - _, "Actual Type", inst, 6, ext_inst_name, false); - if (validate_actual_type != SPV_SUCCESS) return validate_actual_type; - if (!DoesDebugInfoOperandMatchExpectation( - _, - [](OpenCLDebugInfo100Instructions dbg_inst) { - return dbg_inst == OpenCLDebugInfo100DebugInfoNone; - }, - inst, 7)) { - CHECK_OPERAND("Value", SpvOpConstant, 7); - } - CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 8); - break; - } - case OpenCLDebugInfo100DebugGlobalVariable: { - CHECK_OPERAND("Name", SpvOpString, 5); - auto validate_type = - ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name, false); - if (validate_type != SPV_SUCCESS) return validate_type; - CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7); - auto validate_scope = - ValidateOperandLexicalScope(_, "Scope", inst, 10, ext_inst_name); - if (validate_scope != SPV_SUCCESS) return validate_scope; - CHECK_OPERAND("Linkage Name", SpvOpString, 11); - if (!DoesDebugInfoOperandMatchExpectation( - _, - [](OpenCLDebugInfo100Instructions dbg_inst) { - return dbg_inst == OpenCLDebugInfo100DebugInfoNone; - }, - inst, 12)) { - auto* operand = _.FindDef(inst->word(12)); + case CommonDebugInfoDebugDeclare: { + CHECK_DEBUG_OPERAND("Local Variable", + CommonDebugInfoDebugLocalVariable, 5); + auto* operand = _.FindDef(inst->word(6)); if (operand->opcode() != SpvOpVariable && - operand->opcode() != SpvOpConstant) { + operand->opcode() != SpvOpFunctionParameter) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << ext_inst_name() << ": " << "expected operand Variable must be a result id of " - "OpVariable or OpConstant or DebugInfoNone"; + "OpVariable or OpFunctionParameter"; } + + CHECK_DEBUG_OPERAND("Expression", CommonDebugInfoDebugExpression, 7); + + if (vulkanDebugInfo) { + for (uint32_t word_index = 8; word_index < num_words; + ++word_index) { + auto index_inst = _.FindDef(inst->word(word_index)); + auto type_id = index_inst != nullptr ? index_inst->type_id() : 0; + if (type_id == 0 || !IsIntScalar(_, type_id, false, false)) + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected index must be scalar integer"; + } + } + break; } - if (num_words == 15) { - CHECK_DEBUG_OPERAND("Static Member Declaration", - OpenCLDebugInfo100DebugTypeMember, 14); - } - break; - } - case OpenCLDebugInfo100DebugInlinedAt: { - auto validate_scope = - ValidateOperandLexicalScope(_, "Scope", inst, 6, ext_inst_name); - if (validate_scope != SPV_SUCCESS) return validate_scope; - if (num_words == 8) { - CHECK_DEBUG_OPERAND("Inlined", OpenCLDebugInfo100DebugInlinedAt, 7); + case CommonDebugInfoDebugExpression: { + for (uint32_t word_index = 5; word_index < num_words; ++word_index) { + CHECK_DEBUG_OPERAND("Operation", CommonDebugInfoDebugOperation, + word_index); + } + break; } - break; - } - case OpenCLDebugInfo100DebugValue: { - CHECK_DEBUG_OPERAND("Local Variable", - OpenCLDebugInfo100DebugLocalVariable, 5); - CHECK_DEBUG_OPERAND("Expression", OpenCLDebugInfo100DebugExpression, 7); - - for (uint32_t word_index = 8; word_index < num_words; ++word_index) { - // TODO: The following code simply checks if it is a const int scalar - // or a DebugLocalVariable or DebugGlobalVariable, but we have to - // check it using the same validation for Indexes of OpAccessChain. - if (!IsConstWithIntScalarType(_, inst, word_index) && - !IsDebugVariableWithIntScalarType(_, inst, word_index)) { + case CommonDebugInfoDebugTypeTemplate: { + if (!DoesDebugInfoOperandMatchExpectation( + _, + [](CommonDebugInfoInstructions dbg_inst) { + return dbg_inst == CommonDebugInfoDebugTypeComposite || + dbg_inst == CommonDebugInfoDebugFunction; + }, + inst, 5)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) - << ext_inst_name() << ": expected operand Indexes is " - << "OpConstant, DebugGlobalVariable, or " - << "type is OpConstant with an integer scalar type"; + << ext_inst_name() << ": " + << "expected operand Target must be DebugTypeComposite " + << "or DebugFunction"; + } + for (uint32_t word_index = 6; word_index < num_words; ++word_index) { + if (!DoesDebugInfoOperandMatchExpectation( + _, + [](CommonDebugInfoInstructions dbg_inst) { + return dbg_inst == + CommonDebugInfoDebugTypeTemplateParameter || + dbg_inst == + CommonDebugInfoDebugTypeTemplateTemplateParameter; + }, + inst, word_index)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand Parameters must be " + << "DebugTypeTemplateParameter or " + << "DebugTypeTemplateTemplateParameter"; + } } + break; } - break; + case CommonDebugInfoDebugTypeTemplateParameter: { + CHECK_OPERAND("Name", SpvOpString, 5); + auto validate_actual_type = ValidateOperandDebugType( + _, "Actual Type", inst, 6, ext_inst_name, false); + if (validate_actual_type != SPV_SUCCESS) return validate_actual_type; + if (!DoesDebugInfoOperandMatchExpectation( + _, + [](CommonDebugInfoInstructions dbg_inst) { + return dbg_inst == CommonDebugInfoDebugInfoNone; + }, + inst, 7)) { + CHECK_OPERAND("Value", SpvOpConstant, 7); + } + CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 8); + CHECK_CONST_UINT_OPERAND("Line", 9); + CHECK_CONST_UINT_OPERAND("Column", 10); + break; + } + case CommonDebugInfoDebugGlobalVariable: { + CHECK_OPERAND("Name", SpvOpString, 5); + auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6, + ext_inst_name, false); + if (validate_type != SPV_SUCCESS) return validate_type; + CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7); + CHECK_CONST_UINT_OPERAND("Line", 8); + CHECK_CONST_UINT_OPERAND("Column", 9); + auto validate_scope = + ValidateOperandLexicalScope(_, "Scope", inst, 10, ext_inst_name); + if (validate_scope != SPV_SUCCESS) return validate_scope; + CHECK_OPERAND("Linkage Name", SpvOpString, 11); + if (!DoesDebugInfoOperandMatchExpectation( + _, + [](CommonDebugInfoInstructions dbg_inst) { + return dbg_inst == CommonDebugInfoDebugInfoNone; + }, + inst, 12)) { + auto* operand = _.FindDef(inst->word(12)); + if (operand->opcode() != SpvOpVariable && + operand->opcode() != SpvOpConstant) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": " + << "expected operand Variable must be a result id of " + "OpVariable or OpConstant or DebugInfoNone"; + } + } + if (num_words == 15) { + CHECK_DEBUG_OPERAND("Static Member Declaration", + CommonDebugInfoDebugTypeMember, 14); + } + break; + } + case CommonDebugInfoDebugInlinedAt: { + CHECK_CONST_UINT_OPERAND("Line", 5); + auto validate_scope = + ValidateOperandLexicalScope(_, "Scope", inst, 6, ext_inst_name); + if (validate_scope != SPV_SUCCESS) return validate_scope; + if (num_words == 8) { + CHECK_DEBUG_OPERAND("Inlined", CommonDebugInfoDebugInlinedAt, 7); + } + break; + } + case CommonDebugInfoDebugValue: { + CHECK_DEBUG_OPERAND("Local Variable", + CommonDebugInfoDebugLocalVariable, 5); + CHECK_DEBUG_OPERAND("Expression", CommonDebugInfoDebugExpression, 7); + + for (uint32_t word_index = 8; word_index < num_words; ++word_index) { + // TODO: The following code simply checks if it is a const int + // scalar or a DebugLocalVariable or DebugGlobalVariable, but we + // have to check it using the same validation for Indexes of + // OpAccessChain. + if (!IsConstWithIntScalarType(_, inst, word_index) && + !IsDebugVariableWithIntScalarType(_, inst, word_index)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << ext_inst_name() << ": expected operand Indexes is " + << "OpConstant, DebugGlobalVariable, or " + << "type is OpConstant with an integer scalar type"; + } + } + break; + } + + // TODO: Add validation rules for remaining cases as well. + case CommonDebugInfoDebugTypePtrToMember: + case CommonDebugInfoDebugTypeTemplateTemplateParameter: + case CommonDebugInfoDebugTypeTemplateParameterPack: + case CommonDebugInfoDebugLexicalBlockDiscriminator: + case CommonDebugInfoDebugInlinedVariable: + case CommonDebugInfoDebugMacroDef: + case CommonDebugInfoDebugMacroUndef: + case CommonDebugInfoDebugImportedEntity: + break; + case CommonDebugInfoInstructionsMax: + assert(0); + break; } - - // TODO: Add validation rules for remaining cases as well. - case OpenCLDebugInfo100DebugTypePtrToMember: - case OpenCLDebugInfo100DebugTypeTemplateTemplateParameter: - case OpenCLDebugInfo100DebugTypeTemplateParameterPack: - case OpenCLDebugInfo100DebugLexicalBlockDiscriminator: - case OpenCLDebugInfo100DebugInlinedVariable: - case OpenCLDebugInfo100DebugMacroDef: - case OpenCLDebugInfo100DebugMacroUndef: - case OpenCLDebugInfo100DebugImportedEntity: - case OpenCLDebugInfo100DebugModuleINTEL: - break; - case OpenCLDebugInfo100InstructionsMax: - assert(0); - break; } } else if (ext_inst_type == SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION) { auto import_inst = _.FindDef(inst->GetOperandAs<uint32_t>(2)); |