| 118 | } |
| 119 | |
| 120 | uint32_t WrapOpKill::GetKillingFuncId(spv::Op opcode) { |
| 121 | // Parameterize by opcode |
| 122 | assert(opcode == spv::Op::OpKill || opcode == spv::Op::OpTerminateInvocation); |
| 123 | |
| 124 | std::unique_ptr<Function>* const killing_func = |
| 125 | (opcode == spv::Op::OpKill) ? &opkill_function_ |
| 126 | : &opterminateinvocation_function_; |
| 127 | |
| 128 | if (*killing_func != nullptr) { |
| 129 | return (*killing_func)->result_id(); |
| 130 | } |
| 131 | |
| 132 | uint32_t killing_func_id = TakeNextId(); |
| 133 | if (killing_func_id == 0) { |
| 134 | return 0; |
| 135 | } |
| 136 | |
| 137 | uint32_t void_type_id = GetVoidTypeId(); |
| 138 | if (void_type_id == 0) { |
| 139 | return 0; |
| 140 | } |
| 141 | |
| 142 | // Generate the function start instruction |
| 143 | std::unique_ptr<Instruction> func_start(new Instruction( |
| 144 | context(), spv::Op::OpFunction, void_type_id, killing_func_id, {})); |
| 145 | func_start->AddOperand({SPV_OPERAND_TYPE_FUNCTION_CONTROL, {0}}); |
| 146 | func_start->AddOperand({SPV_OPERAND_TYPE_ID, {GetVoidFunctionTypeId()}}); |
| 147 | (*killing_func).reset(new Function(std::move(func_start))); |
| 148 | |
| 149 | // Generate the function end instruction |
| 150 | std::unique_ptr<Instruction> func_end( |
| 151 | new Instruction(context(), spv::Op::OpFunctionEnd, 0, 0, {})); |
| 152 | (*killing_func)->SetFunctionEnd(std::move(func_end)); |
| 153 | |
| 154 | // Create the one basic block for the function. |
| 155 | uint32_t lab_id = TakeNextId(); |
| 156 | if (lab_id == 0) { |
| 157 | return 0; |
| 158 | } |
| 159 | std::unique_ptr<Instruction> label_inst( |
| 160 | new Instruction(context(), spv::Op::OpLabel, 0, lab_id, {})); |
| 161 | std::unique_ptr<BasicBlock> bb(new BasicBlock(std::move(label_inst))); |
| 162 | |
| 163 | // Add the OpKill to the basic block |
| 164 | std::unique_ptr<Instruction> kill_inst( |
| 165 | new Instruction(context(), opcode, 0, 0, {})); |
| 166 | bb->AddInstruction(std::move(kill_inst)); |
| 167 | |
| 168 | // Add the bb to the function |
| 169 | (*killing_func)->AddBasicBlock(std::move(bb)); |
| 170 | |
| 171 | // Add the function to the module. |
| 172 | if (context()->AreAnalysesValid(IRContext::kAnalysisDefUse)) { |
| 173 | (*killing_func)->ForEachInst([this](Instruction* inst) { |
| 174 | context()->AnalyzeDefUse(inst); |
| 175 | }); |
| 176 | } |
| 177 |
nothing calls this directly
no test coverage detected