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