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