xref: /aosp_15_r20/development/vndk/tools/header-checker/src/repr/ir_representation.cpp (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
1 // Copyright (C) 2019 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 #include "repr/ir_representation.h"
16 
17 #include "repr/ir_reader.h"
18 #include "repr/ir_representation_internal.h"
19 
20 #include <utility>
21 
22 
23 namespace header_checker {
24 namespace repr {
25 
26 
27 template <typename T, typename U>
CreateTemp(const U & lm)28 static inline T CreateTemp(const U &lm) {
29   // Cast source const reference to destination const reference and then create
30   // a temporary copy.
31   return static_cast<const T &>(lm);
32 }
33 
34 
AddLinkableMessage(const LinkableMessageIR & lm)35 bool ModuleIR::AddLinkableMessage(const LinkableMessageIR &lm) {
36   switch (lm.GetKind()) {
37     case RecordTypeKind:
38       AddRecordType(CreateTemp<RecordTypeIR>(lm));
39       return true;
40     case EnumTypeKind:
41       AddEnumType(CreateTemp<EnumTypeIR>(lm));
42       return true;
43     case PointerTypeKind:
44       AddPointerType(CreateTemp<PointerTypeIR>(lm));
45       return true;
46     case QualifiedTypeKind:
47       AddQualifiedType(CreateTemp<QualifiedTypeIR>(lm));
48       return true;
49     case ArrayTypeKind:
50       AddArrayType(CreateTemp<ArrayTypeIR>(lm));
51       return true;
52     case LvalueReferenceTypeKind:
53       AddLvalueReferenceType(CreateTemp<LvalueReferenceTypeIR>(lm));
54       return true;
55     case RvalueReferenceTypeKind:
56       AddRvalueReferenceType(CreateTemp<RvalueReferenceTypeIR>(lm));
57       return true;
58     case BuiltinTypeKind:
59       AddBuiltinType(CreateTemp<BuiltinTypeIR>(lm));
60       return true;
61     case FunctionTypeKind:
62       AddFunctionType(CreateTemp<FunctionTypeIR>(lm));
63       return true;
64     case GlobalVarKind:
65       AddGlobalVariable(CreateTemp<GlobalVarIR>(lm));
66       return true;
67     case FunctionKind:
68       AddFunction(CreateTemp<FunctionIR>(lm));
69       return true;
70   }
71   return false;
72 }
73 
74 
AddElfSymbol(const ElfSymbolIR & elf_symbol)75 bool ModuleIR::AddElfSymbol(const ElfSymbolIR &elf_symbol) {
76   switch (elf_symbol.GetKind()) {
77     case ElfSymbolIR::ElfFunctionKind:
78       AddElfFunction(CreateTemp<ElfFunctionIR>(elf_symbol));
79       return true;
80     case ElfSymbolIR::ElfObjectKind:
81       AddElfObject(CreateTemp<ElfObjectIR>(elf_symbol));
82       return true;
83   }
84   return false;
85 }
86 
87 
AddFunction(FunctionIR && function)88 void ModuleIR::AddFunction(FunctionIR &&function) {
89   if (!IsLinkableMessageInExportedHeaders(&function) ||
90       !IsAvailable(function)) {
91     return;
92   }
93   functions_.insert({function.GetLinkerSetKey(), std::move(function)});
94 }
95 
96 
AddGlobalVariable(GlobalVarIR && global_var)97 void ModuleIR::AddGlobalVariable(GlobalVarIR &&global_var) {
98   if (!IsLinkableMessageInExportedHeaders(&global_var) ||
99       !IsAvailable(global_var)) {
100     return;
101   }
102   global_variables_.insert(
103       {global_var.GetLinkerSetKey(), std::move(global_var)});
104 }
105 
106 
FilterRecordFields(RecordTypeIR & record_type) const107 void ModuleIR::FilterRecordFields(RecordTypeIR &record_type) const {
108   if (!availability_.has_value()) {
109     return;
110   }
111   std::vector<RecordFieldIR> new_fields;
112   for (const RecordFieldIR &field : record_type.GetFields()) {
113     if (IsAvailable(field)) {
114       new_fields.emplace_back(field);
115     }
116   }
117   record_type.SetRecordFields(std::move(new_fields));
118 }
119 
120 
AddRecordType(RecordTypeIR && record_type)121 void ModuleIR::AddRecordType(RecordTypeIR &&record_type) {
122   if (!IsLinkableMessageInExportedHeaders(&record_type) ||
123       !IsAvailable(record_type)) {
124     return;
125   }
126   FilterRecordFields(record_type);
127   auto it = AddToMapAndTypeGraph(
128       std::move(record_type), &record_types_, &type_graph_);
129   const std::string &key = GetODRListMapKey(&(it->second));
130   AddToODRListMap(key, &(it->second), compilation_unit_path_);
131 }
132 
133 
AddFunctionType(FunctionTypeIR && function_type)134 void ModuleIR::AddFunctionType(FunctionTypeIR &&function_type) {
135   if (!IsLinkableMessageInExportedHeaders(&function_type)) {
136     return;
137   }
138   auto it = AddToMapAndTypeGraph(
139       std::move(function_type), &function_types_, &type_graph_);
140   const std::string &key = GetODRListMapKey(&(it->second));
141   AddToODRListMap(key, &(it->second), compilation_unit_path_);
142 }
143 
144 
FilterEnumFields(EnumTypeIR & enum_type) const145 void ModuleIR::FilterEnumFields(EnumTypeIR &enum_type) const {
146   if (!availability_.has_value()) {
147     return;
148   }
149   std::vector<EnumFieldIR> new_fields;
150   for (const EnumFieldIR &field : enum_type.GetFields()) {
151     if (IsAvailable(field)) {
152       new_fields.emplace_back(field);
153     }
154   }
155   enum_type.SetFields(std::move(new_fields));
156 }
157 
158 
AddEnumType(EnumTypeIR && enum_type)159 void ModuleIR::AddEnumType(EnumTypeIR &&enum_type) {
160   if (!IsLinkableMessageInExportedHeaders(&enum_type) ||
161       !IsAvailable(enum_type)) {
162     return;
163   }
164   FilterEnumFields(enum_type);
165   auto it = AddToMapAndTypeGraph(
166       std::move(enum_type), &enum_types_, &type_graph_);
167   const std::string &key = GetODRListMapKey(&(it->second));
168   AddToODRListMap(key, (&it->second), compilation_unit_path_);
169 }
170 
171 
AddLvalueReferenceType(LvalueReferenceTypeIR && lvalue_reference_type)172 void ModuleIR::AddLvalueReferenceType(
173     LvalueReferenceTypeIR &&lvalue_reference_type) {
174   if (!IsLinkableMessageInExportedHeaders(&lvalue_reference_type)) {
175     return;
176   }
177   AddToMapAndTypeGraph(std::move(lvalue_reference_type),
178                        &lvalue_reference_types_, &type_graph_);
179 }
180 
181 
AddRvalueReferenceType(RvalueReferenceTypeIR && rvalue_reference_type)182 void ModuleIR::AddRvalueReferenceType(
183     RvalueReferenceTypeIR &&rvalue_reference_type) {
184   if (!IsLinkableMessageInExportedHeaders(&rvalue_reference_type)) {
185     return;
186   }
187   AddToMapAndTypeGraph(std::move(rvalue_reference_type),
188                        &rvalue_reference_types_, &type_graph_);
189 }
190 
191 
AddQualifiedType(QualifiedTypeIR && qualified_type)192 void ModuleIR::AddQualifiedType(QualifiedTypeIR &&qualified_type) {
193   if (!IsLinkableMessageInExportedHeaders(&qualified_type)) {
194     return;
195   }
196   AddToMapAndTypeGraph(std::move(qualified_type), &qualified_types_,
197                        &type_graph_);
198 }
199 
200 
AddArrayType(ArrayTypeIR && array_type)201 void ModuleIR::AddArrayType(ArrayTypeIR &&array_type) {
202   if (!IsLinkableMessageInExportedHeaders(&array_type)) {
203     return;
204   }
205   AddToMapAndTypeGraph(std::move(array_type), &array_types_, &type_graph_);
206 }
207 
208 
AddPointerType(PointerTypeIR && pointer_type)209 void ModuleIR::AddPointerType(PointerTypeIR &&pointer_type) {
210   if (!IsLinkableMessageInExportedHeaders(&pointer_type)) {
211     return;
212   }
213   AddToMapAndTypeGraph(std::move(pointer_type), &pointer_types_, &type_graph_);
214 }
215 
216 
AddBuiltinType(BuiltinTypeIR && builtin_type)217 void ModuleIR::AddBuiltinType(BuiltinTypeIR &&builtin_type) {
218   AddToMapAndTypeGraph(std::move(builtin_type), &builtin_types_, &type_graph_);
219 }
220 
221 
AddElfFunction(ElfFunctionIR && elf_function)222 void ModuleIR::AddElfFunction(ElfFunctionIR &&elf_function) {
223   elf_functions_.insert(
224       {elf_function.GetName(), std::move(elf_function)});
225 }
226 
227 
AddElfObject(ElfObjectIR && elf_object)228 void ModuleIR::AddElfObject(ElfObjectIR &&elf_object) {
229   elf_objects_.insert(
230       {elf_object.GetName(), std::move(elf_object)});
231 }
232 
233 
GetCompilationUnitPath(const TypeIR * type_ir) const234 std::string ModuleIR::GetCompilationUnitPath(const TypeIR *type_ir) const {
235   std::string key;
236   switch (type_ir->GetKind()) {
237     case RecordTypeKind:
238       key = GetODRListMapKey(static_cast<const RecordTypeIR *>(type_ir));
239       break;
240     case EnumTypeKind:
241       key = GetODRListMapKey(static_cast<const EnumTypeIR *>(type_ir));
242       break;
243     case FunctionTypeKind:
244       key = GetODRListMapKey(static_cast<const FunctionTypeIR *>(type_ir));
245       break;
246     default:
247       return "";
248   }
249   auto it = odr_list_map_.find(key);
250   if (it == odr_list_map_.end()) {
251     return "";
252   }
253   for (const auto &definition : it->second) {
254     if (definition.type_ir_ == type_ir) {
255       return definition.compilation_unit_path_;
256     }
257   }
258   return "";
259 }
260 
261 
IsLinkableMessageInExportedHeaders(const LinkableMessageIR * linkable_message) const262 bool ModuleIR::IsLinkableMessageInExportedHeaders(
263     const LinkableMessageIR *linkable_message) const {
264   if (exported_headers_ == nullptr || exported_headers_->empty()) {
265     return true;
266   }
267   return exported_headers_->find(linkable_message->GetSourceFile()) !=
268          exported_headers_->end();
269 }
270 
271 
IsAvailable(const HasAvailabilityAttrs & decl_ir) const272 bool ModuleIR::IsAvailable(const HasAvailabilityAttrs &decl_ir) const {
273   if (!availability_.has_value()) {
274     return true;
275   }
276   for (const AvailabilityAttrIR &attr : decl_ir.GetAvailabilityAttrs()) {
277     if (attr.IsUnavailable()) {
278       return false;
279     }
280     if (auto introduced = attr.GetIntroduced();
281         introduced.has_value() && availability_.value() < introduced.value()) {
282       return false;
283     }
284     if (auto obsoleted = attr.GetObsoleted();
285         obsoleted.has_value() && availability_.value() >= obsoleted.value()) {
286       return false;
287     }
288   }
289   return true;
290 }
291 
292 
293 }  // namespace repr
294 }  // namespace header_checker
295