1 // Copyright (C) 2017 The Android Open Source Project 2 // 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 #ifndef IR_ 15 #define IR_ 16 17 #include <cassert> 18 #include <map> 19 #include <unordered_map> 20 #include <memory> 21 #include <list> 22 #include <regex> 23 #include <set> 24 #include <string> 25 #include <vector> 26 27 // Classes which act as middle-men between clang AST parsing routines and 28 // message format specific dumpers. 29 namespace abi_util { 30 31 template <typename T> 32 using AbiElementMap = std::map<std::string, T>; 33 34 template <typename T> 35 using AbiElementUnorderedMap = std::unordered_map<std::string, T>; 36 37 template <typename T> 38 using AbiElementList = std::list<T>; 39 40 enum TextFormatIR { 41 ProtobufTextFormat = 0, 42 }; 43 44 enum CompatibilityStatusIR { 45 Compatible = 0, 46 UnreferencedChanges = 1, 47 Extension = 4, 48 Incompatible = 8, 49 ElfIncompatible = 16 50 }; 51 52 static inline CompatibilityStatusIR operator|(CompatibilityStatusIR f, 53 CompatibilityStatusIR s) { 54 return static_cast<CompatibilityStatusIR>( 55 static_cast<std::underlying_type<CompatibilityStatusIR>::type>(f) | 56 static_cast<std::underlying_type<CompatibilityStatusIR>::type>(s)); 57 } 58 59 static inline CompatibilityStatusIR operator&( 60 CompatibilityStatusIR f, CompatibilityStatusIR s) { 61 return static_cast<CompatibilityStatusIR>( 62 static_cast<std::underlying_type<CompatibilityStatusIR>::type>(f) & 63 static_cast<std::underlying_type<CompatibilityStatusIR>::type>(s)); 64 } 65 66 enum AccessSpecifierIR { 67 PublicAccess = 1, 68 ProtectedAccess = 2, 69 PrivateAccess = 3 70 }; 71 72 enum LinkableMessageKind { 73 RecordTypeKind, 74 EnumTypeKind, 75 PointerTypeKind, 76 QualifiedTypeKind, 77 ArrayTypeKind, 78 LvalueReferenceTypeKind, 79 RvalueReferenceTypeKind, 80 BuiltinTypeKind, 81 FunctionTypeKind, 82 FunctionKind, 83 GlobalVarKind 84 }; 85 86 class LinkableMessageIR { 87 public: 88 const std::string &GetLinkerSetKey() const { 89 return linker_set_key_; 90 } 91 92 void SetSourceFile(const std::string &source_file) { 93 source_file_ = source_file; 94 } 95 96 void SetLinkerSetKey(const std::string &linker_set_key) { 97 linker_set_key_ = linker_set_key; 98 } 99 100 const std::string &GetSourceFile() const { 101 return source_file_; 102 } 103 104 virtual LinkableMessageKind GetKind() const = 0; 105 virtual ~LinkableMessageIR() { }; 106 protected: 107 // The source file where this message comes from. This will be an empty string 108 // for built-in types. 109 std::string source_file_; 110 std::string linker_set_key_; 111 }; 112 113 class ReferencesOtherType { 114 public: 115 void SetReferencedType(const std::string &referenced_type) { 116 referenced_type_ = referenced_type; 117 } 118 119 const std::string &GetReferencedType() const { 120 return referenced_type_; 121 } 122 123 ReferencesOtherType(const std::string &referenced_type) 124 : referenced_type_(referenced_type) { } 125 126 ReferencesOtherType(std::string &&referenced_type) 127 : referenced_type_(std::move(referenced_type)) { } 128 129 ReferencesOtherType() { } 130 131 protected: 132 std::string referenced_type_; 133 }; 134 135 // TODO: Break this up into types with sizes and those without types ? 136 class TypeIR : public LinkableMessageIR , public ReferencesOtherType { 137 public: 138 139 void SetSelfType(const std::string &self_type) { 140 self_type_ = self_type; 141 } 142 143 const std::string &GetSelfType() const { 144 return self_type_; 145 } 146 147 void SetName(const std::string &name) { 148 name_ = name; 149 } 150 151 const std::string &GetName() const { 152 return name_; 153 } 154 155 void SetSize(uint64_t size) { 156 size_ = size; 157 } 158 uint64_t GetSize() const { 159 return size_; 160 } 161 void SetAlignment(uint32_t alignment) { 162 alignment_ = alignment; 163 } 164 uint32_t GetAlignment() const { 165 return alignment_; 166 } 167 168 virtual ~TypeIR() { } 169 170 protected: 171 std::string name_; 172 std::string self_type_; 173 uint64_t size_ = 0; 174 uint32_t alignment_ = 0; 175 }; 176 177 class TagTypeIR { 178 public: 179 const std::string &GetUniqueId() const { 180 return unique_id_; 181 } 182 183 void SetUniqueId(const std::string &unique_id) { 184 unique_id_ = unique_id; 185 } 186 187 protected: 188 std::string unique_id_; 189 }; 190 191 class VTableComponentIR { 192 public: 193 enum Kind { 194 VCallOffset = 0, 195 VBaseOffset = 1, 196 OffsetToTop = 2, 197 RTTI = 3, 198 FunctionPointer = 4, 199 CompleteDtorPointer = 5, 200 DeletingDtorPointer = 6, 201 UnusedFunctionPointer = 7 202 }; 203 204 VTableComponentIR(const std::string &name, Kind kind, int64_t value) 205 : component_name_(name), kind_(kind), value_(value) { } 206 207 VTableComponentIR() { } 208 209 Kind GetKind() const { 210 return kind_; 211 } 212 213 int64_t GetValue() const { 214 return value_; 215 } 216 217 const std::string &GetName() const { 218 return component_name_; 219 } 220 221 protected: 222 std::string component_name_; 223 Kind kind_; 224 int64_t value_ = 0; 225 }; 226 227 class VTableLayoutIR { 228 public: 229 void AddVTableComponent(VTableComponentIR &&vtable_component) { 230 vtable_components_.emplace_back(std::move(vtable_component)); 231 } 232 233 const std::vector<VTableComponentIR> &GetVTableComponents() const { 234 return vtable_components_; 235 } 236 237 uint64_t GetVTableNumEntries() const { 238 return vtable_components_.size(); 239 } 240 241 protected: 242 std::vector<VTableComponentIR> vtable_components_; 243 }; 244 245 class CXXBaseSpecifierIR : public ReferencesOtherType { 246 public: 247 CXXBaseSpecifierIR(const std::string &type, bool is_virtual, 248 AccessSpecifierIR access) : 249 ReferencesOtherType(type), is_virtual_(is_virtual), access_(access) { } 250 251 CXXBaseSpecifierIR() { } 252 253 bool IsVirtual() const { 254 return is_virtual_; 255 } 256 257 AccessSpecifierIR GetAccess() const { 258 return access_; 259 } 260 261 protected: 262 bool is_virtual_ = false; 263 AccessSpecifierIR access_ = AccessSpecifierIR::PublicAccess; 264 }; 265 266 class TemplateElementIR : public ReferencesOtherType { 267 public: 268 TemplateElementIR(std::string &&type) 269 : ReferencesOtherType(std::move(type)) { } 270 271 TemplateElementIR(const std::string &type) 272 : ReferencesOtherType(type) { } 273 274 TemplateElementIR() { } 275 }; 276 277 class TemplateInfoIR { 278 public: 279 void AddTemplateElement(TemplateElementIR &&element) { 280 template_elements_.emplace_back(element); 281 } 282 283 const std::vector<TemplateElementIR> &GetTemplateElements() const { 284 return template_elements_; 285 } 286 287 std::vector<TemplateElementIR> &GetTemplateElements() { 288 return template_elements_; 289 } 290 291 protected: 292 std::vector<TemplateElementIR> template_elements_; 293 }; 294 295 class TemplatedArtifactIR { 296 public: 297 void SetTemplateInfo(TemplateInfoIR &&template_info) { 298 template_info_ = std::move(template_info); 299 } 300 301 const std::vector<TemplateElementIR> &GetTemplateElements() const { 302 return template_info_.GetTemplateElements(); 303 } 304 305 std::vector<TemplateElementIR> &GetTemplateElements() { 306 return template_info_.GetTemplateElements(); 307 } 308 309 protected: 310 TemplateInfoIR template_info_; 311 }; 312 313 class RecordFieldIR : public ReferencesOtherType { 314 public: 315 RecordFieldIR(const std::string &name, const std::string &type, 316 uint64_t offset, AccessSpecifierIR access) 317 : ReferencesOtherType(type), name_(name), offset_(offset), 318 access_(access) { } 319 320 RecordFieldIR() { } 321 322 const std::string &GetName() const { 323 return name_; 324 } 325 326 uint64_t GetOffset() const { 327 return offset_; 328 } 329 330 AccessSpecifierIR GetAccess() const { 331 return access_; 332 } 333 334 protected: 335 std::string name_; 336 uint64_t offset_ = 0; 337 AccessSpecifierIR access_ = AccessSpecifierIR::PublicAccess; 338 }; 339 340 class RecordTypeIR: public TypeIR, public TemplatedArtifactIR, 341 public TagTypeIR { 342 public: 343 enum RecordKind { 344 struct_kind, 345 class_kind, 346 union_kind 347 }; 348 349 void AddRecordField(RecordFieldIR &&field) { 350 fields_.emplace_back(std::move(field)); 351 } 352 353 void SetRecordFields(std::vector<RecordFieldIR> &&fields) { 354 fields_ = std::move(fields); 355 } 356 357 void SetVTableLayout(VTableLayoutIR &&vtable_layout) { 358 vtable_layout_ = std::move(vtable_layout); 359 } 360 361 const VTableLayoutIR &GetVTableLayout() const { 362 return vtable_layout_; 363 } 364 365 void AddCXXBaseSpecifier(CXXBaseSpecifierIR &&base_specifier) { 366 bases_.emplace_back(std::move(base_specifier)); 367 } 368 369 void SetCXXBaseSpecifiers(std::vector<CXXBaseSpecifierIR> &&bases) { 370 bases_ = std::move(bases); 371 } 372 373 const std::vector<CXXBaseSpecifierIR> &GetBases() const { 374 return bases_; 375 } 376 377 std::vector<CXXBaseSpecifierIR> &GetBases() { 378 return bases_; 379 } 380 381 void SetAccess(AccessSpecifierIR access) { access_ = access;} 382 383 AccessSpecifierIR GetAccess() const { 384 return access_; 385 } 386 387 const std::vector<RecordFieldIR> &GetFields() const { 388 return fields_; 389 } 390 391 std::vector<RecordFieldIR> &GetFields() { 392 return fields_; 393 } 394 395 LinkableMessageKind GetKind() const override { 396 return LinkableMessageKind::RecordTypeKind; 397 } 398 399 uint64_t GetVTableNumEntries() const { 400 return vtable_layout_.GetVTableNumEntries(); 401 } 402 403 void SetRecordKind(RecordKind record_kind) { 404 record_kind_ = record_kind; 405 } 406 407 RecordKind GetRecordKind() const { 408 return record_kind_; 409 } 410 411 void SetAnonymity(bool is_anonymous) { 412 is_anonymous_ = is_anonymous; 413 } 414 415 bool IsAnonymous() const { 416 return is_anonymous_; 417 } 418 419 protected: 420 std::vector<RecordFieldIR> fields_; 421 VTableLayoutIR vtable_layout_; 422 std::vector<CXXBaseSpecifierIR> bases_; 423 AccessSpecifierIR access_ = AccessSpecifierIR::PublicAccess; 424 bool is_anonymous_ = false; 425 RecordKind record_kind_; 426 }; 427 428 class EnumFieldIR { 429 public: 430 EnumFieldIR(const std::string &name, int value) 431 : name_(name), value_(value) { } 432 const std::string &GetName() const { 433 return name_; 434 } 435 436 int GetValue() const { 437 return value_; 438 } 439 440 protected: 441 std::string name_; 442 int value_ = 0; 443 }; 444 445 class EnumTypeIR : public TypeIR, public TagTypeIR { 446 public: 447 // Add Methods to get information from the IR. 448 void AddEnumField(EnumFieldIR &&field) { 449 fields_.emplace_back(std::move(field)); 450 } 451 452 void SetAccess(AccessSpecifierIR access) { access_ = access;} 453 454 LinkableMessageKind GetKind() const override { 455 return LinkableMessageKind::EnumTypeKind; 456 } 457 458 AccessSpecifierIR GetAccess() const { 459 return access_; 460 } 461 462 void SetUnderlyingType(std::string &&underlying_type) { 463 underlying_type_ = std::move(underlying_type); 464 } 465 466 void SetUnderlyingType(const std::string &underlying_type) { 467 underlying_type_ = underlying_type; 468 } 469 470 const std::string &GetUnderlyingType() const { 471 return underlying_type_; 472 } 473 474 void SetFields(std::vector<EnumFieldIR> &&fields) { 475 fields_ = std::move(fields); 476 } 477 478 const std::vector<EnumFieldIR> &GetFields() const { 479 return fields_; 480 } 481 482 protected: 483 std::vector<EnumFieldIR> fields_; 484 std::string underlying_type_; 485 AccessSpecifierIR access_ = AccessSpecifierIR::PublicAccess; 486 }; 487 488 class ArrayTypeIR : public TypeIR { 489 public: 490 LinkableMessageKind GetKind() const override { 491 return LinkableMessageKind::ArrayTypeKind; 492 } 493 }; 494 495 class PointerTypeIR : public TypeIR { 496 public: 497 LinkableMessageKind GetKind() const override { 498 return LinkableMessageKind::PointerTypeKind; 499 } 500 }; 501 502 class BuiltinTypeIR : public TypeIR { 503 public: 504 void SetSignedness(bool is_unsigned) { 505 is_unsigned_ = is_unsigned; 506 } 507 508 bool IsUnsigned() const { 509 return is_unsigned_; 510 } 511 512 void SetIntegralType(bool is_integral_type) { 513 is_integral_type_ = is_integral_type; 514 } 515 516 bool IsIntegralType() const { 517 return is_integral_type_; 518 } 519 520 public: 521 LinkableMessageKind GetKind() const override { 522 return LinkableMessageKind::BuiltinTypeKind; 523 } 524 525 protected: 526 bool is_unsigned_ = false; 527 bool is_integral_type_ = false; 528 }; 529 530 class LvalueReferenceTypeIR : public TypeIR { 531 public: 532 LinkableMessageKind GetKind() const override { 533 return LinkableMessageKind::LvalueReferenceTypeKind; 534 } 535 }; 536 537 class RvalueReferenceTypeIR : public TypeIR { 538 public: 539 LinkableMessageKind GetKind() const override { 540 return LinkableMessageKind::RvalueReferenceTypeKind; 541 } 542 }; 543 544 class QualifiedTypeIR : public TypeIR { 545 public: 546 void SetConstness(bool is_const) { 547 is_const_ = is_const; 548 } 549 550 bool IsConst() const { 551 return is_const_; 552 } 553 554 void SetRestrictedness(bool is_restricted) { 555 is_restricted_ = is_restricted; 556 } 557 558 bool IsRestricted() const { 559 return is_restricted_; 560 } 561 562 void SetVolatility(bool is_volatile) { 563 is_volatile_ = is_volatile; 564 } 565 566 bool IsVolatile() const { 567 return is_volatile_; 568 } 569 570 public: 571 LinkableMessageKind GetKind() const override { 572 return LinkableMessageKind::QualifiedTypeKind; 573 } 574 575 protected: 576 bool is_const_; 577 bool is_restricted_; 578 bool is_volatile_; 579 }; 580 581 class GlobalVarIR: public LinkableMessageIR , public ReferencesOtherType { 582 public: 583 // Add Methods to get information from the IR. 584 void SetName(std::string &&name) { 585 name_ = std::move(name); 586 } 587 588 void SetName(const std::string &name) { 589 name_ = name; 590 } 591 592 const std::string &GetName() const { 593 return name_; 594 } 595 596 void SetAccess(AccessSpecifierIR access) { 597 access_ = access; 598 } 599 600 AccessSpecifierIR GetAccess() const { 601 return access_; 602 } 603 604 LinkableMessageKind GetKind() const override { 605 return LinkableMessageKind::GlobalVarKind; 606 } 607 608 protected: 609 std::string name_; 610 AccessSpecifierIR access_ = AccessSpecifierIR::PublicAccess; 611 }; 612 613 class ParamIR : public ReferencesOtherType { 614 public: 615 ParamIR(const std::string &type, bool is_default, bool is_this_ptr) : 616 ReferencesOtherType(type) , is_default_(is_default), 617 is_this_ptr_(is_this_ptr) {} 618 619 bool GetIsDefault() const { 620 return is_default_; 621 } 622 623 bool GetIsThisPtr() const { 624 return is_this_ptr_; 625 } 626 627 protected: 628 bool is_default_ = false; 629 bool is_this_ptr_ = false; 630 }; 631 632 class CFunctionLikeIR { 633 public: 634 void SetReturnType(const std::string &type) { 635 return_type_ = type; 636 } 637 638 const std::string &GetReturnType() const { 639 return return_type_; 640 } 641 642 void AddParameter(ParamIR &¶meter) { 643 parameters_.emplace_back(std::move(parameter)); 644 } 645 646 const std::vector<ParamIR> &GetParameters() const { 647 return parameters_; 648 } 649 650 std::vector<ParamIR> &GetParameters() { 651 return parameters_; 652 } 653 protected: 654 std::string return_type_; // return type reference 655 std::vector<ParamIR> parameters_; 656 }; 657 658 class FunctionTypeIR : public TypeIR, public CFunctionLikeIR { 659 public: 660 LinkableMessageKind GetKind() const override { 661 return LinkableMessageKind::FunctionTypeKind; 662 } 663 }; 664 665 class FunctionIR : public LinkableMessageIR, public TemplatedArtifactIR, 666 public CFunctionLikeIR { 667 public: 668 void SetAccess(AccessSpecifierIR access) { 669 access_ = access; 670 } 671 672 AccessSpecifierIR GetAccess() const { 673 return access_; 674 } 675 676 LinkableMessageKind GetKind() const override { 677 return LinkableMessageKind::FunctionKind; 678 } 679 680 void SetName(const std::string &name) { 681 name_ = name; 682 } 683 684 const std::string &GetName() const { 685 return name_; 686 } 687 688 protected: 689 std::string linkage_name_; 690 std::string name_; 691 AccessSpecifierIR access_ = AccessSpecifierIR::PublicAccess; 692 }; 693 694 class ElfSymbolIR { 695 public: 696 enum ElfSymbolKind { 697 ElfFunctionKind, 698 ElfObjectKind 699 }; 700 701 const std::string GetName() const { 702 return name_; 703 } 704 705 ElfSymbolIR(const std::string &name) : name_(name) { } 706 707 virtual ElfSymbolKind GetKind() const = 0; 708 709 virtual ~ElfSymbolIR() { } 710 711 protected: 712 std::string name_; 713 }; 714 715 class ElfFunctionIR : public ElfSymbolIR{ 716 public: 717 ElfSymbolKind GetKind() const override { 718 return ElfFunctionKind; 719 } 720 721 ElfFunctionIR(const std::string &name) : ElfSymbolIR(name) { } 722 }; 723 724 class ElfObjectIR : public ElfSymbolIR { 725 public: 726 ElfSymbolKind GetKind() const override { 727 return ElfObjectKind; 728 } 729 730 ElfObjectIR(const std::string &name) : ElfSymbolIR(name) { } 731 }; 732 733 class IRDumper { 734 public: 735 IRDumper(const std::string &dump_path) : dump_path_(dump_path) { } 736 737 static std::unique_ptr<IRDumper> CreateIRDumper( 738 TextFormatIR text_format, const std::string &dump_path); 739 740 virtual bool AddLinkableMessageIR(const LinkableMessageIR *) = 0; 741 742 virtual bool AddElfSymbolMessageIR(const ElfSymbolIR *) = 0; 743 744 virtual bool Dump() = 0; 745 746 virtual ~IRDumper() {} 747 748 protected: 749 const std::string &dump_path_; 750 }; 751 752 template <typename T> 753 inline std::string GetReferencedTypeMapKey( 754 T &element) { 755 return element.GetReferencedType(); 756 } 757 758 template <> 759 inline std::string GetReferencedTypeMapKey<ArrayTypeIR>( 760 ArrayTypeIR &element) { 761 return element.GetReferencedType() + ":" + std::to_string(element.GetSize()); 762 } 763 764 template <> 765 inline std::string GetReferencedTypeMapKey<BuiltinTypeIR>( 766 BuiltinTypeIR &element) { 767 return element.GetLinkerSetKey(); 768 } 769 770 inline static std::string BoolToString(bool val) { 771 return val ? "true" : "false"; 772 } 773 774 template <> 775 inline std::string GetReferencedTypeMapKey<QualifiedTypeIR>( 776 QualifiedTypeIR &element) { 777 return element.GetReferencedType() + BoolToString(element.IsRestricted()) + 778 BoolToString(element.IsVolatile()) + BoolToString(element.IsConst()); 779 } 780 781 inline std::string GetODRListMapKey(const RecordTypeIR *record_type_ir) { 782 if (record_type_ir->IsAnonymous()) { 783 return record_type_ir->GetLinkerSetKey() + record_type_ir->GetUniqueId(); 784 } 785 return record_type_ir->GetUniqueId() + record_type_ir->GetSourceFile(); 786 } 787 788 inline std::string GetODRListMapKey(const EnumTypeIR *enum_type_ir) { 789 return enum_type_ir->GetUniqueId() + enum_type_ir->GetSourceFile(); 790 } 791 792 inline std::string GetODRListMapKey(const FunctionTypeIR *function_type_ir) { 793 return function_type_ir->GetLinkerSetKey(); 794 } 795 796 // The map that is being updated maps special_key -> Type / Function/ GlobVar 797 // This special key is needed to distinguish what is being referenced. 798 template <typename T> 799 typename AbiElementMap<T>::iterator AddToMapAndTypeGraph( 800 T &&element, AbiElementMap<T> *map_to_update, 801 AbiElementMap<const TypeIR *> *type_graph) { 802 auto it = map_to_update->emplace(GetReferencedTypeMapKey(element), 803 std::move(element)); 804 type_graph->emplace(it.first->second.GetSelfType(), &(it.first->second)); 805 return it.first; 806 } 807 808 class TextFormatToIRReader { 809 public: 810 811 struct MergeStatus { 812 // type_id_ always has the global_type_id corresponding to the type this 813 // MergeStatus corresponds to. For 814 // generic reference types (pointers, qual types, l(r)value references etc), 815 // this will be a proactively added type_id, which will be added to the 816 // parent type_graph if the we decide to add the referencing type to the 817 // parent post ODR checking. 818 bool was_newly_added_ = false; 819 std::string type_id_; 820 MergeStatus(bool was_newly_added, const std::string &type_id) 821 : was_newly_added_(was_newly_added), type_id_(type_id) { } 822 MergeStatus() { } 823 }; 824 825 TextFormatToIRReader(const std::set<std::string> *exported_headers) 826 : exported_headers_(exported_headers) { } 827 828 const AbiElementMap<FunctionIR> &GetFunctions() const { 829 return functions_; 830 } 831 832 const AbiElementMap<GlobalVarIR> &GetGlobalVariables() const { 833 return global_variables_; 834 } 835 836 const AbiElementMap<RecordTypeIR> &GetRecordTypes() const { 837 return record_types_; 838 } 839 840 const AbiElementMap<FunctionTypeIR> &GetFunctionTypes() const { 841 return function_types_; 842 } 843 844 const AbiElementMap<EnumTypeIR> &GetEnumTypes() const { 845 return enum_types_; 846 } 847 848 const AbiElementMap<LvalueReferenceTypeIR> & 849 GetLvalueReferenceTypes() const { 850 return lvalue_reference_types_; 851 } 852 853 const AbiElementMap<RvalueReferenceTypeIR> & 854 GetRvalueReferenceTypes() const { 855 return rvalue_reference_types_; 856 } 857 858 const AbiElementMap<QualifiedTypeIR> &GetQualifiedTypes() const { 859 return qualified_types_; 860 } 861 862 const AbiElementMap<ArrayTypeIR> &GetArrayTypes() const { 863 return array_types_; 864 } 865 866 const AbiElementMap<PointerTypeIR> &GetPointerTypes() const { 867 return pointer_types_; 868 } 869 870 const AbiElementMap<BuiltinTypeIR> &GetBuiltinTypes() const { 871 return builtin_types_; 872 } 873 874 const AbiElementMap<ElfFunctionIR> &GetElfFunctions() const { 875 return elf_functions_; 876 } 877 878 const AbiElementMap<ElfObjectIR> &GetElfObjects() const { 879 return elf_objects_; 880 } 881 882 const AbiElementMap<const TypeIR *> &GetTypeGraph() const { 883 return type_graph_; 884 } 885 886 const AbiElementUnorderedMap<std::list<const TypeIR *>> & 887 GetODRListMap() const { 888 return odr_list_map_; 889 } 890 891 virtual bool ReadDump(const std::string &dump_file) = 0; 892 893 template <typename Iterator> 894 bool ReadDumps(Iterator begin, Iterator end) { 895 Iterator it = begin; 896 while(it != end) { 897 if (!ReadDump(*it)) { 898 return false; 899 } 900 ++it; 901 } 902 return true; 903 } 904 905 virtual ~TextFormatToIRReader() { } 906 907 void Merge(TextFormatToIRReader &&addend) { 908 MergeElements(&functions_, std::move(addend.functions_)); 909 MergeElements(&global_variables_, std::move(addend.global_variables_)); 910 MergeElements(&record_types_, std::move(addend.record_types_)); 911 MergeElements(&enum_types_, std::move(addend.enum_types_)); 912 MergeElements(&pointer_types_, std::move(addend.pointer_types_)); 913 MergeElements(&lvalue_reference_types_, 914 std::move(addend.lvalue_reference_types_)); 915 MergeElements(&rvalue_reference_types_, 916 std::move(addend.rvalue_reference_types_)); 917 MergeElements(&array_types_, std::move(addend.array_types_)); 918 MergeElements(&builtin_types_, std::move(addend.builtin_types_)); 919 MergeElements(&qualified_types_, std::move(addend.qualified_types_)); 920 } 921 922 void AddToODRListMap(const std::string &key, const TypeIR *value); 923 924 template <typename T> 925 MergeStatus MergeReferencingTypeInternalAndUpdateParent( 926 const TextFormatToIRReader &addend, const T *addend_node, 927 AbiElementMap<MergeStatus> *local_to_global_type_id_map, 928 AbiElementMap<T> *parent_map, const std::string &updated_self_type_id); 929 930 MergeStatus DoesUDTypeODRViolationExist( 931 const TypeIR *ud_type, const TextFormatToIRReader &addend, 932 const std::string ud_type_unique_id, 933 AbiElementMap<MergeStatus> *local_to_global_type_id_map_); 934 935 MergeStatus MergeReferencingTypeInternal( 936 const TextFormatToIRReader &addend, ReferencesOtherType *references_type, 937 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 938 939 MergeStatus MergeReferencingType( 940 const TextFormatToIRReader &addend, const TypeIR *addend_node, 941 AbiElementMap<MergeStatus> *local_to_global_type_id_map, 942 const std::string &updated_self_type_id); 943 944 MergeStatus MergeGenericReferringType( 945 const TextFormatToIRReader &addend, const TypeIR *addend_node, 946 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 947 948 template <typename T> 949 std::pair<MergeStatus, typename AbiElementMap<T>::iterator> 950 UpdateUDTypeAccounting( 951 const T *addend_node, const TextFormatToIRReader &addend, 952 AbiElementMap<MergeStatus> *local_to_global_type_id_map, 953 AbiElementMap<T> *specific_type_map); 954 955 MergeStatus MergeTypeInternal( 956 const TypeIR *addend_node, const TextFormatToIRReader &addend, 957 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 958 959 void MergeCFunctionLikeDeps( 960 const TextFormatToIRReader &addend, CFunctionLikeIR *cfunction_like_ir, 961 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 962 963 MergeStatus MergeFunctionType( 964 const FunctionTypeIR *addend_node, const TextFormatToIRReader &addend, 965 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 966 967 MergeStatus MergeEnumType( 968 const EnumTypeIR *addend_node, const TextFormatToIRReader &addend, 969 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 970 971 void MergeEnumDependencies( 972 const TextFormatToIRReader &addend, EnumTypeIR *added_node, 973 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 974 975 MergeStatus MergeRecordAndDependencies( 976 const RecordTypeIR *addend_node, const TextFormatToIRReader &addend, 977 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 978 979 void MergeRecordDependencies( 980 const TextFormatToIRReader &addend, RecordTypeIR *added_node, 981 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 982 983 void MergeRecordFields( 984 const TextFormatToIRReader &addend, RecordTypeIR *added_node, 985 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 986 987 void MergeRecordCXXBases( 988 const TextFormatToIRReader &addend, RecordTypeIR *added_node, 989 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 990 991 void MergeRecordTemplateElements( 992 const TextFormatToIRReader &addend, RecordTypeIR *added_node, 993 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 994 995 MergeStatus IsBuiltinTypeNodePresent( 996 const BuiltinTypeIR *builtin_type, const TextFormatToIRReader &addend, 997 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 998 999 void MergeGlobalVariable( 1000 const GlobalVarIR *addend_node, const TextFormatToIRReader &addend, 1001 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 1002 1003 void MergeGlobalVariables( 1004 const TextFormatToIRReader &addend, 1005 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 1006 1007 void MergeFunctionDeps( 1008 FunctionIR *added_node, const TextFormatToIRReader &addend, 1009 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 1010 1011 void MergeFunction( 1012 const FunctionIR *addend_node, const TextFormatToIRReader &addend, 1013 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 1014 1015 void MergeGraphs(const TextFormatToIRReader &addend); 1016 1017 void UpdateTextFormatToIRReaderTypeGraph( 1018 const TypeIR *addend_node, const std::string &added_type_id, 1019 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 1020 1021 MergeStatus IsTypeNodePresent( 1022 const TypeIR *addend_node, const TextFormatToIRReader &addend, 1023 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 1024 1025 MergeStatus MergeType(const TypeIR *addend_type, 1026 const TextFormatToIRReader &addend, 1027 AbiElementMap<MergeStatus> *merged_types_cache); 1028 1029 std::string AllocateNewTypeId(); 1030 1031 static std::unique_ptr<TextFormatToIRReader> CreateTextFormatToIRReader( 1032 TextFormatIR text_format, 1033 const std::set<std::string> *exported_headers = nullptr); 1034 1035 protected: 1036 1037 template <typename Augend, typename Addend> 1038 inline void MergeElements(Augend *augend, Addend &&addend) { 1039 augend->insert(std::make_move_iterator(addend.begin()), 1040 std::make_move_iterator(addend.end())); 1041 } 1042 1043 AbiElementList<RecordTypeIR> record_types_list_; 1044 AbiElementMap<FunctionIR> functions_; 1045 AbiElementMap<GlobalVarIR> global_variables_; 1046 AbiElementMap<RecordTypeIR> record_types_; 1047 AbiElementMap<FunctionTypeIR> function_types_; 1048 AbiElementMap<EnumTypeIR> enum_types_; 1049 // These maps which contain generic referring types as values are used while 1050 // looking up whether in the parent graph, a particular reffering type refers 1051 // to a certain type id. The mechanism is useful while trying to determine 1052 // whether a generic referring type needs to be newly added to the parent 1053 // graph or not. 1054 AbiElementMap<PointerTypeIR> pointer_types_; 1055 AbiElementMap<LvalueReferenceTypeIR> lvalue_reference_types_; 1056 AbiElementMap<RvalueReferenceTypeIR> rvalue_reference_types_; 1057 AbiElementMap<ArrayTypeIR> array_types_; 1058 AbiElementMap<BuiltinTypeIR> builtin_types_; 1059 AbiElementMap<QualifiedTypeIR> qualified_types_; 1060 AbiElementMap<ElfFunctionIR> elf_functions_; 1061 AbiElementMap<ElfObjectIR> elf_objects_; 1062 // type-id -> LinkableMessageIR * map 1063 AbiElementMap<const TypeIR *> type_graph_; 1064 // maps unique_id + source_file -> const TypeIR * 1065 AbiElementUnorderedMap<std::list<const TypeIR *>> odr_list_map_; 1066 const std::set<std::string> *exported_headers_; 1067 uint64_t max_type_id_ = 0; 1068 }; 1069 1070 class DiffMessageIR { 1071 public: 1072 1073 enum DiffKind { 1074 Extension, // Applicable for enums. 1075 Added, 1076 Removed, 1077 Referenced, 1078 Unreferenced 1079 }; 1080 1081 virtual LinkableMessageKind Kind() const = 0; 1082 void SetName(const std::string &name) { 1083 name_ = name; 1084 } 1085 1086 const std::string &GetName() const { 1087 return name_; 1088 } 1089 1090 virtual ~DiffMessageIR() { } 1091 1092 protected: 1093 std::string name_; 1094 }; 1095 1096 class AccessSpecifierDiffIR { 1097 public: 1098 AccessSpecifierDiffIR(AccessSpecifierIR old_access, 1099 AccessSpecifierIR new_access) 1100 : old_access_(old_access), new_access_(new_access) { } 1101 1102 protected: 1103 AccessSpecifierIR old_access_; 1104 AccessSpecifierIR new_access_; 1105 }; 1106 1107 class TypeDiffIR { 1108 public: 1109 TypeDiffIR(std::pair<uint64_t, uint64_t> &&sizes, 1110 std::pair<uint32_t, uint32_t> &&alignment) 1111 : sizes_(std::move(sizes)), alignments_(std::move(alignment)) { } 1112 1113 const std::pair<uint64_t, uint64_t> &GetSizes() const { 1114 return sizes_; 1115 } 1116 1117 const std::pair<uint32_t, uint32_t> &GetAlignments() const { 1118 return alignments_; 1119 } 1120 1121 protected: 1122 std::pair<uint64_t, uint64_t> sizes_; 1123 std::pair<uint32_t, uint32_t> alignments_; 1124 }; 1125 1126 class VTableLayoutDiffIR { 1127 public: 1128 VTableLayoutDiffIR(const VTableLayoutIR &old_layout, 1129 const VTableLayoutIR &new_layout) 1130 : old_layout_(old_layout), new_layout_(new_layout) { } 1131 1132 const VTableLayoutIR &GetOldVTable() const { 1133 return old_layout_; 1134 } 1135 1136 const VTableLayoutIR &GetNewVTable() const { 1137 return new_layout_; 1138 } 1139 1140 protected: 1141 const VTableLayoutIR &old_layout_; 1142 const VTableLayoutIR &new_layout_; 1143 }; 1144 1145 class RecordFieldDiffIR { 1146 public: 1147 RecordFieldDiffIR(const RecordFieldIR *old_field, 1148 const RecordFieldIR *new_field) 1149 : old_field_(old_field), new_field_(new_field) { } 1150 const RecordFieldIR *GetOldField() const { 1151 return old_field_; 1152 } 1153 1154 const RecordFieldIR *GetNewField() const { 1155 return new_field_; 1156 } 1157 1158 const RecordFieldIR *old_field_; 1159 const RecordFieldIR *new_field_; 1160 }; 1161 1162 class CXXBaseSpecifierDiffIR { 1163 public: 1164 CXXBaseSpecifierDiffIR( 1165 const std::vector<CXXBaseSpecifierIR> &old_base_specifiers, 1166 const std::vector<CXXBaseSpecifierIR> &new_base_specifiers) 1167 : old_base_specifiers_(old_base_specifiers), 1168 new_base_specifiers_(new_base_specifiers) { } 1169 const std::vector<CXXBaseSpecifierIR> &GetOldBases() const { 1170 return old_base_specifiers_; 1171 } 1172 1173 const std::vector<CXXBaseSpecifierIR> &GetNewBases() const { 1174 return new_base_specifiers_; 1175 } 1176 1177 protected: 1178 const std::vector<CXXBaseSpecifierIR> &old_base_specifiers_; 1179 const std::vector<CXXBaseSpecifierIR> &new_base_specifiers_; 1180 }; 1181 1182 class RecordTypeDiffIR : public DiffMessageIR { 1183 public: 1184 LinkableMessageKind Kind() const override { 1185 return LinkableMessageKind::RecordTypeKind; 1186 } 1187 1188 void SetFieldDiffs(std::vector<RecordFieldDiffIR> &&field_diffs) { 1189 field_diffs_ = std::move(field_diffs); 1190 } 1191 1192 const std::vector<RecordFieldDiffIR> &GetFieldDiffs() const { 1193 return field_diffs_; 1194 } 1195 1196 void SetFieldsRemoved(std::vector<const RecordFieldIR *> &&fields_removed) { 1197 fields_removed_ = std::move(fields_removed); 1198 } 1199 1200 void SetFieldsAdded(std::vector<const RecordFieldIR *> &&fields_added) { 1201 fields_added_ = std::move(fields_added); 1202 } 1203 1204 const std::vector<const RecordFieldIR *> &GetFieldsRemoved() const { 1205 return fields_removed_; 1206 } 1207 1208 const std::vector<const RecordFieldIR *> &GetFieldsAdded() const { 1209 return fields_added_; 1210 } 1211 1212 void SetVTableLayoutDiff(std::unique_ptr<VTableLayoutDiffIR> &&vtable_diffs) { 1213 vtable_diffs_ = std::move(vtable_diffs); 1214 } 1215 1216 void SetTypeDiff(std::unique_ptr<TypeDiffIR> &&type_diff) { 1217 type_diff_ = std::move(type_diff); 1218 } 1219 1220 void SetAccessDiff(std::unique_ptr<AccessSpecifierDiffIR> &&access_diff) { 1221 access_diff_ = std::move(access_diff); 1222 } 1223 1224 void SetBaseSpecifierDiffs( 1225 std::unique_ptr<CXXBaseSpecifierDiffIR> &&base_diffs) { 1226 base_specifier_diffs_ = std::move(base_diffs); 1227 } 1228 1229 bool DiffExists() const { 1230 return (type_diff_ != nullptr) || (vtable_diffs_ != nullptr) || 1231 (fields_removed_.size() != 0) || (field_diffs_.size() != 0) || 1232 (access_diff_ != nullptr) || (base_specifier_diffs_ != nullptr); 1233 } 1234 1235 const TypeDiffIR *GetTypeDiff() const { 1236 return type_diff_.get(); 1237 } 1238 1239 const VTableLayoutDiffIR *GetVTableLayoutDiff() const { 1240 return vtable_diffs_.get(); 1241 } 1242 1243 const CXXBaseSpecifierDiffIR *GetBaseSpecifiers() const { 1244 return base_specifier_diffs_.get(); 1245 } 1246 1247 protected: 1248 // optional implemented with vector / std::unique_ptr. 1249 std::unique_ptr<TypeDiffIR> type_diff_; 1250 std::unique_ptr<VTableLayoutDiffIR> vtable_diffs_; 1251 std::vector<RecordFieldDiffIR> field_diffs_; 1252 std::vector<const RecordFieldIR *> fields_removed_; 1253 std::vector<const RecordFieldIR *> fields_added_; 1254 std::unique_ptr<AccessSpecifierDiffIR> access_diff_; 1255 std::unique_ptr<CXXBaseSpecifierDiffIR> base_specifier_diffs_; 1256 // Template Diffs are not needed since they will show up in the linker set 1257 // key. 1258 }; 1259 1260 class EnumFieldDiffIR { 1261 public: 1262 EnumFieldDiffIR(const EnumFieldIR *old_field, const EnumFieldIR *new_field) 1263 : old_field_(old_field), new_field_(new_field) { } 1264 1265 const EnumFieldIR *GetOldField() const { 1266 return old_field_; 1267 } 1268 1269 const EnumFieldIR *GetNewField() const { 1270 return new_field_; 1271 } 1272 1273 protected: 1274 const EnumFieldIR *old_field_; 1275 const EnumFieldIR *new_field_; 1276 }; 1277 1278 class EnumTypeDiffIR : public DiffMessageIR { 1279 public: 1280 void SetFieldsRemoved(std::vector<const EnumFieldIR *> &&fields_removed) { 1281 fields_removed_ = std::move(fields_removed); 1282 } 1283 1284 const std::vector<const EnumFieldIR *> &GetFieldsRemoved() const { 1285 return fields_removed_; 1286 } 1287 1288 void SetFieldsAdded(std::vector<const EnumFieldIR *> &&fields_added) { 1289 fields_added_ = std::move(fields_added); 1290 } 1291 1292 const std::vector<const EnumFieldIR *> &GetFieldsAdded() const { 1293 return fields_added_; 1294 } 1295 1296 void SetFieldsDiff(std::vector<EnumFieldDiffIR> &&fields_diff) { 1297 fields_diff_ = std::move(fields_diff); 1298 } 1299 1300 const std::vector<EnumFieldDiffIR> &GetFieldsDiff() const { 1301 return fields_diff_; 1302 } 1303 1304 void SetUnderlyingTypeDiff( 1305 std::unique_ptr<std::pair<std::string, std::string>> &&utype_diff) { 1306 underlying_type_diff_ = std::move(utype_diff); 1307 } 1308 1309 const std::pair<std::string, std::string> *GetUnderlyingTypeDiff() const { 1310 return underlying_type_diff_.get(); 1311 } 1312 1313 bool IsExtended() const { 1314 if (fields_removed_.size() == 0 && fields_diff_.size() == 0 && 1315 fields_added_.size() != 0) { 1316 return true; 1317 } 1318 1319 return false; 1320 } 1321 1322 bool IsIncompatible() const { 1323 if (fields_removed_.size() != 0 || fields_diff_.size() != 0) { 1324 return true; 1325 } 1326 1327 return false; 1328 } 1329 1330 LinkableMessageKind Kind() const override { 1331 return LinkableMessageKind::EnumTypeKind; 1332 } 1333 1334 protected: 1335 // The underlying type can only be integral, so we just need to check for 1336 // referenced type. 1337 std::unique_ptr<std::pair<std::string, std::string>> underlying_type_diff_; 1338 std::vector<const EnumFieldIR *> fields_removed_; 1339 std::vector<const EnumFieldIR *> fields_added_; 1340 std::vector<EnumFieldDiffIR> fields_diff_; 1341 // Modifiable to allow implicit construction. 1342 std::string name_; 1343 }; 1344 1345 class GlobalVarDiffIR : public DiffMessageIR { 1346 public: 1347 LinkableMessageKind Kind() const override { 1348 return LinkableMessageKind::GlobalVarKind; 1349 } 1350 1351 GlobalVarDiffIR(const GlobalVarIR *old_global_var, 1352 const GlobalVarIR *new_global_var) 1353 : old_global_var_(old_global_var), new_global_var_(new_global_var) { } 1354 1355 const GlobalVarIR *GetOldGlobalVar() const { 1356 return old_global_var_; 1357 } 1358 1359 const GlobalVarIR *GetNewGlobalVar() const { 1360 return new_global_var_; 1361 } 1362 1363 protected: 1364 const GlobalVarIR *old_global_var_; 1365 const GlobalVarIR *new_global_var_; 1366 }; 1367 1368 class FunctionDiffIR : public DiffMessageIR { 1369 public: 1370 LinkableMessageKind Kind() const override { 1371 return LinkableMessageKind::FunctionKind; 1372 } 1373 1374 FunctionDiffIR(const FunctionIR *old_function, 1375 const FunctionIR *new_function) 1376 : old_function_(old_function), new_function_(new_function) { } 1377 1378 const FunctionIR *GetOldFunction() const { 1379 return old_function_; 1380 } 1381 1382 const FunctionIR *GetNewFunction() const { 1383 return new_function_; 1384 } 1385 1386 protected: 1387 const FunctionIR *old_function_; 1388 const FunctionIR *new_function_; 1389 }; 1390 1391 class IRDiffDumper { 1392 public: 1393 typedef DiffMessageIR::DiffKind DiffKind; 1394 1395 IRDiffDumper(const std::string &dump_path) : dump_path_(dump_path) { } 1396 1397 virtual bool AddDiffMessageIR(const DiffMessageIR *, 1398 const std::string &type_stack, 1399 DiffKind diff_kind) = 0; 1400 1401 virtual bool AddLinkableMessageIR(const LinkableMessageIR *, 1402 DiffKind diff_kind) = 0; 1403 1404 virtual bool AddElfSymbolMessageIR(const ElfSymbolIR *, 1405 DiffKind diff_kind) = 0; 1406 1407 virtual void AddLibNameIR(const std::string &name) = 0; 1408 1409 virtual void AddArchIR(const std::string &arch) = 0; 1410 1411 virtual void AddCompatibilityStatusIR(CompatibilityStatusIR status) = 0; 1412 1413 virtual bool Dump() = 0; 1414 1415 virtual CompatibilityStatusIR GetCompatibilityStatusIR() = 0; 1416 1417 virtual ~IRDiffDumper() {} 1418 static std::unique_ptr<IRDiffDumper> CreateIRDiffDumper( 1419 TextFormatIR, const std::string &dump_path); 1420 protected: 1421 const std::string &dump_path_; 1422 }; 1423 1424 } // namespace abi_util 1425 1426 #endif // IR_ 1427