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 
15 #ifndef IR_REPRESENTATION_H_
16 #define IR_REPRESENTATION_H_
17 
18 #include <list>
19 #include <map>
20 #include <memory>
21 #include <set>
22 #include <string>
23 #include <unordered_map>
24 #include <vector>
25 
26 
27 namespace header_checker {
28 namespace repr {
29 
30 
31 // Classes which act as middle-men between clang AST parsing routines and
32 // message format specific dumpers.
33 
34 template <typename T>
35 using AbiElementMap = std::map<std::string, T>;
36 
37 template <typename T>
38 using AbiElementUnorderedMap = std::unordered_map<std::string, T>;
39 
40 enum TextFormatIR {
41   ProtobufTextFormat = 0,
42   Json = 1,
43 };
44 
45 enum CompatibilityStatusIR {
46   Compatible = 0,
47   UnreferencedChanges = 1,
48   Extension = 4,
49   Incompatible = 8,
50   ElfIncompatible = 16
51 };
52 
53 static inline CompatibilityStatusIR operator|(CompatibilityStatusIR f,
54                                               CompatibilityStatusIR s) {
55   return static_cast<CompatibilityStatusIR>(
56       static_cast<std::underlying_type<CompatibilityStatusIR>::type>(f) |
57       static_cast<std::underlying_type<CompatibilityStatusIR>::type>(s));
58 }
59 
60 static inline CompatibilityStatusIR operator&(CompatibilityStatusIR f,
61                                               CompatibilityStatusIR s) {
62   return static_cast<CompatibilityStatusIR>(
63       static_cast<std::underlying_type<CompatibilityStatusIR>::type>(f) &
64       static_cast<std::underlying_type<CompatibilityStatusIR>::type>(s));
65 }
66 
67 enum AccessSpecifierIR {
68   // Ordered from the least to the most restricted.
69   PublicAccess = 1,
70   ProtectedAccess = 2,
71   PrivateAccess = 3
72 };
73 
74 enum LinkableMessageKind {
75   RecordTypeKind,
76   EnumTypeKind,
77   PointerTypeKind,
78   QualifiedTypeKind,
79   ArrayTypeKind,
80   LvalueReferenceTypeKind,
81   RvalueReferenceTypeKind,
82   BuiltinTypeKind,
83   FunctionTypeKind,
84   FunctionKind,
85   GlobalVarKind
86 };
87 
88 template <typename K, typename V>
CreateInverseMap(const std::map<K,V> & m)89 std::map<V, K> CreateInverseMap(const std::map<K, V> &m) {
90   std::map<V, K> inverse_map;
91   for (auto it : m) {
92     inverse_map[it.second] = it.first;
93   }
94   return inverse_map;
95 }
96 
FormatMultiDefinitionTypeId(const std::string & type_id,const std::string & compilation_unit_path)97 static inline std::string FormatMultiDefinitionTypeId(
98     const std::string &type_id, const std::string &compilation_unit_path) {
99   return type_id + "#ODR:" + compilation_unit_path;
100 }
101 
ExtractMultiDefinitionTypeId(std::string_view type_id)102 static inline std::string_view ExtractMultiDefinitionTypeId(
103     std::string_view type_id) {
104   return type_id.substr(0, type_id.find("#ODR:"));
105 }
106 
107 class LinkableMessageIR {
108  public:
~LinkableMessageIR()109   virtual ~LinkableMessageIR() {}
110 
GetLinkerSetKey()111   const std::string &GetLinkerSetKey() const {
112     return linker_set_key_;
113   }
114 
SetSourceFile(const std::string & source_file)115   void SetSourceFile(const std::string &source_file) {
116     source_file_ = source_file;
117   }
118 
SetLinkerSetKey(const std::string & linker_set_key)119   void SetLinkerSetKey(const std::string &linker_set_key) {
120     linker_set_key_ = linker_set_key;
121   }
122 
GetSourceFile()123   const std::string &GetSourceFile() const {
124     return source_file_;
125   }
126 
127   virtual LinkableMessageKind GetKind() const = 0;
128 
129  protected:
130   // The source file where this message comes from. This will be an empty string
131   // for built-in types.
132   std::string source_file_;
133   std::string linker_set_key_;
134 };
135 
136 class ReferencesOtherType {
137  public:
ReferencesOtherType(const std::string & referenced_type)138   ReferencesOtherType(const std::string &referenced_type)
139       : referenced_type_(referenced_type) {}
140 
ReferencesOtherType(std::string && referenced_type)141   ReferencesOtherType(std::string &&referenced_type)
142       : referenced_type_(std::move(referenced_type)) {}
143 
ReferencesOtherType()144   ReferencesOtherType() {}
145 
SetReferencedType(const std::string & referenced_type)146   void SetReferencedType(const std::string &referenced_type) {
147     referenced_type_ = referenced_type;
148   }
149 
GetReferencedType()150   const std::string &GetReferencedType() const {
151     return referenced_type_;
152   }
153 
154  protected:
155   std::string referenced_type_;
156 };
157 
158 // TODO: Break this up into types with sizes and those without types?
159 class TypeIR : public LinkableMessageIR, public ReferencesOtherType {
160  public:
~TypeIR()161   virtual ~TypeIR() {}
162 
SetSelfType(const std::string & self_type)163   void SetSelfType(const std::string &self_type) {
164     self_type_ = self_type;
165   }
166 
GetSelfType()167   const std::string &GetSelfType() const {
168     return self_type_;
169   }
170 
SetName(const std::string & name)171   void SetName(const std::string &name) {
172     name_ = name;
173   }
174 
GetName()175   const std::string &GetName() const {
176     return name_;
177   }
178 
SetSize(uint64_t size)179   void SetSize(uint64_t size) {
180     size_ = size;
181   }
182 
GetSize()183   uint64_t GetSize() const {
184     return size_;
185   }
186 
SetAlignment(uint32_t alignment)187   void SetAlignment(uint32_t alignment) {
188     alignment_ = alignment;
189   }
190 
GetAlignment()191   uint32_t GetAlignment() const {
192     return alignment_;
193   }
194 
195  protected:
196   std::string name_;
197   std::string self_type_;
198   uint64_t size_ = 0;
199   uint32_t alignment_ = 0;
200 };
201 
202 class VTableComponentIR {
203  public:
204   enum Kind {
205     VCallOffset = 0,
206     VBaseOffset = 1,
207     OffsetToTop = 2,
208     RTTI = 3,
209     FunctionPointer = 4,
210     CompleteDtorPointer = 5,
211     DeletingDtorPointer = 6,
212     UnusedFunctionPointer = 7
213   };
214 
VTableComponentIR(const std::string & name,Kind kind,int64_t value,bool is_pure)215   VTableComponentIR(const std::string &name, Kind kind, int64_t value,
216                     bool is_pure)
217       : component_name_(name), kind_(kind), value_(value), is_pure_(is_pure) {}
218 
VTableComponentIR()219   VTableComponentIR() {}
220 
GetKind()221   Kind GetKind() const {
222     return kind_;
223   }
224 
GetValue()225   int64_t GetValue() const {
226     return value_;
227   }
228 
GetName()229   const std::string &GetName() const {
230     return component_name_;
231   }
232 
GetIsPure()233   bool GetIsPure() const {
234     return is_pure_;
235   }
236 
237  protected:
238   std::string component_name_;
239   Kind kind_;
240   int64_t value_ = 0;
241   bool is_pure_;
242 };
243 
244 class VTableLayoutIR {
245  public:
AddVTableComponent(VTableComponentIR && vtable_component)246   void AddVTableComponent(VTableComponentIR &&vtable_component) {
247     vtable_components_.emplace_back(std::move(vtable_component));
248   }
249 
GetVTableComponents()250   const std::vector<VTableComponentIR> &GetVTableComponents() const {
251     return vtable_components_;
252   }
253 
GetVTableNumEntries()254   uint64_t GetVTableNumEntries() const {
255     return vtable_components_.size();
256   }
257 
258  protected:
259   std::vector<VTableComponentIR> vtable_components_;
260 };
261 
262 class CXXBaseSpecifierIR : public ReferencesOtherType {
263  public:
CXXBaseSpecifierIR(const std::string & type,bool is_virtual,AccessSpecifierIR access)264   CXXBaseSpecifierIR(const std::string &type, bool is_virtual,
265                      AccessSpecifierIR access)
266       : ReferencesOtherType(type), is_virtual_(is_virtual), access_(access) {}
267 
CXXBaseSpecifierIR()268   CXXBaseSpecifierIR() {}
269 
IsVirtual()270   bool IsVirtual() const {
271     return is_virtual_;
272   }
273 
GetAccess()274   AccessSpecifierIR GetAccess() const {
275     return access_;
276   }
277 
278  protected:
279   bool is_virtual_ = false;
280   AccessSpecifierIR access_ = AccessSpecifierIR::PublicAccess;
281 };
282 
283 class TemplateElementIR : public ReferencesOtherType {
284  public:
TemplateElementIR(std::string && type)285   TemplateElementIR(std::string &&type)
286       : ReferencesOtherType(std::move(type)) {}
287 
TemplateElementIR(const std::string & type)288   TemplateElementIR(const std::string &type)
289       : ReferencesOtherType(type) {}
290 
TemplateElementIR()291   TemplateElementIR() {}
292 };
293 
294 class TemplateInfoIR {
295  public:
AddTemplateElement(TemplateElementIR && element)296   void AddTemplateElement(TemplateElementIR &&element) {
297     template_elements_.emplace_back(element);
298   }
299 
GetTemplateElements()300   const std::vector<TemplateElementIR> &GetTemplateElements() const {
301     return template_elements_;
302   }
303 
GetTemplateElements()304   std::vector<TemplateElementIR> &GetTemplateElements() {
305     return template_elements_;
306   }
307 
308  protected:
309   std::vector<TemplateElementIR> template_elements_;
310 };
311 
312 class TemplatedArtifactIR {
313  public:
SetTemplateInfo(TemplateInfoIR && template_info)314   void SetTemplateInfo(TemplateInfoIR &&template_info) {
315     template_info_ = std::move(template_info);
316   }
317 
GetTemplateElements()318   const std::vector<TemplateElementIR> &GetTemplateElements() const {
319     return template_info_.GetTemplateElements();
320   }
321 
GetTemplateElements()322   std::vector<TemplateElementIR> &GetTemplateElements() {
323     return template_info_.GetTemplateElements();
324   }
325 
326  protected:
327   TemplateInfoIR template_info_;
328 };
329 
330 class RecordFieldIR : public ReferencesOtherType {
331  public:
RecordFieldIR(const std::string & name,const std::string & type,uint64_t offset,AccessSpecifierIR access,bool is_bit_field,uint64_t bit_width)332   RecordFieldIR(const std::string &name, const std::string &type,
333                 uint64_t offset, AccessSpecifierIR access, bool is_bit_field,
334                 uint64_t bit_width)
335       : ReferencesOtherType(type),
336         name_(name),
337         offset_(offset),
338         access_(access),
339         is_bit_field_(is_bit_field),
340         bit_width_(bit_width) {}
341 
RecordFieldIR()342   RecordFieldIR() {}
343 
GetName()344   const std::string &GetName() const {
345     return name_;
346   }
347 
GetOffset()348   uint64_t GetOffset() const {
349     return offset_;
350   }
351 
GetAccess()352   AccessSpecifierIR GetAccess() const {
353     return access_;
354   }
355 
IsBitField()356   bool IsBitField() const { return is_bit_field_; }
357 
GetBitWidth()358   uint64_t GetBitWidth() const { return bit_width_; }
359 
360  protected:
361   std::string name_;
362   uint64_t offset_ = 0;
363   AccessSpecifierIR access_ = AccessSpecifierIR::PublicAccess;
364   bool is_bit_field_ = false;
365   uint64_t bit_width_ = 0;
366 };
367 
368 class RecordTypeIR : public TypeIR, public TemplatedArtifactIR {
369  public:
370   enum RecordKind {
371     struct_kind,
372     class_kind,
373     union_kind
374   };
375 
AddRecordField(RecordFieldIR && field)376   void AddRecordField(RecordFieldIR &&field) {
377     fields_.emplace_back(std::move(field));
378   }
379 
SetRecordFields(std::vector<RecordFieldIR> && fields)380   void SetRecordFields(std::vector<RecordFieldIR> &&fields) {
381     fields_ = std::move(fields);
382   }
383 
SetVTableLayout(VTableLayoutIR && vtable_layout)384   void SetVTableLayout(VTableLayoutIR &&vtable_layout) {
385     vtable_layout_ = std::move(vtable_layout);
386   }
387 
GetVTableLayout()388   const VTableLayoutIR &GetVTableLayout() const {
389     return vtable_layout_;
390   }
391 
AddCXXBaseSpecifier(CXXBaseSpecifierIR && base_specifier)392   void AddCXXBaseSpecifier(CXXBaseSpecifierIR &&base_specifier) {
393     bases_.emplace_back(std::move(base_specifier));
394   }
395 
SetCXXBaseSpecifiers(std::vector<CXXBaseSpecifierIR> && bases)396   void SetCXXBaseSpecifiers(std::vector<CXXBaseSpecifierIR> &&bases) {
397     bases_ = std::move(bases);
398   }
399 
GetBases()400   const std::vector<CXXBaseSpecifierIR> &GetBases() const {
401     return bases_;
402   }
403 
GetBases()404   std::vector<CXXBaseSpecifierIR> &GetBases() {
405     return bases_;
406   }
407 
SetAccess(AccessSpecifierIR access)408   void SetAccess(AccessSpecifierIR access) { access_ = access;}
409 
GetAccess()410   AccessSpecifierIR GetAccess() const {
411     return access_;
412   }
413 
GetFields()414   const std::vector<RecordFieldIR> &GetFields() const {
415     return fields_;
416   }
417 
GetFields()418   std::vector<RecordFieldIR> &GetFields() {
419     return fields_;
420   }
421 
GetKind()422   LinkableMessageKind GetKind() const override {
423     return LinkableMessageKind::RecordTypeKind;
424   }
425 
GetVTableNumEntries()426   uint64_t GetVTableNumEntries() const {
427     return vtable_layout_.GetVTableNumEntries();
428   }
429 
SetRecordKind(RecordKind record_kind)430   void SetRecordKind(RecordKind record_kind) {
431     record_kind_ = record_kind;
432   }
433 
GetRecordKind()434   RecordKind GetRecordKind() const {
435     return record_kind_;
436   }
437 
SetAnonymity(bool is_anonymous)438   void SetAnonymity(bool is_anonymous) {
439     is_anonymous_ = is_anonymous;
440   }
441 
IsAnonymous()442   bool IsAnonymous() const {
443     return is_anonymous_;
444   }
445 
446  protected:
447   std::vector<RecordFieldIR> fields_;
448   VTableLayoutIR vtable_layout_;
449   std::vector<CXXBaseSpecifierIR> bases_;
450   AccessSpecifierIR access_ = AccessSpecifierIR::PublicAccess;
451   bool is_anonymous_ = false;
452   RecordKind record_kind_;
453 };
454 
455 class EnumFieldIR {
456  public:
EnumFieldIR(const std::string & name,int64_t value)457   EnumFieldIR(const std::string &name, int64_t value)
458       : name_(name), signed_value_(value), is_signed_(true) {}
459 
EnumFieldIR(const std::string & name,uint64_t value)460   EnumFieldIR(const std::string &name, uint64_t value)
461       : name_(name), unsigned_value_(value), is_signed_(false) {}
462 
GetName()463   const std::string &GetName() const {
464     return name_;
465   }
466 
IsSigned()467   bool IsSigned() const { return is_signed_; }
468 
GetSignedValue()469   int64_t GetSignedValue() const { return signed_value_; }
470 
GetUnsignedValue()471   uint64_t GetUnsignedValue() const { return unsigned_value_; }
472 
473  protected:
474   std::string name_;
475   union {
476     int64_t signed_value_;
477     uint64_t unsigned_value_;
478   };
479   bool is_signed_;
480 };
481 
482 class EnumTypeIR : public TypeIR {
483  public:
484   // Add Methods to get information from the IR.
AddEnumField(EnumFieldIR && field)485   void AddEnumField(EnumFieldIR &&field) {
486     fields_.emplace_back(std::move(field));
487   }
488 
SetAccess(AccessSpecifierIR access)489   void SetAccess(AccessSpecifierIR access) { access_ = access;}
490 
GetKind()491   LinkableMessageKind GetKind() const override {
492     return LinkableMessageKind::EnumTypeKind;
493   }
494 
GetAccess()495   AccessSpecifierIR GetAccess() const {
496     return access_;
497   }
498 
SetUnderlyingType(std::string && underlying_type)499   void SetUnderlyingType(std::string &&underlying_type) {
500     underlying_type_ = std::move(underlying_type);
501   }
502 
SetUnderlyingType(const std::string & underlying_type)503   void SetUnderlyingType(const std::string &underlying_type) {
504     underlying_type_ = underlying_type;
505   }
506 
GetUnderlyingType()507   const std::string &GetUnderlyingType() const {
508     return underlying_type_;
509   }
510 
SetFields(std::vector<EnumFieldIR> && fields)511   void SetFields(std::vector<EnumFieldIR> &&fields) {
512     fields_ = std::move(fields);
513   }
514 
GetFields()515   const std::vector<EnumFieldIR> &GetFields() const {
516     return fields_;
517   }
518 
519  protected:
520   std::vector<EnumFieldIR> fields_;
521   std::string underlying_type_;
522   AccessSpecifierIR access_ = AccessSpecifierIR::PublicAccess;
523 };
524 
525 class ArrayTypeIR : public TypeIR {
526  public:
SetUnknownBound(bool is_of_unknown_bound)527   void SetUnknownBound(bool is_of_unknown_bound) {
528     is_of_unknown_bound_ = is_of_unknown_bound;
529   }
530 
IsOfUnknownBound()531   bool IsOfUnknownBound() const { return is_of_unknown_bound_; }
532 
GetKind()533   LinkableMessageKind GetKind() const override {
534     return LinkableMessageKind::ArrayTypeKind;
535   }
536 
537  private:
538   bool is_of_unknown_bound_ = false;
539 };
540 
541 class PointerTypeIR : public TypeIR {
542  public:
GetKind()543   LinkableMessageKind GetKind() const override {
544     return LinkableMessageKind::PointerTypeKind;
545   }
546 };
547 
548 class BuiltinTypeIR : public TypeIR {
549  public:
SetSignedness(bool is_unsigned)550   void SetSignedness(bool is_unsigned) {
551     is_unsigned_ = is_unsigned;
552   }
553 
IsUnsigned()554   bool IsUnsigned() const {
555     return is_unsigned_;
556   }
557 
SetIntegralType(bool is_integral_type)558   void SetIntegralType(bool is_integral_type) {
559     is_integral_type_ = is_integral_type;
560   }
561 
IsIntegralType()562   bool IsIntegralType() const {
563     return is_integral_type_;
564   }
565 
566  public:
GetKind()567   LinkableMessageKind GetKind() const override {
568     return LinkableMessageKind::BuiltinTypeKind;
569   }
570 
571  protected:
572   bool is_unsigned_ = false;
573   bool is_integral_type_ = false;
574 };
575 
576 class LvalueReferenceTypeIR : public TypeIR {
577  public:
GetKind()578   LinkableMessageKind GetKind() const override {
579     return LinkableMessageKind::LvalueReferenceTypeKind;
580   }
581 };
582 
583 class RvalueReferenceTypeIR : public TypeIR {
584  public:
GetKind()585   LinkableMessageKind GetKind() const override {
586     return LinkableMessageKind::RvalueReferenceTypeKind;
587   }
588 };
589 
590 class QualifiedTypeIR : public TypeIR {
591  public:
SetConstness(bool is_const)592   void SetConstness(bool is_const) {
593     is_const_ = is_const;
594   }
595 
IsConst()596   bool IsConst() const {
597     return is_const_;
598   }
599 
SetRestrictedness(bool is_restricted)600   void SetRestrictedness(bool is_restricted) {
601     is_restricted_ = is_restricted;
602   }
603 
IsRestricted()604   bool IsRestricted() const {
605     return is_restricted_;
606   }
607 
SetVolatility(bool is_volatile)608   void SetVolatility(bool is_volatile) {
609     is_volatile_ = is_volatile;
610   }
611 
IsVolatile()612   bool IsVolatile() const {
613     return is_volatile_;
614   }
615 
616  public:
GetKind()617   LinkableMessageKind GetKind() const override {
618     return LinkableMessageKind::QualifiedTypeKind;
619   }
620 
621  protected:
622   bool is_const_;
623   bool is_restricted_;
624   bool is_volatile_;
625 };
626 
627 class GlobalVarIR : public LinkableMessageIR , public ReferencesOtherType {
628  public:
629   // Add Methods to get information from the IR.
SetName(std::string && name)630   void SetName(std::string &&name) {
631     name_ = std::move(name);
632   }
633 
SetName(const std::string & name)634   void SetName(const std::string &name) {
635     name_ = name;
636   }
637 
GetName()638   const std::string &GetName() const {
639     return name_;
640   }
641 
SetAccess(AccessSpecifierIR access)642   void SetAccess(AccessSpecifierIR access) {
643     access_ = access;
644   }
645 
GetAccess()646   AccessSpecifierIR GetAccess() const {
647     return access_;
648   }
649 
GetKind()650   LinkableMessageKind GetKind() const override {
651     return LinkableMessageKind::GlobalVarKind;
652   }
653 
654  protected:
655   std::string name_;
656   AccessSpecifierIR access_ = AccessSpecifierIR::PublicAccess;
657 };
658 
659 class ParamIR : public ReferencesOtherType {
660  public:
ParamIR(const std::string & type,bool is_default,bool is_this_ptr)661   ParamIR(const std::string &type, bool is_default, bool is_this_ptr)
662       : ReferencesOtherType(type) , is_default_(is_default),
663         is_this_ptr_(is_this_ptr) {}
664 
GetIsDefault()665   bool GetIsDefault() const {
666     return is_default_;
667   }
668 
GetIsThisPtr()669   bool GetIsThisPtr() const {
670     return is_this_ptr_;
671   }
672 
673  protected:
674   bool is_default_ = false;
675   bool is_this_ptr_ = false;
676 };
677 
678 class CFunctionLikeIR {
679  public:
SetReturnType(const std::string & type)680   void SetReturnType(const std::string &type) {
681     return_type_ = type;
682   }
683 
GetReturnType()684   const std::string &GetReturnType() const {
685     return return_type_;
686   }
687 
AddParameter(ParamIR && parameter)688   void AddParameter(ParamIR &&parameter) {
689     parameters_.emplace_back(std::move(parameter));
690   }
691 
GetParameters()692   const std::vector<ParamIR> &GetParameters() const {
693     return parameters_;
694   }
695 
GetParameters()696   std::vector<ParamIR> &GetParameters() {
697     return parameters_;
698   }
699 
700  protected:
701   std::string return_type_;  // return type reference
702   std::vector<ParamIR> parameters_;
703 };
704 
705 class FunctionTypeIR : public TypeIR, public CFunctionLikeIR {
706  public:
GetKind()707   LinkableMessageKind GetKind() const override {
708     return LinkableMessageKind::FunctionTypeKind;
709   }
710 };
711 
712 class FunctionIR : public LinkableMessageIR, public TemplatedArtifactIR,
713                    public CFunctionLikeIR {
714  public:
SetAccess(AccessSpecifierIR access)715   void SetAccess(AccessSpecifierIR access) {
716     access_ = access;
717   }
718 
GetAccess()719   AccessSpecifierIR GetAccess() const {
720     return access_;
721   }
722 
GetKind()723   LinkableMessageKind GetKind() const override {
724     return LinkableMessageKind::FunctionKind;
725   }
726 
SetName(const std::string & name)727   void SetName(const std::string &name) {
728     name_ = name;
729   }
730 
GetName()731   const std::string &GetName() const {
732     return name_;
733   }
734 
735  protected:
736   std::string linkage_name_;
737   std::string name_;
738   AccessSpecifierIR access_ = AccessSpecifierIR::PublicAccess;
739 };
740 
741 class ElfSymbolIR {
742  public:
743   enum ElfSymbolKind {
744     ElfFunctionKind,
745     ElfObjectKind,
746   };
747 
748   enum ElfSymbolBinding {
749     Weak,
750     Global,
751   };
752 
753   enum ElfSymbolVisibility {
754     Default,
755     Protected,
756   };
757 
758  public:
ElfSymbolIR(const std::string & name,ElfSymbolBinding binding)759   ElfSymbolIR(const std::string &name, ElfSymbolBinding binding)
760       : name_(name), binding_(binding) {}
761 
~ElfSymbolIR()762   virtual ~ElfSymbolIR() {}
763 
GetName()764   const std::string GetName() const {
765     return name_;
766   }
767 
GetBinding()768   ElfSymbolBinding GetBinding() const {
769     return binding_;
770   }
771 
772   virtual ElfSymbolKind GetKind() const = 0;
773 
774  protected:
775   std::string name_;
776   ElfSymbolBinding binding_;
777 };
778 
779 class ElfFunctionIR : public ElfSymbolIR {
780  public:
ElfFunctionIR(const std::string & name,ElfSymbolBinding binding)781   ElfFunctionIR(const std::string &name, ElfSymbolBinding binding)
782       : ElfSymbolIR(name, binding) {}
783 
GetKind()784   ElfSymbolKind GetKind() const override {
785     return ElfFunctionKind;
786   }
787 };
788 
789 class ElfObjectIR : public ElfSymbolIR {
790  public:
ElfObjectIR(const std::string & name,ElfSymbolBinding binding)791   ElfObjectIR(const std::string &name, ElfSymbolBinding binding)
792       : ElfSymbolIR(name, binding) {}
793 
GetKind()794   ElfSymbolKind GetKind() const override {
795     return ElfObjectKind;
796   }
797 };
798 
799 class TypeDefinition {
800  public:
TypeDefinition(const TypeIR * type_ir,const std::string * compilation_unit_path)801   TypeDefinition(const TypeIR *type_ir,
802                  const std::string *compilation_unit_path)
803       : type_ir_(type_ir), compilation_unit_path_(*compilation_unit_path) {}
804 
805   const TypeIR *type_ir_;
806   const std::string &compilation_unit_path_;
807 };
808 
809 class ModuleIR {
810  public:
ModuleIR(const std::set<std::string> * exported_headers)811   ModuleIR(const std::set<std::string> *exported_headers)
812       : exported_headers_(exported_headers) {}
813 
GetCompilationUnitPath()814   const std::string &GetCompilationUnitPath() const {
815     return compilation_unit_path_;
816   }
817 
SetCompilationUnitPath(const std::string & compilation_unit_path)818   void SetCompilationUnitPath(const std::string &compilation_unit_path) {
819     compilation_unit_path_ = compilation_unit_path;
820   }
821 
GetFunctions()822   const AbiElementMap<FunctionIR> &GetFunctions() const {
823     return functions_;
824   }
825 
GetGlobalVariables()826   const AbiElementMap<GlobalVarIR> &GetGlobalVariables() const {
827     return global_variables_;
828   }
829 
GetRecordTypes()830   const AbiElementMap<RecordTypeIR> &GetRecordTypes() const {
831     return record_types_;
832   }
833 
GetFunctionTypes()834   const AbiElementMap<FunctionTypeIR> &GetFunctionTypes() const {
835     return function_types_;
836   }
837 
GetEnumTypes()838   const AbiElementMap<EnumTypeIR> &GetEnumTypes() const {
839     return enum_types_;
840   }
841 
GetLvalueReferenceTypes()842   const AbiElementMap<LvalueReferenceTypeIR> &GetLvalueReferenceTypes() const {
843     return lvalue_reference_types_;
844   }
845 
GetRvalueReferenceTypes()846   const AbiElementMap<RvalueReferenceTypeIR> &GetRvalueReferenceTypes() const {
847     return rvalue_reference_types_;
848   }
849 
GetQualifiedTypes()850   const AbiElementMap<QualifiedTypeIR> &GetQualifiedTypes() const {
851     return qualified_types_;
852   }
853 
GetArrayTypes()854   const AbiElementMap<ArrayTypeIR> &GetArrayTypes() const {
855     return array_types_;
856   }
857 
GetPointerTypes()858   const AbiElementMap<PointerTypeIR> &GetPointerTypes() const {
859     return pointer_types_;
860   }
861 
GetBuiltinTypes()862   const AbiElementMap<BuiltinTypeIR> &GetBuiltinTypes() const {
863     return builtin_types_;
864   }
865 
GetElfFunctions()866   const AbiElementMap<ElfFunctionIR> &GetElfFunctions() const {
867     return elf_functions_;
868   }
869 
GetElfObjects()870   const AbiElementMap<ElfObjectIR> &GetElfObjects() const {
871     return elf_objects_;
872   }
873 
GetTypeGraph()874   const AbiElementMap<const TypeIR *> &GetTypeGraph() const {
875     return type_graph_;
876   }
877 
878   const AbiElementUnorderedMap<std::list<TypeDefinition>> &
GetODRListMap()879   GetODRListMap() const {
880     return odr_list_map_;
881   }
882 
883 
884   bool AddLinkableMessage(const LinkableMessageIR &);
885 
886   void AddFunction(FunctionIR &&function);
887 
888   void AddGlobalVariable(GlobalVarIR &&global_var);
889 
890   void AddRecordType(RecordTypeIR &&record_type);
891 
892   void AddFunctionType(FunctionTypeIR &&function_type);
893 
894   void AddEnumType(EnumTypeIR &&enum_type);
895 
896   void AddLvalueReferenceType(LvalueReferenceTypeIR &&lvalue_reference_type);
897 
898   void AddRvalueReferenceType(RvalueReferenceTypeIR &&rvalue_reference_type);
899 
900   void AddQualifiedType(QualifiedTypeIR &&qualified_type);
901 
902   void AddArrayType(ArrayTypeIR &&array_type);
903 
904   void AddPointerType(PointerTypeIR &&pointer_type);
905 
906   void AddBuiltinType(BuiltinTypeIR &&builtin_type);
907 
908   bool AddElfSymbol(const ElfSymbolIR &);
909 
910   void AddElfFunction(ElfFunctionIR &&elf_function);
911 
912   void AddElfObject(ElfObjectIR &&elf_object);
913 
914   // Find the compilation unit path of a RecordTypeIR, FunctionTypeIR, or
915   // EnumTypeIR in odr_list_map_. Return an empty string if the type is not in
916   // the map.
917   std::string GetCompilationUnitPath(const TypeIR *type_ir) const;
918 
AddToODRListMap(const std::string & key,const TypeIR * type_ir,const std::string & compilation_unit_path)919   void AddToODRListMap(const std::string &key, const TypeIR *type_ir,
920                        const std::string &compilation_unit_path) {
921     auto compilation_unit_path_it =
922         compilation_unit_paths_.emplace(compilation_unit_path).first;
923     auto map_it = odr_list_map_.find(key);
924     TypeDefinition value(type_ir, &*compilation_unit_path_it);
925     if (map_it == odr_list_map_.end()) {
926       odr_list_map_.emplace(key, std::list<TypeDefinition>({value}));
927       return;
928     }
929     odr_list_map_[key].emplace_back(value);
930   }
931 
932 
933  private:
934   bool IsLinkableMessageInExportedHeaders(
935       const LinkableMessageIR *linkable_message) const;
936 
937 
938  public:
939   // File path to the compilation unit (*.sdump)
940   std::string compilation_unit_path_;
941 
942   AbiElementMap<FunctionIR> functions_;
943   AbiElementMap<GlobalVarIR> global_variables_;
944   AbiElementMap<RecordTypeIR> record_types_;
945   AbiElementMap<FunctionTypeIR> function_types_;
946   AbiElementMap<EnumTypeIR> enum_types_;
947   // These maps which contain generic referring types as values are used while
948   // looking up whether in the parent graph, a particular referring type refers
949   // to a certain type id. The mechanism is useful while trying to determine
950   // whether a generic referring type needs to be newly added to the parent
951   // graph or not.
952   AbiElementMap<PointerTypeIR> pointer_types_;
953   AbiElementMap<LvalueReferenceTypeIR> lvalue_reference_types_;
954   AbiElementMap<RvalueReferenceTypeIR> rvalue_reference_types_;
955   AbiElementMap<ArrayTypeIR> array_types_;
956   AbiElementMap<BuiltinTypeIR> builtin_types_;
957   AbiElementMap<QualifiedTypeIR> qualified_types_;
958   AbiElementMap<ElfFunctionIR> elf_functions_;
959   AbiElementMap<ElfObjectIR> elf_objects_;
960   // type-id -> LinkableMessageIR * map
961   AbiElementMap<const TypeIR *> type_graph_;
962   // maps unique_id + source_file -> TypeDefinition
963   AbiElementUnorderedMap<std::list<TypeDefinition>> odr_list_map_;
964 
965 
966  private:
967   // The compilation unit paths referenced by odr_list_map_;
968   std::set<std::string> compilation_unit_paths_;
969   const std::set<std::string> *exported_headers_;
970 };
971 
972 
973 }  // namespace repr
974 }  // namespace header_checker
975 
976 
977 #endif  // IR_REPRESENTATION_H_
978