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 #ifndef HEADER_CHECKER_PROTOBUF_CONVERTER_H_
     16 #define HEADER_CHECKER_PROTOBUF_CONVERTER_H_
     17 
     18 #include "repr/ir_diff_representation.h"
     19 #include "repr/ir_representation.h"
     20 #include "repr/protobuf/abi_diff.h"
     21 #include "repr/protobuf/abi_dump.h"
     22 
     23 #include <llvm/Support/raw_ostream.h>
     24 
     25 
     26 namespace header_checker {
     27 namespace repr {
     28 
     29 
     30 inline abi_diff::CompatibilityStatus CompatibilityStatusIRToProtobuf(
     31     CompatibilityStatusIR status) {
     32   switch (status) {
     33     case CompatibilityStatusIR::Incompatible:
     34       return abi_diff::CompatibilityStatus::INCOMPATIBLE;
     35     case CompatibilityStatusIR::Extension:
     36       return abi_diff::CompatibilityStatus::EXTENSION;
     37     default:
     38       break;
     39   }
     40   return abi_diff::CompatibilityStatus::COMPATIBLE;
     41 }
     42 
     43 inline abi_dump::ElfSymbolBinding ElfSymbolBindingIRToProtobuf(
     44     ElfSymbolIR::ElfSymbolBinding binding) {
     45   switch (binding) {
     46     case ElfSymbolIR::ElfSymbolBinding::Global:
     47       return abi_dump::ElfSymbolBinding::Global;
     48     case ElfSymbolIR::ElfSymbolBinding::Weak:
     49       return abi_dump::ElfSymbolBinding::Weak;
     50   }
     51   // We skip symbols of all other Bindings
     52   // TODO: Add all bindings, don't leave out info
     53   assert(0);
     54 }
     55 
     56 inline ElfSymbolIR::ElfSymbolBinding ElfSymbolBindingProtobufToIR(
     57     abi_dump::ElfSymbolBinding binding) {
     58   switch (binding) {
     59     case abi_dump::ElfSymbolBinding::Global:
     60       return ElfSymbolIR::ElfSymbolBinding::Global;
     61     case abi_dump::ElfSymbolBinding::Weak:
     62       return ElfSymbolIR::ElfSymbolBinding::Weak;
     63   }
     64   // We skip symbols of all other Bindings
     65   assert(0);
     66 }
     67 
     68 inline abi_dump::AccessSpecifier AccessIRToProtobuf(AccessSpecifierIR access) {
     69   switch (access) {
     70     case AccessSpecifierIR::ProtectedAccess:
     71       return abi_dump::AccessSpecifier::protected_access;
     72     case AccessSpecifierIR::PrivateAccess:
     73       return abi_dump::AccessSpecifier::private_access;
     74     default:
     75       return abi_dump::AccessSpecifier::public_access;
     76   }
     77   return abi_dump::AccessSpecifier::public_access;
     78 }
     79 
     80 inline AccessSpecifierIR AccessProtobufToIR(
     81     abi_dump::AccessSpecifier access) {
     82   switch (access) {
     83     case abi_dump::AccessSpecifier::protected_access:
     84       return AccessSpecifierIR::ProtectedAccess;
     85     case abi_dump::AccessSpecifier::private_access:
     86       return AccessSpecifierIR::PrivateAccess;
     87     default:
     88       return AccessSpecifierIR::PublicAccess;
     89   }
     90   return AccessSpecifierIR::PublicAccess;
     91 }
     92 
     93 inline abi_dump::RecordKind RecordKindIRToProtobuf(
     94     RecordTypeIR::RecordKind kind) {
     95   switch (kind) {
     96     case RecordTypeIR::RecordKind::struct_kind:
     97       return abi_dump::RecordKind::struct_kind;
     98 
     99     case RecordTypeIR::RecordKind::class_kind:
    100       return abi_dump::RecordKind::class_kind;
    101 
    102     case RecordTypeIR::RecordKind::union_kind:
    103       return abi_dump::RecordKind::union_kind;
    104 
    105     default:
    106       return abi_dump::RecordKind::struct_kind;
    107   }
    108   // Should not be reached
    109   assert(false);
    110 }
    111 
    112 inline RecordTypeIR::RecordKind RecordKindProtobufToIR(
    113     abi_dump::RecordKind kind) {
    114   switch (kind) {
    115     case abi_dump::RecordKind::struct_kind:
    116       return RecordTypeIR::struct_kind;
    117 
    118     case abi_dump::RecordKind::class_kind:
    119       return RecordTypeIR::class_kind;
    120 
    121     case abi_dump::RecordKind::union_kind:
    122       return RecordTypeIR::union_kind;
    123 
    124     default:
    125       return RecordTypeIR::struct_kind;
    126   }
    127   // Should not be reached
    128   assert(false);
    129 }
    130 
    131 inline abi_dump::VTableComponent::Kind VTableComponentKindIRToProtobuf(
    132     VTableComponentIR::Kind kind) {
    133   switch (kind) {
    134     case VTableComponentIR::Kind::VCallOffset:
    135       return abi_dump::VTableComponent_Kind_VCallOffset;
    136 
    137     case VTableComponentIR::Kind::VBaseOffset:
    138       return abi_dump::VTableComponent_Kind_VBaseOffset;
    139 
    140     case VTableComponentIR::Kind::OffsetToTop:
    141       return abi_dump::VTableComponent_Kind_OffsetToTop;
    142 
    143     case VTableComponentIR::Kind::RTTI:
    144       return abi_dump::VTableComponent_Kind_RTTI;
    145 
    146     case VTableComponentIR::Kind::FunctionPointer:
    147       return abi_dump::VTableComponent_Kind_FunctionPointer;
    148 
    149     case VTableComponentIR::Kind::CompleteDtorPointer:
    150       return abi_dump::VTableComponent_Kind_CompleteDtorPointer;
    151 
    152     case VTableComponentIR::Kind::DeletingDtorPointer:
    153       return abi_dump::VTableComponent_Kind_DeletingDtorPointer;
    154 
    155     default:
    156       return abi_dump::VTableComponent_Kind_UnusedFunctionPointer;
    157   }
    158   // Should not be reached
    159   assert(false);
    160 }
    161 
    162 inline VTableComponentIR::Kind VTableComponentKindProtobufToIR(
    163     abi_dump::VTableComponent_Kind kind) {
    164   switch (kind) {
    165     case abi_dump::VTableComponent_Kind_VCallOffset:
    166       return VTableComponentIR::Kind::VCallOffset;
    167 
    168     case abi_dump::VTableComponent_Kind_VBaseOffset:
    169       return VTableComponentIR::Kind::VBaseOffset;
    170 
    171     case abi_dump::VTableComponent_Kind_OffsetToTop:
    172       return VTableComponentIR::Kind::OffsetToTop;
    173 
    174     case abi_dump::VTableComponent_Kind_RTTI:
    175       return VTableComponentIR::Kind::RTTI;
    176 
    177     case abi_dump::VTableComponent_Kind_FunctionPointer:
    178       return VTableComponentIR::Kind::FunctionPointer;
    179 
    180     case abi_dump::VTableComponent_Kind_CompleteDtorPointer:
    181       return VTableComponentIR::Kind::CompleteDtorPointer;
    182 
    183     case abi_dump::VTableComponent_Kind_DeletingDtorPointer:
    184       return VTableComponentIR::Kind::DeletingDtorPointer;
    185 
    186     default:
    187       return VTableComponentIR::Kind::UnusedFunctionPointer;
    188   }
    189   // Should not be reached
    190   assert(false);
    191 }
    192 
    193 class IRToProtobufConverter {
    194  private:
    195   static bool AddTemplateInformation(
    196       abi_dump::TemplateInfo *ti, const TemplatedArtifactIR *ta);
    197 
    198   static bool AddTypeInfo(
    199       abi_dump::BasicNamedAndTypedDecl *type_info, const TypeIR *typep);
    200 
    201   static bool AddRecordFields(
    202       abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
    203 
    204   static bool AddBaseSpecifiers(
    205       abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
    206 
    207   static bool AddVTableLayout(
    208       abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
    209 
    210   static bool AddTagTypeInfo(abi_dump::TagType *tag_type_protobuf,
    211                              const TagTypeIR *tag_type_ir);
    212 
    213   static bool AddEnumFields(abi_dump::EnumType *enum_protobuf,
    214                             const EnumTypeIR *enum_ir);
    215 
    216  public:
    217   static abi_dump::EnumType ConvertEnumTypeIR(const EnumTypeIR *enump);
    218 
    219   static abi_dump::RecordType ConvertRecordTypeIR(const RecordTypeIR *recordp);
    220 
    221   static abi_dump::FunctionType ConvertFunctionTypeIR (
    222       const FunctionTypeIR *function_typep);
    223 
    224   template <typename CFunctionLikeMessage>
    225   static bool AddFunctionParametersAndSetReturnType(
    226       CFunctionLikeMessage *function_like_protobuf,
    227       const CFunctionLikeIR *cfunction_like_ir);
    228 
    229   template <typename CFunctionLikeMessage>
    230   static bool AddFunctionParameters(CFunctionLikeMessage *function_protobuf,
    231                                     const CFunctionLikeIR *cfunction_like_ir);
    232 
    233   static abi_dump::FunctionDecl ConvertFunctionIR(const FunctionIR *functionp);
    234 
    235   static abi_dump::GlobalVarDecl ConvertGlobalVarIR(
    236       const GlobalVarIR *global_varp);
    237 
    238   static abi_dump::PointerType ConvertPointerTypeIR(
    239       const PointerTypeIR *pointerp);
    240 
    241   static abi_dump::QualifiedType ConvertQualifiedTypeIR(
    242       const QualifiedTypeIR *qualtypep);
    243 
    244   static abi_dump::BuiltinType ConvertBuiltinTypeIR(
    245       const BuiltinTypeIR *builtin_typep);
    246 
    247   static abi_dump::ArrayType ConvertArrayTypeIR(
    248       const ArrayTypeIR *array_typep);
    249 
    250   static abi_dump::LvalueReferenceType ConvertLvalueReferenceTypeIR(
    251       const LvalueReferenceTypeIR *lvalue_reference_typep);
    252 
    253   static abi_dump::RvalueReferenceType ConvertRvalueReferenceTypeIR(
    254       const RvalueReferenceTypeIR *rvalue_reference_typep);
    255 
    256   static abi_dump::ElfFunction ConvertElfFunctionIR(
    257       const ElfFunctionIR *elf_function_ir);
    258 
    259   static abi_dump::ElfObject ConvertElfObjectIR(
    260       const ElfObjectIR *elf_object_ir);
    261 };
    262 
    263 class IRDiffToProtobufConverter {
    264  private:
    265   static bool AddTypeInfoDiff(
    266       abi_diff::TypeInfoDiff *type_info_diff_protobuf,
    267       const TypeDiffIR *type_diff_ir);
    268 
    269   static bool AddVTableLayoutDiff(
    270       abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf,
    271       const VTableLayoutDiffIR *vtable_layout_diff_ir);
    272 
    273   static bool AddBaseSpecifierDiffs(
    274       abi_diff::CXXBaseSpecifierDiff *base_specifier_diff_protobuf,
    275       const CXXBaseSpecifierDiffIR *base_specifier_diff_ir);
    276 
    277   static bool AddRecordFields(
    278       abi_diff::RecordTypeDiff *record_diff_protobuf,
    279       const std::vector<const RecordFieldIR *> &record_fields_removed_ir,
    280       bool removed);
    281 
    282   static bool AddRecordFieldDiffs(
    283       abi_diff::RecordTypeDiff *record_diff_protobuf,
    284       const std::vector<RecordFieldDiffIR> &record_field_diff_ir);
    285 
    286   static bool AddEnumUnderlyingTypeDiff(
    287       abi_diff::UnderlyingTypeDiff *underlying_type_diff_protobuf,
    288       const std::pair<std::string, std::string> *underlying_type_diff_ir);
    289 
    290  public:
    291   static abi_diff::RecordTypeDiff ConvertRecordTypeDiffIR(
    292       const RecordTypeDiffIR *record_type_diffp);
    293 
    294   static abi_diff::EnumTypeDiff ConvertEnumTypeDiffIR(
    295       const EnumTypeDiffIR *enum_type_diffp);
    296 
    297   static abi_diff::FunctionDeclDiff ConvertFunctionDiffIR(
    298       const FunctionDiffIR *function_diffp);
    299 
    300   static abi_diff::GlobalVarDeclDiff ConvertGlobalVarDiffIR(
    301       const GlobalVarDiffIR *global_var_diffp);
    302 };
    303 
    304 inline void SetIRToProtobufRecordField(
    305     abi_dump::RecordFieldDecl *record_field_protobuf,
    306     const RecordFieldIR *record_field_ir) {
    307   record_field_protobuf->set_field_name(record_field_ir->GetName());
    308   record_field_protobuf->set_referenced_type(
    309       record_field_ir->GetReferencedType());
    310   record_field_protobuf->set_access(
    311       AccessIRToProtobuf(record_field_ir->GetAccess()));
    312   record_field_protobuf->set_field_offset(record_field_ir->GetOffset());
    313 }
    314 
    315 inline bool SetIRToProtobufBaseSpecifier(
    316     abi_dump::CXXBaseSpecifier *base_specifier_protobuf,
    317     const CXXBaseSpecifierIR &base_specifier_ir) {
    318   if (!base_specifier_protobuf) {
    319     llvm::errs() << "Protobuf base specifier not valid\n";
    320     return false;
    321   }
    322   base_specifier_protobuf->set_referenced_type(
    323       base_specifier_ir.GetReferencedType());
    324   base_specifier_protobuf->set_is_virtual(
    325       base_specifier_ir.IsVirtual());
    326   base_specifier_protobuf->set_access(
    327       AccessIRToProtobuf(base_specifier_ir.GetAccess()));
    328   return true;
    329 }
    330 
    331 inline bool SetIRToProtobufVTableLayout(
    332     abi_dump::VTableLayout *vtable_layout_protobuf,
    333     const VTableLayoutIR &vtable_layout_ir) {
    334   if (vtable_layout_protobuf == nullptr) {
    335     llvm::errs() << "vtable layout protobuf not valid\n";
    336     return false;
    337   }
    338   for (auto &&vtable_component_ir : vtable_layout_ir.GetVTableComponents()) {
    339     abi_dump::VTableComponent *added_vtable_component =
    340         vtable_layout_protobuf->add_vtable_components();
    341     if (!added_vtable_component) {
    342       llvm::errs() << "Couldn't add vtable component\n";
    343       return false;
    344     }
    345     added_vtable_component->set_kind(
    346         VTableComponentKindIRToProtobuf(vtable_component_ir.GetKind()));
    347     added_vtable_component->set_component_value(vtable_component_ir.GetValue());
    348     added_vtable_component->set_mangled_component_name(
    349         vtable_component_ir.GetName());
    350     added_vtable_component->set_is_pure(vtable_component_ir.GetIsPure());
    351   }
    352   return true;
    353 }
    354 
    355 inline bool SetIRToProtobufEnumField(
    356     abi_dump::EnumFieldDecl *enum_field_protobuf,
    357     const EnumFieldIR *enum_field_ir) {
    358   if (enum_field_protobuf == nullptr) {
    359     return true;
    360   }
    361   enum_field_protobuf->set_name(enum_field_ir->GetName());
    362   enum_field_protobuf->set_enum_field_value(enum_field_ir->GetValue());
    363   return true;
    364 }
    365 
    366 
    367 }  // namespace repr
    368 }  // namespace header_checker
    369 
    370 
    371 #endif  // HEADER_CHECKER_PROTOBUF_CONVERTER_H_
    372