1 /* 2 * Copyright (c) 2021 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 #include "macros.h" 29 30 namespace panda::pandasm { 31 32 class AnnotationElement; 33 34 class AnnotationData { 35 public: AnnotationData(std::string_view record_name,std::vector<AnnotationElement> elements)36 AnnotationData(std::string_view record_name, std::vector<AnnotationElement> elements) 37 : record_name_(record_name), elements_(std::move(elements)) 38 { 39 } 40 AnnotationData(std::string_view record_name)41 explicit AnnotationData(std::string_view record_name) : record_name_(record_name) {} 42 43 DEFAULT_MOVE_SEMANTIC(AnnotationData); 44 DEFAULT_COPY_SEMANTIC(AnnotationData); 45 46 ~AnnotationData() = default; 47 GetName()48 std::string GetName() const 49 { 50 return record_name_; 51 } 52 GetElements()53 const std::vector<AnnotationElement> &GetElements() const 54 { 55 return elements_; 56 } 57 AddElement(AnnotationElement && element)58 void AddElement(AnnotationElement &&element) 59 { 60 elements_.push_back(std::forward<AnnotationElement>(element)); 61 } 62 63 private: 64 std::string record_name_; 65 std::vector<AnnotationElement> elements_; 66 }; 67 68 class ScalarValue; 69 class ArrayValue; 70 71 class Value { 72 public: 73 enum class Type { 74 U1, 75 I8, 76 U8, 77 I16, 78 U16, 79 I32, 80 U32, 81 I64, 82 U64, 83 F32, 84 F64, 85 STRING, 86 STRING_NULLPTR, 87 RECORD, 88 METHOD, 89 ENUM, 90 ANNOTATION, 91 ARRAY, 92 VOID, 93 METHOD_HANDLE, 94 UNKNOWN 95 }; 96 97 // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_FUNCTION_SIZE) 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 break; 166 } 167 return type; 168 } 169 170 // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_FUNCTION_SIZE) GetArrayTypeAsChar(Type t)171 static constexpr char GetArrayTypeAsChar(Type t) 172 { 173 char type = '0'; 174 switch (t) { 175 case Type::U1: 176 type = 'K'; 177 break; 178 case Type::I8: 179 type = 'L'; 180 break; 181 case Type::U8: 182 type = 'M'; 183 break; 184 case Type::I16: 185 type = 'N'; 186 break; 187 case Type::U16: 188 type = 'O'; 189 break; 190 case Type::I32: 191 type = 'P'; 192 break; 193 case Type::U32: 194 type = 'Q'; 195 break; 196 case Type::I64: 197 type = 'R'; 198 break; 199 case Type::U64: 200 type = 'S'; 201 break; 202 case Type::F32: 203 type = 'T'; 204 break; 205 case Type::F64: 206 type = 'U'; 207 break; 208 case Type::STRING: 209 type = 'V'; 210 break; 211 case Type::RECORD: 212 type = 'W'; 213 break; 214 case Type::METHOD: 215 type = 'X'; 216 break; 217 case Type::ENUM: 218 type = 'Y'; 219 break; 220 case Type::ANNOTATION: 221 type = 'Z'; 222 break; 223 case Type::METHOD_HANDLE: 224 type = '@'; 225 break; 226 case Type::UNKNOWN: 227 default: 228 type = '0'; 229 break; 230 } 231 return type; 232 } 233 234 // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_FUNCTION_SIZE) GetCharAsType(char c)235 static constexpr Type GetCharAsType(char c) 236 { 237 Type type = Type::UNKNOWN; 238 switch (c) { 239 case '1': 240 type = Type::U1; 241 break; 242 case '2': 243 type = Type::I8; 244 break; 245 case '3': 246 type = Type::U8; 247 break; 248 case '4': 249 type = Type::I16; 250 break; 251 case '5': 252 type = Type::U16; 253 break; 254 case '6': 255 type = Type::I32; 256 break; 257 case '7': 258 type = Type::U32; 259 break; 260 case '8': 261 type = Type::I64; 262 break; 263 case '9': 264 type = Type::U64; 265 break; 266 case 'A': 267 type = Type::F32; 268 break; 269 case 'B': 270 type = Type::F64; 271 break; 272 case 'C': 273 type = Type::STRING; 274 break; 275 case 'D': 276 type = Type::RECORD; 277 break; 278 case 'E': 279 type = Type::METHOD; 280 break; 281 case 'F': 282 type = Type::ENUM; 283 break; 284 case 'G': 285 type = Type::ANNOTATION; 286 break; 287 case 'H': 288 type = Type::ARRAY; 289 break; 290 case 'I': 291 type = Type::VOID; 292 break; 293 case 'J': 294 type = Type::METHOD_HANDLE; 295 break; 296 case '*': 297 type = Type::STRING_NULLPTR; 298 break; 299 case '0': 300 default: 301 type = Type::UNKNOWN; 302 break; 303 } 304 return type; 305 } 306 307 // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_FUNCTION_SIZE) 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 break; 367 } 368 return type; 369 } 370 GetType()371 Type GetType() const 372 { 373 return type_; 374 } 375 IsArray()376 bool IsArray() const 377 { 378 return type_ == Type::ARRAY; 379 } 380 381 ScalarValue *GetAsScalar(); 382 383 const ScalarValue *GetAsScalar() const; 384 385 ArrayValue *GetAsArray(); 386 387 const ArrayValue *GetAsArray() const; 388 389 virtual ~Value() = default; 390 391 DEFAULT_COPY_SEMANTIC(Value); 392 DEFAULT_MOVE_SEMANTIC(Value); 393 394 protected: Value(Type type)395 explicit Value(Type type) : type_(type) {} 396 397 private: 398 Type type_; 399 }; 400 401 // clang-format off 402 403 template <Value::Type value_type> 404 struct ValueTypeHelper { 405 // Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=40640 406 // NOLINTNEXTLINE(readability-magic-numbers) 407 using type = std::conditional_t<value_type == Value::Type::U1, uint8_t, 408 // NOLINTNEXTLINE(readability-magic-numbers) 409 std::conditional_t<value_type == Value::Type::I8, int8_t, 410 // NOLINTNEXTLINE(readability-magic-numbers) 411 std::conditional_t<value_type == Value::Type::U8, uint8_t, 412 // NOLINTNEXTLINE(readability-magic-numbers) 413 std::conditional_t<value_type == Value::Type::I16, int16_t, 414 // NOLINTNEXTLINE(readability-magic-numbers) 415 std::conditional_t<value_type == Value::Type::U16, uint16_t, 416 // NOLINTNEXTLINE(readability-magic-numbers) 417 std::conditional_t<value_type == Value::Type::I32, int32_t, 418 // NOLINTNEXTLINE(readability-magic-numbers) 419 std::conditional_t<value_type == Value::Type::U32, uint32_t, 420 // NOLINTNEXTLINE(readability-magic-numbers) 421 std::conditional_t<value_type == Value::Type::I64, int64_t, 422 // NOLINTNEXTLINE(readability-magic-numbers) 423 std::conditional_t<value_type == Value::Type::U64, uint64_t, 424 // NOLINTNEXTLINE(readability-magic-numbers) 425 std::conditional_t<value_type == Value::Type::F32, float, 426 // NOLINTNEXTLINE(readability-magic-numbers) 427 std::conditional_t<value_type == Value::Type::F64, double, 428 // NOLINTNEXTLINE(readability-magic-numbers) 429 std::conditional_t<value_type == Value::Type::STRING, std::string_view, 430 // NOLINTNEXTLINE(readability-magic-numbers) 431 std::conditional_t<value_type == Value::Type::STRING_NULLPTR, uint32_t, 432 // NOLINTNEXTLINE(readability-magic-numbers) 433 std::conditional_t<value_type == Value::Type::RECORD, pandasm::Type, 434 // NOLINTNEXTLINE(readability-magic-numbers) 435 std::conditional_t<value_type == Value::Type::METHOD, std::string_view, 436 // NOLINTNEXTLINE(readability-magic-numbers) 437 std::conditional_t<value_type == Value::Type::ENUM, std::string_view, 438 // NOLINTNEXTLINE(readability-magic-numbers) 439 std::conditional_t<value_type == Value::Type::ANNOTATION, AnnotationData, 440 void>>>>>>>>>>>>>>>>>; 441 }; 442 443 // clang-format on 444 445 template <Value::Type type> 446 using ValueTypeHelperT = typename ValueTypeHelper<type>::type; 447 448 class ScalarValue : public Value { 449 public: 450 template <Value::Type type> 451 // Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=40640 452 // NOLINTNEXTLINE(readability-magic-numbers) Create(ValueTypeHelperT<type> value)453 static ScalarValue Create(ValueTypeHelperT<type> value) 454 { 455 // NOLINTNEXTLINE(readability-magic-numbers) 456 using T = ValueTypeHelperT<type>; 457 // Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203 458 // NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements) 459 if constexpr (std::is_integral_v<T>) { // NOLINT(bugprone-suspicious-semicolon) 460 // NOLINTNEXTLINE(readability-magic-numbers) 461 return ScalarValue(type, static_cast<uint64_t>(value)); 462 } 463 464 // NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements) 465 if constexpr (!std::is_integral_v<T>) { // NOLINT(bugprone-suspicious-semicolon) 466 // NOLINTNEXTLINE(readability-magic-numbers) 467 return ScalarValue(type, value); 468 } 469 } 470 471 template <class T> GetValue()472 T GetValue() const 473 { 474 // Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203 475 // NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements) 476 if constexpr (std::is_integral_v<T>) { // NOLINT(bugprone-suspicious-semicolon) 477 return static_cast<T>(std::get<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 return std::get<T>(value_); 483 } 484 } 485 486 DEFAULT_MOVE_SEMANTIC(ScalarValue); 487 DEFAULT_COPY_SEMANTIC(ScalarValue); 488 489 ~ScalarValue() override = default; 490 491 private: ScalarValue(Type type,uint64_t value)492 ScalarValue(Type type, uint64_t value) : Value(type), value_(value) {} 493 ScalarValue(Type type,float value)494 ScalarValue(Type type, float value) : Value(type), value_(value) {} 495 ScalarValue(Type type,double value)496 ScalarValue(Type type, double value) : Value(type), value_(value) {} 497 ScalarValue(Type type,std::string_view value)498 ScalarValue(Type type, std::string_view value) : Value(type), value_(std::string(value)) {} 499 ScalarValue(Type type,pandasm::Type value)500 ScalarValue(Type type, pandasm::Type value) : Value(type), value_(std::move(value)) {} 501 ScalarValue(Type type,const AnnotationData & value)502 ScalarValue(Type type, const AnnotationData &value) : Value(type), value_(value) {} 503 504 std::variant<uint64_t, float, double, std::string, pandasm::Type, AnnotationData> value_; 505 }; 506 507 class ArrayValue : public Value { 508 public: ArrayValue(Type component_type,std::vector<ScalarValue> values)509 ArrayValue(Type component_type, std::vector<ScalarValue> values) 510 : Value(Type::ARRAY), component_type_(component_type), values_(std::move(values)) 511 { 512 } 513 514 DEFAULT_MOVE_SEMANTIC(ArrayValue); 515 DEFAULT_COPY_SEMANTIC(ArrayValue); 516 517 ~ArrayValue() override = default; 518 GetValues()519 const std::vector<ScalarValue> &GetValues() const 520 { 521 return values_; 522 } 523 GetComponentType()524 Type GetComponentType() const 525 { 526 return component_type_; 527 } 528 529 private: 530 Type component_type_; 531 std::vector<ScalarValue> values_; 532 }; 533 534 class AnnotationElement { 535 public: AnnotationElement(std::string_view name,std::unique_ptr<Value> value)536 AnnotationElement(std::string_view name, std::unique_ptr<Value> value) : name_(name), value_(std::move(value)) {} 537 538 AnnotationElement(const AnnotationElement &ann_elem); 539 AnnotationElement &operator=(const AnnotationElement &ann_elem); 540 DEFAULT_MOVE_SEMANTIC(AnnotationElement); 541 ~AnnotationElement() = default; 542 GetName()543 std::string GetName() const 544 { 545 return name_; 546 } 547 GetValue()548 Value *GetValue() const 549 { 550 return value_.get(); 551 } 552 553 static std::string TypeToString(Value::Type type); 554 555 private: 556 std::string name_; 557 std::unique_ptr<Value> value_; 558 }; 559 560 } // namespace panda::pandasm 561 562 #endif // PANDA_ASSEMBLER_ANNOTATION_H_ 563