• 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_ASSEMBLER_ANNOTATION_H_
17 #define PANDA_ASSEMBLER_ANNOTATION_H_
18 
19 #include <cstddef>
20 #include <memory>
21 #include <string>
22 #include <string_view>
23 #include <type_traits>
24 #include <variant>
25 #include <vector>
26 
27 #include "assembly-type.h"
28 #include "macros.h"
29 
30 namespace panda::pandasm {
31 
32 class AnnotationElement;
33 
34 class AnnotationData {
35 public:
AnnotationData(std::string_view record_name,std::vector<AnnotationElement> elements)36     AnnotationData(std::string_view record_name, std::vector<AnnotationElement> elements)
37         : record_name_(record_name), elements_(std::move(elements))
38     {
39     }
40 
AnnotationData(std::string_view record_name)41     explicit AnnotationData(std::string_view record_name) : record_name_(record_name) {}
42 
43     DEFAULT_MOVE_SEMANTIC(AnnotationData);
44     DEFAULT_COPY_SEMANTIC(AnnotationData);
45 
46     ~AnnotationData() = default;
47 
GetName()48     std::string GetName() const
49     {
50         return record_name_;
51     }
52 
GetElements()53     const std::vector<AnnotationElement> &GetElements() const
54     {
55         return elements_;
56     }
57 
AddElement(AnnotationElement && element)58     void AddElement(AnnotationElement &&element)
59     {
60         elements_.push_back(std::forward<AnnotationElement>(element));
61     }
62 
63 private:
64     std::string record_name_;
65     std::vector<AnnotationElement> elements_;
66 };
67 
68 class ScalarValue;
69 class ArrayValue;
70 
71 class Value {
72 public:
73     enum class Type {
74         U1,
75         I8,
76         U8,
77         I16,
78         U16,
79         I32,
80         U32,
81         I64,
82         U64,
83         F32,
84         F64,
85         STRING,
86         STRING_NULLPTR,
87         RECORD,
88         METHOD,
89         ENUM,
90         ANNOTATION,
91         ARRAY,
92         VOID,
93         METHOD_HANDLE,
94         UNKNOWN
95     };
96 
97     // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_FUNCTION_SIZE)
GetTypeAsChar(Type t)98     static constexpr char GetTypeAsChar(Type t)
99     {
100         char type = '0';
101         switch (t) {
102             case Type::U1:
103                 type = '1';
104                 break;
105             case Type::I8:
106                 type = '2';
107                 break;
108             case Type::U8:
109                 type = '3';
110                 break;
111             case Type::I16:
112                 type = '4';
113                 break;
114             case Type::U16:
115                 type = '5';
116                 break;
117             case Type::I32:
118                 type = '6';
119                 break;
120             case Type::U32:
121                 type = '7';
122                 break;
123             case Type::I64:
124                 type = '8';
125                 break;
126             case Type::U64:
127                 type = '9';
128                 break;
129             case Type::F32:
130                 type = 'A';
131                 break;
132             case Type::F64:
133                 type = 'B';
134                 break;
135             case Type::STRING:
136                 type = 'C';
137                 break;
138             case Type::RECORD:
139                 type = 'D';
140                 break;
141             case Type::METHOD:
142                 type = 'E';
143                 break;
144             case Type::ENUM:
145                 type = 'F';
146                 break;
147             case Type::ANNOTATION:
148                 type = 'G';
149                 break;
150             case Type::ARRAY:
151                 type = 'H';
152                 break;
153             case Type::VOID:
154                 type = 'I';
155                 break;
156             case Type::METHOD_HANDLE:
157                 type = 'J';
158                 break;
159             case Type::STRING_NULLPTR:
160                 type = '*';
161                 break;
162             case Type::UNKNOWN:
163             default:
164                 type = '0';
165                 break;
166         }
167         return type;
168     }
169 
170     // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_FUNCTION_SIZE)
GetArrayTypeAsChar(Type t)171     static constexpr char GetArrayTypeAsChar(Type t)
172     {
173         char type = '0';
174         switch (t) {
175             case Type::U1:
176                 type = 'K';
177                 break;
178             case Type::I8:
179                 type = 'L';
180                 break;
181             case Type::U8:
182                 type = 'M';
183                 break;
184             case Type::I16:
185                 type = 'N';
186                 break;
187             case Type::U16:
188                 type = 'O';
189                 break;
190             case Type::I32:
191                 type = 'P';
192                 break;
193             case Type::U32:
194                 type = 'Q';
195                 break;
196             case Type::I64:
197                 type = 'R';
198                 break;
199             case Type::U64:
200                 type = 'S';
201                 break;
202             case Type::F32:
203                 type = 'T';
204                 break;
205             case Type::F64:
206                 type = 'U';
207                 break;
208             case Type::STRING:
209                 type = 'V';
210                 break;
211             case Type::RECORD:
212                 type = 'W';
213                 break;
214             case Type::METHOD:
215                 type = 'X';
216                 break;
217             case Type::ENUM:
218                 type = 'Y';
219                 break;
220             case Type::ANNOTATION:
221                 type = 'Z';
222                 break;
223             case Type::METHOD_HANDLE:
224                 type = '@';
225                 break;
226             case Type::UNKNOWN:
227             default:
228                 type = '0';
229                 break;
230         }
231         return type;
232     }
233 
234     // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_FUNCTION_SIZE)
GetCharAsType(char c)235     static constexpr Type GetCharAsType(char c)
236     {
237         Type type = Type::UNKNOWN;
238         switch (c) {
239             case '1':
240                 type = Type::U1;
241                 break;
242             case '2':
243                 type = Type::I8;
244                 break;
245             case '3':
246                 type = Type::U8;
247                 break;
248             case '4':
249                 type = Type::I16;
250                 break;
251             case '5':
252                 type = Type::U16;
253                 break;
254             case '6':
255                 type = Type::I32;
256                 break;
257             case '7':
258                 type = Type::U32;
259                 break;
260             case '8':
261                 type = Type::I64;
262                 break;
263             case '9':
264                 type = Type::U64;
265                 break;
266             case 'A':
267                 type = Type::F32;
268                 break;
269             case 'B':
270                 type = Type::F64;
271                 break;
272             case 'C':
273                 type = Type::STRING;
274                 break;
275             case 'D':
276                 type = Type::RECORD;
277                 break;
278             case 'E':
279                 type = Type::METHOD;
280                 break;
281             case 'F':
282                 type = Type::ENUM;
283                 break;
284             case 'G':
285                 type = Type::ANNOTATION;
286                 break;
287             case 'H':
288                 type = Type::ARRAY;
289                 break;
290             case 'I':
291                 type = Type::VOID;
292                 break;
293             case 'J':
294                 type = Type::METHOD_HANDLE;
295                 break;
296             case '*':
297                 type = Type::STRING_NULLPTR;
298                 break;
299             case '0':
300             default:
301                 type = Type::UNKNOWN;
302                 break;
303         }
304         return type;
305     }
306 
307     // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_FUNCTION_SIZE)
GetCharAsArrayType(char c)308     static constexpr Type GetCharAsArrayType(char c)
309     {
310         Type type = Type::UNKNOWN;
311         switch (c) {
312             case 'K':
313                 type = Type::U1;
314                 break;
315             case 'L':
316                 type = Type::I8;
317                 break;
318             case 'M':
319                 type = Type::U8;
320                 break;
321             case 'N':
322                 type = Type::I16;
323                 break;
324             case 'O':
325                 type = Type::U16;
326                 break;
327             case 'P':
328                 type = Type::I32;
329                 break;
330             case 'Q':
331                 type = Type::U32;
332                 break;
333             case 'R':
334                 type = Type::I64;
335                 break;
336             case 'S':
337                 type = Type::U64;
338                 break;
339             case 'T':
340                 type = Type::F32;
341                 break;
342             case 'U':
343                 type = Type::F64;
344                 break;
345             case 'V':
346                 type = Type::STRING;
347                 break;
348             case 'W':
349                 type = Type::RECORD;
350                 break;
351             case 'X':
352                 type = Type::METHOD;
353                 break;
354             case 'Y':
355                 type = Type::ENUM;
356                 break;
357             case 'Z':
358                 type = Type::ANNOTATION;
359                 break;
360             case '@':
361                 type = Type::METHOD_HANDLE;
362                 break;
363             case '0':
364             default:
365                 type = Type::UNKNOWN;
366                 break;
367         }
368         return type;
369     }
370 
GetType()371     Type GetType() const
372     {
373         return type_;
374     }
375 
IsArray()376     bool IsArray() const
377     {
378         return type_ == Type::ARRAY;
379     }
380 
381     ScalarValue *GetAsScalar();
382 
383     const ScalarValue *GetAsScalar() const;
384 
385     ArrayValue *GetAsArray();
386 
387     const ArrayValue *GetAsArray() const;
388 
389     virtual ~Value() = default;
390 
391     DEFAULT_COPY_SEMANTIC(Value);
392     DEFAULT_MOVE_SEMANTIC(Value);
393 
394 protected:
Value(Type type)395     explicit Value(Type type) : type_(type) {}
396 
397 private:
398     Type type_;
399 };
400 
401 // clang-format off
402 
403 template <Value::Type value_type>
404 struct ValueTypeHelper {
405     // Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=40640
406     // NOLINTNEXTLINE(readability-magic-numbers)
407     using type = std::conditional_t<value_type == Value::Type::U1, uint8_t,
408                 // NOLINTNEXTLINE(readability-magic-numbers)
409                 std::conditional_t<value_type == Value::Type::I8, int8_t,
410                 // NOLINTNEXTLINE(readability-magic-numbers)
411                 std::conditional_t<value_type == Value::Type::U8, uint8_t,
412                 // NOLINTNEXTLINE(readability-magic-numbers)
413                 std::conditional_t<value_type == Value::Type::I16, int16_t,
414                 // NOLINTNEXTLINE(readability-magic-numbers)
415                 std::conditional_t<value_type == Value::Type::U16, uint16_t,
416                 // NOLINTNEXTLINE(readability-magic-numbers)
417                 std::conditional_t<value_type == Value::Type::I32, int32_t,
418                 // NOLINTNEXTLINE(readability-magic-numbers)
419                 std::conditional_t<value_type == Value::Type::U32, uint32_t,
420                 // NOLINTNEXTLINE(readability-magic-numbers)
421                 std::conditional_t<value_type == Value::Type::I64, int64_t,
422                 // NOLINTNEXTLINE(readability-magic-numbers)
423                 std::conditional_t<value_type == Value::Type::U64, uint64_t,
424                 // NOLINTNEXTLINE(readability-magic-numbers)
425                 std::conditional_t<value_type == Value::Type::F32, float,
426                 // NOLINTNEXTLINE(readability-magic-numbers)
427                 std::conditional_t<value_type == Value::Type::F64, double,
428                 // NOLINTNEXTLINE(readability-magic-numbers)
429                 std::conditional_t<value_type == Value::Type::STRING, std::string_view,
430                 // NOLINTNEXTLINE(readability-magic-numbers)
431                 std::conditional_t<value_type == Value::Type::STRING_NULLPTR, uint32_t,
432                 // NOLINTNEXTLINE(readability-magic-numbers)
433                 std::conditional_t<value_type == Value::Type::RECORD, pandasm::Type,
434                 // NOLINTNEXTLINE(readability-magic-numbers)
435                 std::conditional_t<value_type == Value::Type::METHOD, std::string_view,
436                 // NOLINTNEXTLINE(readability-magic-numbers)
437                 std::conditional_t<value_type == Value::Type::ENUM, std::string_view,
438                 // NOLINTNEXTLINE(readability-magic-numbers)
439                 std::conditional_t<value_type == Value::Type::ANNOTATION, AnnotationData,
440                 void>>>>>>>>>>>>>>>>>;
441 };
442 
443 // clang-format on
444 
445 template <Value::Type type>
446 using ValueTypeHelperT = typename ValueTypeHelper<type>::type;
447 
448 class ScalarValue : public Value {
449 public:
450     template <Value::Type type>
451     // Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=40640
452     // NOLINTNEXTLINE(readability-magic-numbers)
Create(ValueTypeHelperT<type> value)453     static ScalarValue Create(ValueTypeHelperT<type> value)
454     {
455         // NOLINTNEXTLINE(readability-magic-numbers)
456         using T = ValueTypeHelperT<type>;
457         // Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203
458         // NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements)
459         if constexpr (std::is_integral_v<T>) {  // NOLINT(bugprone-suspicious-semicolon)
460             // NOLINTNEXTLINE(readability-magic-numbers)
461             return ScalarValue(type, static_cast<uint64_t>(value));
462         }
463 
464         // NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements)
465         if constexpr (!std::is_integral_v<T>) {  // NOLINT(bugprone-suspicious-semicolon)
466             // NOLINTNEXTLINE(readability-magic-numbers)
467             return ScalarValue(type, value);
468         }
469     }
470 
471     template <class T>
GetValue()472     T GetValue() const
473     {
474         // Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203
475         // NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements)
476         if constexpr (std::is_integral_v<T>) {  // NOLINT(bugprone-suspicious-semicolon)
477             return static_cast<T>(std::get<uint64_t>(value_));
478         }
479 
480         // NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements)
481         if constexpr (!std::is_integral_v<T>) {  // NOLINT(bugprone-suspicious-semicolon)
482             return std::get<T>(value_);
483         }
484     }
485 
486     DEFAULT_MOVE_SEMANTIC(ScalarValue);
487     DEFAULT_COPY_SEMANTIC(ScalarValue);
488 
489     ~ScalarValue() override = default;
490 
491 private:
ScalarValue(Type type,uint64_t value)492     ScalarValue(Type type, uint64_t value) : Value(type), value_(value) {}
493 
ScalarValue(Type type,float value)494     ScalarValue(Type type, float value) : Value(type), value_(value) {}
495 
ScalarValue(Type type,double value)496     ScalarValue(Type type, double value) : Value(type), value_(value) {}
497 
ScalarValue(Type type,std::string_view value)498     ScalarValue(Type type, std::string_view value) : Value(type), value_(std::string(value)) {}
499 
ScalarValue(Type type,pandasm::Type value)500     ScalarValue(Type type, pandasm::Type value) : Value(type), value_(std::move(value)) {}
501 
ScalarValue(Type type,const AnnotationData & value)502     ScalarValue(Type type, const AnnotationData &value) : Value(type), value_(value) {}
503 
504     std::variant<uint64_t, float, double, std::string, pandasm::Type, AnnotationData> value_;
505 };
506 
507 class ArrayValue : public Value {
508 public:
ArrayValue(Type component_type,std::vector<ScalarValue> values)509     ArrayValue(Type component_type, std::vector<ScalarValue> values)
510         : Value(Type::ARRAY), component_type_(component_type), values_(std::move(values))
511     {
512     }
513 
514     DEFAULT_MOVE_SEMANTIC(ArrayValue);
515     DEFAULT_COPY_SEMANTIC(ArrayValue);
516 
517     ~ArrayValue() override = default;
518 
GetValues()519     const std::vector<ScalarValue> &GetValues() const
520     {
521         return values_;
522     }
523 
GetComponentType()524     Type GetComponentType() const
525     {
526         return component_type_;
527     }
528 
529 private:
530     Type component_type_;
531     std::vector<ScalarValue> values_;
532 };
533 
534 class AnnotationElement {
535 public:
AnnotationElement(std::string_view name,std::unique_ptr<Value> value)536     AnnotationElement(std::string_view name, std::unique_ptr<Value> value) : name_(name), value_(std::move(value)) {}
537 
538     AnnotationElement(const AnnotationElement &ann_elem);
539     AnnotationElement &operator=(const AnnotationElement &ann_elem);
540     DEFAULT_MOVE_SEMANTIC(AnnotationElement);
541     ~AnnotationElement() = default;
542 
GetName()543     std::string GetName() const
544     {
545         return name_;
546     }
547 
GetValue()548     Value *GetValue() const
549     {
550         return value_.get();
551     }
552 
553     static std::string TypeToString(Value::Type type);
554 
555 private:
556     std::string name_;
557     std::unique_ptr<Value> value_;
558 };
559 
560 }  // namespace panda::pandasm
561 
562 #endif  // PANDA_ASSEMBLER_ANNOTATION_H_
563