Home | History | Annotate | Download | only in include
      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 &&parameter) {
    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