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