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