| 60 | // If `condition` is false, the children of the current node are ignored. |
| 61 | template <class UnaryPredicate> |
| 62 | static void DFSWhile(const Instruction* instruction, UnaryPredicate condition) { |
| 63 | std::stack<uint32_t> instructions_to_visit; |
| 64 | std::unordered_set<uint32_t> visited_instructions; |
| 65 | instructions_to_visit.push(instruction->result_id()); |
| 66 | const auto* def_use_mgr = instruction->context()->get_def_use_mgr(); |
| 67 | |
| 68 | while (!instructions_to_visit.empty()) { |
| 69 | const Instruction* item = def_use_mgr->GetDef(instructions_to_visit.top()); |
| 70 | instructions_to_visit.pop(); |
| 71 | |
| 72 | // Forward references can be allowed, meaning we can have cycles |
| 73 | // between ID uses. Need to keep track of this. |
| 74 | if (visited_instructions.count(item->result_id())) continue; |
| 75 | visited_instructions.insert(item->result_id()); |
| 76 | |
| 77 | if (!condition(item)) { |
| 78 | continue; |
| 79 | } |
| 80 | |
| 81 | if (item->opcode() == spv::Op::OpTypePointer) { |
| 82 | instructions_to_visit.push( |
| 83 | item->GetSingleWordInOperand(kTypePointerTypeIdInIndex)); |
| 84 | continue; |
| 85 | } |
| 86 | |
| 87 | if (item->opcode() == spv::Op::OpTypeMatrix || |
| 88 | item->opcode() == spv::Op::OpTypeVector || |
| 89 | item->opcode() == spv::Op::OpTypeArray || |
| 90 | item->opcode() == spv::Op::OpTypeRuntimeArray) { |
| 91 | instructions_to_visit.push( |
| 92 | item->GetSingleWordInOperand(kTypeArrayTypeIndex)); |
| 93 | continue; |
| 94 | } |
| 95 | |
| 96 | if (item->opcode() == spv::Op::OpTypeStruct) { |
| 97 | item->ForEachInOperand([&instructions_to_visit](const uint32_t* op_id) { |
| 98 | instructions_to_visit.push(*op_id); |
| 99 | }); |
| 100 | continue; |
| 101 | } |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | // Walks the type defined by `instruction` (OpType* only). |
| 106 | // Returns `true` if any call to `predicate` with the type/subtype returns true. |
no test coverage detected