xref: /aosp_15_r20/development/vndk/tools/header-checker/src/repr/protobuf/ir_dumper.cpp (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
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 &&parameter : 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