Home | History | Annotate | Download | only in protobuf
      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/converter.h"
     16 
     17 #include <llvm/Support/raw_ostream.h>
     18 
     19 #include <fstream>
     20 #include <iostream>
     21 #include <memory>
     22 #include <string>
     23 
     24 
     25 namespace header_checker {
     26 namespace repr {
     27 
     28 
     29 bool IRDiffToProtobufConverter::AddTypeInfoDiff(
     30     abi_diff::TypeInfoDiff *type_info_diff_protobuf,
     31     const TypeDiffIR *type_diff_ir) {
     32   abi_diff::TypeInfo *old_type_info_protobuf =
     33       type_info_diff_protobuf->mutable_old_type_info();
     34   abi_diff::TypeInfo *new_type_info_protobuf =
     35       type_info_diff_protobuf->mutable_new_type_info();
     36   if (old_type_info_protobuf == nullptr || new_type_info_protobuf == nullptr) {
     37     return false;
     38   }
     39   const std::pair<uint64_t, uint64_t> &sizes = type_diff_ir->GetSizes();
     40   const std::pair<uint32_t, uint32_t> &alignments =
     41       type_diff_ir->GetAlignments();
     42   old_type_info_protobuf->set_size(sizes.first);
     43   new_type_info_protobuf->set_size(sizes.second);
     44 
     45   old_type_info_protobuf->set_alignment(alignments.first);
     46   new_type_info_protobuf->set_alignment(alignments.second);
     47   return true;
     48 }
     49 
     50 bool IRDiffToProtobufConverter::AddVTableLayoutDiff(
     51     abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf,
     52     const VTableLayoutDiffIR *vtable_layout_diff_ir) {
     53   abi_dump:: VTableLayout *old_vtable =
     54       vtable_layout_diff_protobuf->mutable_old_vtable();
     55   abi_dump:: VTableLayout *new_vtable =
     56       vtable_layout_diff_protobuf->mutable_new_vtable();
     57   if (old_vtable == nullptr || new_vtable == nullptr ||
     58       !SetIRToProtobufVTableLayout(old_vtable,
     59                                    vtable_layout_diff_ir->GetOldVTable()) ||
     60       !SetIRToProtobufVTableLayout(new_vtable,
     61                                    vtable_layout_diff_ir->GetNewVTable())) {
     62     return false;
     63   }
     64   return true;
     65 }
     66 
     67 template <typename T>
     68 static bool CopyBaseSpecifiersDiffIRToProtobuf(
     69     google::protobuf::RepeatedPtrField<T> *dst,
     70     const std::vector<CXXBaseSpecifierIR> &bases_ir) {
     71   for (auto &&base_ir : bases_ir) {
     72     T *added_base = dst->Add();
     73     if (!SetIRToProtobufBaseSpecifier(added_base, base_ir)) {
     74       return false;
     75     }
     76   }
     77   return true;
     78 }
     79 
     80 bool IRDiffToProtobufConverter::AddBaseSpecifierDiffs(
     81     abi_diff::CXXBaseSpecifierDiff *base_specifiers_diff_protobuf,
     82     const CXXBaseSpecifierDiffIR *base_specifiers_diff_ir) {
     83   if (!CopyBaseSpecifiersDiffIRToProtobuf(
     84           base_specifiers_diff_protobuf->mutable_old_bases(),
     85           base_specifiers_diff_ir->GetOldBases()) ||
     86       !CopyBaseSpecifiersDiffIRToProtobuf(
     87           base_specifiers_diff_protobuf->mutable_new_bases(),
     88           base_specifiers_diff_ir->GetNewBases())) {
     89     return false;
     90   }
     91   return true;
     92 }
     93 
     94 bool IRDiffToProtobufConverter::AddRecordFields(
     95     abi_diff::RecordTypeDiff *record_diff_protobuf,
     96     const std::vector<const RecordFieldIR *> &record_fields_ir,
     97     bool field_removed) {
     98   for (auto &&record_field_ir : record_fields_ir) {
     99     abi_dump::RecordFieldDecl *field = nullptr;
    100     if (field_removed) {
    101       field = record_diff_protobuf->add_fields_removed();
    102     } else {
    103       field = record_diff_protobuf->add_fields_added();
    104     }
    105     if (field == nullptr) {
    106       return false;
    107     }
    108     SetIRToProtobufRecordField(field, record_field_ir);
    109   }
    110   return true;
    111 }
    112 
    113 bool IRDiffToProtobufConverter::AddRecordFieldDiffs(
    114     abi_diff::RecordTypeDiff *record_diff_protobuf,
    115     const std::vector<RecordFieldDiffIR> &record_field_diffs_ir) {
    116   for (auto &&record_field_diff_ir : record_field_diffs_ir) {
    117     abi_diff::RecordFieldDeclDiff *record_field_diff =
    118         record_diff_protobuf->add_fields_diff();
    119     if (record_field_diff == nullptr) {
    120       return false;
    121     }
    122     abi_dump::RecordFieldDecl *old_field =
    123         record_field_diff->mutable_old_field();
    124     abi_dump::RecordFieldDecl *new_field =
    125         record_field_diff->mutable_new_field();
    126     if (old_field == nullptr || new_field == nullptr) {
    127       return false;
    128     }
    129     SetIRToProtobufRecordField(old_field,
    130                                record_field_diff_ir.GetOldField());
    131     SetIRToProtobufRecordField(new_field,
    132                                record_field_diff_ir.GetNewField());
    133   }
    134   return true;
    135 }
    136 
    137 abi_diff::RecordTypeDiff IRDiffToProtobufConverter::ConvertRecordTypeDiffIR(
    138     const RecordTypeDiffIR *record_type_diff_ir) {
    139   abi_diff::RecordTypeDiff record_type_diff_protobuf;
    140   record_type_diff_protobuf.set_name(record_type_diff_ir->GetName());
    141   const TypeDiffIR *type_diff_ir = record_type_diff_ir->GetTypeDiff();
    142   // If a type_info diff exists
    143   if (type_diff_ir != nullptr) {
    144     abi_diff::TypeInfoDiff *type_info_diff =
    145         record_type_diff_protobuf.mutable_type_info_diff();
    146     if (!AddTypeInfoDiff(type_info_diff, type_diff_ir)) {
    147       llvm::errs() << "RecordType could not be converted\n";
    148       ::exit(1);
    149     }
    150   }
    151   // If vtables differ.
    152   const VTableLayoutDiffIR *vtable_layout_diff_ir =
    153       record_type_diff_ir->GetVTableLayoutDiff();
    154   if (vtable_layout_diff_ir != nullptr) {
    155     abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf =
    156         record_type_diff_protobuf.mutable_vtable_layout_diff();
    157     if (!AddVTableLayoutDiff(vtable_layout_diff_protobuf,
    158                              vtable_layout_diff_ir)) {
    159       llvm::errs() << "VTable layout diff could not be added\n";
    160       ::exit(1);
    161     }
    162   }
    163   // If base specifiers differ.
    164   const CXXBaseSpecifierDiffIR *base_specifier_diff_ir =
    165       record_type_diff_ir->GetBaseSpecifiers();
    166   if (base_specifier_diff_ir != nullptr) {
    167     abi_diff::CXXBaseSpecifierDiff *base_specifier_diff_protobuf =
    168         record_type_diff_protobuf.mutable_bases_diff();
    169     if (!AddBaseSpecifierDiffs(base_specifier_diff_protobuf,
    170                                base_specifier_diff_ir)) {
    171       llvm::errs() << "Base Specifier diff could not be added\n";
    172       ::exit(1);
    173     }
    174   }
    175   // Field diffs
    176   if (!AddRecordFields(&record_type_diff_protobuf,
    177                        record_type_diff_ir->GetFieldsRemoved(), true) ||
    178       !AddRecordFields(&record_type_diff_protobuf,
    179                        record_type_diff_ir->GetFieldsAdded(), false) ||
    180       !AddRecordFieldDiffs(&record_type_diff_protobuf,
    181                            record_type_diff_ir->GetFieldDiffs())) {
    182     llvm::errs() << "Record Field diff could not be added\n";
    183     ::exit(1);
    184   }
    185   return record_type_diff_protobuf;
    186 }
    187 
    188 bool IRDiffToProtobufConverter::AddEnumUnderlyingTypeDiff(
    189     abi_diff::UnderlyingTypeDiff *underlying_type_diff_protobuf,
    190     const std::pair<std::string, std::string> *underlying_type_diff_ir) {
    191   if (underlying_type_diff_protobuf == nullptr) {
    192     return false;
    193   }
    194   underlying_type_diff_protobuf->set_old_type(underlying_type_diff_ir->first);
    195   underlying_type_diff_protobuf->set_new_type(underlying_type_diff_ir->second);
    196   return true;
    197 }
    198 
    199 static bool AddEnumFields(
    200     google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> *dst,
    201     const std::vector<const EnumFieldIR *> &enum_fields) {
    202   for (auto &&enum_field : enum_fields) {
    203     abi_dump::EnumFieldDecl *added_enum_field = dst->Add();
    204     if (!SetIRToProtobufEnumField(added_enum_field, enum_field)) {
    205       return false;
    206     }
    207   }
    208   return true;
    209 }
    210 
    211 static bool AddEnumFieldDiffs(
    212     google::protobuf::RepeatedPtrField<abi_diff::EnumFieldDeclDiff> *dst,
    213     const std::vector<EnumFieldDiffIR> &fields_diff_ir) {
    214   for (auto &&field_diff_ir : fields_diff_ir) {
    215     abi_diff::EnumFieldDeclDiff *field_diff_protobuf = dst->Add();
    216     if (field_diff_protobuf == nullptr) {
    217       return false;
    218     }
    219     if (!SetIRToProtobufEnumField(field_diff_protobuf->mutable_old_field(),
    220                                   field_diff_ir.GetOldField()) ||
    221         !SetIRToProtobufEnumField(field_diff_protobuf->mutable_new_field(),
    222                                   field_diff_ir.GetNewField())) {
    223       return false;
    224     }
    225   }
    226   return true;
    227 }
    228 
    229 abi_diff::EnumTypeDiff IRDiffToProtobufConverter::ConvertEnumTypeDiffIR(
    230     const EnumTypeDiffIR *enum_type_diff_ir) {
    231   abi_diff::EnumTypeDiff enum_type_diff_protobuf;
    232   enum_type_diff_protobuf.set_name(enum_type_diff_ir->GetName());
    233   const std::pair<std::string, std::string> *underlying_type_diff =
    234       enum_type_diff_ir->GetUnderlyingTypeDiff();
    235   if ((underlying_type_diff != nullptr &&
    236        !AddEnumUnderlyingTypeDiff(
    237            enum_type_diff_protobuf.mutable_underlying_type_diff(),
    238            underlying_type_diff)) ||
    239       !AddEnumFields(enum_type_diff_protobuf.mutable_fields_removed(),
    240                      enum_type_diff_ir->GetFieldsRemoved()) ||
    241       !AddEnumFields(enum_type_diff_protobuf.mutable_fields_added(),
    242                      enum_type_diff_ir->GetFieldsAdded()) ||
    243       !AddEnumFieldDiffs(enum_type_diff_protobuf.mutable_fields_diff(),
    244                          enum_type_diff_ir->GetFieldsDiff())) {
    245     llvm::errs() << "Enum field diff could not be added\n";
    246     ::exit(1);
    247   }
    248   return enum_type_diff_protobuf;
    249 }
    250 
    251 abi_diff::GlobalVarDeclDiff IRDiffToProtobufConverter::ConvertGlobalVarDiffIR(
    252     const GlobalVarDiffIR *global_var_diff_ir) {
    253   abi_diff::GlobalVarDeclDiff global_var_diff;
    254   global_var_diff.set_name(global_var_diff_ir->GetName());
    255   abi_dump::GlobalVarDecl *old_global_var = global_var_diff.mutable_old();
    256   abi_dump::GlobalVarDecl *new_global_var = global_var_diff.mutable_new_();
    257   if (old_global_var == nullptr || new_global_var == nullptr) {
    258     llvm::errs() << "Globar Var diff could not be added\n";
    259     ::exit(1);
    260   }
    261   *old_global_var =
    262       IRToProtobufConverter::ConvertGlobalVarIR(
    263           global_var_diff_ir->GetOldGlobalVar());
    264   *new_global_var =
    265       IRToProtobufConverter::ConvertGlobalVarIR(
    266           global_var_diff_ir->GetNewGlobalVar());
    267   return global_var_diff;
    268 }
    269 
    270 abi_diff::FunctionDeclDiff IRDiffToProtobufConverter::ConvertFunctionDiffIR(
    271     const FunctionDiffIR *function_diff_ir) {
    272   abi_diff::FunctionDeclDiff function_diff;
    273   function_diff.set_name(function_diff_ir->GetName());
    274   abi_dump::FunctionDecl *old_function = function_diff.mutable_old();
    275   abi_dump::FunctionDecl *new_function = function_diff.mutable_new_();
    276   if (old_function == nullptr || new_function == nullptr) {
    277     llvm::errs() << "Function diff could not be added\n";
    278     ::exit(1);
    279   }
    280   *old_function = IRToProtobufConverter::ConvertFunctionIR(
    281       function_diff_ir->GetOldFunction());
    282   *new_function = IRToProtobufConverter::ConvertFunctionIR(
    283       function_diff_ir->GetNewFunction());
    284   return function_diff;
    285 }
    286 
    287 
    288 }  // namespace repr
    289 }  // namespace header_checker
    290