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:
GetLinkerSetKey()88   const std::string &GetLinkerSetKey() const {
89     return linker_set_key_;
90   }
91 
SetSourceFile(const std::string & source_file)92   void SetSourceFile(const std::string &source_file) {
93     source_file_ = source_file;
94   }
95 
SetLinkerSetKey(const std::string & linker_set_key)96   void SetLinkerSetKey(const std::string &linker_set_key) {
97     linker_set_key_ = linker_set_key;
98   }
99 
GetSourceFile()100   const std::string &GetSourceFile() const {
101     return source_file_;
102   }
103 
104   virtual LinkableMessageKind GetKind() const = 0;
~LinkableMessageIR()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:
SetReferencedType(const std::string & referenced_type)115   void SetReferencedType(const std::string &referenced_type) {
116     referenced_type_ = referenced_type;
117   }
118 
GetReferencedType()119   const std::string &GetReferencedType() const {
120     return referenced_type_;
121   }
122 
ReferencesOtherType(const std::string & referenced_type)123   ReferencesOtherType(const std::string &referenced_type)
124       : referenced_type_(referenced_type) { }
125 
ReferencesOtherType(std::string && referenced_type)126   ReferencesOtherType(std::string &&referenced_type)
127       : referenced_type_(std::move(referenced_type)) { }
128 
ReferencesOtherType()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 
SetSelfType(const std::string & self_type)139   void SetSelfType(const std::string &self_type) {
140     self_type_ = self_type;
141   }
142 
GetSelfType()143   const std::string &GetSelfType() const {
144     return self_type_;
145   }
146 
SetName(const std::string & name)147   void SetName(const std::string &name) {
148     name_ = name;
149   }
150 
GetName()151   const std::string &GetName() const {
152     return name_;
153   }
154 
SetSize(uint64_t size)155   void SetSize(uint64_t size) {
156     size_ = size;
157   }
GetSize()158   uint64_t GetSize() const {
159    return size_;
160   }
SetAlignment(uint32_t alignment)161   void SetAlignment(uint32_t alignment) {
162     alignment_ = alignment;
163   }
GetAlignment()164   uint32_t GetAlignment() const {
165     return alignment_;
166   }
167 
~TypeIR()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:
GetUniqueId()179   const std::string &GetUniqueId() const {
180     return unique_id_;
181   }
182 
SetUniqueId(const std::string & unique_id)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 
VTableComponentIR(const std::string & name,Kind kind,int64_t value)204   VTableComponentIR(const std::string &name, Kind kind, int64_t value)
205       : component_name_(name), kind_(kind), value_(value) { }
206 
VTableComponentIR()207   VTableComponentIR() { }
208 
GetKind()209   Kind GetKind() const {
210     return kind_;
211   }
212 
GetValue()213   int64_t GetValue() const {
214     return value_;
215   }
216 
GetName()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:
AddVTableComponent(VTableComponentIR && vtable_component)229   void AddVTableComponent(VTableComponentIR &&vtable_component) {
230     vtable_components_.emplace_back(std::move(vtable_component));
231   }
232 
GetVTableComponents()233   const std::vector<VTableComponentIR> &GetVTableComponents() const {
234     return vtable_components_;
235   }
236 
GetVTableNumEntries()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:
CXXBaseSpecifierIR(const std::string & type,bool is_virtual,AccessSpecifierIR access)247   CXXBaseSpecifierIR(const std::string &type, bool is_virtual,
248                      AccessSpecifierIR access) :
249     ReferencesOtherType(type), is_virtual_(is_virtual), access_(access) { }
250 
CXXBaseSpecifierIR()251   CXXBaseSpecifierIR() { }
252 
IsVirtual()253   bool IsVirtual() const {
254     return is_virtual_;
255   }
256 
GetAccess()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:
TemplateElementIR(std::string && type)268   TemplateElementIR(std::string &&type)
269       : ReferencesOtherType(std::move(type)) { }
270 
TemplateElementIR(const std::string & type)271   TemplateElementIR(const std::string &type)
272       : ReferencesOtherType(type) { }
273 
TemplateElementIR()274   TemplateElementIR() { }
275 };
276 
277 class TemplateInfoIR {
278  public:
AddTemplateElement(TemplateElementIR && element)279   void AddTemplateElement(TemplateElementIR &&element) {
280     template_elements_.emplace_back(element);
281   }
282 
GetTemplateElements()283   const std::vector<TemplateElementIR> &GetTemplateElements() const {
284     return template_elements_;
285   }
286 
GetTemplateElements()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:
SetTemplateInfo(TemplateInfoIR && template_info)297   void SetTemplateInfo(TemplateInfoIR &&template_info) {
298     template_info_ = std::move(template_info);
299   }
300 
GetTemplateElements()301   const std::vector<TemplateElementIR> &GetTemplateElements() const {
302     return template_info_.GetTemplateElements();
303   }
304 
GetTemplateElements()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:
RecordFieldIR(const std::string & name,const std::string & type,uint64_t offset,AccessSpecifierIR access)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 
RecordFieldIR()320   RecordFieldIR() { }
321 
GetName()322   const std::string &GetName() const {
323     return name_;
324   }
325 
GetOffset()326   uint64_t GetOffset() const {
327     return offset_;
328   }
329 
GetAccess()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 
AddRecordField(RecordFieldIR && field)349   void AddRecordField(RecordFieldIR &&field) {
350     fields_.emplace_back(std::move(field));
351   }
352 
SetRecordFields(std::vector<RecordFieldIR> && fields)353   void SetRecordFields(std::vector<RecordFieldIR> &&fields) {
354     fields_ = std::move(fields);
355   }
356 
SetVTableLayout(VTableLayoutIR && vtable_layout)357   void SetVTableLayout(VTableLayoutIR &&vtable_layout) {
358     vtable_layout_ = std::move(vtable_layout);
359   }
360 
GetVTableLayout()361   const VTableLayoutIR &GetVTableLayout() const {
362     return vtable_layout_;
363   }
364 
AddCXXBaseSpecifier(CXXBaseSpecifierIR && base_specifier)365   void AddCXXBaseSpecifier(CXXBaseSpecifierIR &&base_specifier) {
366     bases_.emplace_back(std::move(base_specifier));
367   }
368 
SetCXXBaseSpecifiers(std::vector<CXXBaseSpecifierIR> && bases)369   void SetCXXBaseSpecifiers(std::vector<CXXBaseSpecifierIR> &&bases) {
370     bases_ = std::move(bases);
371   }
372 
GetBases()373   const std::vector<CXXBaseSpecifierIR> &GetBases() const {
374     return bases_;
375   }
376 
GetBases()377   std::vector<CXXBaseSpecifierIR> &GetBases() {
378     return bases_;
379   }
380 
SetAccess(AccessSpecifierIR access)381   void SetAccess(AccessSpecifierIR access) { access_ = access;}
382 
GetAccess()383   AccessSpecifierIR GetAccess() const {
384     return access_;
385   }
386 
GetFields()387   const std::vector<RecordFieldIR> &GetFields() const {
388     return fields_;
389   }
390 
GetFields()391   std::vector<RecordFieldIR> &GetFields() {
392     return fields_;
393   }
394 
GetKind()395    LinkableMessageKind GetKind() const override {
396     return LinkableMessageKind::RecordTypeKind;
397   }
398 
GetVTableNumEntries()399   uint64_t GetVTableNumEntries() const {
400     return vtable_layout_.GetVTableNumEntries();
401   }
402 
SetRecordKind(RecordKind record_kind)403   void SetRecordKind(RecordKind record_kind) {
404     record_kind_ = record_kind;
405   }
406 
GetRecordKind()407   RecordKind GetRecordKind() const {
408     return record_kind_;
409   }
410 
SetAnonymity(bool is_anonymous)411   void SetAnonymity(bool is_anonymous) {
412     is_anonymous_ = is_anonymous;
413   }
414 
IsAnonymous()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:
EnumFieldIR(const std::string & name,int value)430   EnumFieldIR(const std::string &name, int value)
431       : name_(name), value_(value) { }
GetName()432   const std::string &GetName() const {
433     return name_;
434   }
435 
GetValue()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.
AddEnumField(EnumFieldIR && field)448   void AddEnumField(EnumFieldIR &&field) {
449     fields_.emplace_back(std::move(field));
450   }
451 
SetAccess(AccessSpecifierIR access)452   void SetAccess(AccessSpecifierIR access) { access_ = access;}
453 
GetKind()454    LinkableMessageKind GetKind() const override {
455     return LinkableMessageKind::EnumTypeKind;
456   }
457 
GetAccess()458   AccessSpecifierIR GetAccess() const {
459     return access_;
460   }
461 
SetUnderlyingType(std::string && underlying_type)462   void SetUnderlyingType(std::string &&underlying_type) {
463     underlying_type_ = std::move(underlying_type);
464   }
465 
SetUnderlyingType(const std::string & underlying_type)466   void SetUnderlyingType(const std::string &underlying_type) {
467     underlying_type_ = underlying_type;
468   }
469 
GetUnderlyingType()470   const std::string &GetUnderlyingType() const {
471     return underlying_type_;
472   }
473 
SetFields(std::vector<EnumFieldIR> && fields)474   void SetFields(std::vector<EnumFieldIR> &&fields) {
475     fields_ = std::move(fields);
476   }
477 
GetFields()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:
GetKind()490   LinkableMessageKind GetKind() const override {
491     return LinkableMessageKind::ArrayTypeKind;
492   }
493 };
494 
495 class PointerTypeIR : public TypeIR {
496  public:
GetKind()497   LinkableMessageKind GetKind() const override {
498     return LinkableMessageKind::PointerTypeKind;
499   }
500 };
501 
502 class BuiltinTypeIR : public TypeIR {
503  public:
SetSignedness(bool is_unsigned)504   void SetSignedness(bool is_unsigned) {
505     is_unsigned_ = is_unsigned;
506   }
507 
IsUnsigned()508   bool IsUnsigned() const {
509     return is_unsigned_;
510   }
511 
SetIntegralType(bool is_integral_type)512   void SetIntegralType(bool is_integral_type) {
513     is_integral_type_ = is_integral_type;
514   }
515 
IsIntegralType()516   bool IsIntegralType() const {
517     return is_integral_type_;
518   }
519 
520  public:
GetKind()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:
GetKind()532   LinkableMessageKind GetKind() const override {
533     return LinkableMessageKind::LvalueReferenceTypeKind;
534   }
535 };
536 
537 class RvalueReferenceTypeIR : public TypeIR {
538  public:
GetKind()539   LinkableMessageKind GetKind() const override {
540     return LinkableMessageKind::RvalueReferenceTypeKind;
541   }
542 };
543 
544 class QualifiedTypeIR : public TypeIR {
545  public:
SetConstness(bool is_const)546   void SetConstness(bool is_const) {
547     is_const_ = is_const;
548   }
549 
IsConst()550   bool IsConst() const {
551     return is_const_;
552   }
553 
SetRestrictedness(bool is_restricted)554   void SetRestrictedness(bool is_restricted) {
555     is_restricted_ = is_restricted;
556   }
557 
IsRestricted()558   bool IsRestricted() const {
559     return is_restricted_;
560   }
561 
SetVolatility(bool is_volatile)562   void SetVolatility(bool is_volatile) {
563     is_volatile_ = is_volatile;
564   }
565 
IsVolatile()566   bool IsVolatile() const {
567     return is_volatile_;
568   }
569 
570  public:
GetKind()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.
SetName(std::string && name)584   void SetName(std::string &&name) {
585     name_ = std::move(name);
586   }
587 
SetName(const std::string & name)588   void SetName(const std::string &name) {
589     name_ = name;
590   }
591 
GetName()592   const std::string &GetName() const {
593     return name_;
594   }
595 
SetAccess(AccessSpecifierIR access)596   void SetAccess(AccessSpecifierIR access) {
597     access_ = access;
598   }
599 
GetAccess()600   AccessSpecifierIR GetAccess() const {
601     return access_;
602   }
603 
GetKind()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:
ParamIR(const std::string & type,bool is_default,bool is_this_ptr)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 
GetIsDefault()619   bool GetIsDefault() const {
620     return is_default_;
621   }
622 
GetIsThisPtr()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:
SetReturnType(const std::string & type)634   void SetReturnType(const std::string &type) {
635     return_type_ = type;
636   }
637 
GetReturnType()638   const std::string &GetReturnType() const {
639     return return_type_;
640   }
641 
AddParameter(ParamIR && parameter)642   void AddParameter(ParamIR &&parameter) {
643     parameters_.emplace_back(std::move(parameter));
644   }
645 
GetParameters()646   const std::vector<ParamIR> &GetParameters() const {
647     return parameters_;
648   }
649 
GetParameters()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:
GetKind()660   LinkableMessageKind GetKind() const override {
661     return LinkableMessageKind::FunctionTypeKind;
662   }
663 };
664 
665 class FunctionIR : public LinkableMessageIR, public TemplatedArtifactIR,
666                    public CFunctionLikeIR {
667  public:
SetAccess(AccessSpecifierIR access)668   void SetAccess(AccessSpecifierIR access) {
669     access_ = access;
670   }
671 
GetAccess()672   AccessSpecifierIR GetAccess() const {
673     return access_;
674   }
675 
GetKind()676   LinkableMessageKind GetKind() const override {
677     return LinkableMessageKind::FunctionKind;
678   }
679 
SetName(const std::string & name)680   void SetName(const std::string &name) {
681     name_ = name;
682   }
683 
GetName()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 
GetName()701   const std::string GetName() const {
702     return name_;
703   }
704 
ElfSymbolIR(const std::string & name)705   ElfSymbolIR(const std::string &name) : name_(name) { }
706 
707   virtual ElfSymbolKind GetKind() const = 0;
708 
~ElfSymbolIR()709   virtual ~ElfSymbolIR() { }
710 
711  protected:
712   std::string name_;
713 };
714 
715 class ElfFunctionIR : public ElfSymbolIR{
716  public:
GetKind()717   ElfSymbolKind GetKind() const override {
718     return ElfFunctionKind;
719   }
720 
ElfFunctionIR(const std::string & name)721   ElfFunctionIR(const std::string &name) : ElfSymbolIR(name) { }
722 };
723 
724 class ElfObjectIR : public ElfSymbolIR {
725  public:
GetKind()726   ElfSymbolKind GetKind() const override {
727     return ElfObjectKind;
728   }
729 
ElfObjectIR(const std::string & name)730   ElfObjectIR(const std::string &name) : ElfSymbolIR(name) { }
731 };
732 
733 class IRDumper {
734  public:
IRDumper(const std::string & dump_path)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 
~IRDumper()746   virtual ~IRDumper() {}
747 
748  protected:
749   const std::string &dump_path_;
750 };
751 
752 template <typename T>
GetReferencedTypeMapKey(T & element)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 
BoolToString(bool val)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 
GetODRListMapKey(const RecordTypeIR * record_type_ir)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 
GetODRListMapKey(const EnumTypeIR * enum_type_ir)788 inline std::string GetODRListMapKey(const EnumTypeIR *enum_type_ir) {
789   return enum_type_ir->GetUniqueId() + enum_type_ir->GetSourceFile();
790 }
791 
GetODRListMapKey(const FunctionTypeIR * function_type_ir)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>
AddToMapAndTypeGraph(T && element,AbiElementMap<T> * map_to_update,AbiElementMap<const TypeIR * > * type_graph)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_;
MergeStatusMergeStatus820     MergeStatus(bool was_newly_added, const std::string &type_id)
821         : was_newly_added_(was_newly_added), type_id_(type_id) { }
MergeStatusMergeStatus822     MergeStatus() { }
823   };
824 
TextFormatToIRReader(const std::set<std::string> * exported_headers)825   TextFormatToIRReader(const std::set<std::string> *exported_headers)
826       : exported_headers_(exported_headers) { }
827 
GetFunctions()828   const AbiElementMap<FunctionIR> &GetFunctions() const {
829     return functions_;
830   }
831 
GetGlobalVariables()832   const AbiElementMap<GlobalVarIR> &GetGlobalVariables() const {
833     return global_variables_;
834   }
835 
GetRecordTypes()836   const AbiElementMap<RecordTypeIR> &GetRecordTypes() const {
837     return record_types_;
838   }
839 
GetFunctionTypes()840   const AbiElementMap<FunctionTypeIR> &GetFunctionTypes() const {
841     return function_types_;
842   }
843 
GetEnumTypes()844   const AbiElementMap<EnumTypeIR> &GetEnumTypes() const {
845     return enum_types_;
846   }
847 
848   const AbiElementMap<LvalueReferenceTypeIR> &
GetLvalueReferenceTypes()849       GetLvalueReferenceTypes() const {
850     return lvalue_reference_types_;
851   }
852 
853   const AbiElementMap<RvalueReferenceTypeIR> &
GetRvalueReferenceTypes()854       GetRvalueReferenceTypes() const {
855     return rvalue_reference_types_;
856   }
857 
GetQualifiedTypes()858   const AbiElementMap<QualifiedTypeIR> &GetQualifiedTypes() const {
859     return qualified_types_;
860   }
861 
GetArrayTypes()862   const AbiElementMap<ArrayTypeIR> &GetArrayTypes() const {
863     return array_types_;
864   }
865 
GetPointerTypes()866   const AbiElementMap<PointerTypeIR> &GetPointerTypes() const {
867     return pointer_types_;
868   }
869 
GetBuiltinTypes()870   const AbiElementMap<BuiltinTypeIR> &GetBuiltinTypes() const {
871     return builtin_types_;
872   }
873 
GetElfFunctions()874   const AbiElementMap<ElfFunctionIR> &GetElfFunctions() const {
875     return elf_functions_;
876   }
877 
GetElfObjects()878   const AbiElementMap<ElfObjectIR> &GetElfObjects() const {
879     return elf_objects_;
880   }
881 
GetTypeGraph()882   const AbiElementMap<const TypeIR *> &GetTypeGraph() const {
883     return type_graph_;
884   }
885 
886   const AbiElementUnorderedMap<std::list<const TypeIR *>> &
GetODRListMap()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>
ReadDumps(Iterator begin,Iterator end)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 
~TextFormatToIRReader()905   virtual ~TextFormatToIRReader() { }
906 
Merge(TextFormatToIRReader && addend)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>
MergeElements(Augend * augend,Addend && 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;
SetName(const std::string & name)1082   void SetName(const std::string &name) {
1083     name_ = name;
1084   }
1085 
GetName()1086   const std::string &GetName() const {
1087     return name_;
1088   }
1089 
~DiffMessageIR()1090   virtual ~DiffMessageIR() { }
1091 
1092  protected:
1093   std::string name_;
1094 };
1095 
1096 class AccessSpecifierDiffIR {
1097  public:
AccessSpecifierDiffIR(AccessSpecifierIR old_access,AccessSpecifierIR new_access)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:
TypeDiffIR(std::pair<uint64_t,uint64_t> && sizes,std::pair<uint32_t,uint32_t> && alignment)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 
GetSizes()1113   const std::pair<uint64_t, uint64_t> &GetSizes() const {
1114     return sizes_;
1115   }
1116 
GetAlignments()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:
VTableLayoutDiffIR(const VTableLayoutIR & old_layout,const VTableLayoutIR & new_layout)1128   VTableLayoutDiffIR(const VTableLayoutIR &old_layout,
1129                      const VTableLayoutIR &new_layout)
1130       : old_layout_(old_layout), new_layout_(new_layout) { }
1131 
GetOldVTable()1132   const VTableLayoutIR &GetOldVTable() const {
1133     return old_layout_;
1134   }
1135 
GetNewVTable()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:
RecordFieldDiffIR(const RecordFieldIR * old_field,const RecordFieldIR * new_field)1147   RecordFieldDiffIR(const RecordFieldIR *old_field,
1148                     const RecordFieldIR *new_field)
1149       : old_field_(old_field), new_field_(new_field) { }
GetOldField()1150   const RecordFieldIR *GetOldField() const {
1151     return old_field_;
1152   }
1153 
GetNewField()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:
CXXBaseSpecifierDiffIR(const std::vector<CXXBaseSpecifierIR> & old_base_specifiers,const std::vector<CXXBaseSpecifierIR> & new_base_specifiers)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) { }
GetOldBases()1169   const std::vector<CXXBaseSpecifierIR> &GetOldBases() const {
1170     return old_base_specifiers_;
1171   }
1172 
GetNewBases()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:
Kind()1184   LinkableMessageKind Kind() const override {
1185     return LinkableMessageKind::RecordTypeKind;
1186   }
1187 
SetFieldDiffs(std::vector<RecordFieldDiffIR> && field_diffs)1188   void SetFieldDiffs(std::vector<RecordFieldDiffIR> &&field_diffs) {
1189     field_diffs_ = std::move(field_diffs);
1190   }
1191 
GetFieldDiffs()1192   const std::vector<RecordFieldDiffIR> &GetFieldDiffs() const {
1193     return field_diffs_;
1194   }
1195 
SetFieldsRemoved(std::vector<const RecordFieldIR * > && fields_removed)1196   void SetFieldsRemoved(std::vector<const RecordFieldIR *> &&fields_removed) {
1197     fields_removed_ = std::move(fields_removed);
1198   }
1199 
SetFieldsAdded(std::vector<const RecordFieldIR * > && fields_added)1200   void SetFieldsAdded(std::vector<const RecordFieldIR *> &&fields_added) {
1201     fields_added_ = std::move(fields_added);
1202   }
1203 
GetFieldsRemoved()1204   const std::vector<const RecordFieldIR *> &GetFieldsRemoved() const {
1205     return fields_removed_;
1206   }
1207 
GetFieldsAdded()1208   const std::vector<const RecordFieldIR *> &GetFieldsAdded() const {
1209     return fields_added_;
1210   }
1211 
SetVTableLayoutDiff(std::unique_ptr<VTableLayoutDiffIR> && vtable_diffs)1212   void SetVTableLayoutDiff(std::unique_ptr<VTableLayoutDiffIR> &&vtable_diffs) {
1213     vtable_diffs_ = std::move(vtable_diffs);
1214   }
1215 
SetTypeDiff(std::unique_ptr<TypeDiffIR> && type_diff)1216   void SetTypeDiff(std::unique_ptr<TypeDiffIR> &&type_diff) {
1217     type_diff_ = std::move(type_diff);
1218   }
1219 
SetAccessDiff(std::unique_ptr<AccessSpecifierDiffIR> && access_diff)1220   void SetAccessDiff(std::unique_ptr<AccessSpecifierDiffIR> &&access_diff) {
1221     access_diff_ = std::move(access_diff);
1222   }
1223 
SetBaseSpecifierDiffs(std::unique_ptr<CXXBaseSpecifierDiffIR> && base_diffs)1224   void SetBaseSpecifierDiffs(
1225       std::unique_ptr<CXXBaseSpecifierDiffIR> &&base_diffs) {
1226     base_specifier_diffs_ = std::move(base_diffs);
1227   }
1228 
DiffExists()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 
GetTypeDiff()1235   const TypeDiffIR *GetTypeDiff() const {
1236     return type_diff_.get();
1237   }
1238 
GetVTableLayoutDiff()1239   const VTableLayoutDiffIR *GetVTableLayoutDiff() const {
1240     return vtable_diffs_.get();
1241   }
1242 
GetBaseSpecifiers()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:
EnumFieldDiffIR(const EnumFieldIR * old_field,const EnumFieldIR * new_field)1262   EnumFieldDiffIR(const EnumFieldIR *old_field, const EnumFieldIR *new_field)
1263       : old_field_(old_field), new_field_(new_field) { }
1264 
GetOldField()1265   const EnumFieldIR *GetOldField() const {
1266     return old_field_;
1267   }
1268 
GetNewField()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:
SetFieldsRemoved(std::vector<const EnumFieldIR * > && fields_removed)1280   void SetFieldsRemoved(std::vector<const EnumFieldIR *> &&fields_removed) {
1281     fields_removed_ = std::move(fields_removed);
1282   }
1283 
GetFieldsRemoved()1284   const std::vector<const EnumFieldIR *> &GetFieldsRemoved() const {
1285     return fields_removed_;
1286   }
1287 
SetFieldsAdded(std::vector<const EnumFieldIR * > && fields_added)1288   void SetFieldsAdded(std::vector<const EnumFieldIR *> &&fields_added) {
1289     fields_added_ = std::move(fields_added);
1290   }
1291 
GetFieldsAdded()1292   const std::vector<const EnumFieldIR *> &GetFieldsAdded() const {
1293     return fields_added_;
1294   }
1295 
SetFieldsDiff(std::vector<EnumFieldDiffIR> && fields_diff)1296   void SetFieldsDiff(std::vector<EnumFieldDiffIR> &&fields_diff) {
1297     fields_diff_ = std::move(fields_diff);
1298   }
1299 
GetFieldsDiff()1300   const std::vector<EnumFieldDiffIR> &GetFieldsDiff() const {
1301     return fields_diff_;
1302   }
1303 
SetUnderlyingTypeDiff(std::unique_ptr<std::pair<std::string,std::string>> && utype_diff)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 
GetUnderlyingTypeDiff()1309   const std::pair<std::string, std::string> *GetUnderlyingTypeDiff() const {
1310     return underlying_type_diff_.get();
1311   }
1312 
IsExtended()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 
IsIncompatible()1322   bool IsIncompatible() const {
1323     if (fields_removed_.size() != 0 || fields_diff_.size() != 0) {
1324         return true;
1325     }
1326 
1327     return false;
1328   }
1329 
Kind()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:
Kind()1347   LinkableMessageKind Kind() const override {
1348     return LinkableMessageKind::GlobalVarKind;
1349   }
1350 
GlobalVarDiffIR(const GlobalVarIR * old_global_var,const GlobalVarIR * new_global_var)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 
GetOldGlobalVar()1355  const GlobalVarIR *GetOldGlobalVar() const {
1356    return old_global_var_;
1357  }
1358 
GetNewGlobalVar()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:
Kind()1370   LinkableMessageKind Kind() const override {
1371     return LinkableMessageKind::FunctionKind;
1372   }
1373 
FunctionDiffIR(const FunctionIR * old_function,const FunctionIR * new_function)1374   FunctionDiffIR(const FunctionIR *old_function,
1375                  const FunctionIR *new_function)
1376       : old_function_(old_function), new_function_(new_function) { }
1377 
GetOldFunction()1378   const FunctionIR *GetOldFunction() const {
1379     return old_function_;
1380   }
1381 
GetNewFunction()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 
IRDiffDumper(const std::string & dump_path)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 
~IRDiffDumper()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