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