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