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 &¶meter) {
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