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