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