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