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