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