| 55 | } |
| 56 | |
| 57 | Reducer::ReductionResultStatus Reducer::Run( |
| 58 | const std::vector<uint32_t>& binary_in, std::vector<uint32_t>* binary_out, |
| 59 | spv_const_reducer_options options, |
| 60 | spv_validator_options validator_options) { |
| 61 | std::vector<uint32_t> current_binary(binary_in); |
| 62 | |
| 63 | spvtools::SpirvTools tools(target_env_); |
| 64 | assert(tools.IsValid() && "Failed to create SPIRV-Tools interface"); |
| 65 | |
| 66 | // Keeps track of how many reduction attempts have been tried. Reduction |
| 67 | // bails out if this reaches a given limit. |
| 68 | uint32_t reductions_applied = 0; |
| 69 | |
| 70 | // Initial state should be valid. |
| 71 | if (!tools.Validate(¤t_binary[0], current_binary.size(), |
| 72 | validator_options)) { |
| 73 | consumer_(SPV_MSG_INFO, nullptr, {}, |
| 74 | "Initial binary is invalid; stopping."); |
| 75 | return Reducer::ReductionResultStatus::kInitialStateInvalid; |
| 76 | } |
| 77 | |
| 78 | // Initial state should be interesting. |
| 79 | if (!interestingness_function_(current_binary, reductions_applied)) { |
| 80 | consumer_(SPV_MSG_INFO, nullptr, {}, |
| 81 | "Initial state was not interesting; stopping."); |
| 82 | return Reducer::ReductionResultStatus::kInitialStateNotInteresting; |
| 83 | } |
| 84 | |
| 85 | Reducer::ReductionResultStatus result = |
| 86 | RunPasses(&passes_, options, validator_options, tools, ¤t_binary, |
| 87 | &reductions_applied); |
| 88 | |
| 89 | if (result == Reducer::ReductionResultStatus::kComplete) { |
| 90 | // Cleanup passes. |
| 91 | result = RunPasses(&cleanup_passes_, options, validator_options, tools, |
| 92 | ¤t_binary, &reductions_applied); |
| 93 | } |
| 94 | |
| 95 | if (result == Reducer::ReductionResultStatus::kComplete) { |
| 96 | consumer_(SPV_MSG_INFO, nullptr, {}, "No more to reduce; stopping."); |
| 97 | } |
| 98 | |
| 99 | // Even if the reduction has failed by this point (e.g. due to producing an |
| 100 | // invalid binary), we still update the output binary for better debugging. |
| 101 | *binary_out = std::move(current_binary); |
| 102 | |
| 103 | return result; |
| 104 | } |
| 105 | |
| 106 | void Reducer::AddDefaultReductionPasses() { |
| 107 | AddReductionPass( |