1 // Copyright (C) 2017 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 <ir_representation_protobuf.h>
16
17 #include <llvm/Support/raw_ostream.h>
18
19 #include <fstream>
20 #include <iostream>
21 #include <string>
22 #include <memory>
23
24 namespace abi_util {
25
IsPresentInExportedHeaders(const LinkableMessageIR & linkable_message,const std::set<std::string> * exported_headers)26 static bool IsPresentInExportedHeaders(
27 const LinkableMessageIR &linkable_message,
28 const std::set<std::string> *exported_headers) {
29 if (exported_headers == nullptr || exported_headers->empty()) {
30 return true;
31 }
32 return exported_headers->find(linkable_message.GetSourceFile())
33 != exported_headers->end();
34 }
35
ReadTypeInfo(const abi_dump::BasicNamedAndTypedDecl & type_info,TypeIR * typep)36 void ProtobufTextFormatToIRReader::ReadTypeInfo(
37 const abi_dump::BasicNamedAndTypedDecl &type_info,
38 TypeIR *typep) {
39 typep->SetLinkerSetKey(type_info.linker_set_key());
40 typep->SetName(type_info.name());
41 typep->SetSourceFile(type_info.source_file());
42 typep->SetReferencedType(type_info.referenced_type());
43 typep->SetSelfType(type_info.self_type());
44 typep->SetSize(type_info.size());
45 typep->SetAlignment(type_info.alignment());
46 }
47
ReadDump(const std::string & dump_file)48 bool ProtobufTextFormatToIRReader::ReadDump(const std::string &dump_file) {
49 abi_dump::TranslationUnit tu;
50 std::ifstream input(dump_file);
51 google::protobuf::io::IstreamInputStream text_is(&input);
52
53 if (!google::protobuf::TextFormat::Parse(&text_is, &tu)) {
54 llvm::errs() << "Failed to parse protobuf TextFormat file\n";
55 return false;
56 }
57 ReadFunctions(tu);
58 ReadGlobalVariables(tu);
59
60 ReadEnumTypes(tu);
61 ReadRecordTypes(tu);
62 ReadFunctionTypes(tu);
63 ReadArrayTypes(tu);
64 ReadPointerTypes(tu);
65 ReadQualifiedTypes(tu);
66 ReadBuiltinTypes(tu);
67 ReadLvalueReferenceTypes(tu);
68 ReadRvalueReferenceTypes(tu);
69
70 ReadElfFunctions(tu);
71 ReadElfObjects(tu);
72 return true;
73 }
74
TemplateInfoProtobufToIR(const abi_dump::TemplateInfo & template_info_protobuf)75 TemplateInfoIR ProtobufTextFormatToIRReader::TemplateInfoProtobufToIR(
76 const abi_dump::TemplateInfo &template_info_protobuf) {
77 TemplateInfoIR template_info_ir;
78 for (auto &&template_element : template_info_protobuf.elements()) {
79 TemplateElementIR template_element_ir(template_element.referenced_type());
80 template_info_ir.AddTemplateElement(std::move(template_element_ir));
81 }
82 return template_info_ir;
83 }
84
85 template< typename T>
SetupCFunctionLikeIR(const T & cfunction_like_protobuf,CFunctionLikeIR * cfunction_like_ir)86 static void SetupCFunctionLikeIR(const T &cfunction_like_protobuf,
87 CFunctionLikeIR *cfunction_like_ir) {
88 cfunction_like_ir->SetReturnType(cfunction_like_protobuf.return_type());
89 for (auto &¶meter: cfunction_like_protobuf.parameters()) {
90 ParamIR param_ir(parameter.referenced_type(), parameter.default_arg(),
91 false);
92 cfunction_like_ir->AddParameter(std::move(param_ir));
93 }
94 }
95
FunctionProtobufToIR(const abi_dump::FunctionDecl & function_protobuf)96 FunctionIR ProtobufTextFormatToIRReader::FunctionProtobufToIR(
97 const abi_dump::FunctionDecl &function_protobuf) {
98 FunctionIR function_ir;
99 function_ir.SetReturnType(function_protobuf.return_type());
100 function_ir.SetLinkerSetKey(function_protobuf.linker_set_key());
101 function_ir.SetName(function_protobuf.function_name());
102 function_ir.SetAccess(AccessProtobufToIR(function_protobuf.access()));
103 function_ir.SetSourceFile(function_protobuf.source_file());
104 // Set parameters
105 for (auto &¶meter: function_protobuf.parameters()) {
106 ParamIR param_ir(parameter.referenced_type(), parameter.default_arg(),
107 parameter.is_this_ptr());
108 function_ir.AddParameter(std::move(param_ir));
109 }
110 // Set Template info
111 function_ir.SetTemplateInfo(
112 TemplateInfoProtobufToIR(function_protobuf.template_info()));
113 return function_ir;
114 }
115
FunctionTypeProtobufToIR(const abi_dump::FunctionType & function_type_protobuf)116 FunctionTypeIR ProtobufTextFormatToIRReader::FunctionTypeProtobufToIR(
117 const abi_dump::FunctionType &function_type_protobuf) {
118 FunctionTypeIR function_type_ir;
119 ReadTypeInfo(function_type_protobuf.type_info(), &function_type_ir);
120 SetupCFunctionLikeIR(function_type_protobuf, &function_type_ir);
121 return function_type_ir;
122 }
123
VTableLayoutProtobufToIR(const abi_dump::VTableLayout & vtable_layout_protobuf)124 VTableLayoutIR ProtobufTextFormatToIRReader::VTableLayoutProtobufToIR(
125 const abi_dump::VTableLayout &vtable_layout_protobuf) {
126 VTableLayoutIR vtable_layout_ir;
127 for (auto &&vtable_component : vtable_layout_protobuf.vtable_components()) {
128 VTableComponentIR vtable_component_ir(
129 vtable_component.mangled_component_name(),
130 VTableComponentKindProtobufToIR(vtable_component.kind()),
131 vtable_component.component_value());
132 vtable_layout_ir.AddVTableComponent(std::move(vtable_component_ir));
133 }
134 return vtable_layout_ir;
135 }
136
137 std::vector<RecordFieldIR>
RecordFieldsProtobufToIR(const google::protobuf::RepeatedPtrField<abi_dump::RecordFieldDecl> & rfp)138 ProtobufTextFormatToIRReader::RecordFieldsProtobufToIR(
139 const google::protobuf::RepeatedPtrField<abi_dump::RecordFieldDecl> &rfp) {
140 std::vector<RecordFieldIR> record_type_fields_ir;
141 for (auto &&field : rfp) {
142 RecordFieldIR record_field_ir(field.field_name(), field.referenced_type(),
143 field.field_offset(),
144 AccessProtobufToIR(field.access()));
145 record_type_fields_ir.emplace_back(std::move(record_field_ir));
146 }
147 return record_type_fields_ir;
148 }
149
150 std::vector<CXXBaseSpecifierIR>
RecordCXXBaseSpecifiersProtobufToIR(const google::protobuf::RepeatedPtrField<abi_dump::CXXBaseSpecifier> & rbs)151 ProtobufTextFormatToIRReader::RecordCXXBaseSpecifiersProtobufToIR(
152 const google::protobuf::RepeatedPtrField<abi_dump::CXXBaseSpecifier> &rbs) {
153 std::vector<CXXBaseSpecifierIR> record_type_bases_ir;
154 for (auto &&base : rbs) {
155 CXXBaseSpecifierIR record_base_ir(
156 base.referenced_type(), base.is_virtual(),
157 AccessProtobufToIR(base.access()));
158 record_type_bases_ir.emplace_back(std::move(record_base_ir));
159 }
160 return record_type_bases_ir;
161 }
162
RecordTypeProtobufToIR(const abi_dump::RecordType & record_type_protobuf)163 RecordTypeIR ProtobufTextFormatToIRReader::RecordTypeProtobufToIR(
164 const abi_dump::RecordType &record_type_protobuf) {
165 RecordTypeIR record_type_ir;
166 ReadTypeInfo(record_type_protobuf.type_info(), &record_type_ir);
167 record_type_ir.SetTemplateInfo(
168 TemplateInfoProtobufToIR(record_type_protobuf.template_info()));
169 record_type_ir.SetAccess(AccessProtobufToIR(record_type_protobuf.access()));
170 record_type_ir.SetVTableLayout(
171 VTableLayoutProtobufToIR(record_type_protobuf.vtable_layout()));
172 // Get fields
173 record_type_ir.SetRecordFields(RecordFieldsProtobufToIR(
174 record_type_protobuf.fields()));
175 // Base Specifiers
176 record_type_ir.SetCXXBaseSpecifiers(RecordCXXBaseSpecifiersProtobufToIR(
177 record_type_protobuf.base_specifiers()));
178 record_type_ir.SetRecordKind(
179 RecordKindProtobufToIR(record_type_protobuf.record_kind()));
180 record_type_ir.SetAnonymity(record_type_protobuf.is_anonymous());
181 record_type_ir.SetUniqueId(record_type_protobuf.tag_info().unique_id());
182 return record_type_ir;
183 }
184
185 std::vector<EnumFieldIR>
EnumFieldsProtobufToIR(const google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> & efp)186 ProtobufTextFormatToIRReader::EnumFieldsProtobufToIR(
187 const google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> &efp) {
188 std::vector<EnumFieldIR> enum_type_fields_ir;
189 for (auto &&field : efp) {
190 EnumFieldIR enum_field_ir(field.name(), field.enum_field_value());
191 enum_type_fields_ir.emplace_back(std::move(enum_field_ir));
192 }
193 return enum_type_fields_ir;
194 }
195
EnumTypeProtobufToIR(const abi_dump::EnumType & enum_type_protobuf)196 EnumTypeIR ProtobufTextFormatToIRReader::EnumTypeProtobufToIR(
197 const abi_dump::EnumType &enum_type_protobuf) {
198 EnumTypeIR enum_type_ir;
199 ReadTypeInfo(enum_type_protobuf.type_info(), &enum_type_ir);
200 enum_type_ir.SetUnderlyingType(enum_type_protobuf.underlying_type());
201 enum_type_ir.SetAccess(AccessProtobufToIR(enum_type_protobuf.access()));
202 enum_type_ir.SetFields(
203 EnumFieldsProtobufToIR(enum_type_protobuf.enum_fields()));
204 enum_type_ir.SetUniqueId(enum_type_protobuf.tag_info().unique_id());
205 return enum_type_ir;
206 }
207
ReadGlobalVariables(const abi_dump::TranslationUnit & tu)208 void ProtobufTextFormatToIRReader::ReadGlobalVariables(
209 const abi_dump::TranslationUnit &tu) {
210 for (auto &&global_variable_protobuf : tu.global_vars()) {
211 GlobalVarIR global_variable_ir;
212 global_variable_ir.SetName(global_variable_protobuf.name());
213 global_variable_ir.SetAccess(AccessProtobufToIR(global_variable_protobuf.access()));
214 global_variable_ir.SetSourceFile(global_variable_protobuf.source_file());
215 global_variable_ir.SetReferencedType(
216 global_variable_protobuf.referenced_type());
217 global_variable_ir.SetLinkerSetKey(
218 global_variable_protobuf.linker_set_key());
219 if (!IsPresentInExportedHeaders(global_variable_ir, exported_headers_)) {
220 continue;
221 }
222 global_variables_.insert(
223 {global_variable_ir.GetLinkerSetKey(), std::move(global_variable_ir)});
224 }
225 }
226
ReadPointerTypes(const abi_dump::TranslationUnit & tu)227 void ProtobufTextFormatToIRReader::ReadPointerTypes(
228 const abi_dump::TranslationUnit &tu) {
229 for (auto &&pointer_type_protobuf : tu.pointer_types()) {
230 PointerTypeIR pointer_type_ir;
231 ReadTypeInfo(pointer_type_protobuf.type_info(), &pointer_type_ir);
232 if (!IsPresentInExportedHeaders(pointer_type_ir, exported_headers_)) {
233 continue;
234 }
235 AddToMapAndTypeGraph(std::move(pointer_type_ir), &pointer_types_,
236 &type_graph_);
237 }
238 }
239
ReadBuiltinTypes(const abi_dump::TranslationUnit & tu)240 void ProtobufTextFormatToIRReader::ReadBuiltinTypes(
241 const abi_dump::TranslationUnit &tu) {
242 for (auto &&builtin_type_protobuf : tu.builtin_types()) {
243 BuiltinTypeIR builtin_type_ir;
244 ReadTypeInfo(builtin_type_protobuf.type_info(), &builtin_type_ir);
245 builtin_type_ir.SetSignedness(builtin_type_protobuf.is_unsigned());
246 builtin_type_ir.SetIntegralType(builtin_type_protobuf.is_integral());
247 AddToMapAndTypeGraph(std::move(builtin_type_ir), &builtin_types_,
248 &type_graph_);
249 }
250 }
251
ReadQualifiedTypes(const abi_dump::TranslationUnit & tu)252 void ProtobufTextFormatToIRReader::ReadQualifiedTypes(
253 const abi_dump::TranslationUnit &tu) {
254 for (auto &&qualified_type_protobuf : tu.qualified_types()) {
255 QualifiedTypeIR qualified_type_ir;
256 ReadTypeInfo(qualified_type_protobuf.type_info(), &qualified_type_ir);
257 qualified_type_ir.SetConstness(qualified_type_protobuf.is_const());
258 qualified_type_ir.SetVolatility(qualified_type_protobuf.is_volatile());
259 qualified_type_ir.SetRestrictedness(
260 qualified_type_protobuf.is_restricted());
261 if (!IsPresentInExportedHeaders(qualified_type_ir, exported_headers_)) {
262 continue;
263 }
264 AddToMapAndTypeGraph(std::move(qualified_type_ir), &qualified_types_,
265 &type_graph_);
266 }
267 }
268
ReadArrayTypes(const abi_dump::TranslationUnit & tu)269 void ProtobufTextFormatToIRReader::ReadArrayTypes(
270 const abi_dump::TranslationUnit &tu) {
271 for (auto &&array_type_protobuf : tu.array_types()) {
272 ArrayTypeIR array_type_ir;
273 ReadTypeInfo(array_type_protobuf.type_info(), &array_type_ir);
274 if (!IsPresentInExportedHeaders(array_type_ir, exported_headers_)) {
275 continue;
276 }
277 AddToMapAndTypeGraph(std::move(array_type_ir), &array_types_,
278 &type_graph_);
279 }
280 }
281
ReadLvalueReferenceTypes(const abi_dump::TranslationUnit & tu)282 void ProtobufTextFormatToIRReader::ReadLvalueReferenceTypes(
283 const abi_dump::TranslationUnit &tu) {
284 for (auto &&lvalue_reference_type_protobuf : tu.lvalue_reference_types()) {
285 LvalueReferenceTypeIR lvalue_reference_type_ir;
286 ReadTypeInfo(lvalue_reference_type_protobuf.type_info(),
287 &lvalue_reference_type_ir);
288 if (!IsPresentInExportedHeaders(lvalue_reference_type_ir,
289 exported_headers_)) {
290 continue;
291 }
292 AddToMapAndTypeGraph(std::move(lvalue_reference_type_ir),
293 &lvalue_reference_types_, &type_graph_);
294 }
295 }
296
ReadRvalueReferenceTypes(const abi_dump::TranslationUnit & tu)297 void ProtobufTextFormatToIRReader::ReadRvalueReferenceTypes(
298 const abi_dump::TranslationUnit &tu) {
299 for (auto &&rvalue_reference_type_protobuf : tu.rvalue_reference_types()) {
300 RvalueReferenceTypeIR rvalue_reference_type_ir;
301 ReadTypeInfo(rvalue_reference_type_protobuf.type_info(),
302 &rvalue_reference_type_ir);
303 if (!IsPresentInExportedHeaders(rvalue_reference_type_ir,
304 exported_headers_)) {
305 continue;
306 }
307 AddToMapAndTypeGraph(std::move(rvalue_reference_type_ir),
308 &rvalue_reference_types_, &type_graph_);
309 }
310 }
311
ReadFunctions(const abi_dump::TranslationUnit & tu)312 void ProtobufTextFormatToIRReader::ReadFunctions(
313 const abi_dump::TranslationUnit &tu) {
314 for (auto &&function_protobuf : tu.functions()) {
315 FunctionIR function_ir = FunctionProtobufToIR(function_protobuf);
316 if (!IsPresentInExportedHeaders(function_ir, exported_headers_)) {
317 continue;
318 }
319 functions_.insert({function_ir.GetLinkerSetKey(), std::move(function_ir)});
320 }
321 }
322
ReadRecordTypes(const abi_dump::TranslationUnit & tu)323 void ProtobufTextFormatToIRReader::ReadRecordTypes(
324 const abi_dump::TranslationUnit &tu) {
325 for (auto &&record_type_protobuf : tu.record_types()) {
326 RecordTypeIR record_type_ir = RecordTypeProtobufToIR(record_type_protobuf);
327 if (!IsPresentInExportedHeaders(record_type_ir, exported_headers_)) {
328 continue;
329 }
330 auto it = AddToMapAndTypeGraph(std::move(record_type_ir), &record_types_,
331 &type_graph_);
332 const std::string &key = GetODRListMapKey(&(it->second));
333 AddToODRListMap(key, &(it->second));
334 }
335 }
336
ReadFunctionTypes(const abi_dump::TranslationUnit & tu)337 void ProtobufTextFormatToIRReader::ReadFunctionTypes(
338 const abi_dump::TranslationUnit &tu) {
339 for (auto &&function_type_protobuf : tu.function_types()) {
340 FunctionTypeIR function_type_ir =
341 FunctionTypeProtobufToIR(function_type_protobuf);
342 if (!IsPresentInExportedHeaders(function_type_ir, exported_headers_)) {
343 continue;
344 }
345 auto it = AddToMapAndTypeGraph(std::move(function_type_ir),
346 &function_types_, &type_graph_);
347 const std::string &key = GetODRListMapKey(&(it->second));
348 AddToODRListMap(key, &(it->second));
349 }
350 }
351
ReadEnumTypes(const abi_dump::TranslationUnit & tu)352 void ProtobufTextFormatToIRReader::ReadEnumTypes(
353 const abi_dump::TranslationUnit &tu) {
354 for (auto &&enum_type_protobuf : tu.enum_types()) {
355 EnumTypeIR enum_type_ir = EnumTypeProtobufToIR(enum_type_protobuf);
356 if (!IsPresentInExportedHeaders(enum_type_ir, exported_headers_)) {
357 continue;
358 }
359 auto it = AddToMapAndTypeGraph(std::move(enum_type_ir), &enum_types_,
360 &type_graph_);
361 AddToODRListMap(it->second.GetUniqueId() + it->second.GetSourceFile(),
362 (&it->second));
363 }
364 }
365
ReadElfFunctions(const abi_dump::TranslationUnit & tu)366 void ProtobufTextFormatToIRReader::ReadElfFunctions(
367 const abi_dump::TranslationUnit &tu) {
368 for (auto &&elf_function : tu.elf_functions()) {
369 ElfFunctionIR elf_function_ir(elf_function.name());
370 elf_functions_.insert(
371 {elf_function_ir.GetName(), std::move(elf_function_ir)});
372 }
373 }
374
ReadElfObjects(const abi_dump::TranslationUnit & tu)375 void ProtobufTextFormatToIRReader::ReadElfObjects(
376 const abi_dump::TranslationUnit &tu) {
377 for (auto &&elf_object : tu.elf_objects()) {
378 ElfObjectIR elf_object_ir(elf_object.name());
379 elf_objects_.insert(
380 {elf_object_ir.GetName(), std::move(elf_object_ir)});
381 }
382 }
383
AddTemplateInformation(abi_dump::TemplateInfo * ti,const abi_util::TemplatedArtifactIR * ta)384 bool IRToProtobufConverter::AddTemplateInformation(
385 abi_dump::TemplateInfo *ti, const abi_util::TemplatedArtifactIR *ta) {
386 for (auto &&template_element : ta->GetTemplateElements()) {
387 abi_dump::TemplateElement *added_element = ti->add_elements();
388 if (!added_element) {
389 llvm::errs() << "Failed to add template element\n";
390 return false;
391 }
392 added_element->set_referenced_type(template_element.GetReferencedType());
393 }
394 return true;
395 }
396
AddTypeInfo(abi_dump::BasicNamedAndTypedDecl * type_info,const TypeIR * typep)397 bool IRToProtobufConverter::AddTypeInfo(
398 abi_dump::BasicNamedAndTypedDecl *type_info,
399 const TypeIR *typep) {
400 if (!type_info || !typep) {
401 llvm::errs() << "Typeinfo not valid\n";
402 return false;
403 }
404 type_info->set_linker_set_key(typep->GetLinkerSetKey());
405 type_info->set_source_file(typep->GetSourceFile());
406 type_info->set_name(typep->GetName());
407 type_info->set_size(typep->GetSize());
408 type_info->set_alignment(typep->GetAlignment());
409 type_info->set_referenced_type(typep->GetReferencedType());
410 type_info->set_self_type(typep->GetSelfType());
411 return true;
412 }
413
SetIRToProtobufRecordField(abi_dump::RecordFieldDecl * record_field_protobuf,const RecordFieldIR * record_field_ir)414 static void SetIRToProtobufRecordField(
415 abi_dump::RecordFieldDecl *record_field_protobuf,
416 const RecordFieldIR *record_field_ir) {
417 record_field_protobuf->set_field_name(record_field_ir->GetName());
418 record_field_protobuf->set_referenced_type(
419 record_field_ir->GetReferencedType());
420 record_field_protobuf->set_access(
421 AccessIRToProtobuf(record_field_ir->GetAccess()));
422 record_field_protobuf->set_field_offset(record_field_ir->GetOffset());
423 }
424
AddRecordFields(abi_dump::RecordType * record_protobuf,const RecordTypeIR * record_ir)425 bool IRToProtobufConverter::AddRecordFields(
426 abi_dump::RecordType *record_protobuf,
427 const RecordTypeIR *record_ir) {
428 // Iterate through the fields and create corresponding ones for the protobuf
429 // record
430 for (auto &&field_ir : record_ir->GetFields()) {
431 abi_dump::RecordFieldDecl *added_field = record_protobuf->add_fields();
432 if (!added_field) {
433 llvm::errs() << "Couldn't add record field\n";
434 }
435 SetIRToProtobufRecordField(added_field, &field_ir);
436 }
437 return true;
438 }
439
SetIRToProtobufBaseSpecifier(abi_dump::CXXBaseSpecifier * base_specifier_protobuf,const CXXBaseSpecifierIR & base_specifier_ir)440 static bool SetIRToProtobufBaseSpecifier(
441 abi_dump::CXXBaseSpecifier *base_specifier_protobuf,
442 const CXXBaseSpecifierIR &base_specifier_ir) {
443 if (!base_specifier_protobuf) {
444 llvm::errs() << "Protobuf base specifier not valid\n";
445 return false;
446 }
447 base_specifier_protobuf->set_referenced_type(
448 base_specifier_ir.GetReferencedType());
449 base_specifier_protobuf->set_is_virtual(
450 base_specifier_ir.IsVirtual());
451 base_specifier_protobuf->set_access(
452 AccessIRToProtobuf(base_specifier_ir.GetAccess()));
453 return true;
454 }
455
AddBaseSpecifiers(abi_dump::RecordType * record_protobuf,const RecordTypeIR * record_ir)456 bool IRToProtobufConverter::AddBaseSpecifiers(
457 abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir) {
458 for (auto &&base_ir : record_ir->GetBases()) {
459 abi_dump::CXXBaseSpecifier *added_base =
460 record_protobuf->add_base_specifiers();
461 if (!SetIRToProtobufBaseSpecifier(added_base, base_ir)) {
462 return false;
463 }
464 }
465 return true;
466 }
467
SetIRToProtobufVTableLayout(abi_dump::VTableLayout * vtable_layout_protobuf,const VTableLayoutIR & vtable_layout_ir)468 static bool SetIRToProtobufVTableLayout(
469 abi_dump::VTableLayout *vtable_layout_protobuf,
470 const VTableLayoutIR &vtable_layout_ir) {
471 if (vtable_layout_protobuf == nullptr) {
472 llvm::errs() << "vtable layout protobuf not valid\n";
473 return false;
474 }
475 for (auto &&vtable_component_ir : vtable_layout_ir.GetVTableComponents()) {
476 abi_dump::VTableComponent *added_vtable_component =
477 vtable_layout_protobuf->add_vtable_components();
478 if (!added_vtable_component) {
479 llvm::errs() << "Couldn't add vtable component\n";
480 return false;
481 }
482 added_vtable_component->set_kind(
483 VTableComponentKindIRToProtobuf(vtable_component_ir.GetKind()));
484 added_vtable_component->set_component_value(vtable_component_ir.GetValue());
485 added_vtable_component->set_mangled_component_name(
486 vtable_component_ir.GetName());
487 }
488 return true;
489 }
490
AddVTableLayout(abi_dump::RecordType * record_protobuf,const RecordTypeIR * record_ir)491 bool IRToProtobufConverter::AddVTableLayout(
492 abi_dump::RecordType *record_protobuf,
493 const RecordTypeIR *record_ir) {
494 // If there are no entries in the vtable, just return.
495 if (record_ir->GetVTableNumEntries() == 0) {
496 return true;
497 }
498 const VTableLayoutIR &vtable_layout_ir = record_ir->GetVTableLayout();
499 abi_dump::VTableLayout *vtable_layout_protobuf =
500 record_protobuf->mutable_vtable_layout();
501 if (!SetIRToProtobufVTableLayout(vtable_layout_protobuf, vtable_layout_ir)) {
502 return false;
503 }
504 return true;
505 }
506
AddTagTypeInfo(abi_dump::TagType * tag_type_protobuf,const abi_util::TagTypeIR * tag_type_ir)507 bool IRToProtobufConverter::AddTagTypeInfo(
508 abi_dump::TagType *tag_type_protobuf,
509 const abi_util::TagTypeIR *tag_type_ir) {
510 if (!tag_type_protobuf || !tag_type_ir) {
511 return false;
512 }
513 tag_type_protobuf->set_unique_id(tag_type_ir->GetUniqueId());
514 return true;
515 }
516
ConvertRecordTypeIR(const RecordTypeIR * recordp)517 abi_dump::RecordType IRToProtobufConverter::ConvertRecordTypeIR(
518 const RecordTypeIR *recordp) {
519 abi_dump::RecordType added_record_type;
520 added_record_type.set_access(AccessIRToProtobuf(recordp->GetAccess()));
521 added_record_type.set_record_kind(
522 RecordKindIRToProtobuf(recordp->GetRecordKind()));
523 if (recordp->IsAnonymous()) {
524 added_record_type.set_is_anonymous(true);
525 }
526 if (!AddTypeInfo(added_record_type.mutable_type_info(), recordp) ||
527 !AddRecordFields(&added_record_type, recordp) ||
528 !AddBaseSpecifiers(&added_record_type, recordp) ||
529 !AddVTableLayout(&added_record_type, recordp) ||
530 !AddTagTypeInfo(added_record_type.mutable_tag_info(), recordp) ||
531 !(recordp->GetTemplateElements().size() ?
532 AddTemplateInformation(added_record_type.mutable_template_info(),
533 recordp) : true)) {
534 llvm::errs() << "Template information could not be added\n";
535 ::exit(1);
536 }
537 return added_record_type;
538 }
539
540
ConvertElfObjectIR(const ElfObjectIR * elf_object_ir)541 abi_dump::ElfObject IRToProtobufConverter::ConvertElfObjectIR(
542 const ElfObjectIR *elf_object_ir) {
543 abi_dump::ElfObject elf_object_protobuf;
544 elf_object_protobuf.set_name(elf_object_ir->GetName());
545 return elf_object_protobuf;
546 }
547
ConvertElfFunctionIR(const ElfFunctionIR * elf_function_ir)548 abi_dump::ElfFunction IRToProtobufConverter::ConvertElfFunctionIR(
549 const ElfFunctionIR *elf_function_ir) {
550 abi_dump::ElfFunction elf_function_protobuf;
551 elf_function_protobuf.set_name(elf_function_ir->GetName());
552 return elf_function_protobuf;
553 }
554
555 template <typename CFunctionLikeMessage>
AddFunctionParametersAndSetReturnType(CFunctionLikeMessage * function_like_protobuf,const CFunctionLikeIR * cfunction_like_ir)556 bool IRToProtobufConverter::AddFunctionParametersAndSetReturnType(
557 CFunctionLikeMessage *function_like_protobuf,
558 const CFunctionLikeIR *cfunction_like_ir) {
559 function_like_protobuf->set_return_type(cfunction_like_ir->GetReturnType());
560 return AddFunctionParameters(function_like_protobuf, cfunction_like_ir);
561 }
562
563 template <typename CFunctionLikeMessage>
AddFunctionParameters(CFunctionLikeMessage * function_like_protobuf,const CFunctionLikeIR * cfunction_like_ir)564 bool IRToProtobufConverter::AddFunctionParameters(
565 CFunctionLikeMessage *function_like_protobuf,
566 const CFunctionLikeIR *cfunction_like_ir) {
567 for (auto &¶meter : cfunction_like_ir->GetParameters()) {
568 abi_dump::ParamDecl *added_parameter =
569 function_like_protobuf->add_parameters();
570 if (!added_parameter) {
571 return false;
572 }
573 added_parameter->set_referenced_type(
574 parameter.GetReferencedType());
575 added_parameter->set_default_arg(parameter.GetIsDefault());
576 added_parameter->set_is_this_ptr(parameter.GetIsThisPtr());
577 }
578 return true;
579 }
580
ConvertFunctionTypeIR(const FunctionTypeIR * function_typep)581 abi_dump::FunctionType IRToProtobufConverter::ConvertFunctionTypeIR (
582 const FunctionTypeIR *function_typep) {
583 abi_dump::FunctionType added_function_type;
584 if (!AddTypeInfo(added_function_type.mutable_type_info(), function_typep) ||
585 !AddFunctionParametersAndSetReturnType(&added_function_type,
586 function_typep)) {
587 llvm::errs() << "Could not convert FunctionTypeIR to protobuf\n";
588 ::exit(1);
589 }
590 return added_function_type;
591 }
592
ConvertFunctionIR(const FunctionIR * functionp)593 abi_dump::FunctionDecl IRToProtobufConverter::ConvertFunctionIR(
594 const FunctionIR *functionp) {
595 abi_dump::FunctionDecl added_function;
596 added_function.set_access(AccessIRToProtobuf(functionp->GetAccess()));
597 added_function.set_linker_set_key(functionp->GetLinkerSetKey());
598 added_function.set_source_file(functionp->GetSourceFile());
599 added_function.set_function_name(functionp->GetName());
600 if (!AddFunctionParametersAndSetReturnType(&added_function, functionp) ||
601 !(functionp->GetTemplateElements().size() ?
602 AddTemplateInformation(added_function.mutable_template_info(), functionp)
603 : true)) {
604 llvm::errs() << "Template information could not be added\n";
605 ::exit(1);
606 }
607 return added_function;
608 }
609
SetIRToProtobufEnumField(abi_dump::EnumFieldDecl * enum_field_protobuf,const EnumFieldIR * enum_field_ir)610 static bool SetIRToProtobufEnumField(
611 abi_dump::EnumFieldDecl *enum_field_protobuf,
612 const EnumFieldIR *enum_field_ir) {
613 if (enum_field_protobuf == nullptr) {
614 return true;
615 }
616 enum_field_protobuf->set_name(enum_field_ir->GetName());
617 enum_field_protobuf->set_enum_field_value(enum_field_ir->GetValue());
618 return true;
619 }
620
AddEnumFields(abi_dump::EnumType * enum_protobuf,const EnumTypeIR * enum_ir)621 bool IRToProtobufConverter::AddEnumFields(abi_dump::EnumType *enum_protobuf,
622 const EnumTypeIR *enum_ir) {
623 for (auto &&field : enum_ir->GetFields()) {
624 abi_dump::EnumFieldDecl *enum_fieldp = enum_protobuf->add_enum_fields();
625 if (!SetIRToProtobufEnumField(enum_fieldp, &field)) {
626 return false;
627 }
628 }
629 return true;
630 }
631
632
ConvertEnumTypeIR(const EnumTypeIR * enump)633 abi_dump::EnumType IRToProtobufConverter::ConvertEnumTypeIR(
634 const EnumTypeIR *enump) {
635 abi_dump::EnumType added_enum_type;
636 added_enum_type.set_access(AccessIRToProtobuf(enump->GetAccess()));
637 added_enum_type.set_underlying_type(enump->GetUnderlyingType());
638 if (!AddTypeInfo(added_enum_type.mutable_type_info(), enump) ||
639 !AddEnumFields(&added_enum_type, enump) ||
640 !AddTagTypeInfo(added_enum_type.mutable_tag_info(), enump)) {
641 llvm::errs() << "EnumTypeIR could not be converted\n";
642 ::exit(1);
643 }
644 return added_enum_type;
645 }
646
ConvertGlobalVarIR(const GlobalVarIR * global_varp)647 abi_dump::GlobalVarDecl IRToProtobufConverter::ConvertGlobalVarIR(
648 const GlobalVarIR *global_varp) {
649 abi_dump::GlobalVarDecl added_global_var;
650 added_global_var.set_referenced_type(global_varp->GetReferencedType());
651 added_global_var.set_source_file(global_varp->GetSourceFile());
652 added_global_var.set_name(global_varp->GetName());
653 added_global_var.set_linker_set_key(global_varp->GetLinkerSetKey());
654 added_global_var.set_access(
655 AccessIRToProtobuf(global_varp->GetAccess()));
656 return added_global_var;
657 }
658
ConvertPointerTypeIR(const PointerTypeIR * pointerp)659 abi_dump::PointerType IRToProtobufConverter::ConvertPointerTypeIR(
660 const PointerTypeIR *pointerp) {
661 abi_dump::PointerType added_pointer_type;
662 if (!AddTypeInfo(added_pointer_type.mutable_type_info(), pointerp)) {
663 llvm::errs() << "PointerTypeIR could not be converted\n";
664 ::exit(1);
665 }
666 return added_pointer_type;
667 }
668
ConvertQualifiedTypeIR(const QualifiedTypeIR * qualtypep)669 abi_dump::QualifiedType IRToProtobufConverter::ConvertQualifiedTypeIR(
670 const QualifiedTypeIR *qualtypep) {
671 abi_dump::QualifiedType added_qualified_type;
672 if (!AddTypeInfo(added_qualified_type.mutable_type_info(), qualtypep)) {
673 llvm::errs() << "QualifiedTypeIR could not be converted\n";
674 ::exit(1);
675 }
676 added_qualified_type.set_is_const(qualtypep->IsConst());
677 added_qualified_type.set_is_volatile(qualtypep->IsVolatile());
678 added_qualified_type.set_is_restricted(qualtypep->IsRestricted());
679 return added_qualified_type;
680 }
681
ConvertBuiltinTypeIR(const BuiltinTypeIR * builtin_typep)682 abi_dump::BuiltinType IRToProtobufConverter::ConvertBuiltinTypeIR(
683 const BuiltinTypeIR *builtin_typep) {
684 abi_dump::BuiltinType added_builtin_type;
685 added_builtin_type.set_is_unsigned(builtin_typep->IsUnsigned());
686 added_builtin_type.set_is_integral(builtin_typep->IsIntegralType());
687 if (!AddTypeInfo(added_builtin_type.mutable_type_info(), builtin_typep)) {
688 llvm::errs() << "BuiltinTypeIR could not be converted\n";
689 ::exit(1);
690 }
691 return added_builtin_type;
692 }
693
ConvertArrayTypeIR(const ArrayTypeIR * array_typep)694 abi_dump::ArrayType IRToProtobufConverter::ConvertArrayTypeIR(
695 const ArrayTypeIR *array_typep) {
696 abi_dump::ArrayType added_array_type;
697 if (!AddTypeInfo(added_array_type.mutable_type_info(), array_typep)) {
698 llvm::errs() << "ArrayTypeIR could not be converted\n";
699 ::exit(1);
700 }
701 return added_array_type;
702 }
703
704 abi_dump::LvalueReferenceType
ConvertLvalueReferenceTypeIR(const LvalueReferenceTypeIR * lvalue_reference_typep)705 IRToProtobufConverter::ConvertLvalueReferenceTypeIR(
706 const LvalueReferenceTypeIR *lvalue_reference_typep) {
707 abi_dump::LvalueReferenceType added_lvalue_reference_type;
708 if (!AddTypeInfo(added_lvalue_reference_type.mutable_type_info(),
709 lvalue_reference_typep)) {
710 llvm::errs() << "LvalueReferenceTypeIR could not be converted\n";
711 ::exit(1);
712 }
713 return added_lvalue_reference_type;
714 }
715
716 abi_dump::RvalueReferenceType
ConvertRvalueReferenceTypeIR(const RvalueReferenceTypeIR * rvalue_reference_typep)717 IRToProtobufConverter::ConvertRvalueReferenceTypeIR(
718 const RvalueReferenceTypeIR *rvalue_reference_typep) {
719 abi_dump::RvalueReferenceType added_rvalue_reference_type;
720 if (!AddTypeInfo(added_rvalue_reference_type.mutable_type_info(),
721 rvalue_reference_typep)) {
722 llvm::errs() << "RvalueReferenceTypeIR could not be converted\n";
723 ::exit(1);
724 }
725 return added_rvalue_reference_type;
726 }
727
728
AddTypeInfoDiff(abi_diff::TypeInfoDiff * type_info_diff_protobuf,const TypeDiffIR * type_diff_ir)729 bool IRDiffToProtobufConverter::AddTypeInfoDiff(
730 abi_diff::TypeInfoDiff *type_info_diff_protobuf,
731 const TypeDiffIR *type_diff_ir) {
732 abi_diff::TypeInfo *old_type_info_protobuf =
733 type_info_diff_protobuf->mutable_old_type_info();
734 abi_diff::TypeInfo *new_type_info_protobuf =
735 type_info_diff_protobuf->mutable_new_type_info();
736 if (old_type_info_protobuf == nullptr || new_type_info_protobuf == nullptr) {
737 return false;
738 }
739 const std::pair<uint64_t, uint64_t> &sizes = type_diff_ir->GetSizes();
740 const std::pair<uint32_t, uint32_t> &alignments =
741 type_diff_ir->GetAlignments();
742 old_type_info_protobuf->set_size(sizes.first);
743 new_type_info_protobuf->set_size(sizes.second);
744
745 old_type_info_protobuf->set_alignment(alignments.first);
746 new_type_info_protobuf->set_alignment(alignments.second);
747 return true;
748 }
749
AddVTableLayoutDiff(abi_diff::VTableLayoutDiff * vtable_layout_diff_protobuf,const VTableLayoutDiffIR * vtable_layout_diff_ir)750 bool IRDiffToProtobufConverter::AddVTableLayoutDiff(
751 abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf,
752 const VTableLayoutDiffIR *vtable_layout_diff_ir) {
753 abi_dump:: VTableLayout *old_vtable =
754 vtable_layout_diff_protobuf->mutable_old_vtable();
755 abi_dump:: VTableLayout *new_vtable =
756 vtable_layout_diff_protobuf->mutable_new_vtable();
757 if (old_vtable == nullptr || new_vtable == nullptr ||
758 !SetIRToProtobufVTableLayout(old_vtable,
759 vtable_layout_diff_ir->GetOldVTable()) ||
760 !SetIRToProtobufVTableLayout(new_vtable,
761 vtable_layout_diff_ir->GetNewVTable())) {
762 return false;
763 }
764 return true;
765 }
766
767 template <typename T>
CopyBaseSpecifiersDiffIRToProtobuf(google::protobuf::RepeatedPtrField<T> * dst,const std::vector<CXXBaseSpecifierIR> & bases_ir)768 static bool CopyBaseSpecifiersDiffIRToProtobuf(
769 google::protobuf::RepeatedPtrField<T> *dst,
770 const std::vector<CXXBaseSpecifierIR> &bases_ir) {
771 for (auto &&base_ir : bases_ir) {
772 T *added_base = dst->Add();
773 if (!SetIRToProtobufBaseSpecifier(added_base, base_ir)) {
774 return false;
775 }
776 }
777 return true;
778 }
779
AddBaseSpecifierDiffs(abi_diff::CXXBaseSpecifierDiff * base_specifiers_diff_protobuf,const CXXBaseSpecifierDiffIR * base_specifiers_diff_ir)780 bool IRDiffToProtobufConverter::AddBaseSpecifierDiffs(
781 abi_diff::CXXBaseSpecifierDiff *base_specifiers_diff_protobuf,
782 const CXXBaseSpecifierDiffIR *base_specifiers_diff_ir) {
783 if (!CopyBaseSpecifiersDiffIRToProtobuf(
784 base_specifiers_diff_protobuf->mutable_old_bases(),
785 base_specifiers_diff_ir->GetOldBases()) ||
786 !CopyBaseSpecifiersDiffIRToProtobuf(
787 base_specifiers_diff_protobuf->mutable_new_bases(),
788 base_specifiers_diff_ir->GetNewBases())) {
789 return false;
790 }
791 return true;
792 }
793
AddRecordFields(abi_diff::RecordTypeDiff * record_diff_protobuf,const std::vector<const RecordFieldIR * > & record_fields_ir,bool field_removed)794 bool IRDiffToProtobufConverter::AddRecordFields(
795 abi_diff::RecordTypeDiff *record_diff_protobuf,
796 const std::vector<const RecordFieldIR *> &record_fields_ir,
797 bool field_removed) {
798 for (auto &&record_field_ir : record_fields_ir) {
799 abi_dump::RecordFieldDecl *field = nullptr;
800 if (field_removed) {
801 field = record_diff_protobuf->add_fields_removed();
802 } else {
803 field = record_diff_protobuf->add_fields_added();
804 }
805 if (field == nullptr) {
806 return false;
807 }
808 SetIRToProtobufRecordField(field, record_field_ir);
809 }
810 return true;
811 }
812
AddRecordFieldDiffs(abi_diff::RecordTypeDiff * record_diff_protobuf,const std::vector<RecordFieldDiffIR> & record_field_diffs_ir)813 bool IRDiffToProtobufConverter::AddRecordFieldDiffs(
814 abi_diff::RecordTypeDiff *record_diff_protobuf,
815 const std::vector<RecordFieldDiffIR> &record_field_diffs_ir) {
816 for (auto &&record_field_diff_ir : record_field_diffs_ir) {
817 abi_diff::RecordFieldDeclDiff *record_field_diff =
818 record_diff_protobuf->add_fields_diff();
819 if (record_field_diff == nullptr) {
820 return false;
821 }
822 abi_dump::RecordFieldDecl *old_field =
823 record_field_diff->mutable_old_field();
824 abi_dump::RecordFieldDecl *new_field =
825 record_field_diff->mutable_new_field();
826 if (old_field == nullptr || new_field == nullptr) {
827 return false;
828 }
829 SetIRToProtobufRecordField(old_field,
830 record_field_diff_ir.GetOldField());
831 SetIRToProtobufRecordField(new_field,
832 record_field_diff_ir.GetNewField());
833 }
834 return true;
835 }
836
ConvertRecordTypeDiffIR(const RecordTypeDiffIR * record_type_diff_ir)837 abi_diff::RecordTypeDiff IRDiffToProtobufConverter::ConvertRecordTypeDiffIR(
838 const RecordTypeDiffIR *record_type_diff_ir) {
839 abi_diff::RecordTypeDiff record_type_diff_protobuf;
840 record_type_diff_protobuf.set_name(record_type_diff_ir->GetName());
841 const TypeDiffIR *type_diff_ir = record_type_diff_ir->GetTypeDiff();
842 // If a type_info diff exists
843 if (type_diff_ir != nullptr) {
844 abi_diff::TypeInfoDiff *type_info_diff =
845 record_type_diff_protobuf.mutable_type_info_diff();
846 if (!AddTypeInfoDiff(type_info_diff, type_diff_ir)) {
847 llvm::errs() << "RecordType could not be converted\n";
848 ::exit(1);
849 }
850 }
851 // If vtables differ.
852 const VTableLayoutDiffIR *vtable_layout_diff_ir =
853 record_type_diff_ir->GetVTableLayoutDiff();
854 if (vtable_layout_diff_ir != nullptr) {
855 abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf =
856 record_type_diff_protobuf.mutable_vtable_layout_diff();
857 if (!AddVTableLayoutDiff(vtable_layout_diff_protobuf,
858 vtable_layout_diff_ir)) {
859 llvm::errs() << "VTable layout diff could not be added\n";
860 ::exit(1);
861 }
862 }
863 // If base specifiers differ.
864 const CXXBaseSpecifierDiffIR *base_specifier_diff_ir =
865 record_type_diff_ir->GetBaseSpecifiers();
866 if ( base_specifier_diff_ir != nullptr) {
867 abi_diff::CXXBaseSpecifierDiff *base_specifier_diff_protobuf =
868 record_type_diff_protobuf.mutable_bases_diff();
869 if (!AddBaseSpecifierDiffs(base_specifier_diff_protobuf,
870 base_specifier_diff_ir)) {
871 llvm::errs() << "Base Specifier diff could not be added\n";
872 ::exit(1);
873 }
874 }
875 // Field diffs
876 if (!AddRecordFields(&record_type_diff_protobuf,
877 record_type_diff_ir->GetFieldsRemoved(), true) ||
878 !AddRecordFields(&record_type_diff_protobuf,
879 record_type_diff_ir->GetFieldsAdded(), false) ||
880 !AddRecordFieldDiffs(&record_type_diff_protobuf,
881 record_type_diff_ir->GetFieldDiffs())) {
882 llvm::errs() << "Record Field diff could not be added\n";
883 ::exit(1);
884 }
885 return record_type_diff_protobuf;
886 }
887
AddEnumUnderlyingTypeDiff(abi_diff::UnderlyingTypeDiff * underlying_type_diff_protobuf,const std::pair<std::string,std::string> * underlying_type_diff_ir)888 bool IRDiffToProtobufConverter::AddEnumUnderlyingTypeDiff(
889 abi_diff::UnderlyingTypeDiff *underlying_type_diff_protobuf,
890 const std::pair<std::string, std::string> *underlying_type_diff_ir) {
891 if (underlying_type_diff_protobuf == nullptr) {
892 return false;
893 }
894 underlying_type_diff_protobuf->set_old_type(underlying_type_diff_ir->first);
895 underlying_type_diff_protobuf->set_new_type(underlying_type_diff_ir->second);
896 return true;
897 }
898
AddEnumFields(google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> * dst,const std::vector<const EnumFieldIR * > & enum_fields)899 static bool AddEnumFields(
900 google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> *dst,
901 const std::vector<const EnumFieldIR *> &enum_fields) {
902 for (auto &&enum_field : enum_fields) {
903 abi_dump::EnumFieldDecl *added_enum_field = dst->Add();
904 if (!SetIRToProtobufEnumField(added_enum_field, enum_field)) {
905 return false;
906 }
907 }
908 return true;
909 }
910
AddEnumFieldDiffs(google::protobuf::RepeatedPtrField<abi_diff::EnumFieldDeclDiff> * dst,const std::vector<EnumFieldDiffIR> & fields_diff_ir)911 static bool AddEnumFieldDiffs(
912 google::protobuf::RepeatedPtrField<abi_diff::EnumFieldDeclDiff> *dst,
913 const std::vector<EnumFieldDiffIR> &fields_diff_ir) {
914 for (auto &&field_diff_ir : fields_diff_ir) {
915 abi_diff::EnumFieldDeclDiff *field_diff_protobuf = dst->Add();
916 if (field_diff_protobuf == nullptr) {
917 return false;
918 }
919 if (!SetIRToProtobufEnumField(field_diff_protobuf->mutable_old_field(),
920 field_diff_ir.GetOldField()) ||
921 !SetIRToProtobufEnumField(field_diff_protobuf->mutable_new_field(),
922 field_diff_ir.GetNewField())) {
923 return false;
924 }
925 }
926 return true;
927 }
928
ConvertEnumTypeDiffIR(const EnumTypeDiffIR * enum_type_diff_ir)929 abi_diff::EnumTypeDiff IRDiffToProtobufConverter::ConvertEnumTypeDiffIR(
930 const EnumTypeDiffIR *enum_type_diff_ir) {
931 abi_diff::EnumTypeDiff enum_type_diff_protobuf;
932 enum_type_diff_protobuf.set_name(enum_type_diff_ir->GetName());
933 const std::pair<std::string, std::string> *underlying_type_diff =
934 enum_type_diff_ir->GetUnderlyingTypeDiff();
935 if ((underlying_type_diff != nullptr &&
936 !AddEnumUnderlyingTypeDiff(
937 enum_type_diff_protobuf.mutable_underlying_type_diff(),
938 underlying_type_diff)) ||
939 !AddEnumFields(enum_type_diff_protobuf.mutable_fields_removed(),
940 enum_type_diff_ir->GetFieldsRemoved()) ||
941 !AddEnumFields(enum_type_diff_protobuf.mutable_fields_added(),
942 enum_type_diff_ir->GetFieldsAdded()) ||
943 !AddEnumFieldDiffs(enum_type_diff_protobuf.mutable_fields_diff(),
944 enum_type_diff_ir->GetFieldsDiff())) {
945 llvm::errs() << "Enum field diff could not be added\n";
946 ::exit(1);
947 }
948 return enum_type_diff_protobuf;
949 }
950
ConvertGlobalVarDiffIR(const GlobalVarDiffIR * global_var_diff_ir)951 abi_diff::GlobalVarDeclDiff IRDiffToProtobufConverter::ConvertGlobalVarDiffIR(
952 const GlobalVarDiffIR *global_var_diff_ir) {
953 abi_diff::GlobalVarDeclDiff global_var_diff;
954 global_var_diff.set_name(global_var_diff_ir->GetName());
955 abi_dump::GlobalVarDecl *old_global_var = global_var_diff.mutable_old();
956 abi_dump::GlobalVarDecl *new_global_var = global_var_diff.mutable_new_();
957 if (old_global_var == nullptr || new_global_var == nullptr) {
958 llvm::errs() << "Globar Var diff could not be added\n";
959 ::exit(1);
960 }
961 *old_global_var =
962 IRToProtobufConverter::ConvertGlobalVarIR(
963 global_var_diff_ir->GetOldGlobalVar());
964 *new_global_var =
965 IRToProtobufConverter::ConvertGlobalVarIR(
966 global_var_diff_ir->GetNewGlobalVar());
967 return global_var_diff;
968 }
969
ConvertFunctionDiffIR(const FunctionDiffIR * function_diff_ir)970 abi_diff::FunctionDeclDiff IRDiffToProtobufConverter::ConvertFunctionDiffIR(
971 const FunctionDiffIR *function_diff_ir) {
972 abi_diff::FunctionDeclDiff function_diff;
973 function_diff.set_name(function_diff_ir->GetName());
974 abi_dump::FunctionDecl *old_function = function_diff.mutable_old();
975 abi_dump::FunctionDecl *new_function = function_diff.mutable_new_();
976 if (old_function == nullptr || new_function == nullptr) {
977 llvm::errs() << "Function diff could not be added\n";
978 ::exit(1);
979 }
980 *old_function =
981 IRToProtobufConverter::ConvertFunctionIR(
982 function_diff_ir->GetOldFunction());
983 *new_function =
984 IRToProtobufConverter::ConvertFunctionIR(
985 function_diff_ir->GetNewFunction());
986 return function_diff;
987 }
988
AddLinkableMessageIR(const LinkableMessageIR * lm)989 bool ProtobufIRDumper::AddLinkableMessageIR (const LinkableMessageIR *lm) {
990 // No RTTI
991 switch (lm->GetKind()) {
992 case RecordTypeKind:
993 return AddRecordTypeIR(static_cast<const RecordTypeIR *>(lm));
994 case EnumTypeKind:
995 return AddEnumTypeIR(static_cast<const EnumTypeIR *>(lm));
996 case PointerTypeKind:
997 return AddPointerTypeIR(static_cast<const PointerTypeIR *>(lm));
998 case QualifiedTypeKind:
999 return AddQualifiedTypeIR(static_cast<const QualifiedTypeIR *>(lm));
1000 case ArrayTypeKind:
1001 return AddArrayTypeIR(static_cast<const ArrayTypeIR *>(lm));
1002 case LvalueReferenceTypeKind:
1003 return AddLvalueReferenceTypeIR(
1004 static_cast<const LvalueReferenceTypeIR *>(lm));
1005 case RvalueReferenceTypeKind:
1006 return AddRvalueReferenceTypeIR(
1007 static_cast<const RvalueReferenceTypeIR*>(lm));
1008 case BuiltinTypeKind:
1009 return AddBuiltinTypeIR(static_cast<const BuiltinTypeIR*>(lm));
1010 case FunctionTypeKind:
1011 return AddFunctionTypeIR(static_cast<const FunctionTypeIR*>(lm));
1012 case GlobalVarKind:
1013 return AddGlobalVarIR(static_cast<const GlobalVarIR*>(lm));
1014 case FunctionKind:
1015 return AddFunctionIR(static_cast<const FunctionIR*>(lm));
1016 }
1017 return false;
1018 }
1019
AddElfFunctionIR(const ElfFunctionIR * elf_function)1020 bool ProtobufIRDumper::AddElfFunctionIR(const ElfFunctionIR *elf_function) {
1021 abi_dump::ElfFunction *added_elf_function = tu_ptr_->add_elf_functions();
1022 if (!added_elf_function) {
1023 return false;
1024 }
1025 added_elf_function->set_name(elf_function->GetName());
1026 return true;
1027 }
1028
AddElfObjectIR(const ElfObjectIR * elf_object)1029 bool ProtobufIRDumper::AddElfObjectIR(const ElfObjectIR *elf_object) {
1030 abi_dump::ElfObject *added_elf_object = tu_ptr_->add_elf_objects();
1031 if (!added_elf_object) {
1032 return false;
1033 }
1034 added_elf_object->set_name(elf_object->GetName());
1035 return true;
1036 }
1037
AddElfSymbolMessageIR(const ElfSymbolIR * em)1038 bool ProtobufIRDumper::AddElfSymbolMessageIR(const ElfSymbolIR *em) {
1039 switch (em->GetKind()) {
1040 case ElfSymbolIR::ElfFunctionKind:
1041 return AddElfFunctionIR(static_cast<const ElfFunctionIR *>(em));
1042 case ElfSymbolIR::ElfObjectKind:
1043 return AddElfObjectIR(static_cast<const ElfObjectIR *>(em));
1044 }
1045 return false;
1046 }
1047
AddRecordTypeIR(const RecordTypeIR * recordp)1048 bool ProtobufIRDumper::AddRecordTypeIR(const RecordTypeIR *recordp) {
1049 abi_dump::RecordType *added_record_type = tu_ptr_->add_record_types();
1050 if (!added_record_type) {
1051 return false;
1052 }
1053 *added_record_type = ConvertRecordTypeIR(recordp);
1054 return true;
1055 }
1056
AddFunctionTypeIR(const FunctionTypeIR * function_typep)1057 bool ProtobufIRDumper::AddFunctionTypeIR(const FunctionTypeIR *function_typep) {
1058 abi_dump::FunctionType *added_function_type = tu_ptr_->add_function_types();
1059 if (!added_function_type) {
1060 return false;
1061 }
1062 *added_function_type = ConvertFunctionTypeIR(function_typep);
1063 return true;
1064 }
1065
AddFunctionIR(const FunctionIR * functionp)1066 bool ProtobufIRDumper::AddFunctionIR(const FunctionIR *functionp) {
1067 abi_dump::FunctionDecl *added_function = tu_ptr_->add_functions();
1068 if (!added_function) {
1069 return false;
1070 }
1071 *added_function = ConvertFunctionIR(functionp);
1072 return true;
1073 }
1074
AddEnumTypeIR(const EnumTypeIR * enump)1075 bool ProtobufIRDumper::AddEnumTypeIR(const EnumTypeIR *enump) {
1076 abi_dump::EnumType *added_enum_type = tu_ptr_->add_enum_types();
1077 if (!added_enum_type) {
1078 return false;
1079 }
1080 *added_enum_type = ConvertEnumTypeIR(enump);
1081 return true;
1082 }
1083
AddGlobalVarIR(const GlobalVarIR * global_varp)1084 bool ProtobufIRDumper::AddGlobalVarIR(const GlobalVarIR *global_varp) {
1085 abi_dump::GlobalVarDecl *added_global_var = tu_ptr_->add_global_vars();
1086 if (!added_global_var) {
1087 return false;
1088 }
1089 *added_global_var = ConvertGlobalVarIR(global_varp);
1090 return true;
1091 }
1092
AddPointerTypeIR(const PointerTypeIR * pointerp)1093 bool ProtobufIRDumper::AddPointerTypeIR(const PointerTypeIR *pointerp) {
1094 abi_dump::PointerType *added_pointer_type = tu_ptr_->add_pointer_types();
1095 if (!added_pointer_type) {
1096 return false;
1097 }
1098 *added_pointer_type = ConvertPointerTypeIR(pointerp);
1099 return true;
1100 }
1101
AddQualifiedTypeIR(const QualifiedTypeIR * qualtypep)1102 bool ProtobufIRDumper::AddQualifiedTypeIR(const QualifiedTypeIR *qualtypep) {
1103 abi_dump::QualifiedType *added_qualified_type =
1104 tu_ptr_->add_qualified_types();
1105 if (!added_qualified_type) {
1106 return false;
1107 }
1108 *added_qualified_type = ConvertQualifiedTypeIR(qualtypep);
1109 return true;
1110 }
1111
AddBuiltinTypeIR(const BuiltinTypeIR * builtin_typep)1112 bool ProtobufIRDumper::AddBuiltinTypeIR(const BuiltinTypeIR *builtin_typep) {
1113 abi_dump::BuiltinType *added_builtin_type =
1114 tu_ptr_->add_builtin_types();
1115 if (!added_builtin_type) {
1116 return false;
1117 }
1118 *added_builtin_type = ConvertBuiltinTypeIR(builtin_typep);
1119 return true;
1120 }
1121
AddArrayTypeIR(const ArrayTypeIR * array_typep)1122 bool ProtobufIRDumper::AddArrayTypeIR(const ArrayTypeIR *array_typep) {
1123 abi_dump::ArrayType *added_array_type =
1124 tu_ptr_->add_array_types();
1125 if (!added_array_type) {
1126 return false;
1127 }
1128 *added_array_type = ConvertArrayTypeIR(array_typep);
1129 return true;
1130 }
1131
AddLvalueReferenceTypeIR(const LvalueReferenceTypeIR * lvalue_reference_typep)1132 bool ProtobufIRDumper::AddLvalueReferenceTypeIR(
1133 const LvalueReferenceTypeIR *lvalue_reference_typep) {
1134 abi_dump::LvalueReferenceType *added_lvalue_reference_type =
1135 tu_ptr_->add_lvalue_reference_types();
1136 if (!added_lvalue_reference_type) {
1137 return false;
1138 }
1139 *added_lvalue_reference_type =
1140 ConvertLvalueReferenceTypeIR(lvalue_reference_typep);
1141 return true;
1142 }
1143
AddRvalueReferenceTypeIR(const RvalueReferenceTypeIR * rvalue_reference_typep)1144 bool ProtobufIRDumper::AddRvalueReferenceTypeIR(
1145 const RvalueReferenceTypeIR *rvalue_reference_typep) {
1146 abi_dump::RvalueReferenceType *added_rvalue_reference_type =
1147 tu_ptr_->add_rvalue_reference_types();
1148 if (!added_rvalue_reference_type) {
1149 return false;
1150 }
1151 *added_rvalue_reference_type =
1152 ConvertRvalueReferenceTypeIR(rvalue_reference_typep);
1153 return true;
1154 }
1155
Dump()1156 bool ProtobufIRDumper::Dump() {
1157 GOOGLE_PROTOBUF_VERIFY_VERSION;
1158 assert( tu_ptr_.get() != nullptr);
1159 std::ofstream text_output(dump_path_);
1160 google::protobuf::io::OstreamOutputStream text_os(&text_output);
1161 return google::protobuf::TextFormat::Print(*tu_ptr_.get(), &text_os);
1162 }
1163
AddLibNameIR(const std::string & name)1164 void ProtobufIRDiffDumper::AddLibNameIR(const std::string &name) {
1165 diff_tu_->set_lib_name(name);
1166 }
1167
AddArchIR(const std::string & arch)1168 void ProtobufIRDiffDumper::AddArchIR(const std::string &arch) {
1169 diff_tu_->set_arch(arch);
1170 }
1171
GetCompatibilityStatusIR()1172 CompatibilityStatusIR ProtobufIRDiffDumper::GetCompatibilityStatusIR() {
1173 if (diff_tu_->functions_removed().size() != 0 ||
1174 diff_tu_->global_vars_removed().size() != 0 ||
1175 diff_tu_->function_diffs().size() != 0 ||
1176 diff_tu_->global_var_diffs().size() != 0 ||
1177 diff_tu_->enum_type_diffs().size() != 0 ||
1178 diff_tu_->record_type_diffs().size() != 0) {
1179 return CompatibilityStatusIR::Incompatible;
1180 }
1181
1182 CompatibilityStatusIR combined_status = CompatibilityStatusIR::Compatible;
1183
1184 if (diff_tu_->enum_type_extension_diffs().size() != 0 ||
1185 diff_tu_->functions_added().size() != 0 ||
1186 diff_tu_->global_vars_added().size() != 0) {
1187 combined_status = combined_status | CompatibilityStatusIR::Extension;
1188 }
1189
1190 if (diff_tu_->unreferenced_enum_type_diffs().size() != 0 ||
1191 diff_tu_->unreferenced_enum_types_removed().size() != 0 ||
1192 diff_tu_->unreferenced_record_types_removed().size() != 0 ||
1193 diff_tu_->unreferenced_record_type_diffs().size() != 0 ||
1194 diff_tu_->unreferenced_enum_type_extension_diffs().size() != 0 ||
1195 diff_tu_->unreferenced_record_types_added().size() != 0 ||
1196 diff_tu_->unreferenced_enum_types_added().size()) {
1197 combined_status =
1198 combined_status | CompatibilityStatusIR::UnreferencedChanges;
1199 }
1200
1201 if(diff_tu_->removed_elf_functions().size() != 0 ||
1202 diff_tu_->removed_elf_objects().size() != 0) {
1203 combined_status = combined_status | CompatibilityStatusIR::ElfIncompatible;
1204 }
1205
1206 return combined_status;
1207 }
1208
AddCompatibilityStatusIR(CompatibilityStatusIR status)1209 void ProtobufIRDiffDumper::AddCompatibilityStatusIR(
1210 CompatibilityStatusIR status) {
1211 diff_tu_->set_compatibility_status(CompatibilityStatusIRToProtobuf(status));
1212 }
1213
AddDiffMessageIR(const DiffMessageIR * message,const std::string & type_stack,DiffKind diff_kind)1214 bool ProtobufIRDiffDumper::AddDiffMessageIR(
1215 const DiffMessageIR *message,
1216 const std::string &type_stack,
1217 DiffKind diff_kind) {
1218 switch (message->Kind()) {
1219 case RecordTypeKind:
1220 return AddRecordTypeDiffIR(
1221 static_cast<const RecordTypeDiffIR *>(message),
1222 type_stack, diff_kind);
1223 case EnumTypeKind:
1224 return AddEnumTypeDiffIR(
1225 static_cast<const EnumTypeDiffIR *>(message),
1226 type_stack, diff_kind);
1227 case GlobalVarKind:
1228 return AddGlobalVarDiffIR(
1229 static_cast<const GlobalVarDiffIR*>(message),
1230 type_stack, diff_kind);
1231 case FunctionKind:
1232 return AddFunctionDiffIR(
1233 static_cast<const FunctionDiffIR*>(message),
1234 type_stack, diff_kind);
1235 default:
1236 break;
1237 }
1238 llvm::errs() << "Dump Diff attempted on something not a user defined type" <<
1239 "/ function / global variable\n";
1240 return false;
1241 }
1242
AddLinkableMessageIR(const LinkableMessageIR * message,DiffKind diff_kind)1243 bool ProtobufIRDiffDumper::AddLinkableMessageIR(
1244 const LinkableMessageIR *message,
1245 DiffKind diff_kind) {
1246 switch (message->GetKind()) {
1247 case RecordTypeKind:
1248 return AddLoneRecordTypeDiffIR(
1249 static_cast<const RecordTypeIR *>(message), diff_kind);
1250 case EnumTypeKind:
1251 return AddLoneEnumTypeDiffIR(
1252 static_cast<const EnumTypeIR *>(message), diff_kind);
1253 case GlobalVarKind:
1254 return AddLoneGlobalVarDiffIR(
1255 static_cast<const GlobalVarIR*>(message), diff_kind);
1256 case FunctionKind:
1257 return AddLoneFunctionDiffIR(
1258 static_cast<const FunctionIR*>(message), diff_kind);
1259 default:
1260 break;
1261 }
1262 llvm::errs() << "Dump Diff attempted on something not a user defined type" <<
1263 "/ function / global variable\n";
1264 return false;
1265 }
1266
AddElfSymbolMessageIR(const ElfSymbolIR * elf_symbol,DiffKind diff_kind)1267 bool ProtobufIRDiffDumper::AddElfSymbolMessageIR (const ElfSymbolIR *elf_symbol,
1268 DiffKind diff_kind) {
1269 switch (elf_symbol->GetKind()) {
1270 case ElfSymbolIR::ElfFunctionKind:
1271 return AddElfFunctionIR(static_cast<const ElfFunctionIR *>(elf_symbol),
1272 diff_kind);
1273 break;
1274 case ElfSymbolIR::ElfObjectKind:
1275 return AddElfObjectIR(static_cast<const ElfObjectIR *>(elf_symbol),
1276 diff_kind);
1277 break;
1278 }
1279 // Any other kind is invalid
1280 return false;
1281 }
1282
AddElfFunctionIR(const ElfFunctionIR * elf_function_ir,DiffKind diff_kind)1283 bool ProtobufIRDiffDumper::AddElfFunctionIR(
1284 const ElfFunctionIR *elf_function_ir, DiffKind diff_kind) {
1285 abi_dump::ElfFunction *added_elf_function = nullptr;
1286 switch(diff_kind) {
1287 case DiffKind::Removed:
1288 added_elf_function = diff_tu_->add_removed_elf_functions();
1289 break;
1290 case DiffKind::Added:
1291 added_elf_function = diff_tu_->add_added_elf_functions();
1292 break;
1293 default:
1294 llvm::errs() << "Invalid call to AddElfFunctionIR\n";
1295 return false;
1296 }
1297 if (added_elf_function == nullptr) {
1298 return false;
1299 }
1300 *added_elf_function =
1301 IRToProtobufConverter::ConvertElfFunctionIR(elf_function_ir);
1302 return true;
1303 }
1304
AddElfObjectIR(const ElfObjectIR * elf_object_ir,DiffKind diff_kind)1305 bool ProtobufIRDiffDumper::AddElfObjectIR(
1306 const ElfObjectIR *elf_object_ir, DiffKind diff_kind) {
1307 abi_dump::ElfObject *added_elf_object = nullptr;
1308 switch(diff_kind) {
1309 case DiffKind::Removed:
1310 added_elf_object = diff_tu_->add_removed_elf_objects();
1311 break;
1312 case DiffKind::Added:
1313 added_elf_object = diff_tu_->add_added_elf_objects();
1314 break;
1315 default:
1316 llvm::errs() << "Invalid call to AddElfObjectIR\n";
1317 return false;
1318 }
1319 if (added_elf_object == nullptr) {
1320 return false;
1321 }
1322 *added_elf_object =
1323 IRToProtobufConverter::ConvertElfObjectIR(elf_object_ir);
1324 return true;
1325 }
1326
AddLoneRecordTypeDiffIR(const RecordTypeIR * record_type_ir,DiffKind diff_kind)1327 bool ProtobufIRDiffDumper::AddLoneRecordTypeDiffIR(
1328 const RecordTypeIR *record_type_ir,
1329 DiffKind diff_kind) {
1330 abi_dump::RecordType *added_record_type = nullptr;
1331 switch (diff_kind) {
1332 case DiffKind::Removed:
1333 // Referenced record types do not get reported as added / removed,
1334 // the diff shows up in the parent type / function/ global variable
1335 // referencing the record.
1336 added_record_type = diff_tu_->add_unreferenced_record_types_removed();
1337 break;
1338 case DiffKind::Added:
1339 added_record_type = diff_tu_->add_unreferenced_record_types_added();
1340 break;
1341 default:
1342 llvm::errs() << "Invalid call to AddLoneRecordTypeDiffIR\n";
1343 return false;
1344 }
1345 if (added_record_type == nullptr) {
1346 return false;
1347 }
1348 *added_record_type =
1349 IRToProtobufConverter::ConvertRecordTypeIR(record_type_ir);
1350 return true;
1351 }
1352
AddLoneFunctionDiffIR(const FunctionIR * function_ir,DiffKind diff_kind)1353 bool ProtobufIRDiffDumper::AddLoneFunctionDiffIR(
1354 const FunctionIR *function_ir,
1355 DiffKind diff_kind) {
1356 abi_dump::FunctionDecl *added_function = nullptr;
1357 switch (diff_kind) {
1358 case DiffKind::Removed:
1359 added_function = diff_tu_->add_functions_removed();
1360 break;
1361 case DiffKind::Added:
1362 added_function = diff_tu_->add_functions_added();
1363 break;
1364 default:
1365 llvm::errs() << "Invalid call to AddLoneFunctionDiffIR\n";
1366 return false;
1367 }
1368 *added_function = IRToProtobufConverter::ConvertFunctionIR(function_ir);
1369 return true;
1370 }
1371
AddLoneEnumTypeDiffIR(const EnumTypeIR * enum_type_ir,DiffKind diff_kind)1372 bool ProtobufIRDiffDumper::AddLoneEnumTypeDiffIR(
1373 const EnumTypeIR *enum_type_ir, DiffKind diff_kind) {
1374 abi_dump::EnumType *added_enum_type = nullptr;
1375 switch (diff_kind) {
1376 case DiffKind::Removed:
1377 // Referenced enum types do not get reported as added / removed,
1378 // the diff shows up in the parent type / function/ global variable
1379 // referencing the enum.
1380 added_enum_type = diff_tu_->add_unreferenced_enum_types_removed();
1381 break;
1382 case DiffKind::Added:
1383 added_enum_type = diff_tu_->add_unreferenced_enum_types_added();
1384 break;
1385 default:
1386 llvm::errs() << "Invalid call to AddLoneRecordTypeDiffIR\n";
1387 return false;
1388 }
1389 if (added_enum_type == nullptr) {
1390 return false;
1391 }
1392 *added_enum_type = IRToProtobufConverter::ConvertEnumTypeIR(enum_type_ir);
1393 return true;
1394 }
1395
AddLoneGlobalVarDiffIR(const GlobalVarIR * global_var_ir,DiffKind diff_kind)1396 bool ProtobufIRDiffDumper::AddLoneGlobalVarDiffIR(
1397 const GlobalVarIR *global_var_ir, DiffKind diff_kind) {
1398 abi_dump::GlobalVarDecl *added_global_var = nullptr;
1399 switch (diff_kind) {
1400 case DiffKind::Removed:
1401 added_global_var = diff_tu_->add_global_vars_removed();
1402 break;
1403 case DiffKind::Added:
1404 added_global_var = diff_tu_->add_global_vars_added();
1405 break;
1406 default:
1407 llvm::errs() << "Invalid call to AddLoneFunctionDiffIR\n";
1408 return false;
1409 }
1410 *added_global_var = IRToProtobufConverter::ConvertGlobalVarIR(global_var_ir);
1411 return true;
1412 }
1413
AddRecordTypeDiffIR(const RecordTypeDiffIR * record_diff_ir,const std::string & type_stack,DiffKind diff_kind)1414 bool ProtobufIRDiffDumper::AddRecordTypeDiffIR(
1415 const RecordTypeDiffIR *record_diff_ir,
1416 const std::string &type_stack,
1417 DiffKind diff_kind) {
1418 abi_diff::RecordTypeDiff *added_record_type_diff = nullptr;
1419 switch (diff_kind) {
1420 case DiffKind::Unreferenced:
1421 added_record_type_diff = diff_tu_->add_unreferenced_record_type_diffs();
1422 break;
1423 case DiffKind::Referenced:
1424 added_record_type_diff = diff_tu_->add_record_type_diffs();
1425 break;
1426 default:
1427 break;
1428 }
1429 if (!added_record_type_diff) {
1430 return false;
1431 }
1432
1433 *added_record_type_diff =
1434 IRDiffToProtobufConverter::ConvertRecordTypeDiffIR(record_diff_ir);
1435 added_record_type_diff->set_type_stack(type_stack);
1436 return true;
1437 }
1438
AddFunctionDiffIR(const FunctionDiffIR * function_diff_ir,const std::string & type_stack,DiffKind diff_kind)1439 bool ProtobufIRDiffDumper::AddFunctionDiffIR(
1440 const FunctionDiffIR *function_diff_ir, const std::string &type_stack,
1441 DiffKind diff_kind) {
1442 abi_diff::FunctionDeclDiff *added_function_diff =
1443 diff_tu_->add_function_diffs();
1444 if (!added_function_diff) {
1445 return false;
1446 }
1447 *added_function_diff =
1448 IRDiffToProtobufConverter::ConvertFunctionDiffIR(function_diff_ir);
1449 return true;
1450 }
1451
AddEnumTypeDiffIR(const EnumTypeDiffIR * enum_diff_ir,const std::string & type_stack,DiffKind diff_kind)1452 bool ProtobufIRDiffDumper::AddEnumTypeDiffIR(const EnumTypeDiffIR *enum_diff_ir,
1453 const std::string &type_stack,
1454 DiffKind diff_kind) {
1455 abi_diff::EnumTypeDiff *added_enum_type_diff = nullptr;
1456 switch (diff_kind) {
1457 case DiffKind::Unreferenced:
1458 if (enum_diff_ir->IsExtended()) {
1459 added_enum_type_diff =
1460 diff_tu_->add_unreferenced_enum_type_extension_diffs();
1461 } else {
1462 added_enum_type_diff =
1463 diff_tu_->add_unreferenced_enum_type_diffs();
1464 }
1465 break;
1466 case DiffKind::Referenced:
1467 if (enum_diff_ir->IsExtended()) {
1468 added_enum_type_diff =
1469 diff_tu_->add_enum_type_extension_diffs();
1470 } else {
1471 added_enum_type_diff =
1472 diff_tu_->add_enum_type_diffs();
1473 }
1474 break;
1475 default:
1476 break;
1477 }
1478 if (!added_enum_type_diff) {
1479 return false;
1480 }
1481 *added_enum_type_diff =
1482 IRDiffToProtobufConverter::ConvertEnumTypeDiffIR(enum_diff_ir);
1483 added_enum_type_diff->set_type_stack(type_stack);
1484 return true;
1485 }
1486
AddGlobalVarDiffIR(const GlobalVarDiffIR * global_var_diff_ir,const std::string & type_stack,DiffKind diff_kind)1487 bool ProtobufIRDiffDumper::AddGlobalVarDiffIR(
1488 const GlobalVarDiffIR *global_var_diff_ir,
1489 const std::string &type_stack,
1490 DiffKind diff_kind) {
1491 abi_diff::GlobalVarDeclDiff *added_global_var_diff =
1492 diff_tu_->add_global_var_diffs();
1493 if (!added_global_var_diff) {
1494 return false;
1495 }
1496 *added_global_var_diff =
1497 IRDiffToProtobufConverter::ConvertGlobalVarDiffIR(global_var_diff_ir);
1498 return true;
1499 }
1500
Dump()1501 bool ProtobufIRDiffDumper::Dump() {
1502 GOOGLE_PROTOBUF_VERIFY_VERSION;
1503 assert(diff_tu_.get() != nullptr);
1504 std::ofstream text_output(dump_path_);
1505 google::protobuf::io::OstreamOutputStream text_os(&text_output);
1506 return google::protobuf::TextFormat::Print(*diff_tu_.get(), &text_os);
1507 }
1508
1509 } //abi_util
1510