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