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