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 
24 namespace header_checker {
25 namespace repr {
26 
27 
CompatibilityStatusIRToProtobuf(CompatibilityStatusIR status)28 inline abi_diff::CompatibilityStatus CompatibilityStatusIRToProtobuf(
29     CompatibilityStatusIR status) {
30   switch (status) {
31     case CompatibilityStatusIR::Incompatible:
32       return abi_diff::CompatibilityStatus::INCOMPATIBLE;
33     case CompatibilityStatusIR::Extension:
34       return abi_diff::CompatibilityStatus::EXTENSION;
35     default:
36       break;
37   }
38   return abi_diff::CompatibilityStatus::COMPATIBLE;
39 }
40 
ElfSymbolBindingIRToProtobuf(ElfSymbolIR::ElfSymbolBinding binding)41 inline abi_dump::ElfSymbolBinding ElfSymbolBindingIRToProtobuf(
42     ElfSymbolIR::ElfSymbolBinding binding) {
43   switch (binding) {
44     case ElfSymbolIR::ElfSymbolBinding::Global:
45       return abi_dump::ElfSymbolBinding::Global;
46     case ElfSymbolIR::ElfSymbolBinding::Weak:
47       return abi_dump::ElfSymbolBinding::Weak;
48   }
49   // We skip symbols of all other Bindings
50   // TODO: Add all bindings, don't leave out info
51   assert(0);
52 }
53 
ElfSymbolBindingProtobufToIR(abi_dump::ElfSymbolBinding binding)54 inline ElfSymbolIR::ElfSymbolBinding ElfSymbolBindingProtobufToIR(
55     abi_dump::ElfSymbolBinding binding) {
56   switch (binding) {
57     case abi_dump::ElfSymbolBinding::Global:
58       return ElfSymbolIR::ElfSymbolBinding::Global;
59     case abi_dump::ElfSymbolBinding::Weak:
60       return ElfSymbolIR::ElfSymbolBinding::Weak;
61   }
62   // We skip symbols of all other Bindings
63   assert(0);
64 }
65 
AccessIRToProtobuf(AccessSpecifierIR access)66 inline abi_dump::AccessSpecifier AccessIRToProtobuf(AccessSpecifierIR access) {
67   switch (access) {
68     case AccessSpecifierIR::ProtectedAccess:
69       return abi_dump::AccessSpecifier::protected_access;
70     case AccessSpecifierIR::PrivateAccess:
71       return abi_dump::AccessSpecifier::private_access;
72     default:
73       return abi_dump::AccessSpecifier::public_access;
74   }
75   return abi_dump::AccessSpecifier::public_access;
76 }
77 
AccessProtobufToIR(abi_dump::AccessSpecifier access)78 inline AccessSpecifierIR AccessProtobufToIR(
79     abi_dump::AccessSpecifier access) {
80   switch (access) {
81     case abi_dump::AccessSpecifier::protected_access:
82       return AccessSpecifierIR::ProtectedAccess;
83     case abi_dump::AccessSpecifier::private_access:
84       return AccessSpecifierIR::PrivateAccess;
85     default:
86       return AccessSpecifierIR::PublicAccess;
87   }
88   return AccessSpecifierIR::PublicAccess;
89 }
90 
RecordKindIRToProtobuf(RecordTypeIR::RecordKind kind)91 inline abi_dump::RecordKind RecordKindIRToProtobuf(
92     RecordTypeIR::RecordKind kind) {
93   switch (kind) {
94     case RecordTypeIR::RecordKind::struct_kind:
95       return abi_dump::RecordKind::struct_kind;
96 
97     case RecordTypeIR::RecordKind::class_kind:
98       return abi_dump::RecordKind::class_kind;
99 
100     case RecordTypeIR::RecordKind::union_kind:
101       return abi_dump::RecordKind::union_kind;
102 
103     default:
104       return abi_dump::RecordKind::struct_kind;
105   }
106   // Should not be reached
107   assert(false);
108 }
109 
RecordKindProtobufToIR(abi_dump::RecordKind kind)110 inline RecordTypeIR::RecordKind RecordKindProtobufToIR(
111     abi_dump::RecordKind kind) {
112   switch (kind) {
113     case abi_dump::RecordKind::struct_kind:
114       return RecordTypeIR::struct_kind;
115 
116     case abi_dump::RecordKind::class_kind:
117       return RecordTypeIR::class_kind;
118 
119     case abi_dump::RecordKind::union_kind:
120       return RecordTypeIR::union_kind;
121 
122     default:
123       return RecordTypeIR::struct_kind;
124   }
125   // Should not be reached
126   assert(false);
127 }
128 
VTableComponentKindIRToProtobuf(VTableComponentIR::Kind kind)129 inline abi_dump::VTableComponent::Kind VTableComponentKindIRToProtobuf(
130     VTableComponentIR::Kind kind) {
131   switch (kind) {
132     case VTableComponentIR::Kind::VCallOffset:
133       return abi_dump::VTableComponent_Kind_VCallOffset;
134 
135     case VTableComponentIR::Kind::VBaseOffset:
136       return abi_dump::VTableComponent_Kind_VBaseOffset;
137 
138     case VTableComponentIR::Kind::OffsetToTop:
139       return abi_dump::VTableComponent_Kind_OffsetToTop;
140 
141     case VTableComponentIR::Kind::RTTI:
142       return abi_dump::VTableComponent_Kind_RTTI;
143 
144     case VTableComponentIR::Kind::FunctionPointer:
145       return abi_dump::VTableComponent_Kind_FunctionPointer;
146 
147     case VTableComponentIR::Kind::CompleteDtorPointer:
148       return abi_dump::VTableComponent_Kind_CompleteDtorPointer;
149 
150     case VTableComponentIR::Kind::DeletingDtorPointer:
151       return abi_dump::VTableComponent_Kind_DeletingDtorPointer;
152 
153     default:
154       return abi_dump::VTableComponent_Kind_UnusedFunctionPointer;
155   }
156   // Should not be reached
157   assert(false);
158 }
159 
VTableComponentKindProtobufToIR(abi_dump::VTableComponent_Kind kind)160 inline VTableComponentIR::Kind VTableComponentKindProtobufToIR(
161     abi_dump::VTableComponent_Kind kind) {
162   switch (kind) {
163     case abi_dump::VTableComponent_Kind_VCallOffset:
164       return VTableComponentIR::Kind::VCallOffset;
165 
166     case abi_dump::VTableComponent_Kind_VBaseOffset:
167       return VTableComponentIR::Kind::VBaseOffset;
168 
169     case abi_dump::VTableComponent_Kind_OffsetToTop:
170       return VTableComponentIR::Kind::OffsetToTop;
171 
172     case abi_dump::VTableComponent_Kind_RTTI:
173       return VTableComponentIR::Kind::RTTI;
174 
175     case abi_dump::VTableComponent_Kind_FunctionPointer:
176       return VTableComponentIR::Kind::FunctionPointer;
177 
178     case abi_dump::VTableComponent_Kind_CompleteDtorPointer:
179       return VTableComponentIR::Kind::CompleteDtorPointer;
180 
181     case abi_dump::VTableComponent_Kind_DeletingDtorPointer:
182       return VTableComponentIR::Kind::DeletingDtorPointer;
183 
184     default:
185       return VTableComponentIR::Kind::UnusedFunctionPointer;
186   }
187   // Should not be reached
188   assert(false);
189 }
190 
191 // Convert IR to the messages defined in abi_dump.proto.
192 class IRToProtobufConverter {
193  private:
194   static bool AddTemplateInformation(
195       abi_dump::TemplateInfo *ti, const TemplatedArtifactIR *ta);
196 
197   static bool AddTypeInfo(
198       abi_dump::BasicNamedAndTypedDecl *type_info, const TypeIR *typep);
199 
200   static bool AddRecordFields(
201       abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
202 
203   static bool AddBaseSpecifiers(
204       abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
205 
206   static bool AddVTableLayout(
207       abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
208 
209   static bool AddEnumFields(abi_dump::EnumType *enum_protobuf,
210                             const EnumTypeIR *enum_ir);
211 
212  public:
213   static bool ConvertRecordFieldIR(
214       abi_dump::RecordFieldDecl *record_field_protobuf,
215       const RecordFieldIR *record_field_ir);
216 
217   static bool ConvertCXXBaseSpecifierIR(
218       abi_dump::CXXBaseSpecifier *base_specifier_protobuf,
219       const CXXBaseSpecifierIR &base_specifier_ir);
220 
221   static bool ConvertVTableLayoutIR(
222       abi_dump::VTableLayout *vtable_layout_protobuf,
223       const VTableLayoutIR &vtable_layout_ir);
224 
225   static bool ConvertEnumFieldIR(abi_dump::EnumFieldDecl *enum_field_protobuf,
226                                  const EnumFieldIR *enum_field_ir);
227 
228   static abi_dump::EnumType ConvertEnumTypeIR(const EnumTypeIR *enump);
229 
230   static abi_dump::RecordType ConvertRecordTypeIR(const RecordTypeIR *recordp);
231 
232   static abi_dump::FunctionType ConvertFunctionTypeIR (
233       const FunctionTypeIR *function_typep);
234 
235   template <typename CFunctionLikeMessage>
236   static bool AddFunctionParametersAndSetReturnType(
237       CFunctionLikeMessage *function_like_protobuf,
238       const CFunctionLikeIR *cfunction_like_ir);
239 
240   template <typename CFunctionLikeMessage>
241   static bool AddFunctionParameters(CFunctionLikeMessage *function_protobuf,
242                                     const CFunctionLikeIR *cfunction_like_ir);
243 
244   static abi_dump::FunctionDecl ConvertFunctionIR(const FunctionIR *functionp);
245 
246   static abi_dump::GlobalVarDecl ConvertGlobalVarIR(
247       const GlobalVarIR *global_varp);
248 
249   static abi_dump::PointerType ConvertPointerTypeIR(
250       const PointerTypeIR *pointerp);
251 
252   static abi_dump::QualifiedType ConvertQualifiedTypeIR(
253       const QualifiedTypeIR *qualtypep);
254 
255   static abi_dump::BuiltinType ConvertBuiltinTypeIR(
256       const BuiltinTypeIR *builtin_typep);
257 
258   static abi_dump::ArrayType ConvertArrayTypeIR(
259       const ArrayTypeIR *array_typep);
260 
261   static abi_dump::LvalueReferenceType ConvertLvalueReferenceTypeIR(
262       const LvalueReferenceTypeIR *lvalue_reference_typep);
263 
264   static abi_dump::RvalueReferenceType ConvertRvalueReferenceTypeIR(
265       const RvalueReferenceTypeIR *rvalue_reference_typep);
266 
267   static abi_dump::ElfFunction ConvertElfFunctionIR(
268       const ElfFunctionIR *elf_function_ir);
269 
270   static abi_dump::ElfObject ConvertElfObjectIR(
271       const ElfObjectIR *elf_object_ir);
272 };
273 
274 // Convert IR to the messages defined in abi_diff.proto.
275 class IRDiffToProtobufConverter {
276  private:
277   static bool AddTypeInfoDiff(
278       abi_diff::TypeInfoDiff *type_info_diff_protobuf,
279       const TypeDiffIR *type_diff_ir);
280 
281   static bool AddVTableLayoutDiff(
282       abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf,
283       const VTableLayoutDiffIR *vtable_layout_diff_ir);
284 
285   static bool AddBaseSpecifierDiffs(
286       abi_diff::CXXBaseSpecifierDiff *base_specifier_diff_protobuf,
287       const CXXBaseSpecifierDiffIR *base_specifier_diff_ir);
288 
289   static bool AddRecordFields(
290       abi_diff::RecordTypeDiff *record_diff_protobuf,
291       const std::vector<const RecordFieldIR *> &record_fields_removed_ir,
292       bool removed);
293 
294   static bool AddRecordFieldDiffs(
295       abi_diff::RecordTypeDiff *record_diff_protobuf,
296       const std::vector<RecordFieldDiffIR> &record_field_diff_ir);
297 
298   static bool AddEnumUnderlyingTypeDiff(
299       abi_diff::UnderlyingTypeDiff *underlying_type_diff_protobuf,
300       const std::pair<std::string, std::string> *underlying_type_diff_ir);
301 
302  public:
303   static abi_diff::RecordTypeDiff ConvertRecordTypeDiffIR(
304       const RecordTypeDiffIR *record_type_diffp);
305 
306   static abi_diff::EnumTypeDiff ConvertEnumTypeDiffIR(
307       const EnumTypeDiffIR *enum_type_diffp);
308 
309   static abi_diff::FunctionDeclDiff ConvertFunctionDiffIR(
310       const FunctionDiffIR *function_diffp);
311 
312   static abi_diff::GlobalVarDeclDiff ConvertGlobalVarDiffIR(
313       const GlobalVarDiffIR *global_var_diffp);
314 };
315 
316 
317 }  // namespace repr
318 }  // namespace header_checker
319 
320 
321 #endif  // HEADER_CHECKER_PROTOBUF_CONVERTER_H_
322