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/protobuf/ir_dumper.h"
16
17 #include "repr/protobuf/abi_dump.h"
18 #include "repr/protobuf/api.h"
19 #include "repr/protobuf/converter.h"
20
21 #include <fstream>
22 #include <memory>
23
24 #include <llvm/Support/raw_ostream.h>
25
26 #include <google/protobuf/io/zero_copy_stream_impl.h>
27 #include <google/protobuf/text_format.h>
28
29
30 namespace header_checker {
31 namespace repr {
32
AddTemplateInformation(abi_dump::TemplateInfo * ti,const TemplatedArtifactIR * ta)33 static bool AddTemplateInformation(abi_dump::TemplateInfo *ti,
34 const TemplatedArtifactIR *ta) {
35 for (auto &&template_element : ta->GetTemplateElements()) {
36 abi_dump::TemplateElement *added_element = ti->add_elements();
37 if (!added_element) {
38 llvm::errs() << "Failed to add template element\n";
39 return false;
40 }
41 added_element->set_referenced_type(template_element.GetReferencedType());
42 }
43 return true;
44 }
45
AddTypeInfo(abi_dump::BasicNamedAndTypedDecl * type_info,const TypeIR * typep)46 static bool AddTypeInfo(abi_dump::BasicNamedAndTypedDecl *type_info,
47 const TypeIR *typep) {
48 if (!type_info || !typep) {
49 llvm::errs() << "Typeinfo not valid\n";
50 return false;
51 }
52 type_info->set_linker_set_key(typep->GetLinkerSetKey());
53 type_info->set_source_file(typep->GetSourceFile());
54 type_info->set_name(typep->GetName());
55 type_info->set_size(typep->GetSize());
56 type_info->set_alignment(typep->GetAlignment());
57 type_info->set_referenced_type(typep->GetReferencedType());
58 type_info->set_self_type(typep->GetSelfType());
59 return true;
60 }
61
62 template <typename HasAvailabilityAttrsMessage>
AddAvailabilityAttrs(HasAvailabilityAttrsMessage * decl_protobuf,const HasAvailabilityAttrs * decl_ir)63 void AddAvailabilityAttrs(HasAvailabilityAttrsMessage *decl_protobuf,
64 const HasAvailabilityAttrs *decl_ir) {
65 for (const AvailabilityAttrIR &attr : decl_ir->GetAvailabilityAttrs()) {
66 abi_dump::AvailabilityAttr *attr_protobuf =
67 decl_protobuf->add_availability_attrs();
68 if (auto introduced = attr.GetIntroduced(); introduced.has_value()) {
69 attr_protobuf->set_introduced_major(introduced.value());
70 }
71 if (auto deprecated = attr.GetDeprecated(); deprecated.has_value()) {
72 attr_protobuf->set_deprecated_major(deprecated.value());
73 }
74 if (auto obsoleted = attr.GetObsoleted(); obsoleted.has_value()) {
75 attr_protobuf->set_obsoleted_major(obsoleted.value());
76 }
77 if (attr.IsUnavailable()) {
78 attr_protobuf->set_unavailable(true);
79 }
80 }
81 }
82
ConvertRecordFieldIR(abi_dump::RecordFieldDecl * record_field_protobuf,const RecordFieldIR * record_field_ir)83 bool ConvertRecordFieldIR(abi_dump::RecordFieldDecl *record_field_protobuf,
84 const RecordFieldIR *record_field_ir) {
85 if (!record_field_protobuf) {
86 llvm::errs() << "Invalid record field\n";
87 return false;
88 }
89 record_field_protobuf->set_field_name(record_field_ir->GetName());
90 record_field_protobuf->set_referenced_type(
91 record_field_ir->GetReferencedType());
92 record_field_protobuf->set_access(
93 AccessIRToProtobuf(record_field_ir->GetAccess()));
94 record_field_protobuf->set_field_offset(record_field_ir->GetOffset());
95 if (record_field_ir->IsBitField()) {
96 record_field_protobuf->set_is_bit_field(true);
97 record_field_protobuf->set_bit_width(record_field_ir->GetBitWidth());
98 }
99 AddAvailabilityAttrs(record_field_protobuf, record_field_ir);
100 return true;
101 }
102
AddRecordFields(abi_dump::RecordType * record_protobuf,const RecordTypeIR * record_ir)103 static bool AddRecordFields(abi_dump::RecordType *record_protobuf,
104 const RecordTypeIR *record_ir) {
105 for (auto &&field_ir : record_ir->GetFields()) {
106 abi_dump::RecordFieldDecl *added_field = record_protobuf->add_fields();
107 if (!ConvertRecordFieldIR(added_field, &field_ir)) {
108 return false;
109 }
110 }
111 return true;
112 }
113
ConvertCXXBaseSpecifierIR(abi_dump::CXXBaseSpecifier * base_specifier_protobuf,const CXXBaseSpecifierIR & base_specifier_ir)114 bool ConvertCXXBaseSpecifierIR(
115 abi_dump::CXXBaseSpecifier *base_specifier_protobuf,
116 const CXXBaseSpecifierIR &base_specifier_ir) {
117 if (!base_specifier_protobuf) {
118 llvm::errs() << "Protobuf base specifier not valid\n";
119 return false;
120 }
121 base_specifier_protobuf->set_referenced_type(
122 base_specifier_ir.GetReferencedType());
123 base_specifier_protobuf->set_is_virtual(base_specifier_ir.IsVirtual());
124 base_specifier_protobuf->set_access(
125 AccessIRToProtobuf(base_specifier_ir.GetAccess()));
126 return true;
127 }
128
AddBaseSpecifiers(abi_dump::RecordType * record_protobuf,const RecordTypeIR * record_ir)129 static bool AddBaseSpecifiers(abi_dump::RecordType *record_protobuf,
130 const RecordTypeIR *record_ir) {
131 for (auto &&base_ir : record_ir->GetBases()) {
132 abi_dump::CXXBaseSpecifier *added_base =
133 record_protobuf->add_base_specifiers();
134 if (!ConvertCXXBaseSpecifierIR(added_base, base_ir)) {
135 return false;
136 }
137 }
138 return true;
139 }
140
ConvertVTableLayoutIR(abi_dump::VTableLayout * vtable_layout_protobuf,const VTableLayoutIR & vtable_layout_ir)141 bool ConvertVTableLayoutIR(abi_dump::VTableLayout *vtable_layout_protobuf,
142 const VTableLayoutIR &vtable_layout_ir) {
143 if (vtable_layout_protobuf == nullptr) {
144 llvm::errs() << "vtable layout protobuf not valid\n";
145 return false;
146 }
147 for (auto &&vtable_component_ir : vtable_layout_ir.GetVTableComponents()) {
148 abi_dump::VTableComponent *added_vtable_component =
149 vtable_layout_protobuf->add_vtable_components();
150 if (!added_vtable_component) {
151 llvm::errs() << "Couldn't add vtable component\n";
152 return false;
153 }
154 added_vtable_component->set_kind(
155 VTableComponentKindIRToProtobuf(vtable_component_ir.GetKind()));
156 added_vtable_component->set_component_value(vtable_component_ir.GetValue());
157 added_vtable_component->set_mangled_component_name(
158 vtable_component_ir.GetName());
159 added_vtable_component->set_is_pure(vtable_component_ir.GetIsPure());
160 }
161 return true;
162 }
163
AddVTableLayout(abi_dump::RecordType * record_protobuf,const RecordTypeIR * record_ir)164 static bool AddVTableLayout(abi_dump::RecordType *record_protobuf,
165 const RecordTypeIR *record_ir) {
166 // If there are no entries in the vtable, just return.
167 if (record_ir->GetVTableNumEntries() == 0) {
168 return true;
169 }
170 const VTableLayoutIR &vtable_layout_ir = record_ir->GetVTableLayout();
171 abi_dump::VTableLayout *vtable_layout_protobuf =
172 record_protobuf->mutable_vtable_layout();
173 if (!ConvertVTableLayoutIR(vtable_layout_protobuf, vtable_layout_ir)) {
174 return false;
175 }
176 return true;
177 }
178
ConvertRecordTypeIR(const RecordTypeIR * recordp)179 abi_dump::RecordType ConvertRecordTypeIR(const RecordTypeIR *recordp) {
180 abi_dump::RecordType added_record_type;
181 added_record_type.set_access(AccessIRToProtobuf(recordp->GetAccess()));
182 added_record_type.set_record_kind(
183 RecordKindIRToProtobuf(recordp->GetRecordKind()));
184 if (recordp->IsAnonymous()) {
185 added_record_type.set_is_anonymous(true);
186 }
187 if (!AddTypeInfo(added_record_type.mutable_type_info(), recordp) ||
188 !AddRecordFields(&added_record_type, recordp) ||
189 !AddBaseSpecifiers(&added_record_type, recordp) ||
190 !AddVTableLayout(&added_record_type, recordp) ||
191 !(recordp->GetTemplateElements().size() ?
192 AddTemplateInformation(added_record_type.mutable_template_info(),
193 recordp) : true)) {
194 llvm::errs() << "Template information could not be added\n";
195 ::exit(1);
196 }
197 AddAvailabilityAttrs(&added_record_type, recordp);
198 return added_record_type;
199 }
200
ConvertElfObjectIR(const ElfObjectIR * elf_object_ir)201 abi_dump::ElfObject ConvertElfObjectIR(const ElfObjectIR *elf_object_ir) {
202 abi_dump::ElfObject elf_object_protobuf;
203 elf_object_protobuf.set_name(elf_object_ir->GetName());
204 elf_object_protobuf.set_binding(
205 ElfSymbolBindingIRToProtobuf(elf_object_ir->GetBinding()));
206 return elf_object_protobuf;
207 }
208
ConvertElfFunctionIR(const ElfFunctionIR * elf_function_ir)209 abi_dump::ElfFunction ConvertElfFunctionIR(
210 const ElfFunctionIR *elf_function_ir) {
211 abi_dump::ElfFunction elf_function_protobuf;
212 elf_function_protobuf.set_name(elf_function_ir->GetName());
213 elf_function_protobuf.set_binding(
214 ElfSymbolBindingIRToProtobuf(elf_function_ir->GetBinding()));
215 return elf_function_protobuf;
216 }
217
218 template <typename CFunctionLikeMessage>
AddFunctionParametersAndSetReturnType(CFunctionLikeMessage * function_like_protobuf,const CFunctionLikeIR * cfunction_like_ir)219 static bool AddFunctionParametersAndSetReturnType(
220 CFunctionLikeMessage *function_like_protobuf,
221 const CFunctionLikeIR *cfunction_like_ir) {
222 function_like_protobuf->set_return_type(cfunction_like_ir->GetReturnType());
223 return AddFunctionParameters(function_like_protobuf, cfunction_like_ir);
224 }
225
226 template <typename CFunctionLikeMessage>
AddFunctionParameters(CFunctionLikeMessage * function_like_protobuf,const CFunctionLikeIR * cfunction_like_ir)227 static bool AddFunctionParameters(CFunctionLikeMessage *function_like_protobuf,
228 const CFunctionLikeIR *cfunction_like_ir) {
229 for (auto &¶meter : cfunction_like_ir->GetParameters()) {
230 abi_dump::ParamDecl *added_parameter =
231 function_like_protobuf->add_parameters();
232 if (!added_parameter) {
233 return false;
234 }
235 added_parameter->set_referenced_type(
236 parameter.GetReferencedType());
237 added_parameter->set_default_arg(parameter.GetIsDefault());
238 added_parameter->set_is_this_ptr(parameter.GetIsThisPtr());
239 }
240 return true;
241 }
242
ConvertFunctionTypeIR(const FunctionTypeIR * function_typep)243 static abi_dump::FunctionType ConvertFunctionTypeIR(
244 const FunctionTypeIR *function_typep) {
245 abi_dump::FunctionType added_function_type;
246 if (!AddTypeInfo(added_function_type.mutable_type_info(), function_typep) ||
247 !AddFunctionParametersAndSetReturnType(&added_function_type,
248 function_typep)) {
249 llvm::errs() << "Could not convert FunctionTypeIR to protobuf\n";
250 ::exit(1);
251 }
252 return added_function_type;
253 }
254
ConvertFunctionIR(const FunctionIR * functionp)255 abi_dump::FunctionDecl ConvertFunctionIR(const FunctionIR *functionp) {
256 abi_dump::FunctionDecl added_function;
257 added_function.set_access(AccessIRToProtobuf(functionp->GetAccess()));
258 added_function.set_linker_set_key(functionp->GetLinkerSetKey());
259 added_function.set_source_file(functionp->GetSourceFile());
260 added_function.set_function_name(functionp->GetName());
261 if (!AddFunctionParametersAndSetReturnType(&added_function, functionp) ||
262 !(functionp->GetTemplateElements().size() ?
263 AddTemplateInformation(added_function.mutable_template_info(), functionp)
264 : true)) {
265 llvm::errs() << "Template information could not be added\n";
266 ::exit(1);
267 }
268 AddAvailabilityAttrs(&added_function, functionp);
269 return added_function;
270 }
271
ConvertEnumFieldIR(abi_dump::EnumFieldDecl * enum_field_protobuf,const EnumFieldIR * enum_field_ir)272 bool ConvertEnumFieldIR(abi_dump::EnumFieldDecl *enum_field_protobuf,
273 const EnumFieldIR *enum_field_ir) {
274 if (enum_field_protobuf == nullptr) {
275 llvm::errs() << "Invalid enum field\n";
276 return false;
277 }
278 enum_field_protobuf->set_name(enum_field_ir->GetName());
279 // The "enum_field_value" in the .proto is a signed 64-bit integer. An
280 // unsigned integer >= (1 << 63) is represented with a negative integer in the
281 // dump file. Despite the wrong representation, the diff result isn't affected
282 // because every integer has a unique representation.
283 enum_field_protobuf->set_enum_field_value(enum_field_ir->GetSignedValue());
284 AddAvailabilityAttrs(enum_field_protobuf, enum_field_ir);
285 return true;
286 }
287
AddEnumFields(abi_dump::EnumType * enum_protobuf,const EnumTypeIR * enum_ir)288 static bool AddEnumFields(abi_dump::EnumType *enum_protobuf,
289 const EnumTypeIR *enum_ir) {
290 for (auto &&field : enum_ir->GetFields()) {
291 abi_dump::EnumFieldDecl *enum_fieldp = enum_protobuf->add_enum_fields();
292 if (!ConvertEnumFieldIR(enum_fieldp, &field)) {
293 return false;
294 }
295 }
296 return true;
297 }
298
ConvertEnumTypeIR(const EnumTypeIR * enump)299 abi_dump::EnumType ConvertEnumTypeIR(const EnumTypeIR *enump) {
300 abi_dump::EnumType added_enum_type;
301 added_enum_type.set_access(AccessIRToProtobuf(enump->GetAccess()));
302 added_enum_type.set_underlying_type(enump->GetUnderlyingType());
303 if (!AddTypeInfo(added_enum_type.mutable_type_info(), enump) ||
304 !AddEnumFields(&added_enum_type, enump)) {
305 llvm::errs() << "EnumTypeIR could not be converted\n";
306 ::exit(1);
307 }
308 AddAvailabilityAttrs(&added_enum_type, enump);
309 return added_enum_type;
310 }
311
ConvertGlobalVarIR(const GlobalVarIR * global_varp)312 abi_dump::GlobalVarDecl ConvertGlobalVarIR(const GlobalVarIR *global_varp) {
313 abi_dump::GlobalVarDecl added_global_var;
314 added_global_var.set_referenced_type(global_varp->GetReferencedType());
315 added_global_var.set_source_file(global_varp->GetSourceFile());
316 added_global_var.set_name(global_varp->GetName());
317 added_global_var.set_linker_set_key(global_varp->GetLinkerSetKey());
318 added_global_var.set_access(
319 AccessIRToProtobuf(global_varp->GetAccess()));
320 AddAvailabilityAttrs(&added_global_var, global_varp);
321 return added_global_var;
322 }
323
ConvertPointerTypeIR(const PointerTypeIR * pointerp)324 static abi_dump::PointerType ConvertPointerTypeIR(
325 const PointerTypeIR *pointerp) {
326 abi_dump::PointerType added_pointer_type;
327 if (!AddTypeInfo(added_pointer_type.mutable_type_info(), pointerp)) {
328 llvm::errs() << "PointerTypeIR could not be converted\n";
329 ::exit(1);
330 }
331 return added_pointer_type;
332 }
333
ConvertQualifiedTypeIR(const QualifiedTypeIR * qualtypep)334 static abi_dump::QualifiedType ConvertQualifiedTypeIR(
335 const QualifiedTypeIR *qualtypep) {
336 abi_dump::QualifiedType added_qualified_type;
337 if (!AddTypeInfo(added_qualified_type.mutable_type_info(), qualtypep)) {
338 llvm::errs() << "QualifiedTypeIR could not be converted\n";
339 ::exit(1);
340 }
341 added_qualified_type.set_is_const(qualtypep->IsConst());
342 added_qualified_type.set_is_volatile(qualtypep->IsVolatile());
343 added_qualified_type.set_is_restricted(qualtypep->IsRestricted());
344 return added_qualified_type;
345 }
346
ConvertBuiltinTypeIR(const BuiltinTypeIR * builtin_typep)347 static abi_dump::BuiltinType ConvertBuiltinTypeIR(
348 const BuiltinTypeIR *builtin_typep) {
349 abi_dump::BuiltinType added_builtin_type;
350 added_builtin_type.set_is_unsigned(builtin_typep->IsUnsigned());
351 added_builtin_type.set_is_integral(builtin_typep->IsIntegralType());
352 if (!AddTypeInfo(added_builtin_type.mutable_type_info(), builtin_typep)) {
353 llvm::errs() << "BuiltinTypeIR could not be converted\n";
354 ::exit(1);
355 }
356 return added_builtin_type;
357 }
358
ConvertArrayTypeIR(const ArrayTypeIR * array_typep)359 static abi_dump::ArrayType ConvertArrayTypeIR(const ArrayTypeIR *array_typep) {
360 abi_dump::ArrayType added_array_type;
361 added_array_type.set_is_of_unknown_bound(array_typep->IsOfUnknownBound());
362 if (!AddTypeInfo(added_array_type.mutable_type_info(), array_typep)) {
363 llvm::errs() << "ArrayTypeIR could not be converted\n";
364 ::exit(1);
365 }
366 return added_array_type;
367 }
368
ConvertLvalueReferenceTypeIR(const LvalueReferenceTypeIR * lvalue_reference_typep)369 static abi_dump::LvalueReferenceType ConvertLvalueReferenceTypeIR(
370 const LvalueReferenceTypeIR *lvalue_reference_typep) {
371 abi_dump::LvalueReferenceType added_lvalue_reference_type;
372 if (!AddTypeInfo(added_lvalue_reference_type.mutable_type_info(),
373 lvalue_reference_typep)) {
374 llvm::errs() << "LvalueReferenceTypeIR could not be converted\n";
375 ::exit(1);
376 }
377 return added_lvalue_reference_type;
378 }
379
ConvertRvalueReferenceTypeIR(const RvalueReferenceTypeIR * rvalue_reference_typep)380 static abi_dump::RvalueReferenceType ConvertRvalueReferenceTypeIR(
381 const RvalueReferenceTypeIR *rvalue_reference_typep) {
382 abi_dump::RvalueReferenceType added_rvalue_reference_type;
383 if (!AddTypeInfo(added_rvalue_reference_type.mutable_type_info(),
384 rvalue_reference_typep)) {
385 llvm::errs() << "RvalueReferenceTypeIR could not be converted\n";
386 ::exit(1);
387 }
388 return added_rvalue_reference_type;
389 }
390
AddLinkableMessageIR(const LinkableMessageIR * lm)391 bool ProtobufIRDumper::AddLinkableMessageIR (const LinkableMessageIR *lm) {
392 // No RTTI
393 switch (lm->GetKind()) {
394 case RecordTypeKind:
395 return AddRecordTypeIR(static_cast<const RecordTypeIR *>(lm));
396 case EnumTypeKind:
397 return AddEnumTypeIR(static_cast<const EnumTypeIR *>(lm));
398 case PointerTypeKind:
399 return AddPointerTypeIR(static_cast<const PointerTypeIR *>(lm));
400 case QualifiedTypeKind:
401 return AddQualifiedTypeIR(static_cast<const QualifiedTypeIR *>(lm));
402 case ArrayTypeKind:
403 return AddArrayTypeIR(static_cast<const ArrayTypeIR *>(lm));
404 case LvalueReferenceTypeKind:
405 return AddLvalueReferenceTypeIR(
406 static_cast<const LvalueReferenceTypeIR *>(lm));
407 case RvalueReferenceTypeKind:
408 return AddRvalueReferenceTypeIR(
409 static_cast<const RvalueReferenceTypeIR*>(lm));
410 case BuiltinTypeKind:
411 return AddBuiltinTypeIR(static_cast<const BuiltinTypeIR*>(lm));
412 case FunctionTypeKind:
413 return AddFunctionTypeIR(static_cast<const FunctionTypeIR*>(lm));
414 case GlobalVarKind:
415 return AddGlobalVarIR(static_cast<const GlobalVarIR*>(lm));
416 case FunctionKind:
417 return AddFunctionIR(static_cast<const FunctionIR*>(lm));
418 }
419 return false;
420 }
421
AddElfFunctionIR(const ElfFunctionIR * elf_function)422 bool ProtobufIRDumper::AddElfFunctionIR(const ElfFunctionIR *elf_function) {
423 abi_dump::ElfFunction *added_elf_function = tu_ptr_->add_elf_functions();
424 if (!added_elf_function) {
425 return false;
426 }
427 *added_elf_function = ConvertElfFunctionIR(elf_function);
428 return true;
429 }
430
AddElfObjectIR(const ElfObjectIR * elf_object)431 bool ProtobufIRDumper::AddElfObjectIR(const ElfObjectIR *elf_object) {
432 abi_dump::ElfObject *added_elf_object = tu_ptr_->add_elf_objects();
433 if (!added_elf_object) {
434 return false;
435 }
436 *added_elf_object = ConvertElfObjectIR(elf_object);
437 return true;
438 }
439
AddElfSymbolMessageIR(const ElfSymbolIR * em)440 bool ProtobufIRDumper::AddElfSymbolMessageIR(const ElfSymbolIR *em) {
441 switch (em->GetKind()) {
442 case ElfSymbolIR::ElfFunctionKind:
443 return AddElfFunctionIR(static_cast<const ElfFunctionIR *>(em));
444 case ElfSymbolIR::ElfObjectKind:
445 return AddElfObjectIR(static_cast<const ElfObjectIR *>(em));
446 }
447 return false;
448 }
449
AddRecordTypeIR(const RecordTypeIR * recordp)450 bool ProtobufIRDumper::AddRecordTypeIR(const RecordTypeIR *recordp) {
451 abi_dump::RecordType *added_record_type = tu_ptr_->add_record_types();
452 if (!added_record_type) {
453 return false;
454 }
455 *added_record_type = ConvertRecordTypeIR(recordp);
456 return true;
457 }
458
AddFunctionTypeIR(const FunctionTypeIR * function_typep)459 bool ProtobufIRDumper::AddFunctionTypeIR(const FunctionTypeIR *function_typep) {
460 abi_dump::FunctionType *added_function_type = tu_ptr_->add_function_types();
461 if (!added_function_type) {
462 return false;
463 }
464 *added_function_type = ConvertFunctionTypeIR(function_typep);
465 return true;
466 }
467
AddFunctionIR(const FunctionIR * functionp)468 bool ProtobufIRDumper::AddFunctionIR(const FunctionIR *functionp) {
469 abi_dump::FunctionDecl *added_function = tu_ptr_->add_functions();
470 if (!added_function) {
471 return false;
472 }
473 *added_function = ConvertFunctionIR(functionp);
474 return true;
475 }
476
AddEnumTypeIR(const EnumTypeIR * enump)477 bool ProtobufIRDumper::AddEnumTypeIR(const EnumTypeIR *enump) {
478 abi_dump::EnumType *added_enum_type = tu_ptr_->add_enum_types();
479 if (!added_enum_type) {
480 return false;
481 }
482 *added_enum_type = ConvertEnumTypeIR(enump);
483 return true;
484 }
485
AddGlobalVarIR(const GlobalVarIR * global_varp)486 bool ProtobufIRDumper::AddGlobalVarIR(const GlobalVarIR *global_varp) {
487 abi_dump::GlobalVarDecl *added_global_var = tu_ptr_->add_global_vars();
488 if (!added_global_var) {
489 return false;
490 }
491 *added_global_var = ConvertGlobalVarIR(global_varp);
492 return true;
493 }
494
AddPointerTypeIR(const PointerTypeIR * pointerp)495 bool ProtobufIRDumper::AddPointerTypeIR(const PointerTypeIR *pointerp) {
496 abi_dump::PointerType *added_pointer_type = tu_ptr_->add_pointer_types();
497 if (!added_pointer_type) {
498 return false;
499 }
500 *added_pointer_type = ConvertPointerTypeIR(pointerp);
501 return true;
502 }
503
AddQualifiedTypeIR(const QualifiedTypeIR * qualtypep)504 bool ProtobufIRDumper::AddQualifiedTypeIR(const QualifiedTypeIR *qualtypep) {
505 abi_dump::QualifiedType *added_qualified_type =
506 tu_ptr_->add_qualified_types();
507 if (!added_qualified_type) {
508 return false;
509 }
510 *added_qualified_type = ConvertQualifiedTypeIR(qualtypep);
511 return true;
512 }
513
AddBuiltinTypeIR(const BuiltinTypeIR * builtin_typep)514 bool ProtobufIRDumper::AddBuiltinTypeIR(const BuiltinTypeIR *builtin_typep) {
515 abi_dump::BuiltinType *added_builtin_type =
516 tu_ptr_->add_builtin_types();
517 if (!added_builtin_type) {
518 return false;
519 }
520 *added_builtin_type = ConvertBuiltinTypeIR(builtin_typep);
521 return true;
522 }
523
AddArrayTypeIR(const ArrayTypeIR * array_typep)524 bool ProtobufIRDumper::AddArrayTypeIR(const ArrayTypeIR *array_typep) {
525 abi_dump::ArrayType *added_array_type =
526 tu_ptr_->add_array_types();
527 if (!added_array_type) {
528 return false;
529 }
530 *added_array_type = ConvertArrayTypeIR(array_typep);
531 return true;
532 }
533
AddLvalueReferenceTypeIR(const LvalueReferenceTypeIR * lvalue_reference_typep)534 bool ProtobufIRDumper::AddLvalueReferenceTypeIR(
535 const LvalueReferenceTypeIR *lvalue_reference_typep) {
536 abi_dump::LvalueReferenceType *added_lvalue_reference_type =
537 tu_ptr_->add_lvalue_reference_types();
538 if (!added_lvalue_reference_type) {
539 return false;
540 }
541 *added_lvalue_reference_type =
542 ConvertLvalueReferenceTypeIR(lvalue_reference_typep);
543 return true;
544 }
545
AddRvalueReferenceTypeIR(const RvalueReferenceTypeIR * rvalue_reference_typep)546 bool ProtobufIRDumper::AddRvalueReferenceTypeIR(
547 const RvalueReferenceTypeIR *rvalue_reference_typep) {
548 abi_dump::RvalueReferenceType *added_rvalue_reference_type =
549 tu_ptr_->add_rvalue_reference_types();
550 if (!added_rvalue_reference_type) {
551 return false;
552 }
553 *added_rvalue_reference_type =
554 ConvertRvalueReferenceTypeIR(rvalue_reference_typep);
555 return true;
556 }
557
Dump(const ModuleIR & module)558 bool ProtobufIRDumper::Dump(const ModuleIR &module) {
559 GOOGLE_PROTOBUF_VERIFY_VERSION;
560 DumpModule(module);
561 assert( tu_ptr_.get() != nullptr);
562 std::ofstream text_output(dump_path_);
563 {
564 google::protobuf::io::OstreamOutputStream text_os(&text_output);
565 if (!google::protobuf::TextFormat::Print(*tu_ptr_.get(), &text_os)) {
566 return false;
567 }
568 }
569 return text_output.flush().good();
570 }
571
CreateProtobufIRDumper(const std::string & dump_path)572 std::unique_ptr<IRDumper> CreateProtobufIRDumper(const std::string &dump_path) {
573 return std::make_unique<ProtobufIRDumper>(dump_path);
574 }
575
576
577 } // namespace repr
578 } // namespace header_checker
579