• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef HEADER_CHECKER_PROTOBUF_CONVERTER_H_
16 #define HEADER_CHECKER_PROTOBUF_CONVERTER_H_
17 
18 #include "repr/ir_diff_representation.h"
19 #include "repr/ir_representation.h"
20 #include "repr/protobuf/abi_diff.h"
21 #include "repr/protobuf/abi_dump.h"
22 
23 #include <llvm/Support/raw_ostream.h>
24 
25 
26 namespace header_checker {
27 namespace repr {
28 
29 
CompatibilityStatusIRToProtobuf(CompatibilityStatusIR status)30 inline abi_diff::CompatibilityStatus CompatibilityStatusIRToProtobuf(
31     CompatibilityStatusIR status) {
32   switch (status) {
33     case CompatibilityStatusIR::Incompatible:
34       return abi_diff::CompatibilityStatus::INCOMPATIBLE;
35     case CompatibilityStatusIR::Extension:
36       return abi_diff::CompatibilityStatus::EXTENSION;
37     default:
38       break;
39   }
40   return abi_diff::CompatibilityStatus::COMPATIBLE;
41 }
42 
ElfSymbolBindingIRToProtobuf(ElfSymbolIR::ElfSymbolBinding binding)43 inline abi_dump::ElfSymbolBinding ElfSymbolBindingIRToProtobuf(
44     ElfSymbolIR::ElfSymbolBinding binding) {
45   switch (binding) {
46     case ElfSymbolIR::ElfSymbolBinding::Global:
47       return abi_dump::ElfSymbolBinding::Global;
48     case ElfSymbolIR::ElfSymbolBinding::Weak:
49       return abi_dump::ElfSymbolBinding::Weak;
50   }
51   // We skip symbols of all other Bindings
52   // TODO: Add all bindings, don't leave out info
53   assert(0);
54 }
55 
ElfSymbolBindingProtobufToIR(abi_dump::ElfSymbolBinding binding)56 inline ElfSymbolIR::ElfSymbolBinding ElfSymbolBindingProtobufToIR(
57     abi_dump::ElfSymbolBinding binding) {
58   switch (binding) {
59     case abi_dump::ElfSymbolBinding::Global:
60       return ElfSymbolIR::ElfSymbolBinding::Global;
61     case abi_dump::ElfSymbolBinding::Weak:
62       return ElfSymbolIR::ElfSymbolBinding::Weak;
63   }
64   // We skip symbols of all other Bindings
65   assert(0);
66 }
67 
AccessIRToProtobuf(AccessSpecifierIR access)68 inline abi_dump::AccessSpecifier AccessIRToProtobuf(AccessSpecifierIR access) {
69   switch (access) {
70     case AccessSpecifierIR::ProtectedAccess:
71       return abi_dump::AccessSpecifier::protected_access;
72     case AccessSpecifierIR::PrivateAccess:
73       return abi_dump::AccessSpecifier::private_access;
74     default:
75       return abi_dump::AccessSpecifier::public_access;
76   }
77   return abi_dump::AccessSpecifier::public_access;
78 }
79 
AccessProtobufToIR(abi_dump::AccessSpecifier access)80 inline AccessSpecifierIR AccessProtobufToIR(
81     abi_dump::AccessSpecifier access) {
82   switch (access) {
83     case abi_dump::AccessSpecifier::protected_access:
84       return AccessSpecifierIR::ProtectedAccess;
85     case abi_dump::AccessSpecifier::private_access:
86       return AccessSpecifierIR::PrivateAccess;
87     default:
88       return AccessSpecifierIR::PublicAccess;
89   }
90   return AccessSpecifierIR::PublicAccess;
91 }
92 
RecordKindIRToProtobuf(RecordTypeIR::RecordKind kind)93 inline abi_dump::RecordKind RecordKindIRToProtobuf(
94     RecordTypeIR::RecordKind kind) {
95   switch (kind) {
96     case RecordTypeIR::RecordKind::struct_kind:
97       return abi_dump::RecordKind::struct_kind;
98 
99     case RecordTypeIR::RecordKind::class_kind:
100       return abi_dump::RecordKind::class_kind;
101 
102     case RecordTypeIR::RecordKind::union_kind:
103       return abi_dump::RecordKind::union_kind;
104 
105     default:
106       return abi_dump::RecordKind::struct_kind;
107   }
108   // Should not be reached
109   assert(false);
110 }
111 
RecordKindProtobufToIR(abi_dump::RecordKind kind)112 inline RecordTypeIR::RecordKind RecordKindProtobufToIR(
113     abi_dump::RecordKind kind) {
114   switch (kind) {
115     case abi_dump::RecordKind::struct_kind:
116       return RecordTypeIR::struct_kind;
117 
118     case abi_dump::RecordKind::class_kind:
119       return RecordTypeIR::class_kind;
120 
121     case abi_dump::RecordKind::union_kind:
122       return RecordTypeIR::union_kind;
123 
124     default:
125       return RecordTypeIR::struct_kind;
126   }
127   // Should not be reached
128   assert(false);
129 }
130 
VTableComponentKindIRToProtobuf(VTableComponentIR::Kind kind)131 inline abi_dump::VTableComponent::Kind VTableComponentKindIRToProtobuf(
132     VTableComponentIR::Kind kind) {
133   switch (kind) {
134     case VTableComponentIR::Kind::VCallOffset:
135       return abi_dump::VTableComponent_Kind_VCallOffset;
136 
137     case VTableComponentIR::Kind::VBaseOffset:
138       return abi_dump::VTableComponent_Kind_VBaseOffset;
139 
140     case VTableComponentIR::Kind::OffsetToTop:
141       return abi_dump::VTableComponent_Kind_OffsetToTop;
142 
143     case VTableComponentIR::Kind::RTTI:
144       return abi_dump::VTableComponent_Kind_RTTI;
145 
146     case VTableComponentIR::Kind::FunctionPointer:
147       return abi_dump::VTableComponent_Kind_FunctionPointer;
148 
149     case VTableComponentIR::Kind::CompleteDtorPointer:
150       return abi_dump::VTableComponent_Kind_CompleteDtorPointer;
151 
152     case VTableComponentIR::Kind::DeletingDtorPointer:
153       return abi_dump::VTableComponent_Kind_DeletingDtorPointer;
154 
155     default:
156       return abi_dump::VTableComponent_Kind_UnusedFunctionPointer;
157   }
158   // Should not be reached
159   assert(false);
160 }
161 
VTableComponentKindProtobufToIR(abi_dump::VTableComponent_Kind kind)162 inline VTableComponentIR::Kind VTableComponentKindProtobufToIR(
163     abi_dump::VTableComponent_Kind kind) {
164   switch (kind) {
165     case abi_dump::VTableComponent_Kind_VCallOffset:
166       return VTableComponentIR::Kind::VCallOffset;
167 
168     case abi_dump::VTableComponent_Kind_VBaseOffset:
169       return VTableComponentIR::Kind::VBaseOffset;
170 
171     case abi_dump::VTableComponent_Kind_OffsetToTop:
172       return VTableComponentIR::Kind::OffsetToTop;
173 
174     case abi_dump::VTableComponent_Kind_RTTI:
175       return VTableComponentIR::Kind::RTTI;
176 
177     case abi_dump::VTableComponent_Kind_FunctionPointer:
178       return VTableComponentIR::Kind::FunctionPointer;
179 
180     case abi_dump::VTableComponent_Kind_CompleteDtorPointer:
181       return VTableComponentIR::Kind::CompleteDtorPointer;
182 
183     case abi_dump::VTableComponent_Kind_DeletingDtorPointer:
184       return VTableComponentIR::Kind::DeletingDtorPointer;
185 
186     default:
187       return VTableComponentIR::Kind::UnusedFunctionPointer;
188   }
189   // Should not be reached
190   assert(false);
191 }
192 
193 class IRToProtobufConverter {
194  private:
195   static bool AddTemplateInformation(
196       abi_dump::TemplateInfo *ti, const TemplatedArtifactIR *ta);
197 
198   static bool AddTypeInfo(
199       abi_dump::BasicNamedAndTypedDecl *type_info, const TypeIR *typep);
200 
201   static bool AddRecordFields(
202       abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
203 
204   static bool AddBaseSpecifiers(
205       abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
206 
207   static bool AddVTableLayout(
208       abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
209 
210   static bool AddTagTypeInfo(abi_dump::TagType *tag_type_protobuf,
211                              const TagTypeIR *tag_type_ir);
212 
213   static bool AddEnumFields(abi_dump::EnumType *enum_protobuf,
214                             const EnumTypeIR *enum_ir);
215 
216  public:
217   static abi_dump::EnumType ConvertEnumTypeIR(const EnumTypeIR *enump);
218 
219   static abi_dump::RecordType ConvertRecordTypeIR(const RecordTypeIR *recordp);
220 
221   static abi_dump::FunctionType ConvertFunctionTypeIR (
222       const FunctionTypeIR *function_typep);
223 
224   template <typename CFunctionLikeMessage>
225   static bool AddFunctionParametersAndSetReturnType(
226       CFunctionLikeMessage *function_like_protobuf,
227       const CFunctionLikeIR *cfunction_like_ir);
228 
229   template <typename CFunctionLikeMessage>
230   static bool AddFunctionParameters(CFunctionLikeMessage *function_protobuf,
231                                     const CFunctionLikeIR *cfunction_like_ir);
232 
233   static abi_dump::FunctionDecl ConvertFunctionIR(const FunctionIR *functionp);
234 
235   static abi_dump::GlobalVarDecl ConvertGlobalVarIR(
236       const GlobalVarIR *global_varp);
237 
238   static abi_dump::PointerType ConvertPointerTypeIR(
239       const PointerTypeIR *pointerp);
240 
241   static abi_dump::QualifiedType ConvertQualifiedTypeIR(
242       const QualifiedTypeIR *qualtypep);
243 
244   static abi_dump::BuiltinType ConvertBuiltinTypeIR(
245       const BuiltinTypeIR *builtin_typep);
246 
247   static abi_dump::ArrayType ConvertArrayTypeIR(
248       const ArrayTypeIR *array_typep);
249 
250   static abi_dump::LvalueReferenceType ConvertLvalueReferenceTypeIR(
251       const LvalueReferenceTypeIR *lvalue_reference_typep);
252 
253   static abi_dump::RvalueReferenceType ConvertRvalueReferenceTypeIR(
254       const RvalueReferenceTypeIR *rvalue_reference_typep);
255 
256   static abi_dump::ElfFunction ConvertElfFunctionIR(
257       const ElfFunctionIR *elf_function_ir);
258 
259   static abi_dump::ElfObject ConvertElfObjectIR(
260       const ElfObjectIR *elf_object_ir);
261 };
262 
263 class IRDiffToProtobufConverter {
264  private:
265   static bool AddTypeInfoDiff(
266       abi_diff::TypeInfoDiff *type_info_diff_protobuf,
267       const TypeDiffIR *type_diff_ir);
268 
269   static bool AddVTableLayoutDiff(
270       abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf,
271       const VTableLayoutDiffIR *vtable_layout_diff_ir);
272 
273   static bool AddBaseSpecifierDiffs(
274       abi_diff::CXXBaseSpecifierDiff *base_specifier_diff_protobuf,
275       const CXXBaseSpecifierDiffIR *base_specifier_diff_ir);
276 
277   static bool AddRecordFields(
278       abi_diff::RecordTypeDiff *record_diff_protobuf,
279       const std::vector<const RecordFieldIR *> &record_fields_removed_ir,
280       bool removed);
281 
282   static bool AddRecordFieldDiffs(
283       abi_diff::RecordTypeDiff *record_diff_protobuf,
284       const std::vector<RecordFieldDiffIR> &record_field_diff_ir);
285 
286   static bool AddEnumUnderlyingTypeDiff(
287       abi_diff::UnderlyingTypeDiff *underlying_type_diff_protobuf,
288       const std::pair<std::string, std::string> *underlying_type_diff_ir);
289 
290  public:
291   static abi_diff::RecordTypeDiff ConvertRecordTypeDiffIR(
292       const RecordTypeDiffIR *record_type_diffp);
293 
294   static abi_diff::EnumTypeDiff ConvertEnumTypeDiffIR(
295       const EnumTypeDiffIR *enum_type_diffp);
296 
297   static abi_diff::FunctionDeclDiff ConvertFunctionDiffIR(
298       const FunctionDiffIR *function_diffp);
299 
300   static abi_diff::GlobalVarDeclDiff ConvertGlobalVarDiffIR(
301       const GlobalVarDiffIR *global_var_diffp);
302 };
303 
SetIRToProtobufRecordField(abi_dump::RecordFieldDecl * record_field_protobuf,const RecordFieldIR * record_field_ir)304 inline void SetIRToProtobufRecordField(
305     abi_dump::RecordFieldDecl *record_field_protobuf,
306     const RecordFieldIR *record_field_ir) {
307   record_field_protobuf->set_field_name(record_field_ir->GetName());
308   record_field_protobuf->set_referenced_type(
309       record_field_ir->GetReferencedType());
310   record_field_protobuf->set_access(
311       AccessIRToProtobuf(record_field_ir->GetAccess()));
312   record_field_protobuf->set_field_offset(record_field_ir->GetOffset());
313 }
314 
SetIRToProtobufBaseSpecifier(abi_dump::CXXBaseSpecifier * base_specifier_protobuf,const CXXBaseSpecifierIR & base_specifier_ir)315 inline bool SetIRToProtobufBaseSpecifier(
316     abi_dump::CXXBaseSpecifier *base_specifier_protobuf,
317     const CXXBaseSpecifierIR &base_specifier_ir) {
318   if (!base_specifier_protobuf) {
319     llvm::errs() << "Protobuf base specifier not valid\n";
320     return false;
321   }
322   base_specifier_protobuf->set_referenced_type(
323       base_specifier_ir.GetReferencedType());
324   base_specifier_protobuf->set_is_virtual(
325       base_specifier_ir.IsVirtual());
326   base_specifier_protobuf->set_access(
327       AccessIRToProtobuf(base_specifier_ir.GetAccess()));
328   return true;
329 }
330 
SetIRToProtobufVTableLayout(abi_dump::VTableLayout * vtable_layout_protobuf,const VTableLayoutIR & vtable_layout_ir)331 inline bool SetIRToProtobufVTableLayout(
332     abi_dump::VTableLayout *vtable_layout_protobuf,
333     const VTableLayoutIR &vtable_layout_ir) {
334   if (vtable_layout_protobuf == nullptr) {
335     llvm::errs() << "vtable layout protobuf not valid\n";
336     return false;
337   }
338   for (auto &&vtable_component_ir : vtable_layout_ir.GetVTableComponents()) {
339     abi_dump::VTableComponent *added_vtable_component =
340         vtable_layout_protobuf->add_vtable_components();
341     if (!added_vtable_component) {
342       llvm::errs() << "Couldn't add vtable component\n";
343       return false;
344     }
345     added_vtable_component->set_kind(
346         VTableComponentKindIRToProtobuf(vtable_component_ir.GetKind()));
347     added_vtable_component->set_component_value(vtable_component_ir.GetValue());
348     added_vtable_component->set_mangled_component_name(
349         vtable_component_ir.GetName());
350     added_vtable_component->set_is_pure(vtable_component_ir.GetIsPure());
351   }
352   return true;
353 }
354 
SetIRToProtobufEnumField(abi_dump::EnumFieldDecl * enum_field_protobuf,const EnumFieldIR * enum_field_ir)355 inline bool SetIRToProtobufEnumField(
356     abi_dump::EnumFieldDecl *enum_field_protobuf,
357     const EnumFieldIR *enum_field_ir) {
358   if (enum_field_protobuf == nullptr) {
359     return true;
360   }
361   enum_field_protobuf->set_name(enum_field_ir->GetName());
362   enum_field_protobuf->set_enum_field_value(enum_field_ir->GetValue());
363   return true;
364 }
365 
366 
367 }  // namespace repr
368 }  // namespace header_checker
369 
370 
371 #endif  // HEADER_CHECKER_PROTOBUF_CONVERTER_H_
372