| /* Copyright (c) 2024 LunarG, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "inject_function_pass.h" |
| #include "module.h" |
| |
| namespace gpuav { |
| namespace spirv { |
| |
| InjectFunctionPass::InjectFunctionPass(Module& module) : Pass(module) { module.use_bda_ = true; } |
| |
| bool InjectFunctionPass::Run() { |
| // Can safely loop function list as there is no injecting of new Functions until linking time |
| for (const auto& function : module_.functions_) { |
| for (auto block_it = function->blocks_.begin(); block_it != function->blocks_.end(); ++block_it) { |
| if ((*block_it)->loop_header_) { |
| continue; // Currently can't properly handle injecting CFG logic into a loop header block |
| } |
| auto& block_instructions = (*block_it)->instructions_; |
| for (auto inst_it = block_instructions.begin(); inst_it != block_instructions.end(); ++inst_it) { |
| // Every instruction is analyzed by the specific pass and lets us know if we need to inject a function or not |
| if (!RequiresInstrumentation(*function, *(inst_it->get()))) continue; |
| |
| if (module_.max_instrumentations_count_ != 0 && instrumentations_count_ >= module_.max_instrumentations_count_) { |
| return true; // hit limit |
| } |
| instrumentations_count_++; |
| |
| // Add any debug information to pass into the function call |
| InjectionData injection_data; |
| injection_data.stage_info_id = GetStageInfo(*function, block_it, inst_it); |
| const uint32_t inst_position = target_instruction_->position_index_; |
| auto inst_position_constant = module_.type_manager_.CreateConstantUInt32(inst_position); |
| injection_data.inst_position_id = inst_position_constant.Id(); |
| |
| // inst_it is updated to the instruction after the new function call, it will not add/remove any Blocks |
| CreateFunctionCall(**block_it, &inst_it, injection_data); |
| Reset(); |
| } |
| } |
| } |
| |
| return instrumentations_count_ != 0; |
| } |
| |
| } // namespace spirv |
| } // namespace gpuav |