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