| 1009 | } // namespace |
| 1010 | |
| 1011 | spv_result_t ValidateFloatControls2(ValidationState_t& _) { |
| 1012 | std::unordered_set<uint32_t> fp_fast_math_default_entry_points; |
| 1013 | for (auto entry_point : _.entry_points()) { |
| 1014 | const auto* exec_modes = _.GetExecutionModes(entry_point); |
| 1015 | if (exec_modes && |
| 1016 | exec_modes->count(spv::ExecutionMode::FPFastMathDefault)) { |
| 1017 | fp_fast_math_default_entry_points.insert(entry_point); |
| 1018 | } |
| 1019 | } |
| 1020 | |
| 1021 | std::vector<std::pair<const Instruction*, spv::Decoration>> worklist; |
| 1022 | for (const auto& inst : _.ordered_instructions()) { |
| 1023 | if (inst.opcode() != spv::Op::OpDecorate) { |
| 1024 | continue; |
| 1025 | } |
| 1026 | |
| 1027 | const auto decoration = inst.GetOperandAs<spv::Decoration>(1); |
| 1028 | const auto target_id = inst.GetOperandAs<uint32_t>(0); |
| 1029 | const auto target = _.FindDef(target_id); |
| 1030 | if (decoration == spv::Decoration::NoContraction) { |
| 1031 | worklist.push_back(std::make_pair(target, decoration)); |
| 1032 | } else if (decoration == spv::Decoration::FPFastMathMode) { |
| 1033 | auto mask = inst.GetOperandAs<spv::FPFastMathModeMask>(2); |
| 1034 | if ((mask & spv::FPFastMathModeMask::Fast) != |
| 1035 | spv::FPFastMathModeMask::MaskNone) { |
| 1036 | worklist.push_back(std::make_pair(target, decoration)); |
| 1037 | } |
| 1038 | } |
| 1039 | } |
| 1040 | |
| 1041 | std::unordered_set<const Instruction*> visited; |
| 1042 | while (!worklist.empty()) { |
| 1043 | const auto inst = worklist.back().first; |
| 1044 | const auto decoration = worklist.back().second; |
| 1045 | worklist.pop_back(); |
| 1046 | |
| 1047 | if (!visited.insert(inst).second) { |
| 1048 | continue; |
| 1049 | } |
| 1050 | |
| 1051 | const auto function = inst->function(); |
| 1052 | if (function) { |
| 1053 | const auto& entry_points = _.FunctionEntryPoints(function->id()); |
| 1054 | for (auto entry_point : entry_points) { |
| 1055 | if (fp_fast_math_default_entry_points.count(entry_point)) { |
| 1056 | const std::string dec = decoration == spv::Decoration::NoContraction |
| 1057 | ? "NoContraction" |
| 1058 | : "FPFastMathMode Fast"; |
| 1059 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 1060 | << dec |
| 1061 | << " cannot be used by an entry point with the " |
| 1062 | "FPFastMathDefault execution mode"; |
| 1063 | } |
| 1064 | } |
| 1065 | } else { |
| 1066 | for (const auto& pair : inst->uses()) { |
| 1067 | worklist.push_back(std::make_pair(pair.first, decoration)); |
| 1068 | } |
no test coverage detected