• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 "verification/util/flags.h"
20 #include "verification/util/saturated_enum.h"
21 #include "verifier_messages.h"
22 
23 #include <functional>
24 
25 namespace panda::verifier {
26 
27 struct MethodOption {
28     enum class InfoType { CONTEXT, REG_CHANGES, CFLOW, JOBFILL };
29     enum class MsgClass { ERROR, WARNING, HIDDEN };
30     enum class CheckType { CFLOW, RESOLVE_ID, REG_USAGE, TYPING, ABSINT };
31     using InfoTypeFlag =
32         FlagsForEnum<unsigned, InfoType, InfoType::CONTEXT, InfoType::REG_CHANGES, InfoType::CFLOW, InfoType::JOBFILL>;
33     using MsgClassFlag = FlagsForEnum<unsigned, MsgClass, MsgClass::ERROR, MsgClass::WARNING, MsgClass::HIDDEN>;
34     using CheckEnum = SaturatedEnum<CheckType, CheckType::ABSINT, CheckType::TYPING, CheckType::REG_USAGE,
35                                     CheckType::RESOLVE_ID, CheckType::CFLOW>;
36 };
37 
38 class MethodOptions {
39 public:
ShowContext()40     bool ShowContext() const
41     {
42         return ShowInfo[MethodOption::InfoType::CONTEXT];
43     }
44 
ShowRegChanges()45     bool ShowRegChanges() const
46     {
47         return ShowInfo[MethodOption::InfoType::REG_CHANGES];
48     }
49 
ShowCflow()50     bool ShowCflow() const
51     {
52         return ShowInfo[MethodOption::InfoType::CFLOW];
53     }
54 
ShowJobFill()55     bool ShowJobFill() const
56     {
57         return ShowInfo[MethodOption::InfoType::JOBFILL];
58     }
59 
SetShow(MethodOption::InfoType info)60     void SetShow(MethodOption::InfoType info)
61     {
62         ShowInfo[info] = true;
63     }
64 
SetMsgClass(VerifierMessage msg_num,MethodOption::MsgClass klass)65     void SetMsgClass(VerifierMessage msg_num, MethodOption::MsgClass klass)
66     {
67         msg_classes[msg_num][klass] = true;
68     }
69 
70     template <typename Validator>
SetMsgClass(Validator validator,size_t msg_num,MethodOption::MsgClass klass)71     void SetMsgClass(Validator validator, size_t msg_num, MethodOption::MsgClass klass)
72     {
73         if (validator(static_cast<VerifierMessage>(msg_num))) {
74             msg_classes[static_cast<VerifierMessage>(msg_num)][klass] = true;
75         }
76     }
77 
AddUpLevel(const MethodOptions & up)78     void AddUpLevel(const MethodOptions &up)
79     {
80         uplevel.push_back(std::cref(up));
81     }
82 
CanHandleMsg(VerifierMessage msg_num)83     bool CanHandleMsg(VerifierMessage msg_num) const
84     {
85         return msg_classes.count(msg_num) > 0;
86     }
87 
IsInMsgClass(VerifierMessage msg_num,MethodOption::MsgClass klass)88     bool IsInMsgClass(VerifierMessage msg_num, MethodOption::MsgClass klass) const
89     {
90         if (msg_classes.count(msg_num) > 0) {
91             return msg_classes.at(msg_num)[klass];
92         }
93         for (const auto &up : uplevel) {
94             if (up.get().CanHandleMsg(msg_num)) {
95                 return up.get().IsInMsgClass(msg_num, klass);
96             }
97         }
98         return false;
99     }
100 
101     template <typename Handler>
IfInMsgClassThen(VerifierMessage msg_num,MethodOption::MsgClass klass,Handler && handler)102     void IfInMsgClassThen(VerifierMessage msg_num, MethodOption::MsgClass klass, Handler &&handler) const
103     {
104         if (IsInMsgClass(msg_num, klass)) {
105             handler();
106         }
107     }
108 
109     template <typename Handler>
IfNotInMsgClassThen(VerifierMessage msg_num,MethodOption::MsgClass klass,Handler && handler)110     void IfNotInMsgClassThen(VerifierMessage msg_num, MethodOption::MsgClass klass, Handler &&handler) const
111     {
112         if (!IsInMsgClass(msg_num, klass)) {
113             handler();
114         }
115     }
116 
117     class Proxy {
118     public:
Proxy(VerifierMessage mess_num,const MethodOptions & method_opts)119         Proxy(VerifierMessage mess_num, const MethodOptions &method_opts) : num {mess_num}, opts {method_opts} {}
120         Proxy() = delete;
121         Proxy(const Proxy &) = delete;
122         Proxy(Proxy &&) = delete;
123         ~Proxy() = default;
124 
IsError()125         bool IsError() const
126         {
127             return Is(MethodOption::MsgClass::ERROR);
128         }
129 
IsNotError()130         bool IsNotError() const
131         {
132             return IsNot(MethodOption::MsgClass::ERROR);
133         }
134 
IsWarning()135         bool IsWarning() const
136         {
137             return Is(MethodOption::MsgClass::WARNING);
138         }
139 
IsNotWarning()140         bool IsNotWarning() const
141         {
142             return IsNot(MethodOption::MsgClass::WARNING);
143         }
144 
145         template <typename Handler>
IfError(Handler && handler)146         void IfError(Handler &&handler) const
147         {
148             opts.IfInMsgClassThen(num, MethodOption::MsgClass::ERROR, std::move(handler));
149         }
150 
151         template <typename Handler>
IfNotError(Handler && handler)152         void IfNotError(Handler &&handler) const
153         {
154             opts.IfNotInMsgClassThen(num, MethodOption::MsgClass::ERROR, std::move(handler));
155         }
156 
157         template <typename Handler>
IfWarning(Handler && handler)158         void IfWarning(Handler &&handler) const
159         {
160             opts.IfInMsgClassThen(num, MethodOption::MsgClass::WARNING, std::move(handler));
161         }
162 
163         template <typename Handler>
IfNotWarning(Handler && handler)164         void IfNotWarning(Handler &&handler) const
165         {
166             opts.IfNotInMsgClassThen(num, MethodOption::MsgClass::WARNING, std::move(handler));
167         }
168 
169         template <typename Handler>
IfHidden(Handler && handler)170         void IfHidden(Handler &&handler) const
171         {
172             opts.IfInMsgClassThen(num, MethodOption::MsgClass::HIDDEN, std::move(handler));
173         }
174 
175         template <typename Handler>
IfNotHidden(Handler && handler)176         void IfNotHidden(Handler &&handler) const
177         {
178             opts.IfNotInMsgClassThen(num, MethodOption::MsgClass::HIDDEN, std::move(handler));
179         }
180 
Is(MethodOption::MsgClass klass)181         bool Is(MethodOption::MsgClass klass) const
182         {
183             return opts.IsInMsgClass(num, klass);
184         }
185 
IsNot(MethodOption::MsgClass klass)186         bool IsNot(MethodOption::MsgClass klass) const
187         {
188             return !opts.IsInMsgClass(num, klass);
189         }
190 
191         template <typename Handler>
If(MethodOption::MsgClass klass,Handler && handler)192         void If(MethodOption::MsgClass klass, Handler &&handler) const
193         {
194             opts.IfInMsgClassThen(num, klass, std::move(handler));
195         }
196 
197         template <typename Handler>
IfNot(MethodOption::MsgClass klass,Handler && handler)198         void IfNot(MethodOption::MsgClass klass, Handler &&handler) const
199         {
200             opts.IfNotInMsgClassThen(num, klass, std::move(handler));
201         }
202 
203     private:
204         const VerifierMessage num;
205         const MethodOptions &opts;
206     };
207 
Msg(VerifierMessage num)208     Proxy Msg(VerifierMessage num) const
209     {
210         return {num, *this};
211     }
212 
Image()213     PandaString Image() const
214     {
215         PandaString result {"\n"};
216         result += " Verifier messages config '" + name + "'\n";
217         result += "  Uplevel configs: ";
218         for (const auto &up : uplevel) {
219             result += "'" + up.get().name + "' ";
220         }
221         result += "\n";
222         result += "  Show: ";
223         ShowInfo.EnumerateFlags([&](auto flag) {
224             switch (flag) {
225                 case MethodOption::InfoType::CONTEXT:
226                     result += "'context' ";
227                     break;
228                 case MethodOption::InfoType::REG_CHANGES:
229                     result += "'reg-changes' ";
230                     break;
231                 case MethodOption::InfoType::CFLOW:
232                     result += "'cflow' ";
233                     break;
234                 case MethodOption::InfoType::JOBFILL:
235                     result += "'jobfill' ";
236                     break;
237                 default:
238                     result += "<unknown>(";
239                     result += static_cast<size_t>(flag);
240                     result += ") ";
241                     break;
242             }
243             return true;
244         });
245         result += "\n";
246         result += "  Checks: ";
247         EnabledCheck.EnumerateValues([&](auto flag) {
248             switch (flag) {
249                 case MethodOption::CheckType::TYPING:
250                     result += "'typing' ";
251                     break;
252                 case MethodOption::CheckType::ABSINT:
253                     result += "'absint' ";
254                     break;
255                 case MethodOption::CheckType::REG_USAGE:
256                     result += "'reg-usage' ";
257                     break;
258                 case MethodOption::CheckType::CFLOW:
259                     result += "'cflow' ";
260                     break;
261                 case MethodOption::CheckType::RESOLVE_ID:
262                     result += "'resolve-id' ";
263                     break;
264                 default:
265                     result += "<unknown>(";
266                     result += static_cast<size_t>(flag);
267                     result += ") ";
268                     break;
269             }
270             return true;
271         });
272 
273         result += "\n";
274         result += ImageMessages();
275         return result;
276     }
277 
MethodOptions(const PandaString & param_name)278     MethodOptions(const PandaString &param_name) : name {param_name} {}
279 
GetName()280     const PandaString &GetName() const
281     {
282         return name;
283     }
284 
Check()285     MethodOption::CheckEnum &Check()
286     {
287         return EnabledCheck;
288     }
289 
Check()290     const MethodOption::CheckEnum &Check() const
291     {
292         return EnabledCheck;
293     }
294 
295 private:
ImageMessages()296     PandaString ImageMessages() const
297     {
298         PandaString result;
299         result += "  Messages:\n";
300         for (const auto &m : msg_classes) {
301             const auto &msg_num = m.first;
302             const auto &klass = m.second;
303             result += "    ";
304             result += VerifierMessageToString(msg_num);
305             result += " : ";
306             klass.EnumerateFlags([&](auto flag) {
307                 switch (flag) {
308                     case MethodOption::MsgClass::ERROR:
309                         result += "E";
310                         break;
311                     case MethodOption::MsgClass::WARNING:
312                         result += "W";
313                         break;
314                     case MethodOption::MsgClass::HIDDEN:
315                         result += "H";
316                         break;
317                     default:
318                         result += "<unknown>(";
319                         result += static_cast<size_t>(flag);
320                         result += ")";
321                         break;
322                 }
323                 return true;
324             });
325             result += "\n";
326         }
327         return result;
328     }
329 
330     const PandaString name;
331     PandaVector<std::reference_wrapper<const MethodOptions>> uplevel;
332     PandaUnorderedMap<VerifierMessage, MethodOption::MsgClassFlag> msg_classes;
333     MethodOption::InfoTypeFlag ShowInfo;
334     MethodOption::CheckEnum EnabledCheck;
335 };
336 
337 }  // namespace panda::verifier
338 
339 #endif  //! PANDA_VERIFIER_DEBUG_OPTIONS_METHOD_OPTIONS_H_
340