diff options
author | dan sinclair <dj2@everburning.com> | 2018-07-10 10:57:52 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-10 10:57:52 -0400 |
commit | a3e3869540b7c2d2f01c846fc76453be55d1ac34 (patch) | |
tree | 01461814734f17347698dc329acd0d9472f2ca41 /source | |
parent | 43144e36c15c687e6edc2e5f4f166e1f9ec1d7eb (diff) |
Convert validation to use libspriv::Instruction where possible. (#1663)
For the instructions which execute after the IdPass check we can provide
the Instruction instead of the spv_parsed_instruction_t. This
Instruction class provides a bit more context (like the source line)
that is not available from spv_parsed_instruction_t.
Diffstat (limited to 'source')
-rw-r--r-- | source/val/instruction.h | 18 | ||||
-rw-r--r-- | source/val/validation_state.cpp | 23 | ||||
-rw-r--r-- | source/val/validation_state.h | 4 | ||||
-rw-r--r-- | source/validate.cpp | 34 | ||||
-rw-r--r-- | source/validate.h | 51 | ||||
-rw-r--r-- | source/validate_arithmetics.cpp | 72 | ||||
-rw-r--r-- | source/validate_atomics.cpp | 22 | ||||
-rw-r--r-- | source/validate_barriers.cpp | 36 | ||||
-rw-r--r-- | source/validate_bitwise.cpp | 54 | ||||
-rw-r--r-- | source/validate_cfg.cpp | 2 | ||||
-rw-r--r-- | source/validate_composites.cpp | 23 | ||||
-rw-r--r-- | source/validate_conversion.cpp | 9 | ||||
-rw-r--r-- | source/validate_datarules.cpp | 50 | ||||
-rw-r--r-- | source/validate_decorations.cpp | 12 | ||||
-rw-r--r-- | source/validate_derivatives.cpp | 7 | ||||
-rw-r--r-- | source/validate_ext_inst.cpp | 19 | ||||
-rw-r--r-- | source/validate_image.cpp | 103 | ||||
-rw-r--r-- | source/validate_instruction.cpp | 142 | ||||
-rw-r--r-- | source/validate_layout.cpp | 21 | ||||
-rw-r--r-- | source/validate_literals.cpp | 21 | ||||
-rw-r--r-- | source/validate_logicals.cpp | 51 | ||||
-rw-r--r-- | source/validate_non_uniform.cpp | 12 | ||||
-rw-r--r-- | source/validate_primitives.cpp | 7 | ||||
-rw-r--r-- | source/validate_type_unique.cpp | 11 |
24 files changed, 343 insertions, 461 deletions
diff --git a/source/val/instruction.h b/source/val/instruction.h index c47e6bad..72881d99 100644 --- a/source/val/instruction.h +++ b/source/val/instruction.h @@ -67,6 +67,11 @@ class Instruction { /// The words used to define the Instruction const std::vector<uint32_t>& words() const { return words_; } + /// Returns the operand at |idx|. + const spv_parsed_operand_t& operand(size_t idx) const { + return operands_[idx]; + } + /// The operands of the Instruction const std::vector<spv_parsed_operand_t>& operands() const { return operands_; @@ -75,13 +80,18 @@ class Instruction { /// Provides direct access to the stored C instruction object. const spv_parsed_instruction_t& c_inst() const { return inst_; } + /// Provides direct access to instructions spv_ext_inst_type_t object. + const spv_ext_inst_type_t& ext_inst_type() const { + return inst_.ext_inst_type; + } + // Casts the words belonging to the operand under |index| to |T| and returns. template <typename T> T GetOperandAs(size_t index) const { - const spv_parsed_operand_t& operand = operands_.at(index); - assert(operand.num_words * 4 >= sizeof(T)); - assert(operand.offset + operand.num_words <= inst_.num_words); - return *reinterpret_cast<const T*>(&words_[operand.offset]); + const spv_parsed_operand_t& o = operands_.at(index); + assert(o.num_words * 4 >= sizeof(T)); + assert(o.offset + o.num_words <= inst_.num_words); + return *reinterpret_cast<const T*>(&words_[o.offset]); } int InstructionPosition() const { return instruction_position_; } diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp index afcc7863..6907e599 100644 --- a/source/val/validation_state.cpp +++ b/source/val/validation_state.cpp @@ -487,20 +487,20 @@ uint32_t ValidationState_t::getIdBound() const { return id_bound_; } void ValidationState_t::setIdBound(const uint32_t bound) { id_bound_ = bound; } -bool ValidationState_t::RegisterUniqueTypeDeclaration( - const spv_parsed_instruction_t& inst) { +bool ValidationState_t::RegisterUniqueTypeDeclaration(const Instruction* inst) { std::vector<uint32_t> key; - key.push_back(static_cast<uint32_t>(inst.opcode)); - for (int index = 0; index < inst.num_operands; ++index) { - const spv_parsed_operand_t& operand = inst.operands[index]; + key.push_back(static_cast<uint32_t>(inst->opcode())); + for (size_t index = 0; index < inst->operands().size(); ++index) { + const spv_parsed_operand_t& operand = inst->operand(index); if (operand.type == SPV_OPERAND_TYPE_RESULT_ID) continue; const int words_begin = operand.offset; const int words_end = words_begin + operand.num_words; - assert(words_end <= static_cast<int>(inst.num_words)); + assert(words_end <= static_cast<int>(inst->words().size())); - key.insert(key.end(), inst.words + words_begin, inst.words + words_end); + key.insert(key.end(), inst->words().begin() + words_begin, + inst->words().begin() + words_end); } return unique_type_declarations_.insert(std::move(key)).second; @@ -784,12 +784,9 @@ bool ValidationState_t::GetPointerTypeInfo(uint32_t id, uint32_t* data_type, return true; } -uint32_t ValidationState_t::GetOperandTypeId( - const spv_parsed_instruction_t* inst, size_t operand_index) const { - assert(operand_index < inst->num_operands); - const spv_parsed_operand_t& operand = inst->operands[operand_index]; - assert(operand.num_words == 1); - return GetTypeId(inst->words[operand.offset]); +uint32_t ValidationState_t::GetOperandTypeId(const Instruction* inst, + size_t operand_index) const { + return GetTypeId(inst->GetOperandAs<uint32_t>(operand_index)); } bool ValidationState_t::GetConstantValUint64(uint32_t id, uint64_t* val) const { diff --git a/source/val/validation_state.h b/source/val/validation_state.h index 463cb232..d1b52815 100644 --- a/source/val/validation_state.h +++ b/source/val/validation_state.h @@ -400,7 +400,7 @@ class ValidationState_t { /// Adds the instruction data to unique_type_declarations_. /// Returns false if an identical type declaration already exists. - bool RegisterUniqueTypeDeclaration(const spv_parsed_instruction_t& inst); + bool RegisterUniqueTypeDeclaration(const Instruction* inst); // Returns type_id of the scalar component of |id|. // |id| can be either @@ -466,7 +466,7 @@ class ValidationState_t { // Returns type_id for given id operand if it has a type or zero otherwise. // |operand_index| is expected to be pointing towards an operand which is an // id. - uint32_t GetOperandTypeId(const spv_parsed_instruction_t* inst, + uint32_t GetOperandTypeId(const Instruction* inst, size_t operand_index) const; // Provides information on pointer type. Returns false iff not pointer type. diff --git a/source/validate.cpp b/source/validate.cpp index 76a81dfa..64321e67 100644 --- a/source/validate.cpp +++ b/source/validate.cpp @@ -174,24 +174,24 @@ spv_result_t ProcessInstruction(void* user_data, const Instruction* instruction = &(_.ordered_instructions().back()); - if (auto error = DataRulesPass(_, inst)) return error; - if (auto error = ModuleLayoutPass(_, inst)) return error; + if (auto error = DataRulesPass(_, instruction)) return error; + if (auto error = ModuleLayoutPass(_, instruction)) return error; if (auto error = CfgPass(_, instruction)) return error; - if (auto error = InstructionPass(_, inst)) return error; - if (auto error = TypeUniquePass(_, inst)) return error; - if (auto error = ArithmeticsPass(_, inst)) return error; - if (auto error = CompositesPass(_, inst)) return error; - if (auto error = ConversionPass(_, inst)) return error; - if (auto error = DerivativesPass(_, inst)) return error; - if (auto error = LogicalsPass(_, inst)) return error; - if (auto error = BitwisePass(_, inst)) return error; - if (auto error = ExtInstPass(_, inst)) return error; - if (auto error = ImagePass(_, inst)) return error; - if (auto error = AtomicsPass(_, inst)) return error; - if (auto error = BarriersPass(_, inst)) return error; - if (auto error = PrimitivesPass(_, inst)) return error; - if (auto error = LiteralsPass(_, inst)) return error; - if (auto error = NonUniformPass(_, inst)) return error; + if (auto error = InstructionPass(_, instruction)) return error; + if (auto error = TypeUniquePass(_, instruction)) return error; + if (auto error = ArithmeticsPass(_, instruction)) return error; + if (auto error = CompositesPass(_, instruction)) return error; + if (auto error = ConversionPass(_, instruction)) return error; + if (auto error = DerivativesPass(_, instruction)) return error; + if (auto error = LogicalsPass(_, instruction)) return error; + if (auto error = BitwisePass(_, instruction)) return error; + if (auto error = ExtInstPass(_, instruction)) return error; + if (auto error = ImagePass(_, instruction)) return error; + if (auto error = AtomicsPass(_, instruction)) return error; + if (auto error = BarriersPass(_, instruction)) return error; + if (auto error = PrimitivesPass(_, instruction)) return error; + if (auto error = LiteralsPass(_, instruction)) return error; + if (auto error = NonUniformPass(_, instruction)) return error; return SPV_SUCCESS; } diff --git a/source/validate.h b/source/validate.h index 5d84629a..845ffa4f 100644 --- a/source/validate.h +++ b/source/validate.h @@ -106,8 +106,7 @@ void printDominatorList(BasicBlock& block); /// Performs logical layout validation as described in section 2.4 of the SPIR-V /// spec. -spv_result_t ModuleLayoutPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t ModuleLayoutPass(ValidationState_t& _, const Instruction* inst); /// Performs Control Flow Graph validation of a module spv_result_t CfgPass(ValidationState_t& _, const Instruction* inst); @@ -118,12 +117,10 @@ 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); +spv_result_t DataRulesPass(ValidationState_t& _, const Instruction* inst); /// Performs instruction validation. -spv_result_t InstructionPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t InstructionPass(ValidationState_t& _, const Instruction* inst); /// Performs decoration validation. spv_result_t ValidateDecorations(ValidationState_t& _); @@ -134,56 +131,43 @@ spv_result_t ValidateBuiltIns(const ValidationState_t& _); /// Validates that type declarations are unique, unless multiple declarations /// of the same data type are allowed by the specification. /// (see section 2.8 Types and Variables) -spv_result_t TypeUniquePass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t TypeUniquePass(ValidationState_t& _, const Instruction* inst); /// Validates correctness of arithmetic instructions. -spv_result_t ArithmeticsPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t ArithmeticsPass(ValidationState_t& _, const Instruction* inst); /// Validates correctness of composite instructions. -spv_result_t CompositesPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t CompositesPass(ValidationState_t& _, const Instruction* inst); /// Validates correctness of conversion instructions. -spv_result_t ConversionPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst); /// Validates correctness of derivative instructions. -spv_result_t DerivativesPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t DerivativesPass(ValidationState_t& _, const Instruction* inst); /// Validates correctness of logical instructions. -spv_result_t LogicalsPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t LogicalsPass(ValidationState_t& _, const Instruction* inst); /// Validates correctness of bitwise instructions. -spv_result_t BitwisePass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t BitwisePass(ValidationState_t& _, const Instruction* inst); /// Validates correctness of image instructions. -spv_result_t ImagePass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t ImagePass(ValidationState_t& _, const Instruction* inst); /// Validates correctness of atomic instructions. -spv_result_t AtomicsPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst); /// Validates correctness of barrier instructions. -spv_result_t BarriersPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t BarriersPass(ValidationState_t& _, const Instruction* inst); /// Validates correctness of literal numbers. -spv_result_t LiteralsPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t LiteralsPass(ValidationState_t& _, const Instruction* inst); /// Validates correctness of ExtInst instructions. -spv_result_t ExtInstPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t ExtInstPass(ValidationState_t& _, const Instruction* inst); /// Validates correctness of non-uniform group instructions. -spv_result_t NonUniformPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t NonUniformPass(ValidationState_t& _, const Instruction* inst); // Validates that capability declarations use operands allowed in the current // context. @@ -191,8 +175,7 @@ spv_result_t CapabilityPass(ValidationState_t& _, const spv_parsed_instruction_t* inst); /// Validates correctness of primitive instructions. -spv_result_t PrimitivesPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst); +spv_result_t PrimitivesPass(ValidationState_t& _, const Instruction* inst); /// @brief Validate the ID usage of the instruction stream /// diff --git a/source/validate_arithmetics.cpp b/source/validate_arithmetics.cpp index 3460cde7..d40c2344 100644 --- a/source/validate_arithmetics.cpp +++ b/source/validate_arithmetics.cpp @@ -23,33 +23,11 @@ namespace spvtools { namespace val { -namespace { - -// Returns operand word for given instruction and operand index. -// The operand is expected to only have one word. -inline uint32_t GetOperandWord(const spv_parsed_instruction_t* inst, - size_t operand_index) { - assert(operand_index < inst->num_operands); - const spv_parsed_operand_t& operand = inst->operands[operand_index]; - assert(operand.num_words == 1); - return inst->words[operand.offset]; -} - -// Returns the type id of instruction operand at |operand_index|. -// The operand is expected to be an id. -inline uint32_t GetOperandTypeId(ValidationState_t& _, - const spv_parsed_instruction_t* inst, - size_t operand_index) { - return _.GetTypeId(GetOperandWord(inst, operand_index)); -} - -} // namespace // Validates correctness of arithmetic instructions. -spv_result_t ArithmeticsPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); - const uint32_t result_type = inst->type_id; +spv_result_t ArithmeticsPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); + const uint32_t result_type = inst->type_id(); switch (opcode) { case SpvOpFAdd: @@ -65,9 +43,9 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, << "Expected floating scalar or vector type as Result Type: " << spvOpcodeString(opcode); - for (size_t operand_index = 2; operand_index < inst->num_operands; + for (size_t operand_index = 2; operand_index < inst->operands().size(); ++operand_index) { - if (GetOperandTypeId(_, inst, operand_index) != result_type) + if (_.GetOperandTypeId(inst, operand_index) != result_type) return _.diag(SPV_ERROR_INVALID_DATA) << "Expected arithmetic operands to be of Result Type: " << spvOpcodeString(opcode) << " operand index " @@ -84,9 +62,9 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, << "Expected unsigned int scalar or vector type as Result Type: " << spvOpcodeString(opcode); - for (size_t operand_index = 2; operand_index < inst->num_operands; + for (size_t operand_index = 2; operand_index < inst->operands().size(); ++operand_index) { - if (GetOperandTypeId(_, inst, operand_index) != result_type) + if (_.GetOperandTypeId(inst, operand_index) != result_type) return _.diag(SPV_ERROR_INVALID_DATA) << "Expected arithmetic operands to be of Result Type: " << spvOpcodeString(opcode) << " operand index " @@ -110,9 +88,9 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, const uint32_t dimension = _.GetDimension(result_type); const uint32_t bit_width = _.GetBitWidth(result_type); - for (size_t operand_index = 2; operand_index < inst->num_operands; + for (size_t operand_index = 2; operand_index < inst->operands().size(); ++operand_index) { - const uint32_t type_id = GetOperandTypeId(_, inst, operand_index); + const uint32_t type_id = _.GetOperandTypeId(inst, operand_index); if (!type_id || (!_.IsIntScalarType(type_id) && !_.IsIntVectorType(type_id))) return _.diag(SPV_ERROR_INVALID_DATA) @@ -143,9 +121,9 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, uint32_t first_vector_num_components = 0; - for (size_t operand_index = 2; operand_index < inst->num_operands; + for (size_t operand_index = 2; operand_index < inst->operands().size(); ++operand_index) { - const uint32_t type_id = GetOperandTypeId(_, inst, operand_index); + const uint32_t type_id = _.GetOperandTypeId(inst, operand_index); if (!type_id || !_.IsFloatVectorType(type_id)) return _.diag(SPV_ERROR_INVALID_DATA) @@ -178,7 +156,7 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, << "Expected float vector type as Result Type: " << spvOpcodeString(opcode); - const uint32_t vector_type_id = GetOperandTypeId(_, inst, 2); + const uint32_t vector_type_id = _.GetOperandTypeId(inst, 2); if (result_type != vector_type_id) return _.diag(SPV_ERROR_INVALID_DATA) << "Expected vector operand type to be equal to Result Type: " @@ -186,7 +164,7 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, const uint32_t component_type = _.GetComponentType(vector_type_id); - const uint32_t scalar_type_id = GetOperandTypeId(_, inst, 3); + const uint32_t scalar_type_id = _.GetOperandTypeId(inst, 3); if (component_type != scalar_type_id) return _.diag(SPV_ERROR_INVALID_DATA) << "Expected scalar operand type to be equal to the component " @@ -201,7 +179,7 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, << "Expected float matrix type as Result Type: " << spvOpcodeString(opcode); - const uint32_t matrix_type_id = GetOperandTypeId(_, inst, 2); + const uint32_t matrix_type_id = _.GetOperandTypeId(inst, 2); if (result_type != matrix_type_id) return _.diag(SPV_ERROR_INVALID_DATA) << "Expected matrix operand type to be equal to Result Type: " @@ -209,7 +187,7 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, const uint32_t component_type = _.GetComponentType(matrix_type_id); - const uint32_t scalar_type_id = GetOperandTypeId(_, inst, 3); + const uint32_t scalar_type_id = _.GetOperandTypeId(inst, 3); if (component_type != scalar_type_id) return _.diag(SPV_ERROR_INVALID_DATA) << "Expected scalar operand type to be equal to the component " @@ -219,8 +197,8 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, } case SpvOpVectorTimesMatrix: { - const uint32_t vector_type_id = GetOperandTypeId(_, inst, 2); - const uint32_t matrix_type_id = GetOperandTypeId(_, inst, 3); + const uint32_t vector_type_id = _.GetOperandTypeId(inst, 2); + const uint32_t matrix_type_id = _.GetOperandTypeId(inst, 3); if (!_.IsFloatVectorType(result_type)) return _.diag(SPV_ERROR_INVALID_DATA) @@ -269,8 +247,8 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, } case SpvOpMatrixTimesVector: { - const uint32_t matrix_type_id = GetOperandTypeId(_, inst, 2); - const uint32_t vector_type_id = GetOperandTypeId(_, inst, 3); + const uint32_t matrix_type_id = _.GetOperandTypeId(inst, 2); + const uint32_t vector_type_id = _.GetOperandTypeId(inst, 3); if (!_.IsFloatVectorType(result_type)) return _.diag(SPV_ERROR_INVALID_DATA) @@ -313,8 +291,8 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, } case SpvOpMatrixTimesMatrix: { - const uint32_t left_type_id = GetOperandTypeId(_, inst, 2); - const uint32_t right_type_id = GetOperandTypeId(_, inst, 3); + const uint32_t left_type_id = _.GetOperandTypeId(inst, 2); + const uint32_t right_type_id = _.GetOperandTypeId(inst, 3); uint32_t res_num_rows = 0; uint32_t res_num_cols = 0; @@ -379,8 +357,8 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, } case SpvOpOuterProduct: { - const uint32_t left_type_id = GetOperandTypeId(_, inst, 2); - const uint32_t right_type_id = GetOperandTypeId(_, inst, 3); + const uint32_t left_type_id = _.GetOperandTypeId(inst, 2); + const uint32_t right_type_id = _.GetOperandTypeId(inst, 3); uint32_t res_num_rows = 0; uint32_t res_num_cols = 0; @@ -451,8 +429,8 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, << "Expected Result Type struct member types to be identical: " << spvOpcodeString(opcode); - const uint32_t left_type_id = GetOperandTypeId(_, inst, 2); - const uint32_t right_type_id = GetOperandTypeId(_, inst, 3); + const uint32_t left_type_id = _.GetOperandTypeId(inst, 2); + const uint32_t right_type_id = _.GetOperandTypeId(inst, 3); if (left_type_id != result_types[0] || right_type_id != result_types[0]) return _.diag(SPV_ERROR_INVALID_DATA) diff --git a/source/validate_atomics.cpp b/source/validate_atomics.cpp index b4a196cb..f4eaba43 100644 --- a/source/validate_atomics.cpp +++ b/source/validate_atomics.cpp @@ -27,10 +27,9 @@ namespace spvtools { namespace val { // Validates Memory Scope operand. -spv_result_t ValidateMemoryScope(ValidationState_t& _, - const spv_parsed_instruction_t* inst, +spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst, uint32_t id) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); + const SpvOp opcode = inst->opcode(); bool is_int32 = false, is_const_int32 = false; uint32_t value = 0; std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(id); @@ -64,13 +63,12 @@ spv_result_t ValidateMemoryScope(ValidationState_t& _, // Validates a Memory Semantics operand. spv_result_t ValidateMemorySemantics(ValidationState_t& _, - const spv_parsed_instruction_t* inst, + const Instruction* inst, uint32_t operand_index) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); + const SpvOp opcode = inst->opcode(); bool is_int32 = false, is_const_int32 = false; uint32_t flags = 0; - const uint32_t memory_semantics_id = - inst->words[inst->operands[operand_index].offset]; + auto memory_semantics_id = inst->GetOperandAs<const uint32_t>(operand_index); std::tie(is_int32, is_const_int32, flags) = _.EvalInt32IfConst(memory_semantics_id); @@ -154,10 +152,9 @@ spv_result_t ValidateMemorySemantics(ValidationState_t& _, } // Validates correctness of atomic instructions. -spv_result_t AtomicsPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); - const uint32_t result_type = inst->type_id; +spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); + const uint32_t result_type = inst->type_id(); switch (opcode) { case SpvOpAtomicLoad: @@ -262,8 +259,7 @@ spv_result_t AtomicsPass(ValidationState_t& _, } } - const uint32_t memory_scope = - inst->words[inst->operands[operand_index++].offset]; + auto memory_scope = inst->GetOperandAs<const uint32_t>(operand_index++); if (auto error = ValidateMemoryScope(_, inst, memory_scope)) { return error; } diff --git a/source/validate_barriers.cpp b/source/validate_barriers.cpp index 8985ada3..0a494075 100644 --- a/source/validate_barriers.cpp +++ b/source/validate_barriers.cpp @@ -30,9 +30,8 @@ namespace { // Validates Execution Scope operand. spv_result_t ValidateExecutionScope(ValidationState_t& _, - const spv_parsed_instruction_t* inst, - uint32_t id) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); + const Instruction* inst, uint32_t id) { + const SpvOp opcode = inst->opcode(); bool is_int32 = false, is_const_int32 = false; uint32_t value = 0; std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(id); @@ -82,10 +81,9 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _, } // Validates Memory Scope operand. -spv_result_t ValidateMemoryScope(ValidationState_t& _, - const spv_parsed_instruction_t* inst, +spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst, uint32_t id) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); + const SpvOp opcode = inst->opcode(); bool is_int32 = false, is_const_int32 = false; uint32_t value = 0; std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(id); @@ -124,9 +122,8 @@ spv_result_t ValidateMemoryScope(ValidationState_t& _, // Validates Memory Semantics operand. spv_result_t ValidateMemorySemantics(ValidationState_t& _, - const spv_parsed_instruction_t* inst, - uint32_t id) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); + const Instruction* inst, uint32_t id) { + const SpvOp opcode = inst->opcode(); bool is_int32 = false, is_const_int32 = false; uint32_t value = 0; std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(id); @@ -193,10 +190,9 @@ spv_result_t ValidateMemorySemantics(ValidationState_t& _, } // namespace // Validates correctness of barrier instructions. -spv_result_t BarriersPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); - const uint32_t result_type = inst->type_id; +spv_result_t BarriersPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); + const uint32_t result_type = inst->type_id(); switch (opcode) { case SpvOpControlBarrier: { @@ -219,9 +215,9 @@ spv_result_t BarriersPass(ValidationState_t& _, }); } - const uint32_t execution_scope = inst->words[1]; - const uint32_t memory_scope = inst->words[2]; - const uint32_t memory_semantics = inst->words[3]; + const uint32_t execution_scope = inst->word(1); + const uint32_t memory_scope = inst->word(2); + const uint32_t memory_semantics = inst->word(3); if (auto error = ValidateExecutionScope(_, inst, execution_scope)) { return error; @@ -238,8 +234,8 @@ spv_result_t BarriersPass(ValidationState_t& _, } case SpvOpMemoryBarrier: { - const uint32_t memory_scope = inst->words[1]; - const uint32_t memory_semantics = inst->words[2]; + const uint32_t memory_scope = inst->word(1); + const uint32_t memory_semantics = inst->word(2); if (auto error = ValidateMemoryScope(_, inst, memory_scope)) { return error; @@ -276,8 +272,8 @@ spv_result_t BarriersPass(ValidationState_t& _, << ": expected Named Barrier to be of type OpTypeNamedBarrier"; } - const uint32_t memory_scope = inst->words[2]; - const uint32_t memory_semantics = inst->words[3]; + const uint32_t memory_scope = inst->word(2); + const uint32_t memory_semantics = inst->word(3); if (auto error = ValidateMemoryScope(_, inst, memory_scope)) { return error; diff --git a/source/validate_bitwise.cpp b/source/validate_bitwise.cpp index cd00cd69..953fc462 100644 --- a/source/validate_bitwise.cpp +++ b/source/validate_bitwise.cpp @@ -23,33 +23,11 @@ namespace spvtools { namespace val { -namespace { - -// Returns operand word for given instruction and operand index. -// The operand is expected to only have one word. -inline uint32_t GetOperandWord(const spv_parsed_instruction_t* inst, - size_t operand_index) { - assert(operand_index < inst->num_operands); - const spv_parsed_operand_t& operand = inst->operands[operand_index]; - assert(operand.num_words == 1); - return inst->words[operand.offset]; -} - -// Returns the type id of instruction operand at |operand_index|. -// The operand is expected to be an id. -inline uint32_t GetOperandTypeId(ValidationState_t& _, - const spv_parsed_instruction_t* inst, - size_t operand_index) { - return _.GetTypeId(GetOperandWord(inst, operand_index)); -} - -} // namespace // Validates correctness of bitwise instructions. -spv_result_t BitwisePass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); - const uint32_t result_type = inst->type_id; +spv_result_t BitwisePass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); + const uint32_t result_type = inst->type_id(); switch (opcode) { case SpvOpShiftRightLogical: @@ -61,8 +39,8 @@ spv_result_t BitwisePass(ValidationState_t& _, << spvOpcodeString(opcode); const uint32_t result_dimension = _.GetDimension(result_type); - const uint32_t base_type = GetOperandTypeId(_, inst, 2); - const uint32_t shift_type = GetOperandTypeId(_, inst, 3); + const uint32_t base_type = _.GetOperandTypeId(inst, 2); + const uint32_t shift_type = _.GetOperandTypeId(inst, 3); if (!base_type || (!_.IsIntScalarType(base_type) && !_.IsIntVectorType(base_type))) @@ -105,9 +83,9 @@ spv_result_t BitwisePass(ValidationState_t& _, const uint32_t result_dimension = _.GetDimension(result_type); const uint32_t result_bit_width = _.GetBitWidth(result_type); - for (size_t operand_index = 2; operand_index < inst->num_operands; + for (size_t operand_index = 2; operand_index < inst->operands().size(); ++operand_index) { - const uint32_t type_id = GetOperandTypeId(_, inst, operand_index); + const uint32_t type_id = _.GetOperandTypeId(inst, operand_index); if (!type_id || (!_.IsIntScalarType(type_id) && !_.IsIntVectorType(type_id))) return _.diag(SPV_ERROR_INVALID_DATA) @@ -136,10 +114,10 @@ spv_result_t BitwisePass(ValidationState_t& _, << "Expected int scalar or vector type as Result Type: " << spvOpcodeString(opcode); - const uint32_t base_type = GetOperandTypeId(_, inst, 2); - const uint32_t insert_type = GetOperandTypeId(_, inst, 3); - const uint32_t offset_type = GetOperandTypeId(_, inst, 4); - const uint32_t count_type = GetOperandTypeId(_, inst, 5); + const uint32_t base_type = _.GetOperandTypeId(inst, 2); + const uint32_t insert_type = _.GetOperandTypeId(inst, 3); + const uint32_t offset_type = _.GetOperandTypeId(inst, 4); + const uint32_t count_type = _.GetOperandTypeId(inst, 5); if (base_type != result_type) return _.diag(SPV_ERROR_INVALID_DATA) @@ -170,9 +148,9 @@ spv_result_t BitwisePass(ValidationState_t& _, << "Expected int scalar or vector type as Result Type: " << spvOpcodeString(opcode); - const uint32_t base_type = GetOperandTypeId(_, inst, 2); - const uint32_t offset_type = GetOperandTypeId(_, inst, 3); - const uint32_t count_type = GetOperandTypeId(_, inst, 4); + const uint32_t base_type = _.GetOperandTypeId(inst, 2); + const uint32_t offset_type = _.GetOperandTypeId(inst, 3); + const uint32_t count_type = _.GetOperandTypeId(inst, 4); if (base_type != result_type) return _.diag(SPV_ERROR_INVALID_DATA) @@ -197,7 +175,7 @@ spv_result_t BitwisePass(ValidationState_t& _, << "Expected int scalar or vector type as Result Type: " << spvOpcodeString(opcode); - const uint32_t base_type = GetOperandTypeId(_, inst, 2); + const uint32_t base_type = _.GetOperandTypeId(inst, 2); if (base_type != result_type) return _.diag(SPV_ERROR_INVALID_DATA) @@ -212,7 +190,7 @@ spv_result_t BitwisePass(ValidationState_t& _, << "Expected int scalar or vector type as Result Type: " << spvOpcodeString(opcode); - const uint32_t base_type = GetOperandTypeId(_, inst, 2); + const uint32_t base_type = _.GetOperandTypeId(inst, 2); if (!base_type || (!_.IsIntScalarType(base_type) && !_.IsIntVectorType(base_type))) return _.diag(SPV_ERROR_INVALID_DATA) diff --git a/source/validate_cfg.cpp b/source/validate_cfg.cpp index e09063ad..ab3cd953 100644 --- a/source/validate_cfg.cpp +++ b/source/validate_cfg.cpp @@ -549,7 +549,7 @@ spv_result_t PerformCfgChecks(ValidationState_t& _) { } spv_result_t CfgPass(ValidationState_t& _, const Instruction* inst) { - SpvOp opcode = static_cast<SpvOp>(inst->opcode()); + SpvOp opcode = inst->opcode(); switch (opcode) { case SpvOpLabel: if (auto error = _.current_function().RegisterBlock(inst->id())) diff --git a/source/validate_composites.cpp b/source/validate_composites.cpp index f4ba74e6..ce0a2dfe 100644 --- a/source/validate_composites.cpp +++ b/source/validate_composites.cpp @@ -32,12 +32,12 @@ namespace { // fails (encountered non-composite, out of bounds, nesting too deep). // Returns the type of Composite operand if the instruction has no indices. spv_result_t GetExtractInsertValueType(ValidationState_t& _, - const spv_parsed_instruction_t& inst, + const Instruction* inst, uint32_t* member_type) { - const SpvOp opcode = static_cast<SpvOp>(inst.opcode); + const SpvOp opcode = inst->opcode(); assert(opcode == SpvOpCompositeExtract || opcode == SpvOpCompositeInsert); uint32_t word_index = opcode == SpvOpCompositeExtract ? 4 : 5; - const uint32_t num_words = static_cast<uint32_t>(inst.num_words); + const uint32_t num_words = static_cast<uint32_t>(inst->words().size()); const uint32_t composite_id_index = word_index - 1; const uint32_t num_indices = num_words - word_index; @@ -49,7 +49,7 @@ spv_result_t GetExtractInsertValueType(ValidationState_t& _, << ". Found " << num_indices << " indexes."; } - *member_type = _.GetTypeId(inst.words[composite_id_index]); + *member_type = _.GetTypeId(inst->word(composite_id_index)); if (*member_type == 0) { return _.diag(SPV_ERROR_INVALID_DATA) << spvOpcodeString(opcode) @@ -57,7 +57,7 @@ spv_result_t GetExtractInsertValueType(ValidationState_t& _, } for (; word_index < num_words; ++word_index) { - const uint32_t component_index = inst.words[word_index]; + const uint32_t component_index = inst->word(word_index); const Instruction* const type_inst = _.FindDef(*member_type); assert(type_inst); switch (type_inst->opcode()) { @@ -136,11 +136,10 @@ spv_result_t GetExtractInsertValueType(ValidationState_t& _, } // anonymous namespace // Validates correctness of composite instructions. -spv_result_t CompositesPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); - const uint32_t result_type = inst->type_id; - const uint32_t num_operands = static_cast<uint32_t>(inst->num_operands); +spv_result_t CompositesPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); + const uint32_t result_type = inst->type_id(); + const uint32_t num_operands = static_cast<uint32_t>(inst->operands().size()); switch (opcode) { case SpvOpVectorExtractDynamic: { @@ -367,7 +366,7 @@ spv_result_t CompositesPass(ValidationState_t& _, case SpvOpCompositeExtract: { uint32_t member_type = 0; if (spv_result_t error = - GetExtractInsertValueType(_, *inst, &member_type)) { + GetExtractInsertValueType(_, inst, &member_type)) { return error; } @@ -396,7 +395,7 @@ spv_result_t CompositesPass(ValidationState_t& _, uint32_t member_type = 0; if (spv_result_t error = - GetExtractInsertValueType(_, *inst, &member_type)) { + GetExtractInsertValueType(_, inst, &member_type)) { return error; } diff --git a/source/validate_conversion.cpp b/source/validate_conversion.cpp index a4e75edd..ff2b7746 100644 --- a/source/validate_conversion.cpp +++ b/source/validate_conversion.cpp @@ -25,10 +25,9 @@ namespace spvtools { namespace val { // Validates correctness of conversion instructions. -spv_result_t ConversionPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); - const uint32_t result_type = inst->type_id; +spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); + const uint32_t result_type = inst->type_id(); switch (opcode) { case SpvOpConvertFToU: { @@ -321,7 +320,7 @@ spv_result_t ConversionPass(ValidationState_t& _, << "Expected Result Type to be a pointer: " << spvOpcodeString(opcode); - const uint32_t target_storage_class = inst->words[4]; + const uint32_t target_storage_class = inst->word(4); if (result_storage_class != target_storage_class) return _.diag(SPV_ERROR_INVALID_DATA) << "Expected Result Type to be of target storage class: " diff --git a/source/validate_datarules.cpp b/source/validate_datarules.cpp index 59dba8b9..7c783180 100644 --- a/source/validate_datarules.cpp +++ b/source/validate_datarules.cpp @@ -34,9 +34,9 @@ namespace { // 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) { + const Instruction* inst) { // Operand 2 specifies the number of components in the vector. - const uint32_t num_components = inst->words[inst->operands[2].offset]; + auto num_components = inst->GetOperandAs<const uint32_t>(2); if (num_components == 2 || num_components == 3 || num_components == 4) { return SPV_SUCCESS; } @@ -46,12 +46,12 @@ spv_result_t ValidateVecNumComponents(ValidationState_t& _, } return _.diag(SPV_ERROR_INVALID_DATA) << "Having " << num_components << " components for " - << spvOpcodeString(static_cast<SpvOp>(inst->opcode)) + << spvOpcodeString(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)); + << spvOpcodeString(inst->opcode()); } // Validates that the number of bits specifed for a float type is valid. @@ -59,10 +59,9 @@ spv_result_t ValidateVecNumComponents(ValidationState_t& _, // 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) { +spv_result_t ValidateFloatSize(ValidationState_t& _, const Instruction* inst) { // Operand 1 is the number of bits for this float - const uint32_t num_bits = inst->words[inst->operands[1].offset]; + auto num_bits = inst->GetOperandAs<const uint32_t>(1); if (num_bits == 32) { return SPV_SUCCESS; } @@ -91,10 +90,9 @@ spv_result_t ValidateFloatSize(ValidationState_t& _, // 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) { +spv_result_t ValidateIntSize(ValidationState_t& _, const Instruction* inst) { // Operand 1 is the number of bits for this integer. - const uint32_t num_bits = inst->words[inst->operands[1].offset]; + auto num_bits = inst->GetOperandAs<const uint32_t>(1); if (num_bits == 32) { return SPV_SUCCESS; } @@ -127,10 +125,10 @@ spv_result_t ValidateIntSize(ValidationState_t& _, // Validates that the matrix is parameterized with floating-point types. spv_result_t ValidateMatrixColumnType(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { + const Instruction* 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 type_id = inst->GetOperandAs<const uint32_t>(1); auto col_type_instr = _.FindDef(type_id); if (col_type_instr->opcode() != SpvOpTypeVector) { return _.diag(SPV_ERROR_INVALID_ID) @@ -152,9 +150,9 @@ spv_result_t ValidateMatrixColumnType(ValidationState_t& _, // Validates that the matrix has 2,3, or 4 columns. spv_result_t ValidateMatrixNumCols(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { + const Instruction* inst) { // Operand 2 is the number of columns in the matrix. - const uint32_t num_cols = inst->words[inst->operands[2].offset]; + auto num_cols = inst->GetOperandAs<const uint32_t>(2); 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, " @@ -165,9 +163,9 @@ spv_result_t ValidateMatrixNumCols(ValidationState_t& _, // Validates that OpSpecConstant specializes to either int or float type. spv_result_t ValidateSpecConstNumerical(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { + const Instruction* 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_id = inst->GetOperandAs<const uint32_t>(0); auto type_instruction = _.FindDef(type_id); auto type_opcode = type_instruction->opcode(); if (type_opcode != SpvOpTypeInt && type_opcode != SpvOpTypeFloat) { @@ -180,9 +178,9 @@ spv_result_t ValidateSpecConstNumerical(ValidationState_t& _, // Validates that OpSpecConstantTrue and OpSpecConstantFalse specialize to bool. spv_result_t ValidateSpecConstBoolean(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { + const Instruction* inst) { // Find out the type that we're specializing to. - auto type_instruction = _.FindDef(inst->type_id); + 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."; @@ -192,21 +190,20 @@ spv_result_t ValidateSpecConstBoolean(ValidationState_t& _, // Records the <id> of the forward pointer to be used for validation. spv_result_t ValidateForwardPointer(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { + const Instruction* 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])); + return (_.RegisterForwardPointer(inst->GetOperandAs<uint32_t>(0))); } // 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) { +spv_result_t ValidateStruct(ValidationState_t& _, const Instruction* 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]; + for (unsigned i = 1; i < inst->operands().size(); i++) { + auto type_id = inst->GetOperandAs<const uint32_t>(i); auto type_instruction = _.FindDef(type_id); if (type_instruction == nullptr && !_.IsForwardPointer(type_id)) { return _.diag(SPV_ERROR_INVALID_ID) @@ -221,9 +218,8 @@ spv_result_t ValidateStruct(ValidationState_t& _, // 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) { +spv_result_t DataRulesPass(ValidationState_t& _, const Instruction* inst) { + switch (inst->opcode()) { case SpvOpTypeVector: { if (auto error = ValidateVecNumComponents(_, inst)) return error; break; diff --git a/source/validate_decorations.cpp b/source/validate_decorations.cpp index 9b320a01..28a68659 100644 --- a/source/validate_decorations.cpp +++ b/source/validate_decorations.cpp @@ -408,7 +408,7 @@ spv_result_t checkLayout(uint32_t struct_id, const char* storage_class_str, } // Check arrays. if (SpvOpTypeArray == opcode) { - const auto typeId = inst->words()[2]; + const auto typeId = inst->word(2); const auto arrayInst = vstate.FindDef(typeId); if (SpvOpTypeStruct == arrayInst->opcode() && SPV_SUCCESS != (recursive_status = checkLayout( @@ -549,8 +549,7 @@ spv_result_t CheckDecorationsOfEntryPoints(ValidationState_t& vstate) { return vstate.diag(SPV_ERROR_INVALID_ID) << "Interfaces passed to OpEntryPoint must be of type " "OpTypeVariable. Found Op" - << spvOpcodeString(static_cast<SpvOp>(var_instr->opcode())) - << "."; + << spvOpcodeString(var_instr->opcode()) << "."; } const uint32_t ptr_id = var_instr->word(1); Instruction* ptr_instr = vstate.FindDef(ptr_id); @@ -622,19 +621,18 @@ spv_result_t CheckDescriptorSetArrayOfArrays(ValidationState_t& vstate) { } if (!has_descriptor_set) continue; - const auto& words = inst->words(); - const auto* ptrInst = vstate.FindDef(words[1]); + const auto* ptrInst = vstate.FindDef(inst->word(1)); assert(SpvOpTypePointer == ptrInst->opcode()); // Check for a first level array - const auto typePtr = vstate.FindDef(ptrInst->words()[3]); + const auto typePtr = vstate.FindDef(ptrInst->word(3)); if (SpvOpTypeRuntimeArray != typePtr->opcode() && SpvOpTypeArray != typePtr->opcode()) { continue; } // Check for a second level array - const auto secondaryTypePtr = vstate.FindDef(typePtr->words()[2]); + const auto secondaryTypePtr = vstate.FindDef(typePtr->word(2)); if (SpvOpTypeRuntimeArray == secondaryTypePtr->opcode() || SpvOpTypeArray == secondaryTypePtr->opcode()) { return vstate.diag(SPV_ERROR_INVALID_ID) diff --git a/source/validate_derivatives.cpp b/source/validate_derivatives.cpp index 5a794f30..df732fd6 100644 --- a/source/validate_derivatives.cpp +++ b/source/validate_derivatives.cpp @@ -25,10 +25,9 @@ namespace spvtools { namespace val { // Validates correctness of derivative instructions. -spv_result_t DerivativesPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); - const uint32_t result_type = inst->type_id; +spv_result_t DerivativesPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); + const uint32_t result_type = inst->type_id(); switch (opcode) { case SpvOpDPdx: diff --git a/source/validate_ext_inst.cpp b/source/validate_ext_inst.cpp index 85e9dcf6..6fb94518 100644 --- a/source/validate_ext_inst.cpp +++ b/source/validate_ext_inst.cpp @@ -41,18 +41,17 @@ uint32_t GetSizeTBitWidth(const ValidationState_t& _) { } // anonymous namespace // Validates correctness of ExtInst instructions. -spv_result_t ExtInstPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); - const uint32_t result_type = inst->type_id; - const uint32_t num_operands = inst->num_operands; +spv_result_t ExtInstPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); + const uint32_t result_type = inst->type_id(); + const uint32_t num_operands = static_cast<uint32_t>(inst->operands().size()); if (opcode != SpvOpExtInst) return SPV_SUCCESS; - const uint32_t ext_inst_set = inst->words[3]; - const uint32_t ext_inst_index = inst->words[4]; + const uint32_t ext_inst_set = inst->word(3); + const uint32_t ext_inst_index = inst->word(4); const spv_ext_inst_type_t ext_inst_type = - spv_ext_inst_type_t(inst->ext_inst_type); + spv_ext_inst_type_t(inst->ext_inst_type()); auto ext_inst_name = [&_, ext_inst_set, ext_inst_type, ext_inst_index]() { spv_ext_inst_desc desc = nullptr; @@ -1530,7 +1529,7 @@ spv_result_t ExtInstPass(ValidationState_t& _, "type of Result Type"; } - const uint32_t n_value = inst->words[7]; + const uint32_t n_value = inst->word(7); if (num_components != n_value) { return _.diag(SPV_ERROR_INVALID_DATA) << ext_inst_name() << ": " @@ -1716,7 +1715,7 @@ spv_result_t ExtInstPass(ValidationState_t& _, << "expected operand P data type to be 16-bit float scalar"; } - const uint32_t n_value = inst->words[7]; + const uint32_t n_value = inst->word(7); if (num_components != n_value) { return _.diag(SPV_ERROR_INVALID_DATA) << ext_inst_name() << ": " diff --git a/source/validate_image.cpp b/source/validate_image.cpp index e4dbe762..c7a5fcad 100644 --- a/source/validate_image.cpp +++ b/source/validate_image.cpp @@ -199,14 +199,14 @@ uint32_t GetMinCoordSize(SpvOp opcode, const ImageTypeInfo& info) { // Checks ImageOperand bitfield and respective operands. spv_result_t ValidateImageOperands(ValidationState_t& _, - const spv_parsed_instruction_t& inst, + const Instruction* inst, const ImageTypeInfo& info, uint32_t mask, uint32_t word_index) { static const bool kAllImageOperandsHandled = CheckAllImageOperandsHandled(); (void)kAllImageOperandsHandled; - const SpvOp opcode = static_cast<SpvOp>(inst.opcode); - const uint32_t num_words = inst.num_words; + const SpvOp opcode = inst->opcode(); + const size_t num_words = inst->words().size(); size_t expected_num_image_operand_words = spvtools::utils::CountSetBits(mask); if (mask & SpvImageOperandsGradMask) { @@ -240,7 +240,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _, << spvOpcodeString(opcode); }; - const uint32_t type_id = _.GetTypeId(inst.words[word_index++]); + const uint32_t type_id = _.GetTypeId(inst->word(word_index++)); if (!_.IsFloatScalarType(type_id)) { return _.diag(SPV_ERROR_INVALID_DATA) << "Expected Image Operand Bias to be float scalar: " @@ -277,7 +277,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _, << spvOpcodeString(opcode); } - const uint32_t type_id = _.GetTypeId(inst.words[word_index++]); + const uint32_t type_id = _.GetTypeId(inst->word(word_index++)); if (is_explicit_lod) { if (!_.IsFloatScalarType(type_id)) { return _.diag(SPV_ERROR_INVALID_DATA) @@ -314,8 +314,8 @@ spv_result_t ValidateImageOperands(ValidationState_t& _, << spvOpcodeString(opcode); }; - const uint32_t dx_type_id = _.GetTypeId(inst.words[word_index++]); - const uint32_t dy_type_id = _.GetTypeId(inst.words[word_index++]); + const uint32_t dx_type_id = _.GetTypeId(inst->word(word_index++)); + const uint32_t dy_type_id = _.GetTypeId(inst->word(word_index++)); if (!_.IsFloatScalarOrVectorType(dx_type_id) || !_.IsFloatScalarOrVectorType(dy_type_id)) { return _.diag(SPV_ERROR_INVALID_DATA) @@ -355,7 +355,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _, << spvOpcodeString(opcode); } - const uint32_t id = inst.words[word_index++]; + const uint32_t id = inst->word(word_index++); const uint32_t type_id = _.GetTypeId(id); if (!_.IsIntScalarOrVectorType(type_id)) { return _.diag(SPV_ERROR_INVALID_DATA) @@ -386,7 +386,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _, << spvOpcodeString(opcode); } - const uint32_t id = inst.words[word_index++]; + const uint32_t id = inst->word(word_index++); const uint32_t type_id = _.GetTypeId(id); if (!_.IsIntScalarOrVectorType(type_id)) { return _.diag(SPV_ERROR_INVALID_DATA) @@ -421,7 +421,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _, << spvOpcodeString(opcode); } - const uint32_t id = inst.words[word_index++]; + const uint32_t id = inst->word(word_index++); const uint32_t type_id = _.GetTypeId(id); const Instruction* type_inst = _.FindDef(type_id); assert(type_inst); @@ -475,7 +475,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _, << spvOpcodeString(opcode); } - const uint32_t type_id = _.GetTypeId(inst.words[word_index++]); + const uint32_t type_id = _.GetTypeId(inst->word(word_index++)); if (!_.IsIntScalarType(type_id)) { return _.diag(SPV_ERROR_INVALID_DATA) << "Expected Image Operand Sample to be int scalar: " @@ -491,7 +491,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _, << spvOpcodeString(opcode); }; - const uint32_t type_id = _.GetTypeId(inst.words[word_index++]); + const uint32_t type_id = _.GetTypeId(inst->word(word_index++)); if (!_.IsFloatScalarType(type_id)) { return _.diag(SPV_ERROR_INVALID_DATA) << "Expected Image Operand MinLod to be float scalar: " @@ -517,10 +517,9 @@ spv_result_t ValidateImageOperands(ValidationState_t& _, } // Checks some of the validation rules which are common to multiple opcodes. -spv_result_t ValidateImageCommon(ValidationState_t& _, - const spv_parsed_instruction_t& inst, +spv_result_t ValidateImageCommon(ValidationState_t& _, const Instruction* inst, const ImageTypeInfo& info) { - const SpvOp opcode = static_cast<SpvOp>(inst.opcode); + const SpvOp opcode = inst->opcode(); if (IsProj(opcode)) { if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D && info.dim != SpvDimRect) { @@ -616,13 +615,12 @@ bool IsSparse(SpvOp opcode) { // Checks sparse image opcode result type and returns the second struct member. // Returns inst.type_id for non-sparse image opcodes. // Not valid for sparse image opcodes which do not return a struct. -spv_result_t GetActualResultType(ValidationState_t& _, - const spv_parsed_instruction_t& inst, +spv_result_t GetActualResultType(ValidationState_t& _, const Instruction* inst, uint32_t* actual_result_type) { - const SpvOp opcode = static_cast<SpvOp>(inst.opcode); + const SpvOp opcode = inst->opcode(); if (IsSparse(opcode)) { - const Instruction* const type_inst = _.FindDef(inst.type_id); + const Instruction* const type_inst = _.FindDef(inst->type_id()); assert(type_inst); if (!type_inst || type_inst->opcode() != SpvOpTypeStruct) { @@ -642,7 +640,7 @@ spv_result_t GetActualResultType(ValidationState_t& _, *actual_result_type = type_inst->word(3); } else { - *actual_result_type = inst.type_id; + *actual_result_type = inst->type_id(); } return SPV_SUCCESS; @@ -658,10 +656,9 @@ const char* GetActualResultTypeStr(SpvOp opcode) { } // namespace // Validates correctness of image instructions. -spv_result_t ImagePass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); - const uint32_t result_type = inst->type_id; +spv_result_t ImagePass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); + const uint32_t result_type = inst->type_id(); if (IsImplicitLod(opcode)) { _.current_function().RegisterExecutionModelLimitation( @@ -674,7 +671,7 @@ spv_result_t ImagePass(ValidationState_t& _, assert(result_type == 0); ImageTypeInfo info; - if (!GetImageTypeInfo(_, inst->words[1], &info)) { + if (!GetImageTypeInfo(_, inst->word(1), &info)) { return _.diag(SPV_ERROR_INVALID_DATA) << "OpTypeImage: corrupt definition"; } @@ -746,7 +743,7 @@ spv_result_t ImagePass(ValidationState_t& _, } case SpvOpTypeSampledImage: { - const uint32_t image_type = inst->words[2]; + const uint32_t image_type = inst->word(2); if (_.GetIdOpcode(image_type) != SpvOpTypeImage) { return _.diag(SPV_ERROR_INVALID_DATA) << spvOpcodeString(opcode) @@ -817,7 +814,7 @@ spv_result_t ImagePass(ValidationState_t& _, case SpvOpImageSparseSampleExplicitLod: { uint32_t actual_result_type = 0; if (spv_result_t error = - GetActualResultType(_, *inst, &actual_result_type)) { + GetActualResultType(_, inst, &actual_result_type)) { return error; } @@ -848,7 +845,7 @@ spv_result_t ImagePass(ValidationState_t& _, << "Corrupt image type definition"; } - if (spv_result_t result = ValidateImageCommon(_, *inst, info)) + if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result; if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) { @@ -889,14 +886,14 @@ spv_result_t ImagePass(ValidationState_t& _, << spvOpcodeString(opcode); } - if (inst->num_words <= 5) { + if (inst->words().size() <= 5) { assert(IsImplicitLod(opcode)); break; } - const uint32_t mask = inst->words[5]; + const uint32_t mask = inst->word(5); if (spv_result_t result = - ValidateImageOperands(_, *inst, info, mask, /* word_index = */ 6)) + ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6)) return result; break; @@ -910,7 +907,7 @@ spv_result_t ImagePass(ValidationState_t& _, case SpvOpImageSparseSampleDrefExplicitLod: { uint32_t actual_result_type = 0; if (spv_result_t error = - GetActualResultType(_, *inst, &actual_result_type)) { + GetActualResultType(_, inst, &actual_result_type)) { return error; } @@ -935,7 +932,7 @@ spv_result_t ImagePass(ValidationState_t& _, << "Corrupt image type definition"; } - if (spv_result_t result = ValidateImageCommon(_, *inst, info)) + if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result; if (actual_result_type != info.sampled_type) { @@ -968,14 +965,14 @@ spv_result_t ImagePass(ValidationState_t& _, << ": Expected Dref to be of 32-bit float type"; } - if (inst->num_words <= 6) { + if (inst->words().size() <= 6) { assert(IsImplicitLod(opcode)); break; } - const uint32_t mask = inst->words[6]; + const uint32_t mask = inst->word(6); if (spv_result_t result = - ValidateImageOperands(_, *inst, info, mask, /* word_index = */ 7)) + ValidateImageOperands(_, inst, info, mask, /* word_index = */ 7)) return result; break; @@ -985,7 +982,7 @@ spv_result_t ImagePass(ValidationState_t& _, case SpvOpImageSparseFetch: { uint32_t actual_result_type = 0; if (spv_result_t error = - GetActualResultType(_, *inst, &actual_result_type)) { + GetActualResultType(_, inst, &actual_result_type)) { return error; } @@ -1054,11 +1051,11 @@ spv_result_t ImagePass(ValidationState_t& _, << spvOpcodeString(opcode); } - if (inst->num_words <= 5) break; + if (inst->words().size() <= 5) break; - const uint32_t mask = inst->words[5]; + const uint32_t mask = inst->word(5); if (spv_result_t result = - ValidateImageOperands(_, *inst, info, mask, /* word_index = */ 6)) + ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6)) return result; break; @@ -1070,7 +1067,7 @@ spv_result_t ImagePass(ValidationState_t& _, case SpvOpImageSparseDrefGather: { uint32_t actual_result_type = 0; if (spv_result_t error = - GetActualResultType(_, *inst, &actual_result_type)) { + GetActualResultType(_, inst, &actual_result_type)) { return error; } @@ -1156,11 +1153,11 @@ spv_result_t ImagePass(ValidationState_t& _, } } - if (inst->num_words <= 6) break; + if (inst->words().size() <= 6) break; - const uint32_t mask = inst->words[6]; + const uint32_t mask = inst->word(6); if (spv_result_t result = - ValidateImageOperands(_, *inst, info, mask, /* word_index = */ 7)) + ValidateImageOperands(_, inst, info, mask, /* word_index = */ 7)) return result; break; @@ -1170,7 +1167,7 @@ spv_result_t ImagePass(ValidationState_t& _, case SpvOpImageSparseRead: { uint32_t actual_result_type = 0; if (spv_result_t error = - GetActualResultType(_, *inst, &actual_result_type)) { + GetActualResultType(_, inst, &actual_result_type)) { return error; } @@ -1228,7 +1225,7 @@ spv_result_t ImagePass(ValidationState_t& _, } } - if (spv_result_t result = ValidateImageCommon(_, *inst, info)) + if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result; const uint32_t coord_type = _.GetOperandTypeId(inst, 3); @@ -1255,11 +1252,11 @@ spv_result_t ImagePass(ValidationState_t& _, << "read storage image: " << spvOpcodeString(opcode); } - if (inst->num_words <= 5) break; + if (inst->words().size() <= 5) break; - const uint32_t mask = inst->words[5]; + const uint32_t mask = inst->word(5); if (spv_result_t result = - ValidateImageOperands(_, *inst, info, mask, /* word_index = */ 6)) + ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6)) return result; break; @@ -1285,7 +1282,7 @@ spv_result_t ImagePass(ValidationState_t& _, << spvOpcodeString(opcode); } - if (spv_result_t result = ValidateImageCommon(_, *inst, info)) + if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result; const uint32_t coord_type = _.GetOperandTypeId(inst, 1); @@ -1341,11 +1338,11 @@ spv_result_t ImagePass(ValidationState_t& _, << "to storage image: " << spvOpcodeString(opcode); } - if (inst->num_words <= 4) break; + if (inst->words().size() <= 4) break; - const uint32_t mask = inst->words[4]; + const uint32_t mask = inst->word(4); if (spv_result_t result = - ValidateImageOperands(_, *inst, info, mask, /* word_index = */ 5)) + ValidateImageOperands(_, inst, info, mask, /* word_index = */ 5)) return result; break; diff --git a/source/validate_instruction.cpp b/source/validate_instruction.cpp index 605ae3ca..b71d6ba9 100644 --- a/source/validate_instruction.cpp +++ b/source/validate_instruction.cpp @@ -57,7 +57,7 @@ std::string ToString(const CapabilitySet& capabilities, // Reports a missing-capability error to _'s diagnostic stream and returns // SPV_ERROR_INVALID_CAPABILITY. -spv_result_t CapabilityError(const ValidationState_t& _, int which_operand, +spv_result_t CapabilityError(const ValidationState_t& _, size_t which_operand, SpvOp opcode, const std::string& required_capabilities) { return _.diag(SPV_ERROR_INVALID_CAPABILITY) @@ -100,7 +100,7 @@ CapabilitySet EnablingCapabilitiesForOp(const ValidationState_t& state, // in the module. Otherwise issues an error message and returns // SPV_ERROR_INVALID_CAPABILITY. spv_result_t CheckRequiredCapabilities(const ValidationState_t& state, - SpvOp opcode, int which_operand, + SpvOp opcode, size_t which_operand, spv_operand_type_t type, uint32_t operand) { // Mere mention of PointSize, ClipDistance, or CullDistance in a Builtin @@ -181,9 +181,8 @@ ExtensionSet RequiredExtensions(const ValidationState_t& state, // Returns SPV_ERROR_INVALID_BINARY and emits a diagnostic if the instruction // is explicitly reserved in the SPIR-V core spec. Otherwise return // SPV_SUCCESS. -spv_result_t ReservedCheck(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); +spv_result_t ReservedCheck(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); switch (opcode) { // These instructions are enabled by a capability, but should never // be used anyway. @@ -204,9 +203,8 @@ spv_result_t ReservedCheck(ValidationState_t& _, // Returns SPV_ERROR_INVALID_BINARY and emits a diagnostic if the instruction // is invalid because of an execution environment constraint. -spv_result_t EnvironmentCheck(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); +spv_result_t EnvironmentCheck(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); switch (opcode) { case SpvOpUndef: if (_.features().bans_op_undef) { @@ -222,9 +220,8 @@ spv_result_t EnvironmentCheck(ValidationState_t& _, // Returns SPV_ERROR_INVALID_CAPABILITY and emits a diagnostic if the // instruction is invalid because the required capability isn't declared // in the module. -spv_result_t CapabilityCheck(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); +spv_result_t CapabilityCheck(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); CapabilitySet opcode_caps = EnablingCapabilitiesForOp(_, opcode); if (!_.HasAnyOfCapabilities(opcode_caps)) { return _.diag(SPV_ERROR_INVALID_CAPABILITY) @@ -232,9 +229,9 @@ spv_result_t CapabilityCheck(ValidationState_t& _, << " requires one of these capabilities: " << ToString(opcode_caps, _.grammar()); } - for (int i = 0; i < inst->num_operands; ++i) { - const auto& operand = inst->operands[i]; - const auto word = inst->words[operand.offset]; + for (size_t i = 0; i < inst->operands().size(); ++i) { + const auto& operand = inst->operand(i); + const auto word = inst->word(operand.offset); if (spvOperandIsConcreteMask(operand.type)) { // Check for required capabilities for each bit position of the mask. for (uint32_t mask_bit = 0x80000000; mask_bit; mask_bit >>= 1) { @@ -260,13 +257,12 @@ spv_result_t CapabilityCheck(ValidationState_t& _, // Checks that all extensions required by the given instruction's operands were // declared in the module. -spv_result_t ExtensionCheck(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); - for (size_t operand_index = 0; operand_index < inst->num_operands; +spv_result_t ExtensionCheck(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); + for (size_t operand_index = 0; operand_index < inst->operands().size(); ++operand_index) { - const auto& operand = inst->operands[operand_index]; - const uint32_t word = inst->words[operand.offset]; + const auto& operand = inst->operand(operand_index); + const uint32_t word = inst->word(operand.offset); const ExtensionSet required_extensions = RequiredExtensions(_, operand.type, word); if (!_.HasAnyOfExtensions(required_extensions)) { @@ -283,9 +279,8 @@ spv_result_t ExtensionCheck(ValidationState_t& _, // Checks that the instruction can be used in this target environment's base // version. Assumes that CapabilityCheck has checked direct capability // dependencies for the opcode. -spv_result_t VersionCheck(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const auto opcode = static_cast<SpvOp>(inst->opcode); +spv_result_t VersionCheck(ValidationState_t& _, const Instruction* inst) { + const auto opcode = inst->opcode(); spv_opcode_desc inst_desc; const bool r = _.grammar().lookupOpcode(opcode, &inst_desc); assert(r == SPV_SUCCESS); @@ -339,20 +334,18 @@ spv_result_t VersionCheck(ValidationState_t& _, } // 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()) { +spv_result_t LimitCheckIdBound(ValidationState_t& _, const Instruction* inst) { + if (inst->id() >= _.getIdBound()) { return _.diag(SPV_ERROR_INVALID_BINARY) - << "Result <id> '" << inst->result_id + << "Result <id> '" << inst->id() << "' must be less than the ID bound '" << _.getIdBound() << "'."; } return SPV_SUCCESS; } // Checks that the number of OpTypeStruct members is within the limit. -spv_result_t LimitCheckStruct(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - if (SpvOpTypeStruct != inst->opcode) { +spv_result_t LimitCheckStruct(ValidationState_t& _, const Instruction* inst) { + if (SpvOpTypeStruct != inst->opcode()) { return SPV_SUCCESS; } @@ -360,9 +353,9 @@ spv_result_t LimitCheckStruct(ValidationState_t& _, // One operand is the result ID. const uint16_t limit = static_cast<uint16_t>(_.options()->universal_limits_.max_struct_members); - if (inst->num_operands - 1 > limit) { + if (inst->operands().size() - 1 > limit) { return _.diag(SPV_ERROR_INVALID_BINARY) - << "Number of OpTypeStruct members (" << inst->num_operands - 1 + << "Number of OpTypeStruct members (" << inst->operands().size() - 1 << ") has exceeded the limit (" << limit << ")."; } @@ -375,8 +368,8 @@ spv_result_t LimitCheckStruct(ValidationState_t& _, // Scalars are at depth 0. uint32_t max_member_depth = 0; // Struct members start at word 2 of OpTypeStruct instruction. - for (size_t word_i = 2; word_i < inst->num_words; ++word_i) { - auto member = inst->words[word_i]; + for (size_t word_i = 2; word_i < inst->words().size(); ++word_i) { + auto member = inst->word(word_i); auto memberTypeInstr = _.FindDef(member); if (memberTypeInstr && SpvOpTypeStruct == memberTypeInstr->opcode()) { max_member_depth = std::max( @@ -386,7 +379,7 @@ spv_result_t LimitCheckStruct(ValidationState_t& _, const uint32_t depth_limit = _.options()->universal_limits_.max_struct_depth; const uint32_t cur_depth = 1 + max_member_depth; - _.set_struct_nesting_depth(inst->result_id, cur_depth); + _.set_struct_nesting_depth(inst->id(), cur_depth); if (cur_depth > depth_limit) { return _.diag(SPV_ERROR_INVALID_BINARY) << "Structure Nesting Depth may not be larger than " << depth_limit @@ -397,14 +390,13 @@ spv_result_t LimitCheckStruct(ValidationState_t& _, // Checks that the number of (literal, label) pairs in OpSwitch is within the // limit. -spv_result_t LimitCheckSwitch(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - if (SpvOpSwitch == inst->opcode) { +spv_result_t LimitCheckSwitch(ValidationState_t& _, const Instruction* inst) { + if (SpvOpSwitch == inst->opcode()) { // The instruction syntax is as follows: // OpSwitch <selector ID> <Default ID> literal label literal label ... // literal,label pairs come after the first 2 operands. // It is guaranteed at this point that num_operands is an even numner. - unsigned int num_pairs = (inst->num_operands - 2) / 2; + size_t num_pairs = (inst->operands().size() - 2) / 2; const unsigned int num_pairs_limit = _.options()->universal_limits_.max_switch_branches; if (num_pairs > num_pairs_limit) { @@ -446,27 +438,27 @@ spv_result_t LimitCheckNumVars(ValidationState_t& _, const uint32_t var_id, // Registers necessary decoration(s) for the appropriate IDs based on the // instruction. spv_result_t RegisterDecorations(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - switch (inst->opcode) { + const Instruction* inst) { + switch (inst->opcode()) { case SpvOpDecorate: { - const uint32_t target_id = inst->words[1]; - const SpvDecoration dec_type = static_cast<SpvDecoration>(inst->words[2]); + const uint32_t target_id = inst->word(1); + const SpvDecoration dec_type = static_cast<SpvDecoration>(inst->word(2)); std::vector<uint32_t> dec_params; - if (inst->num_words > 3) { - dec_params.insert(dec_params.end(), inst->words + 3, - inst->words + inst->num_words); + if (inst->words().size() > 3) { + dec_params.insert(dec_params.end(), inst->words().begin() + 3, + inst->words().end()); } _.RegisterDecorationForId(target_id, Decoration(dec_type, dec_params)); break; } case SpvOpMemberDecorate: { - const uint32_t struct_id = inst->words[1]; - const uint32_t index = inst->words[2]; - const SpvDecoration dec_type = static_cast<SpvDecoration>(inst->words[3]); + const uint32_t struct_id = inst->word(1); + const uint32_t index = inst->word(2); + const SpvDecoration dec_type = static_cast<SpvDecoration>(inst->word(3)); std::vector<uint32_t> dec_params; - if (inst->num_words > 4) { - dec_params.insert(dec_params.end(), inst->words + 4, - inst->words + inst->num_words); + if (inst->words().size() > 4) { + dec_params.insert(dec_params.end(), inst->words().begin() + 4, + inst->words().end()); } _.RegisterDecorationForId(struct_id, Decoration(dec_type, dec_params, index)); @@ -480,11 +472,11 @@ spv_result_t RegisterDecorations(ValidationState_t& _, case SpvOpGroupDecorate: { // Word 1 is the group <id>. All subsequent words are target <id>s that // are going to be decorated with the decorations. - const uint32_t decoration_group_id = inst->words[1]; + const uint32_t decoration_group_id = inst->word(1); std::vector<Decoration>& group_decorations = _.id_decorations(decoration_group_id); - for (int i = 2; i < inst->num_words; ++i) { - const uint32_t target_id = inst->words[i]; + for (size_t i = 2; i < inst->words().size(); ++i) { + const uint32_t target_id = inst->word(i); _.RegisterDecorationsForId(target_id, group_decorations.begin(), group_decorations.end()); } @@ -494,14 +486,14 @@ spv_result_t RegisterDecorations(ValidationState_t& _, // Word 1 is the Decoration Group <id> followed by (struct<id>,literal) // pairs. All decorations of the group should be applied to all the struct // members that are specified in the instructions. - const uint32_t decoration_group_id = inst->words[1]; + const uint32_t decoration_group_id = inst->word(1); std::vector<Decoration>& group_decorations = _.id_decorations(decoration_group_id); // Grammar checks ensures that the number of arguments to this instruction // is an odd number: 1 decoration group + (id,literal) pairs. - for (int i = 2; i + 1 < inst->num_words; i = i + 2) { - const uint32_t struct_id = inst->words[i]; - const uint32_t index = inst->words[i + 1]; + for (size_t i = 2; i + 1 < inst->words().size(); i = i + 2) { + const uint32_t struct_id = inst->word(i); + const uint32_t index = inst->word(i + 1); // ID validation phase ensures this is in fact a struct instruction and // that the index is not out of bound. _.RegisterDecorationsForStructMember(struct_id, index, @@ -517,9 +509,8 @@ spv_result_t RegisterDecorations(ValidationState_t& _, } // Parses OpExtension instruction and logs warnings if unsuccessful. -void CheckIfKnownExtension(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const std::string extension_str = GetExtensionString(inst); +void CheckIfKnownExtension(ValidationState_t& _, const Instruction* inst) { + const std::string extension_str = GetExtensionString(&(inst->c_inst())); Extension extension; if (!GetExtensionFromString(extension_str.c_str(), &extension)) { _.diag(SPV_SUCCESS) << "Found unrecognized extension " << extension_str; @@ -529,31 +520,26 @@ void CheckIfKnownExtension(ValidationState_t& _, } // namespace -spv_result_t InstructionPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); +spv_result_t InstructionPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); if (opcode == SpvOpExtension) { CheckIfKnownExtension(_, inst); } else if (opcode == SpvOpCapability) { - _.RegisterCapability( - static_cast<SpvCapability>(inst->words[inst->operands[0].offset])); + _.RegisterCapability(inst->GetOperandAs<SpvCapability>(0)); } else if (opcode == SpvOpMemoryModel) { if (_.has_memory_model_specified()) { return _.diag(SPV_ERROR_INVALID_LAYOUT) << "OpMemoryModel should only be provided once."; } - _.set_addressing_model( - static_cast<SpvAddressingModel>(inst->words[inst->operands[0].offset])); - _.set_memory_model( - static_cast<SpvMemoryModel>(inst->words[inst->operands[1].offset])); + _.set_addressing_model(inst->GetOperandAs<SpvAddressingModel>(0)); + _.set_memory_model(inst->GetOperandAs<SpvMemoryModel>(1)); } else if (opcode == SpvOpExecutionMode) { - const uint32_t entry_point = inst->words[1]; + const uint32_t entry_point = inst->word(1); _.RegisterExecutionModeForEntryPoint(entry_point, - SpvExecutionMode(inst->words[2])); + SpvExecutionMode(inst->word(2))); } else if (opcode == SpvOpVariable) { - const auto storage_class = - static_cast<SpvStorageClass>(inst->words[inst->operands[2].offset]); - if (auto error = LimitCheckNumVars(_, inst->result_id, storage_class)) { + const auto storage_class = inst->GetOperandAs<SpvStorageClass>(2); + if (auto error = LimitCheckNumVars(_, inst->id(), storage_class)) { return error; } if (storage_class == SpvStorageClassGeneric) @@ -582,8 +568,8 @@ spv_result_t InstructionPass(ValidationState_t& _, // SPIR-V Spec 2.16.3: Validation Rules for Kernel Capabilities: The // Signedness in OpTypeInt must always be 0. - if (SpvOpTypeInt == inst->opcode && _.HasCapability(SpvCapabilityKernel) && - inst->words[inst->operands[2].offset] != 0u) { + if (SpvOpTypeInt == inst->opcode() && _.HasCapability(SpvCapabilityKernel) && + inst->GetOperandAs<uint32_t>(2) != 0u) { return _.diag(SPV_ERROR_INVALID_BINARY) << "The Signedness in OpTypeInt " "must always be 0 when Kernel " "capability is used."; diff --git a/source/validate_layout.cpp b/source/validate_layout.cpp index 287a49e9..e45d4d4b 100644 --- a/source/validate_layout.cpp +++ b/source/validate_layout.cpp @@ -23,6 +23,7 @@ #include "operand.h" #include "spirv-tools/libspirv.h" #include "val/function.h" +#include "val/instruction.h" #include "val/validation_state.h" namespace spvtools { @@ -33,8 +34,7 @@ namespace { // is part of the current layout section. If it is not then the next sections is // checked. spv_result_t ModuleScopedInstructions(ValidationState_t& _, - const spv_parsed_instruction_t* inst, - SpvOp opcode) { + const Instruction* inst, SpvOp opcode) { while (_.IsOpcodeInCurrentLayoutSection(opcode) == false) { _.ProgressToNextLayoutSectionOrder(); @@ -63,8 +63,7 @@ spv_result_t ModuleScopedInstructions(ValidationState_t& _, // inside of another function. This stage ends when the first label is // encountered inside of a function. spv_result_t FunctionScopedInstructions(ValidationState_t& _, - const spv_parsed_instruction_t* inst, - SpvOp opcode) { + const Instruction* inst, SpvOp opcode) { if (_.IsOpcodeInCurrentLayoutSection(opcode)) { switch (opcode) { case SpvOpFunction: { @@ -72,11 +71,10 @@ spv_result_t FunctionScopedInstructions(ValidationState_t& _, return _.diag(SPV_ERROR_INVALID_LAYOUT) << "Cannot declare a function in a function body"; } - auto control_mask = static_cast<SpvFunctionControlMask>( - inst->words[inst->operands[2].offset]); + auto control_mask = inst->GetOperandAs<SpvFunctionControlMask>(2); if (auto error = - _.RegisterFunction(inst->result_id, inst->type_id, control_mask, - inst->words[inst->operands[3].offset])) + _.RegisterFunction(inst->id(), inst->type_id(), control_mask, + inst->GetOperandAs<uint32_t>(3))) return error; if (_.current_layout_section() == kLayoutFunctionDefinitions) { if (auto error = _.current_function().RegisterSetFunctionDeclType( @@ -97,7 +95,7 @@ spv_result_t FunctionScopedInstructions(ValidationState_t& _, "the function definition"; } if (auto error = _.current_function().RegisterFunctionParameter( - inst->result_id, inst->type_id)) + inst->id(), inst->type_id())) return error; break; @@ -174,9 +172,8 @@ spv_result_t FunctionScopedInstructions(ValidationState_t& _, // TODO(umar): Better error messages // NOTE: This function does not handle CFG related validation // Performs logical layout validation. See Section 2.4 -spv_result_t ModuleLayoutPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); +spv_result_t ModuleLayoutPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); switch (_.current_layout_section()) { case kLayoutCapabilities: diff --git a/source/validate_literals.cpp b/source/validate_literals.cpp index 3f8e55e5..76ef467b 100644 --- a/source/validate_literals.cpp +++ b/source/validate_literals.cpp @@ -28,8 +28,8 @@ namespace val { namespace { // Returns true if the operand holds a literal number -bool IsLiteralNumber(const spv_parsed_operand_t* operand) { - switch (operand->number_kind) { +bool IsLiteralNumber(const spv_parsed_operand_t& operand) { + switch (operand.number_kind) { case SPV_NUMBER_SIGNED_INT: case SPV_NUMBER_UNSIGNED_INT: case SPV_NUMBER_FLOATING: @@ -64,31 +64,30 @@ bool VerifyUpperBits(uint32_t word, uint32_t width, bool signed_int) { } // namespace // Validates that literal numbers are represented according to the spec -spv_result_t LiteralsPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { +spv_result_t LiteralsPass(ValidationState_t& _, const Instruction* inst) { // For every operand that is a literal number - for (uint16_t i = 0; i < inst->num_operands; i++) { - const spv_parsed_operand_t* operand = inst->operands + i; + for (size_t i = 0; i < inst->operands().size(); i++) { + const spv_parsed_operand_t& operand = inst->operand(i); if (!IsLiteralNumber(operand)) continue; // The upper bits are always in the last word (little-endian) - int last_index = operand->offset + operand->num_words - 1; - const uint32_t upper_word = inst->words[last_index]; + int last_index = operand.offset + operand.num_words - 1; + const uint32_t upper_word = inst->word(last_index); // TODO(jcaraban): is the |word size| defined in some header? const uint32_t word_size = 32; - uint32_t bit_width = operand->number_bit_width; + uint32_t bit_width = operand.number_bit_width; // Bit widths that are a multiple of the word size have no upper bits const auto remaining_value_bits = bit_width % word_size; if (remaining_value_bits == 0) continue; - const bool signedness = operand->number_kind == SPV_NUMBER_SIGNED_INT; + const bool signedness = operand.number_kind == SPV_NUMBER_SIGNED_INT; if (!VerifyUpperBits(upper_word, remaining_value_bits, signedness)) { return _.diag(SPV_ERROR_INVALID_VALUE) << "The high-order bits of a literal number in instruction <id> " - << inst->result_id << " must be 0 for a floating-point type, " + << inst->id() << " must be 0 for a floating-point type, " << "or 0 for an integer type with Signedness of 0, " << "or sign extended when Signedness is 1"; } diff --git a/source/validate_logicals.cpp b/source/validate_logicals.cpp index a893d3f0..72399686 100644 --- a/source/validate_logicals.cpp +++ b/source/validate_logicals.cpp @@ -23,32 +23,11 @@ namespace spvtools { namespace val { -namespace { - -// Returns operand word for given instruction and operand index. -// The operand is expected to only have one word. -inline uint32_t GetOperandWord(const spv_parsed_instruction_t* inst, - size_t operand_index) { - assert(operand_index < inst->num_operands); - const spv_parsed_operand_t& operand = inst->operands[operand_index]; - assert(operand.num_words == 1); - return inst->words[operand.offset]; -} - -// Returns the type id of instruction operand at |operand_index|. -// The operand is expected to be an id. -inline uint32_t GetOperandTypeId(ValidationState_t& _, - const spv_parsed_instruction_t* inst, - size_t operand_index) { - return _.GetTypeId(GetOperandWord(inst, operand_index)); -} -} // namespace // Validates correctness of logical instructions. -spv_result_t LogicalsPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); - const uint32_t result_type = inst->type_id; +spv_result_t LogicalsPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); + const uint32_t result_type = inst->type_id(); switch (opcode) { case SpvOpAny: @@ -58,7 +37,7 @@ spv_result_t LogicalsPass(ValidationState_t& _, << "Expected bool scalar type as Result Type: " << spvOpcodeString(opcode); - const uint32_t vector_type = GetOperandTypeId(_, inst, 2); + const uint32_t vector_type = _.GetOperandTypeId(inst, 2); if (!vector_type || !_.IsBoolVectorType(vector_type)) return _.diag(SPV_ERROR_INVALID_DATA) << "Expected operand to be vector bool: " @@ -77,7 +56,7 @@ spv_result_t LogicalsPass(ValidationState_t& _, << "Expected bool scalar or vector type as Result Type: " << spvOpcodeString(opcode); - const uint32_t operand_type = GetOperandTypeId(_, inst, 2); + const uint32_t operand_type = _.GetOperandTypeId(inst, 2); if (!operand_type || (!_.IsFloatScalarType(operand_type) && !_.IsFloatVectorType(operand_type))) return _.diag(SPV_ERROR_INVALID_DATA) @@ -113,7 +92,7 @@ spv_result_t LogicalsPass(ValidationState_t& _, << "Expected bool scalar or vector type as Result Type: " << spvOpcodeString(opcode); - const uint32_t left_operand_type = GetOperandTypeId(_, inst, 2); + const uint32_t left_operand_type = _.GetOperandTypeId(inst, 2); if (!left_operand_type || (!_.IsFloatScalarType(left_operand_type) && !_.IsFloatVectorType(left_operand_type))) return _.diag(SPV_ERROR_INVALID_DATA) @@ -126,7 +105,7 @@ spv_result_t LogicalsPass(ValidationState_t& _, "equal: " << spvOpcodeString(opcode); - if (left_operand_type != GetOperandTypeId(_, inst, 3)) + if (left_operand_type != _.GetOperandTypeId(inst, 3)) return _.diag(SPV_ERROR_INVALID_DATA) << "Expected left and right operands to have the same type: " << spvOpcodeString(opcode); @@ -143,8 +122,8 @@ spv_result_t LogicalsPass(ValidationState_t& _, << "Expected bool scalar or vector type as Result Type: " << spvOpcodeString(opcode); - if (result_type != GetOperandTypeId(_, inst, 2) || - result_type != GetOperandTypeId(_, inst, 3)) + if (result_type != _.GetOperandTypeId(inst, 2) || + result_type != _.GetOperandTypeId(inst, 3)) return _.diag(SPV_ERROR_INVALID_DATA) << "Expected both operands to be of Result Type: " << spvOpcodeString(opcode); @@ -158,7 +137,7 @@ spv_result_t LogicalsPass(ValidationState_t& _, << "Expected bool scalar or vector type as Result Type: " << spvOpcodeString(opcode); - if (result_type != GetOperandTypeId(_, inst, 2)) + if (result_type != _.GetOperandTypeId(inst, 2)) return _.diag(SPV_ERROR_INVALID_DATA) << "Expected operand to be of Result Type: " << spvOpcodeString(opcode); @@ -202,9 +181,9 @@ spv_result_t LogicalsPass(ValidationState_t& _, } } - const uint32_t condition_type = GetOperandTypeId(_, inst, 2); - const uint32_t left_type = GetOperandTypeId(_, inst, 3); - const uint32_t right_type = GetOperandTypeId(_, inst, 4); + const uint32_t condition_type = _.GetOperandTypeId(inst, 2); + const uint32_t left_type = _.GetOperandTypeId(inst, 3); + const uint32_t right_type = _.GetOperandTypeId(inst, 4); if (!condition_type || (!_.IsBoolScalarType(condition_type) && !_.IsBoolVectorType(condition_type))) @@ -240,8 +219,8 @@ spv_result_t LogicalsPass(ValidationState_t& _, << "Expected bool scalar or vector type as Result Type: " << spvOpcodeString(opcode); - const uint32_t left_type = GetOperandTypeId(_, inst, 2); - const uint32_t right_type = GetOperandTypeId(_, inst, 3); + const uint32_t left_type = _.GetOperandTypeId(inst, 2); + const uint32_t right_type = _.GetOperandTypeId(inst, 3); if (!left_type || (!_.IsIntScalarType(left_type) && !_.IsIntVectorType(left_type))) diff --git a/source/validate_non_uniform.cpp b/source/validate_non_uniform.cpp index de42dea8..070c773f 100644 --- a/source/validate_non_uniform.cpp +++ b/source/validate_non_uniform.cpp @@ -29,9 +29,8 @@ namespace val { namespace { spv_result_t ValidateExecutionScope(ValidationState_t& _, - const spv_parsed_instruction_t* inst, - uint32_t scope) { - SpvOp opcode = static_cast<SpvOp>(inst->opcode); + const Instruction* inst, uint32_t scope) { + SpvOp opcode = inst->opcode(); bool is_int32 = false, is_const_int32 = false; uint32_t value = 0; std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(scope); @@ -67,12 +66,11 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _, } // namespace // Validates correctness of non-uniform group instructions. -spv_result_t NonUniformPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); +spv_result_t NonUniformPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); if (spvOpcodeIsNonUniformGroupOperation(opcode)) { - const uint32_t execution_scope = inst->words[3]; + const uint32_t execution_scope = inst->word(3); if (auto error = ValidateExecutionScope(_, inst, execution_scope)) { return error; } diff --git a/source/validate_primitives.cpp b/source/validate_primitives.cpp index 47054969..289ac39b 100644 --- a/source/validate_primitives.cpp +++ b/source/validate_primitives.cpp @@ -27,9 +27,8 @@ namespace spvtools { namespace val { // Validates correctness of primitive instructions. -spv_result_t PrimitivesPass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); +spv_result_t PrimitivesPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); switch (opcode) { case SpvOpEmitVertex: @@ -48,7 +47,7 @@ spv_result_t PrimitivesPass(ValidationState_t& _, switch (opcode) { case SpvOpEmitStreamVertex: case SpvOpEndStreamPrimitive: { - const uint32_t stream_id = inst->words[1]; + const uint32_t stream_id = inst->word(1); const uint32_t stream_type = _.GetTypeId(stream_id); if (!_.IsIntScalarType(stream_type)) { return _.diag(SPV_ERROR_INVALID_DATA) diff --git a/source/validate_type_unique.cpp b/source/validate_type_unique.cpp index c251f6c9..643c1e1d 100644 --- a/source/validate_type_unique.cpp +++ b/source/validate_type_unique.cpp @@ -29,12 +29,11 @@ namespace val { // (see section 2.8 Types and Variables) // Doesn't do anything if SPV_VAL_ignore_type_decl_unique was declared in the // module. -spv_result_t TypeUniquePass(ValidationState_t& _, - const spv_parsed_instruction_t* inst) { +spv_result_t TypeUniquePass(ValidationState_t& _, const Instruction* inst) { if (_.HasExtension(Extension::kSPV_VALIDATOR_ignore_type_decl_unique)) return SPV_SUCCESS; - const SpvOp opcode = static_cast<SpvOp>(inst->opcode); + const SpvOp opcode = inst->opcode(); if (spvOpcodeGeneratesType(opcode)) { if (opcode == SpvOpTypeArray || opcode == SpvOpTypeRuntimeArray || @@ -43,11 +42,11 @@ spv_result_t TypeUniquePass(ValidationState_t& _, return SPV_SUCCESS; } - if (!_.RegisterUniqueTypeDeclaration(*inst)) { + if (!_.RegisterUniqueTypeDeclaration(inst)) { return _.diag(SPV_ERROR_INVALID_DATA) << "Duplicate non-aggregate type declarations are not allowed." - << " Opcode: " << spvOpcodeString(SpvOp(inst->opcode)) - << " id: " << inst->result_id; + << " Opcode: " << spvOpcodeString(SpvOp(inst->opcode())) + << " id: " << inst->id(); } } |