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