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