If |skip_builtin| is true, returns true if |storage| contains bool within it and no storage that contains the bool is builtin. If |skip_builtin| is false, returns true if |storage| contains bool within it.
| 162 | // If |skip_builtin| is false, returns true if |storage| contains bool within |
| 163 | // it. |
| 164 | bool ContainsInvalidBool(ValidationState_t& _, const Instruction* storage, |
| 165 | bool skip_builtin) { |
| 166 | if (skip_builtin) { |
| 167 | for (const Decoration& decoration : _.id_decorations(storage->id())) { |
| 168 | if (decoration.dec_type() == spv::Decoration::BuiltIn) return false; |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | const size_t elem_type_index = 1; |
| 173 | uint32_t elem_type_id; |
| 174 | Instruction* elem_type; |
| 175 | |
| 176 | switch (storage->opcode()) { |
| 177 | case spv::Op::OpTypeBool: |
| 178 | return true; |
| 179 | case spv::Op::OpTypeVector: |
| 180 | case spv::Op::OpTypeMatrix: |
| 181 | case spv::Op::OpTypeArray: |
| 182 | case spv::Op::OpTypeRuntimeArray: |
| 183 | elem_type_id = storage->GetOperandAs<uint32_t>(elem_type_index); |
| 184 | elem_type = _.FindDef(elem_type_id); |
| 185 | return ContainsInvalidBool(_, elem_type, skip_builtin); |
| 186 | case spv::Op::OpTypeStruct: |
| 187 | for (size_t member_type_index = 1; |
| 188 | member_type_index < storage->operands().size(); |
| 189 | ++member_type_index) { |
| 190 | auto member_type_id = |
| 191 | storage->GetOperandAs<uint32_t>(member_type_index); |
| 192 | auto member_type = _.FindDef(member_type_id); |
| 193 | if (ContainsInvalidBool(_, member_type, skip_builtin)) return true; |
| 194 | } |
| 195 | default: |
| 196 | break; |
| 197 | } |
| 198 | return false; |
| 199 | } |
| 200 | |
| 201 | std::pair<Instruction*, Instruction*> GetPointerTypes(ValidationState_t& _, |
| 202 | const Instruction* inst) { |