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 AddEnumFields(abi_dump::EnumType *enum_protobuf,
211 const EnumTypeIR *enum_ir);
212
213 public:
214 static abi_dump::EnumType ConvertEnumTypeIR(const EnumTypeIR *enump);
215
216 static abi_dump::RecordType ConvertRecordTypeIR(const RecordTypeIR *recordp);
217
218 static abi_dump::FunctionType ConvertFunctionTypeIR (
219 const FunctionTypeIR *function_typep);
220
221 template <typename CFunctionLikeMessage>
222 static bool AddFunctionParametersAndSetReturnType(
223 CFunctionLikeMessage *function_like_protobuf,
224 const CFunctionLikeIR *cfunction_like_ir);
225
226 template <typename CFunctionLikeMessage>
227 static bool AddFunctionParameters(CFunctionLikeMessage *function_protobuf,
228 const CFunctionLikeIR *cfunction_like_ir);
229
230 static abi_dump::FunctionDecl ConvertFunctionIR(const FunctionIR *functionp);
231
232 static abi_dump::GlobalVarDecl ConvertGlobalVarIR(
233 const GlobalVarIR *global_varp);
234
235 static abi_dump::PointerType ConvertPointerTypeIR(
236 const PointerTypeIR *pointerp);
237
238 static abi_dump::QualifiedType ConvertQualifiedTypeIR(
239 const QualifiedTypeIR *qualtypep);
240
241 static abi_dump::BuiltinType ConvertBuiltinTypeIR(
242 const BuiltinTypeIR *builtin_typep);
243
244 static abi_dump::ArrayType ConvertArrayTypeIR(
245 const ArrayTypeIR *array_typep);
246
247 static abi_dump::LvalueReferenceType ConvertLvalueReferenceTypeIR(
248 const LvalueReferenceTypeIR *lvalue_reference_typep);
249
250 static abi_dump::RvalueReferenceType ConvertRvalueReferenceTypeIR(
251 const RvalueReferenceTypeIR *rvalue_reference_typep);
252
253 static abi_dump::ElfFunction ConvertElfFunctionIR(
254 const ElfFunctionIR *elf_function_ir);
255
256 static abi_dump::ElfObject ConvertElfObjectIR(
257 const ElfObjectIR *elf_object_ir);
258 };
259
260 class IRDiffToProtobufConverter {
261 private:
262 static bool AddTypeInfoDiff(
263 abi_diff::TypeInfoDiff *type_info_diff_protobuf,
264 const TypeDiffIR *type_diff_ir);
265
266 static bool AddVTableLayoutDiff(
267 abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf,
268 const VTableLayoutDiffIR *vtable_layout_diff_ir);
269
270 static bool AddBaseSpecifierDiffs(
271 abi_diff::CXXBaseSpecifierDiff *base_specifier_diff_protobuf,
272 const CXXBaseSpecifierDiffIR *base_specifier_diff_ir);
273
274 static bool AddRecordFields(
275 abi_diff::RecordTypeDiff *record_diff_protobuf,
276 const std::vector<const RecordFieldIR *> &record_fields_removed_ir,
277 bool removed);
278
279 static bool AddRecordFieldDiffs(
280 abi_diff::RecordTypeDiff *record_diff_protobuf,
281 const std::vector<RecordFieldDiffIR> &record_field_diff_ir);
282
283 static bool AddEnumUnderlyingTypeDiff(
284 abi_diff::UnderlyingTypeDiff *underlying_type_diff_protobuf,
285 const std::pair<std::string, std::string> *underlying_type_diff_ir);
286
287 public:
288 static abi_diff::RecordTypeDiff ConvertRecordTypeDiffIR(
289 const RecordTypeDiffIR *record_type_diffp);
290
291 static abi_diff::EnumTypeDiff ConvertEnumTypeDiffIR(
292 const EnumTypeDiffIR *enum_type_diffp);
293
294 static abi_diff::FunctionDeclDiff ConvertFunctionDiffIR(
295 const FunctionDiffIR *function_diffp);
296
297 static abi_diff::GlobalVarDeclDiff ConvertGlobalVarDiffIR(
298 const GlobalVarDiffIR *global_var_diffp);
299 };
300
SetIRToProtobufRecordField(abi_dump::RecordFieldDecl * record_field_protobuf,const RecordFieldIR * record_field_ir)301 inline void SetIRToProtobufRecordField(
302 abi_dump::RecordFieldDecl *record_field_protobuf,
303 const RecordFieldIR *record_field_ir) {
304 record_field_protobuf->set_field_name(record_field_ir->GetName());
305 record_field_protobuf->set_referenced_type(
306 record_field_ir->GetReferencedType());
307 record_field_protobuf->set_access(
308 AccessIRToProtobuf(record_field_ir->GetAccess()));
309 record_field_protobuf->set_field_offset(record_field_ir->GetOffset());
310 }
311
SetIRToProtobufBaseSpecifier(abi_dump::CXXBaseSpecifier * base_specifier_protobuf,const CXXBaseSpecifierIR & base_specifier_ir)312 inline bool SetIRToProtobufBaseSpecifier(
313 abi_dump::CXXBaseSpecifier *base_specifier_protobuf,
314 const CXXBaseSpecifierIR &base_specifier_ir) {
315 if (!base_specifier_protobuf) {
316 llvm::errs() << "Protobuf base specifier not valid\n";
317 return false;
318 }
319 base_specifier_protobuf->set_referenced_type(
320 base_specifier_ir.GetReferencedType());
321 base_specifier_protobuf->set_is_virtual(
322 base_specifier_ir.IsVirtual());
323 base_specifier_protobuf->set_access(
324 AccessIRToProtobuf(base_specifier_ir.GetAccess()));
325 return true;
326 }
327
SetIRToProtobufVTableLayout(abi_dump::VTableLayout * vtable_layout_protobuf,const VTableLayoutIR & vtable_layout_ir)328 inline bool SetIRToProtobufVTableLayout(
329 abi_dump::VTableLayout *vtable_layout_protobuf,
330 const VTableLayoutIR &vtable_layout_ir) {
331 if (vtable_layout_protobuf == nullptr) {
332 llvm::errs() << "vtable layout protobuf not valid\n";
333 return false;
334 }
335 for (auto &&vtable_component_ir : vtable_layout_ir.GetVTableComponents()) {
336 abi_dump::VTableComponent *added_vtable_component =
337 vtable_layout_protobuf->add_vtable_components();
338 if (!added_vtable_component) {
339 llvm::errs() << "Couldn't add vtable component\n";
340 return false;
341 }
342 added_vtable_component->set_kind(
343 VTableComponentKindIRToProtobuf(vtable_component_ir.GetKind()));
344 added_vtable_component->set_component_value(vtable_component_ir.GetValue());
345 added_vtable_component->set_mangled_component_name(
346 vtable_component_ir.GetName());
347 added_vtable_component->set_is_pure(vtable_component_ir.GetIsPure());
348 }
349 return true;
350 }
351
SetIRToProtobufEnumField(abi_dump::EnumFieldDecl * enum_field_protobuf,const EnumFieldIR * enum_field_ir)352 inline bool SetIRToProtobufEnumField(
353 abi_dump::EnumFieldDecl *enum_field_protobuf,
354 const EnumFieldIR *enum_field_ir) {
355 if (enum_field_protobuf == nullptr) {
356 return true;
357 }
358 enum_field_protobuf->set_name(enum_field_ir->GetName());
359 enum_field_protobuf->set_enum_field_value(enum_field_ir->GetValue());
360 return true;
361 }
362
363
364 } // namespace repr
365 } // namespace header_checker
366
367
368 #endif // HEADER_CHECKER_PROTOBUF_CONVERTER_H_
369