1 /** 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef PANDA_VERIFIER_DEBUG_OPTIONS_METHOD_OPTIONS_H_ 17 #define PANDA_VERIFIER_DEBUG_OPTIONS_METHOD_OPTIONS_H_ 18 19 #include "runtime/include/mem/panda_containers.h" 20 #include "runtime/include/mem/panda_string.h" 21 #include "verification/util/flags.h" 22 #include "verification/util/saturated_enum.h" 23 #include "verifier_messages.h" 24 25 #include <functional> 26 27 namespace ark::verifier { 28 29 struct MethodOption { 30 enum class InfoType { CONTEXT, REG_CHANGES, CFLOW, JOBFILL }; 31 enum class MsgClass { ERROR, WARNING, HIDDEN }; 32 enum class CheckType { CFLOW, RESOLVE_ID, REG_USAGE, TYPING, ABSINT }; 33 using InfoTypeFlag = 34 FlagsForEnum<unsigned, InfoType, InfoType::CONTEXT, InfoType::REG_CHANGES, InfoType::CFLOW, InfoType::JOBFILL>; 35 using MsgClassFlag = FlagsForEnum<unsigned, MsgClass, MsgClass::ERROR, MsgClass::WARNING, MsgClass::HIDDEN>; 36 using CheckEnum = SaturatedEnum<CheckType, CheckType::ABSINT, CheckType::TYPING, CheckType::REG_USAGE, 37 CheckType::RESOLVE_ID, CheckType::CFLOW>; 38 }; 39 40 class MethodOptions { 41 public: ShowContext()42 bool ShowContext() const 43 { 44 return showInfo_[MethodOption::InfoType::CONTEXT]; 45 } 46 ShowRegChanges()47 bool ShowRegChanges() const 48 { 49 return showInfo_[MethodOption::InfoType::REG_CHANGES]; 50 } 51 ShowCflow()52 bool ShowCflow() const 53 { 54 return showInfo_[MethodOption::InfoType::CFLOW]; 55 } 56 ShowJobFill()57 bool ShowJobFill() const 58 { 59 return showInfo_[MethodOption::InfoType::JOBFILL]; 60 } 61 SetShow(MethodOption::InfoType info)62 void SetShow(MethodOption::InfoType info) 63 { 64 showInfo_[info] = true; 65 } 66 SetMsgClass(VerifierMessage msgNum,MethodOption::MsgClass klass)67 void SetMsgClass(VerifierMessage msgNum, MethodOption::MsgClass klass) 68 { 69 msgClasses_[msgNum] = klass; 70 } 71 72 template <typename Validator> SetMsgClass(Validator validator,size_t msgNum,MethodOption::MsgClass klass)73 void SetMsgClass(Validator validator, size_t msgNum, MethodOption::MsgClass klass) 74 { 75 if (validator(static_cast<VerifierMessage>(msgNum))) { 76 msgClasses_[static_cast<VerifierMessage>(msgNum)] = klass; 77 } 78 } 79 AddUpLevel(const MethodOptions & up)80 void AddUpLevel(const MethodOptions &up) 81 { 82 uplevel_.push_back(std::cref(up)); 83 } 84 CanHandleMsg(VerifierMessage msgNum)85 bool CanHandleMsg(VerifierMessage msgNum) const 86 { 87 return msgClasses_.count(msgNum) > 0; 88 } 89 90 MethodOption::MsgClass MsgClassFor(VerifierMessage msgNum) const; 91 IsInMsgClass(VerifierMessage msgNum,MethodOption::MsgClass klass)92 bool IsInMsgClass(VerifierMessage msgNum, MethodOption::MsgClass klass) const 93 { 94 return MsgClassFor(msgNum) == klass; 95 } 96 IsHidden(VerifierMessage msgNum)97 bool IsHidden(VerifierMessage msgNum) const 98 { 99 return IsInMsgClass(msgNum, MethodOption::MsgClass::HIDDEN); 100 } 101 IsWarning(VerifierMessage msgNum)102 bool IsWarning(VerifierMessage msgNum) const 103 { 104 return IsInMsgClass(msgNum, MethodOption::MsgClass::WARNING); 105 } 106 IsError(VerifierMessage msgNum)107 bool IsError(VerifierMessage msgNum) const 108 { 109 return IsInMsgClass(msgNum, MethodOption::MsgClass::ERROR); 110 } 111 112 template <typename Flag> EnumerateFlagsHandler(PandaString & result,Flag flag)113 static bool EnumerateFlagsHandler(PandaString &result, Flag flag) 114 { 115 switch (flag) { 116 case MethodOption::InfoType::CONTEXT: 117 result += "'context' "; 118 break; 119 case MethodOption::InfoType::REG_CHANGES: 120 result += "'reg-changes' "; 121 break; 122 case MethodOption::InfoType::CFLOW: 123 result += "'cflow' "; 124 break; 125 case MethodOption::InfoType::JOBFILL: 126 result += "'jobfill' "; 127 break; 128 default: 129 result += "<unknown>("; 130 result += std::to_string(static_cast<size_t>(flag)); 131 result += ") "; 132 break; 133 } 134 return true; 135 } 136 Image()137 PandaString Image() const 138 { 139 PandaString result {"\n"}; 140 result += " Verifier messages config '" + name_ + "'\n"; 141 result += " Uplevel configs: "; 142 for (const auto &up : uplevel_) { 143 result += "'" + up.get().name_ + "' "; 144 } 145 result += "\n"; 146 result += " Show: "; 147 showInfo_.EnumerateFlags([&](auto flag) { return MethodOptions::EnumerateFlagsHandler(result, flag); }); 148 result += "\n"; 149 result += " Checks: "; 150 enabledCheck_.EnumerateValues([&](auto flag) { 151 switch (flag) { 152 case MethodOption::CheckType::TYPING: 153 result += "'typing' "; 154 break; 155 case MethodOption::CheckType::ABSINT: 156 result += "'absint' "; 157 break; 158 case MethodOption::CheckType::REG_USAGE: 159 result += "'reg-usage' "; 160 break; 161 case MethodOption::CheckType::CFLOW: 162 result += "'cflow' "; 163 break; 164 case MethodOption::CheckType::RESOLVE_ID: 165 result += "'resolve-id' "; 166 break; 167 default: 168 result += "<unknown>("; 169 result += std::to_string(static_cast<size_t>(flag)); 170 result += ") "; 171 break; 172 } 173 return true; 174 }); 175 176 result += "\n"; 177 result += ImageMessages(); 178 return result; 179 } 180 MethodOptions(PandaString paramName)181 explicit MethodOptions(PandaString paramName) : name_ {std::move(paramName)} {} 182 GetName()183 const PandaString &GetName() const 184 { 185 return name_; 186 } 187 Check()188 MethodOption::CheckEnum &Check() 189 { 190 return enabledCheck_; 191 } 192 Check()193 const MethodOption::CheckEnum &Check() const 194 { 195 return enabledCheck_; 196 } 197 198 private: ImageMessages()199 PandaString ImageMessages() const 200 { 201 PandaString result; 202 result += " Messages:\n"; 203 for (const auto &m : msgClasses_) { 204 const auto &msgNum = m.first; 205 const auto &klass = m.second; 206 result += " "; 207 result += VerifierMessageToString(msgNum); 208 result += " : "; 209 switch (klass) { 210 case MethodOption::MsgClass::ERROR: 211 result += "E"; 212 break; 213 case MethodOption::MsgClass::WARNING: 214 result += "W"; 215 break; 216 case MethodOption::MsgClass::HIDDEN: 217 result += "H"; 218 break; 219 default: 220 result += "<unknown>("; 221 result += std::to_string(static_cast<size_t>(klass)); 222 result += ")"; 223 break; 224 } 225 result += "\n"; 226 } 227 return result; 228 } 229 230 const PandaString name_; 231 PandaVector<std::reference_wrapper<const MethodOptions>> uplevel_; 232 PandaUnorderedMap<VerifierMessage, MethodOption::MsgClass> msgClasses_; 233 MethodOption::InfoTypeFlag showInfo_; 234 MethodOption::CheckEnum enabledCheck_; 235 236 // In verifier_messages_data.cpp 237 struct VerifierMessageDefault { 238 VerifierMessage msg; 239 MethodOption::MsgClass msgClass; 240 }; 241 242 // NOLINTNEXTLINE(modernize-avoid-c-arrays) 243 static VerifierMessageDefault messageDefaults_[]; 244 }; 245 246 } // namespace ark::verifier 247 248 #endif // PANDA_VERIFIER_DEBUG_OPTIONS_METHOD_OPTIONS_H_ 249