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 &¶meter : 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