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