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 return;
91 }
92 functions_.insert({function.GetLinkerSetKey(), std::move(function)});
93 }
94
95
AddGlobalVariable(GlobalVarIR && global_var)96 void ModuleIR::AddGlobalVariable(GlobalVarIR &&global_var) {
97 if (!IsLinkableMessageInExportedHeaders(&global_var)) {
98 return;
99 }
100 global_variables_.insert(
101 {global_var.GetLinkerSetKey(), std::move(global_var)});
102 }
103
104
AddRecordType(RecordTypeIR && record_type)105 void ModuleIR::AddRecordType(RecordTypeIR &&record_type) {
106 if (!IsLinkableMessageInExportedHeaders(&record_type)) {
107 return;
108 }
109 auto it = AddToMapAndTypeGraph(
110 std::move(record_type), &record_types_, &type_graph_);
111 const std::string &key = GetODRListMapKey(&(it->second));
112 AddToODRListMap(key, &(it->second), compilation_unit_path_);
113 }
114
115
AddFunctionType(FunctionTypeIR && function_type)116 void ModuleIR::AddFunctionType(FunctionTypeIR &&function_type) {
117 if (!IsLinkableMessageInExportedHeaders(&function_type)) {
118 return;
119 }
120 auto it = AddToMapAndTypeGraph(
121 std::move(function_type), &function_types_, &type_graph_);
122 const std::string &key = GetODRListMapKey(&(it->second));
123 AddToODRListMap(key, &(it->second), compilation_unit_path_);
124 }
125
126
AddEnumType(EnumTypeIR && enum_type)127 void ModuleIR::AddEnumType(EnumTypeIR &&enum_type) {
128 if (!IsLinkableMessageInExportedHeaders(&enum_type)) {
129 return;
130 }
131 auto it = AddToMapAndTypeGraph(
132 std::move(enum_type), &enum_types_, &type_graph_);
133 const std::string &key = GetODRListMapKey(&(it->second));
134 AddToODRListMap(key, (&it->second), compilation_unit_path_);
135 }
136
137
AddLvalueReferenceType(LvalueReferenceTypeIR && lvalue_reference_type)138 void ModuleIR::AddLvalueReferenceType(
139 LvalueReferenceTypeIR &&lvalue_reference_type) {
140 if (!IsLinkableMessageInExportedHeaders(&lvalue_reference_type)) {
141 return;
142 }
143 AddToMapAndTypeGraph(std::move(lvalue_reference_type),
144 &lvalue_reference_types_, &type_graph_);
145 }
146
147
AddRvalueReferenceType(RvalueReferenceTypeIR && rvalue_reference_type)148 void ModuleIR::AddRvalueReferenceType(
149 RvalueReferenceTypeIR &&rvalue_reference_type) {
150 if (!IsLinkableMessageInExportedHeaders(&rvalue_reference_type)) {
151 return;
152 }
153 AddToMapAndTypeGraph(std::move(rvalue_reference_type),
154 &rvalue_reference_types_, &type_graph_);
155 }
156
157
AddQualifiedType(QualifiedTypeIR && qualified_type)158 void ModuleIR::AddQualifiedType(QualifiedTypeIR &&qualified_type) {
159 if (!IsLinkableMessageInExportedHeaders(&qualified_type)) {
160 return;
161 }
162 AddToMapAndTypeGraph(std::move(qualified_type), &qualified_types_,
163 &type_graph_);
164 }
165
166
AddArrayType(ArrayTypeIR && array_type)167 void ModuleIR::AddArrayType(ArrayTypeIR &&array_type) {
168 if (!IsLinkableMessageInExportedHeaders(&array_type)) {
169 return;
170 }
171 AddToMapAndTypeGraph(std::move(array_type), &array_types_, &type_graph_);
172 }
173
174
AddPointerType(PointerTypeIR && pointer_type)175 void ModuleIR::AddPointerType(PointerTypeIR &&pointer_type) {
176 if (!IsLinkableMessageInExportedHeaders(&pointer_type)) {
177 return;
178 }
179 AddToMapAndTypeGraph(std::move(pointer_type), &pointer_types_, &type_graph_);
180 }
181
182
AddBuiltinType(BuiltinTypeIR && builtin_type)183 void ModuleIR::AddBuiltinType(BuiltinTypeIR &&builtin_type) {
184 AddToMapAndTypeGraph(std::move(builtin_type), &builtin_types_, &type_graph_);
185 }
186
187
AddElfFunction(ElfFunctionIR && elf_function)188 void ModuleIR::AddElfFunction(ElfFunctionIR &&elf_function) {
189 elf_functions_.insert(
190 {elf_function.GetName(), std::move(elf_function)});
191 }
192
193
AddElfObject(ElfObjectIR && elf_object)194 void ModuleIR::AddElfObject(ElfObjectIR &&elf_object) {
195 elf_objects_.insert(
196 {elf_object.GetName(), std::move(elf_object)});
197 }
198
199
GetCompilationUnitPath(const TypeIR * type_ir) const200 std::string ModuleIR::GetCompilationUnitPath(const TypeIR *type_ir) const {
201 std::string key;
202 switch (type_ir->GetKind()) {
203 case RecordTypeKind:
204 key = GetODRListMapKey(static_cast<const RecordTypeIR *>(type_ir));
205 break;
206 case EnumTypeKind:
207 key = GetODRListMapKey(static_cast<const EnumTypeIR *>(type_ir));
208 break;
209 case FunctionTypeKind:
210 key = GetODRListMapKey(static_cast<const FunctionTypeIR *>(type_ir));
211 break;
212 default:
213 return "";
214 }
215 auto it = odr_list_map_.find(key);
216 if (it == odr_list_map_.end()) {
217 return "";
218 }
219 for (const auto &definition : it->second) {
220 if (definition.type_ir_ == type_ir) {
221 return definition.compilation_unit_path_;
222 }
223 }
224 return "";
225 }
226
227
IsLinkableMessageInExportedHeaders(const LinkableMessageIR * linkable_message) const228 bool ModuleIR::IsLinkableMessageInExportedHeaders(
229 const LinkableMessageIR *linkable_message) const {
230 if (exported_headers_ == nullptr || exported_headers_->empty()) {
231 return true;
232 }
233 return exported_headers_->find(linkable_message->GetSourceFile()) !=
234 exported_headers_->end();
235 }
236
237
238 } // namespace repr
239 } // namespace header_checker
240