1 // Copyright (C) 2016 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 "abi_wrappers.h" 16 17 #include <header_abi_util.h> 18 19 #include <limits.h> 20 #include <stdlib.h> 21 #include <clang/Tooling/Core/QualTypeNames.h> 22 #include <clang/Index/CodegenNameGenerator.h> 23 24 #include <string> 25 26 using namespace abi_wrapper; 27 28 ABIWrapper::ABIWrapper( 29 clang::MangleContext *mangle_contextp, 30 clang::ASTContext *ast_contextp, 31 const clang::CompilerInstance *cip, 32 abi_util::IRDumper *ir_dumper, 33 ast_util::ASTCaches *ast_caches) 34 : cip_(cip), 35 mangle_contextp_(mangle_contextp), 36 ast_contextp_(ast_contextp), 37 ir_dumper_(ir_dumper), 38 ast_caches_(ast_caches) { } 39 40 std::string ABIWrapper::GetCachedDeclSourceFile( 41 const clang::Decl *decl, const clang::CompilerInstance *cip) { 42 assert(decl != nullptr); 43 auto result = ast_caches_->decl_to_source_file_cache_.find(decl); 44 if (result == ast_caches_->decl_to_source_file_cache_.end()) { 45 return GetDeclSourceFile(decl, cip); 46 } 47 return result->second; 48 } 49 50 static const clang::TagDecl *GetTagDecl(clang::QualType qual_type) { 51 const clang::Type *type_ptr = qual_type.getCanonicalType().getTypePtr(); 52 assert(type_ptr != nullptr); 53 const clang::TagDecl *tag_decl = type_ptr->getAsTagDecl(); 54 return tag_decl; 55 } 56 57 static const clang::RecordDecl *GetAnonymousRecord(clang::QualType type) { 58 const clang::Type *type_ptr = type.getTypePtr(); 59 assert(type_ptr != nullptr); 60 if (!type_ptr->isRecordType()) { 61 return nullptr; 62 } 63 const clang::TagDecl *tag_decl = type_ptr->getAsTagDecl(); 64 if (!tag_decl) { 65 return nullptr; 66 } 67 const clang::RecordDecl *record_decl = 68 llvm::dyn_cast<clang::RecordDecl>(tag_decl); 69 70 if (record_decl != nullptr && (!record_decl->hasNameForLinkage() || 71 record_decl->isAnonymousStructOrUnion())) { 72 return record_decl; 73 } 74 return nullptr; 75 } 76 77 static const clang::EnumDecl *GetAnonymousEnum( 78 const clang::QualType qual_type) { 79 const clang::Type *type_ptr = qual_type.getTypePtr(); 80 assert(type_ptr != nullptr); 81 const clang::TagDecl *tag_decl = type_ptr->getAsTagDecl(); 82 if (!tag_decl) { 83 return nullptr; 84 } 85 const clang::EnumDecl *enum_decl = llvm::dyn_cast<clang::EnumDecl>(tag_decl); 86 if (!enum_decl || enum_decl->hasNameForLinkage()) { 87 return nullptr; 88 } 89 return enum_decl; 90 } 91 92 static bool IsReferencingType(clang::QualType qual_type) { 93 const clang::QualType canonical_type = qual_type.getCanonicalType(); 94 const clang::Type *base_type = canonical_type.getTypePtr(); 95 bool is_ptr = base_type->isPointerType(); 96 bool is_reference = base_type->isReferenceType(); 97 bool is_array = base_type->isArrayType(); 98 return is_array || is_ptr || is_reference || 99 qual_type.hasLocalQualifiers(); 100 } 101 102 static clang::QualType GetReferencedType(const clang::QualType qual_type); 103 104 static clang::QualType GetFinalReferencedType(clang::QualType qual_type) { 105 while (IsReferencingType(qual_type)) { 106 qual_type = GetReferencedType(qual_type); 107 } 108 return qual_type; 109 } 110 111 std::string ABIWrapper::TypeNameWithFinalDestination(clang::QualType qual_type) { 112 clang::QualType canonical_qual_type = qual_type.getCanonicalType(); 113 const std::string qual_type_name = QualTypeToString(canonical_qual_type); 114 clang::QualType final_destination_type = 115 GetFinalReferencedType(canonical_qual_type); 116 const clang::RecordDecl *anon_record = 117 GetAnonymousRecord(final_destination_type); 118 if (anon_record) { 119 clang::SourceManager &sm = cip_->getSourceManager(); 120 clang::SourceLocation location = anon_record->getLocation(); 121 return qual_type_name + " at " + location.printToString(sm); 122 } 123 return qual_type_name; 124 } 125 126 std::string ABIWrapper::GetKeyForTypeId(clang::QualType qual_type) { 127 clang::QualType canonical_qual_type = qual_type.getCanonicalType(); 128 clang::QualType final_destination_type = 129 GetFinalReferencedType(canonical_qual_type); 130 // Get the tag id for final destionation and add that to the type name with 131 // final destination. This helps in avoiding aliasing of types when fully 132 // qualified type-name doesn't expand all template parameters with their 133 // namespaces. 134 return TypeNameWithFinalDestination(qual_type) + 135 GetTypeUniqueId(GetTagDecl(final_destination_type)); 136 } 137 138 std::string ABIWrapper::GetDeclSourceFile(const clang::Decl *decl, 139 const clang::CompilerInstance *cip) { 140 clang::SourceManager &sm = cip->getSourceManager(); 141 clang::SourceLocation location = decl->getLocation(); 142 // We need to use the expansion location to identify whether we should recurse 143 // into the AST Node or not. For eg: macros specifying LinkageSpecDecl can 144 // have their spelling location defined somewhere outside a source / header 145 // file belonging to a library. This should not allow the AST node to be 146 // skipped. Its expansion location will still be the source-file / header 147 // belonging to the library. 148 clang::SourceLocation expansion_location = sm.getExpansionLoc(location); 149 llvm::StringRef file_name = sm.getFilename(expansion_location); 150 return abi_util::RealPath(file_name.str()); 151 } 152 153 static abi_util::AccessSpecifierIR AccessClangToIR( 154 const clang::AccessSpecifier sp) { 155 switch (sp) { 156 case clang::AS_private: { 157 return abi_util::AccessSpecifierIR::PrivateAccess; 158 break; 159 } 160 case clang::AS_protected: { 161 return abi_util::AccessSpecifierIR::ProtectedAccess; 162 break; 163 } 164 default: { 165 return abi_util::AccessSpecifierIR::PublicAccess; 166 break; 167 } 168 } 169 } 170 171 bool ABIWrapper::CreateAnonymousRecord(const clang::RecordDecl *record_decl) { 172 RecordDeclWrapper record_decl_wrapper(mangle_contextp_, ast_contextp_, cip_, 173 record_decl, ir_dumper_, ast_caches_); 174 return record_decl_wrapper.GetRecordDecl(); 175 } 176 177 // Get type 'referenced' by qual_type. Referenced type implies, in order: 178 // 1) Strip off all qualifiers if qual_type has CVR qualifiers. 179 // 2) Strip off a pointer level if qual_type is a pointer. 180 // 3) Strip off the reference if qual_type is a reference. 181 // Note: qual_type is expected to be a canonical type. 182 static clang::QualType GetReferencedType(const clang::QualType qual_type) { 183 const clang::Type *type_ptr = qual_type.getTypePtr(); 184 if (qual_type.hasLocalQualifiers()) { 185 return qual_type.getLocalUnqualifiedType(); 186 } 187 if (type_ptr->isPointerType()) { 188 return type_ptr->getPointeeType(); 189 } 190 if (type_ptr->isArrayType()) { 191 return 192 type_ptr->getArrayElementTypeNoTypeQual()->getCanonicalTypeInternal(); 193 } 194 return qual_type.getNonReferenceType(); 195 } 196 197 bool ABIWrapper::CreateExtendedType( 198 clang::QualType qual_type, 199 abi_util::TypeIR *typep) { 200 const clang::QualType canonical_type = qual_type.getCanonicalType(); 201 // The source file is going to be set later anyway. 202 return CreateBasicNamedAndTypedDecl(canonical_type, typep, ""); 203 } 204 205 //This overload takes in a qualtype and adds its information to the abi-dump on 206 //its own. 207 bool ABIWrapper::CreateBasicNamedAndTypedDecl( 208 clang::QualType qual_type, const std::string &source_file) { 209 const std::string &type_key = GetKeyForTypeId(qual_type); 210 const clang::QualType canonical_type = qual_type.getCanonicalType(); 211 const clang::Type *base_type = canonical_type.getTypePtr(); 212 bool is_builtin = base_type->isBuiltinType(); 213 bool should_continue_with_recursive_type_creation = 214 IsReferencingType(canonical_type) || is_builtin || 215 base_type->isFunctionType() || 216 (GetAnonymousRecord(canonical_type) != nullptr); 217 if (!should_continue_with_recursive_type_creation || 218 !ast_caches_->type_cache_.insert(type_key).second) { 219 return true; 220 } 221 // Do something similar to what is being done right now. Create an object 222 // extending Type and return a pointer to that and pass it to CreateBasic... 223 // CreateBasic...(qualtype, Type *) fills in size, alignemnt etc. 224 auto type_and_status = SetTypeKind(canonical_type, source_file); 225 std::unique_ptr<abi_util::TypeIR> typep = std::move(type_and_status.typep_); 226 if (!base_type->isVoidType() && type_and_status.should_create_type_ && 227 !typep) { 228 llvm::errs() << "nullptr with valid type while creating basic type\n"; 229 return false; 230 } 231 return type_and_status.should_create_type_ ? 232 CreateBasicNamedAndTypedDecl(canonical_type, typep.get(), source_file) && 233 ir_dumper_->AddLinkableMessageIR(typep.get()) : true; 234 } 235 236 std::string RecordDeclWrapper::GetMangledRTTI( 237 const clang::CXXRecordDecl *cxx_record_decl) { 238 clang::QualType qual_type = 239 cxx_record_decl->getTypeForDecl()->getCanonicalTypeInternal(); 240 llvm::SmallString<256> uid; 241 llvm::raw_svector_ostream out(uid); 242 mangle_contextp_->mangleCXXRTTI(qual_type, out); 243 return uid.str(); 244 } 245 246 std::string ABIWrapper::GetTypeUniqueId(const clang::TagDecl *tag_decl) { 247 if (!tag_decl) { 248 return ""; 249 } 250 clang::QualType qual_type = 251 tag_decl->getTypeForDecl()->getCanonicalTypeInternal(); 252 if (!tag_decl->isExternCContext() && ast_contextp_->getLangOpts().CPlusPlus) { 253 llvm::SmallString<256> uid; 254 llvm::raw_svector_ostream out(uid); 255 mangle_contextp_->mangleCXXRTTIName(qual_type, out); 256 return uid.str(); 257 } 258 return QualTypeToString(qual_type); 259 } 260 261 // CreateBasicNamedAndTypedDecl creates a BasicNamedAndTypedDecl : that'll 262 // include all the generic information a basic type will have: 263 // abi_dump::BasicNamedAndTypedDecl. Other methods fill in more specific 264 // information, eg: RecordDecl, EnumDecl. 265 bool ABIWrapper::CreateBasicNamedAndTypedDecl( 266 clang::QualType canonical_type, 267 abi_util::TypeIR *typep, const std::string &source_file) { 268 // Cannot determine the size and alignment for template parameter dependent 269 // types as well as incomplete types. 270 const clang::Type *base_type = canonical_type.getTypePtr(); 271 assert(base_type != nullptr); 272 clang::Type::TypeClass type_class = base_type->getTypeClass(); 273 // Temporary Hack for auto type sizes. Not determinable. 274 if ((type_class != clang::Type::Auto) && !base_type->isIncompleteType() && 275 !(base_type->isDependentType())) { 276 std::pair<clang::CharUnits, clang::CharUnits> size_and_alignment = 277 ast_contextp_->getTypeInfoInChars(canonical_type); 278 size_t size = size_and_alignment.first.getQuantity(); 279 size_t alignment = size_and_alignment.second.getQuantity(); 280 typep->SetSize(size); 281 typep->SetAlignment(alignment); 282 } 283 std::string type_name_with_destination = 284 TypeNameWithFinalDestination(canonical_type); 285 typep->SetName(type_name_with_destination); 286 typep->SetLinkerSetKey(type_name_with_destination); 287 // default values are false, we don't set them since explicitly doing that 288 // makes the abi dumps more verbose. 289 // This type has a reference type if its a pointer / reference OR it has CVR 290 // qualifiers. 291 clang::QualType referenced_type = GetReferencedType(canonical_type); 292 typep->SetReferencedType( 293 ast_caches_->GetTypeId(GetKeyForTypeId(referenced_type))); 294 typep->SetSelfType(ast_caches_->GetTypeId(GetKeyForTypeId(canonical_type))); 295 // Create the type for referenced type. 296 return CreateBasicNamedAndTypedDecl(referenced_type, source_file); 297 } 298 299 std::string ABIWrapper::GetTypeLinkageName(const clang::Type *typep) { 300 assert(typep != nullptr); 301 clang::QualType qt = typep->getCanonicalTypeInternal(); 302 return QualTypeToString(qt); 303 } 304 305 // This method returns a TypeAndCreationStatus object. This object contains a 306 // type and information to tell the clients of this method whether the caller 307 // should continue creating the type. 308 TypeAndCreationStatus ABIWrapper::SetTypeKind( 309 const clang::QualType canonical_type, const std::string &source_file) { 310 if (canonical_type.hasLocalQualifiers()) { 311 auto qual_type_ir = 312 std::make_unique<abi_util::QualifiedTypeIR>(); 313 qual_type_ir->SetConstness(canonical_type.isConstQualified()); 314 qual_type_ir->SetRestrictedness(canonical_type.isRestrictQualified()); 315 qual_type_ir->SetVolatility(canonical_type.isVolatileQualified()); 316 qual_type_ir->SetSourceFile(source_file); 317 return TypeAndCreationStatus(std::move(qual_type_ir)); 318 } 319 const clang::Type *type_ptr = canonical_type.getTypePtr(); 320 if (type_ptr->isPointerType()) { 321 auto pointer_type_ir = std::make_unique<abi_util::PointerTypeIR>(); 322 pointer_type_ir->SetSourceFile(source_file); 323 return TypeAndCreationStatus(std::move(pointer_type_ir)); 324 } 325 if (type_ptr->isLValueReferenceType()) { 326 auto lvalue_reference_type_ir = 327 std::make_unique<abi_util::LvalueReferenceTypeIR>(); 328 lvalue_reference_type_ir->SetSourceFile(source_file); 329 return TypeAndCreationStatus(std::move(lvalue_reference_type_ir)); 330 } 331 if (type_ptr->isRValueReferenceType()) { 332 auto rvalue_reference_type_ir = 333 std::make_unique<abi_util::RvalueReferenceTypeIR>(); 334 rvalue_reference_type_ir->SetSourceFile(source_file); 335 return TypeAndCreationStatus(std::move(rvalue_reference_type_ir)); 336 } 337 if (type_ptr->isArrayType()) { 338 auto array_type_ir = std::make_unique<abi_util::ArrayTypeIR>(); 339 array_type_ir->SetSourceFile(source_file); 340 return TypeAndCreationStatus(std::move(array_type_ir)); 341 } 342 if (type_ptr->isEnumeralType()) { 343 return TypeAndCreationStatus(std::make_unique<abi_util::EnumTypeIR>()); 344 } 345 if (type_ptr->isBuiltinType()) { 346 auto builtin_type_ir = std::make_unique<abi_util::BuiltinTypeIR>(); 347 builtin_type_ir->SetSignedness(type_ptr->isUnsignedIntegerType()); 348 builtin_type_ir->SetIntegralType(type_ptr->isIntegralType(*ast_contextp_)); 349 return TypeAndCreationStatus(std::move(builtin_type_ir)); 350 } 351 if (auto &&func_type_ptr = 352 llvm::dyn_cast<const clang::FunctionType>(type_ptr)) { 353 FunctionTypeWrapper function_type_wrapper(mangle_contextp_, ast_contextp_, 354 cip_, func_type_ptr, ir_dumper_, 355 ast_caches_, source_file); 356 if (!function_type_wrapper.GetFunctionType()) { 357 llvm::errs() << "FunctionType could not be created\n"; 358 ::exit(1); 359 } 360 } 361 if (type_ptr->isRecordType()) { 362 // If this record is anonymous, create it. 363 const clang::RecordDecl *anon_record = GetAnonymousRecord(canonical_type); 364 if (anon_record && !CreateAnonymousRecord(anon_record)) { 365 llvm::errs() << "Anonymous record could not be created\n"; 366 ::exit(1); 367 } 368 } 369 return TypeAndCreationStatus(nullptr, false); 370 } 371 372 std::string ABIWrapper::GetMangledNameDecl( 373 const clang::NamedDecl *decl, clang::MangleContext *mangle_contextp) { 374 if (!mangle_contextp->shouldMangleDeclName(decl)) { 375 clang::IdentifierInfo *identifier = decl->getIdentifier(); 376 return identifier ? identifier->getName() : ""; 377 } 378 std::string mangled_name; 379 llvm::raw_string_ostream ostream(mangled_name); 380 mangle_contextp->mangleName(decl, ostream); 381 ostream.flush(); 382 return mangled_name; 383 } 384 385 std::string ABIWrapper::GetTagDeclQualifiedName( 386 const clang::TagDecl *decl) { 387 if (decl->getTypedefNameForAnonDecl()) { 388 return decl->getTypedefNameForAnonDecl()->getQualifiedNameAsString(); 389 } 390 return decl->getQualifiedNameAsString(); 391 } 392 393 bool ABIWrapper::SetupTemplateArguments( 394 const clang::TemplateArgumentList *tl, 395 abi_util::TemplatedArtifactIR *ta, 396 const std::string &source_file) { 397 abi_util::TemplateInfoIR template_info; 398 for (int i = 0; i < tl->size(); i++) { 399 const clang::TemplateArgument &arg = (*tl)[i]; 400 //TODO: More comprehensive checking needed. 401 if (arg.getKind() != clang::TemplateArgument::Type) { 402 continue; 403 } 404 clang::QualType type = arg.getAsType(); 405 template_info.AddTemplateElement( 406 abi_util::TemplateElementIR( 407 ast_caches_->GetTypeId(GetKeyForTypeId(type)))); 408 if (!CreateBasicNamedAndTypedDecl(type, source_file)) { 409 llvm::errs() << "Setting up template arguments failed\n"; 410 return false; 411 } 412 } 413 ta->SetTemplateInfo(std::move(template_info)); 414 return true; 415 } 416 417 std::string ABIWrapper::QualTypeToString( 418 const clang::QualType &sweet_qt) { 419 const clang::QualType salty_qt = sweet_qt.getCanonicalType(); 420 // clang::TypeName::getFullyQualifiedName removes the part of the type related 421 // to it being a template parameter. Don't use it for dependent types. 422 if (salty_qt.getTypePtr()->isDependentType()) { 423 return salty_qt.getAsString(); 424 } 425 return clang::TypeName::getFullyQualifiedName(salty_qt, *ast_contextp_); 426 } 427 428 FunctionTypeWrapper::FunctionTypeWrapper( 429 clang::MangleContext *mangle_contextp, clang::ASTContext *ast_contextp, 430 const clang::CompilerInstance *compiler_instance_p, 431 const clang::FunctionType *function_type, abi_util::IRDumper *ir_dumper, 432 ast_util::ASTCaches *ast_caches, const std::string &source_file) 433 : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p, ir_dumper, 434 ast_caches), function_type_(function_type), 435 source_file_(source_file) { } 436 437 bool FunctionTypeWrapper::SetupFunctionType( 438 abi_util::FunctionTypeIR *function_type_ir) { 439 // Add ReturnType 440 function_type_ir->SetReturnType( 441 ast_caches_->GetTypeId(GetKeyForTypeId(function_type_->getReturnType()))); 442 function_type_ir->SetSourceFile(source_file_); 443 const clang::FunctionProtoType *function_pt = 444 llvm::dyn_cast<clang::FunctionProtoType>(function_type_); 445 if (!function_pt) { 446 return true; 447 } 448 for (unsigned i = 0, e = function_pt->getNumParams(); i != e; ++i) { 449 clang::QualType param_type = function_pt->getParamType(i); 450 if (!SetupFunctionParameter(function_type_ir, param_type, false, 451 source_file_)) { 452 return false; 453 } 454 } 455 return true; 456 } 457 458 bool FunctionTypeWrapper::GetFunctionType() { 459 auto abi_decl = std::make_unique<abi_util::FunctionTypeIR>(); 460 clang::QualType canonical_type = function_type_->getCanonicalTypeInternal(); 461 if (!CreateBasicNamedAndTypedDecl(canonical_type, abi_decl.get(), "")) { 462 llvm::errs() << "Couldn't create (function type) extended type\n"; 463 return false; 464 } 465 return SetupFunctionType(abi_decl.get()) && 466 ir_dumper_->AddLinkableMessageIR(abi_decl.get()); 467 } 468 469 FunctionDeclWrapper::FunctionDeclWrapper( 470 clang::MangleContext *mangle_contextp, 471 clang::ASTContext *ast_contextp, 472 const clang::CompilerInstance *compiler_instance_p, 473 const clang::FunctionDecl *decl, 474 abi_util::IRDumper *ir_dumper, 475 ast_util::ASTCaches *ast_caches) 476 : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p, ir_dumper, 477 ast_caches), 478 function_decl_(decl) { } 479 480 bool FunctionDeclWrapper::SetupThisParameter(abi_util::FunctionIR *functionp, 481 const std::string &source_file) { 482 const clang::CXXMethodDecl *cxx_method_decl = 483 llvm::dyn_cast<clang::CXXMethodDecl>(function_decl_); 484 // No this pointer for static methods. 485 if (!cxx_method_decl || cxx_method_decl->isStatic()) { 486 return true; 487 } 488 clang::QualType this_type = cxx_method_decl->getThisType(*ast_contextp_); 489 return SetupFunctionParameter(functionp, this_type, false, source_file, true); 490 } 491 492 bool ABIWrapper::SetupFunctionParameter( 493 abi_util::CFunctionLikeIR *functionp, const clang::QualType qual_type, 494 bool has_default_arg, const std::string &source_file, bool is_this_ptr) { 495 if (!CreateBasicNamedAndTypedDecl(qual_type, source_file)) { 496 llvm::errs() << "Setting up function parameter failed\n"; 497 return false; 498 } 499 functionp->AddParameter(abi_util::ParamIR( 500 ast_caches_->GetTypeId(GetKeyForTypeId(qual_type)), has_default_arg, 501 is_this_ptr)); 502 return true; 503 } 504 505 bool FunctionDeclWrapper::SetupFunctionParameters( 506 abi_util::FunctionIR *functionp, 507 const std::string &source_file) { 508 clang::FunctionDecl::param_const_iterator param_it = 509 function_decl_->param_begin(); 510 // If this is a CXXMethodDecl, we need to add the "this" pointer. 511 if (!SetupThisParameter(functionp, source_file)) { 512 llvm::errs() << "Setting up 'this' parameter failed\n"; 513 return false; 514 } 515 516 while (param_it != function_decl_->param_end()) { 517 // The linker set key is blank since that shows up in the mangled name. 518 bool has_default_arg = (*param_it)->hasDefaultArg(); 519 clang::QualType param_qt = (*param_it)->getType(); 520 if (!SetupFunctionParameter(functionp, param_qt, has_default_arg, 521 source_file)) { 522 return false; 523 } 524 param_it++; 525 } 526 return true; 527 } 528 529 bool FunctionDeclWrapper::SetupFunction(abi_util::FunctionIR *functionp, 530 const std::string &source_file) { 531 // Go through all the parameters in the method and add them to the fields. 532 // Also get the fully qualfied name. 533 // TODO: Change this to get the complete function signature 534 functionp->SetName(function_decl_->getQualifiedNameAsString()); 535 functionp->SetSourceFile(source_file); 536 clang::QualType return_type = function_decl_->getReturnType(); 537 538 functionp->SetReturnType( 539 ast_caches_->GetTypeId(GetKeyForTypeId(return_type))); 540 functionp->SetAccess(AccessClangToIR(function_decl_->getAccess())); 541 return CreateBasicNamedAndTypedDecl(return_type, source_file) && 542 SetupFunctionParameters(functionp, source_file) && 543 SetupTemplateInfo(functionp, source_file); 544 } 545 546 bool FunctionDeclWrapper::SetupTemplateInfo( 547 abi_util::FunctionIR *functionp, 548 const std::string &source_file) { 549 switch (function_decl_->getTemplatedKind()) { 550 case clang::FunctionDecl::TK_FunctionTemplateSpecialization: { 551 const clang::TemplateArgumentList *arg_list = 552 function_decl_->getTemplateSpecializationArgs(); 553 if (arg_list && !SetupTemplateArguments(arg_list, functionp, 554 source_file)) { 555 return false; 556 } 557 break; 558 } 559 default: { 560 break; 561 } 562 } 563 return true; 564 } 565 566 std::unique_ptr<abi_util::FunctionIR> FunctionDeclWrapper::GetFunctionDecl() { 567 auto abi_decl = std::make_unique<abi_util::FunctionIR>(); 568 std::string source_file = GetCachedDeclSourceFile(function_decl_, cip_); 569 if (!SetupFunction(abi_decl.get(), source_file)) { 570 return nullptr; 571 } 572 return abi_decl; 573 } 574 575 RecordDeclWrapper::RecordDeclWrapper( 576 clang::MangleContext *mangle_contextp, 577 clang::ASTContext *ast_contextp, 578 const clang::CompilerInstance *compiler_instance_p, 579 const clang::RecordDecl *decl, abi_util::IRDumper *ir_dumper, 580 ast_util::ASTCaches *ast_caches) 581 : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p, ir_dumper, 582 ast_caches), 583 record_decl_(decl) { } 584 585 bool RecordDeclWrapper::SetupRecordFields(abi_util::RecordTypeIR *recordp, 586 const std::string &source_file) { 587 clang::RecordDecl::field_iterator field = record_decl_->field_begin(); 588 uint32_t field_index = 0; 589 const clang::ASTRecordLayout &record_layout = 590 ast_contextp_->getASTRecordLayout(record_decl_); 591 while (field != record_decl_->field_end()) { 592 clang::QualType field_type = field->getType(); 593 std::string key_for_type_id = GetKeyForTypeId(field_type); 594 if (const clang::EnumDecl *enum_decl = 595 GetAnonymousEnum(field_type)) { 596 // Handle anonymous enums. 597 key_for_type_id = GetKeyForTypeId(enum_decl->getIntegerType()); 598 } 599 if (!CreateBasicNamedAndTypedDecl(field_type, source_file)) { 600 llvm::errs() << "Creation of Type failed\n"; 601 return false; 602 } 603 std::string field_name = field->getName(); 604 uint64_t field_offset = record_layout.getFieldOffset(field_index); 605 recordp->AddRecordField(abi_util::RecordFieldIR( 606 field_name, ast_caches_->GetTypeId(key_for_type_id), field_offset, 607 AccessClangToIR(field->getAccess()))); 608 field++; 609 field_index++; 610 } 611 return true; 612 } 613 614 bool RecordDeclWrapper::SetupCXXBases( 615 abi_util::RecordTypeIR *cxxp, 616 const clang::CXXRecordDecl *cxx_record_decl) { 617 if (!cxx_record_decl || !cxxp) { 618 return false; 619 } 620 clang::CXXRecordDecl::base_class_const_iterator base_class = 621 cxx_record_decl->bases_begin(); 622 while (base_class != cxx_record_decl->bases_end()) { 623 std::string name = QualTypeToString(base_class->getType()); 624 bool is_virtual = base_class->isVirtual(); 625 abi_util::AccessSpecifierIR access = 626 AccessClangToIR(base_class->getAccessSpecifier()); 627 cxxp->AddCXXBaseSpecifier( 628 abi_util::CXXBaseSpecifierIR( 629 ast_caches_->GetTypeId(GetKeyForTypeId(base_class->getType())), 630 is_virtual, access)); 631 base_class++; 632 } 633 return true; 634 } 635 636 bool RecordDeclWrapper::SetupRecordVTable( 637 abi_util::RecordTypeIR *record_declp, 638 const clang::CXXRecordDecl *cxx_record_decl) { 639 if (!cxx_record_decl || !record_declp) { 640 return false; 641 } 642 clang::VTableContextBase *base_vtable_contextp = 643 ast_contextp_->getVTableContext(); 644 const clang::Type *typep = cxx_record_decl->getTypeForDecl(); 645 if (!base_vtable_contextp || !typep) { 646 return false; 647 } 648 // Skip Microsoft ABI. 649 clang::ItaniumVTableContext *itanium_vtable_contextp = 650 llvm::dyn_cast<clang::ItaniumVTableContext>(base_vtable_contextp); 651 if (!itanium_vtable_contextp || !cxx_record_decl->isPolymorphic() || 652 typep->isDependentType() || typep->isIncompleteType()) { 653 return true; 654 } 655 const clang::VTableLayout &vtable_layout = 656 itanium_vtable_contextp->getVTableLayout(cxx_record_decl); 657 abi_util::VTableLayoutIR vtable_ir_layout; 658 for (const auto &vtable_component : vtable_layout.vtable_components()) { 659 abi_util::VTableComponentIR added_component= 660 SetupRecordVTableComponent(vtable_component); 661 vtable_ir_layout.AddVTableComponent(std::move(added_component)); 662 } 663 record_declp->SetVTableLayout(std::move(vtable_ir_layout)); 664 return true; 665 } 666 667 abi_util::VTableComponentIR RecordDeclWrapper::SetupRecordVTableComponent( 668 const clang::VTableComponent &vtable_component) { 669 abi_util::VTableComponentIR::Kind kind = 670 abi_util::VTableComponentIR::Kind::RTTI; 671 std::string mangled_component_name = ""; 672 llvm::raw_string_ostream ostream(mangled_component_name); 673 int64_t value = 0; 674 clang::VTableComponent::Kind clang_component_kind = 675 vtable_component.getKind(); 676 switch (clang_component_kind) { 677 case clang::VTableComponent::CK_VCallOffset: 678 kind = abi_util::VTableComponentIR::Kind::VCallOffset; 679 value = vtable_component.getVCallOffset().getQuantity(); 680 break; 681 case clang::VTableComponent::CK_VBaseOffset: 682 kind = abi_util::VTableComponentIR::Kind::VBaseOffset; 683 value = vtable_component.getVBaseOffset().getQuantity(); 684 break; 685 case clang::VTableComponent::CK_OffsetToTop: 686 kind = abi_util::VTableComponentIR::Kind::OffsetToTop; 687 value = vtable_component.getOffsetToTop().getQuantity(); 688 break; 689 case clang::VTableComponent::CK_RTTI: 690 { 691 kind = abi_util::VTableComponentIR::Kind::RTTI; 692 const clang::CXXRecordDecl *rtti_decl = 693 vtable_component.getRTTIDecl(); 694 assert(rtti_decl != nullptr); 695 mangled_component_name = GetMangledRTTI(rtti_decl); 696 } 697 break; 698 case clang::VTableComponent::CK_FunctionPointer: 699 case clang::VTableComponent::CK_CompleteDtorPointer: 700 case clang::VTableComponent::CK_DeletingDtorPointer: 701 case clang::VTableComponent::CK_UnusedFunctionPointer: 702 { 703 const clang::CXXMethodDecl *method_decl = 704 vtable_component.getFunctionDecl(); 705 assert(method_decl != nullptr); 706 switch (clang_component_kind) { 707 case clang::VTableComponent::CK_FunctionPointer: 708 kind = abi_util::VTableComponentIR::Kind::FunctionPointer; 709 mangled_component_name = GetMangledNameDecl(method_decl, 710 mangle_contextp_); 711 break; 712 case clang::VTableComponent::CK_CompleteDtorPointer: 713 kind = abi_util::VTableComponentIR::Kind::CompleteDtorPointer; 714 mangle_contextp_->mangleCXXDtor( 715 vtable_component.getDestructorDecl(), 716 clang::CXXDtorType::Dtor_Complete, ostream); 717 ostream.flush(); 718 break; 719 case clang::VTableComponent::CK_DeletingDtorPointer: 720 kind = abi_util::VTableComponentIR::Kind::DeletingDtorPointer; 721 mangle_contextp_->mangleCXXDtor( 722 vtable_component.getDestructorDecl(), 723 clang::CXXDtorType::Dtor_Deleting, ostream); 724 ostream.flush(); 725 break; 726 case clang::VTableComponent::CK_UnusedFunctionPointer: 727 kind = abi_util::VTableComponentIR::Kind::UnusedFunctionPointer; 728 break; 729 default: 730 break; 731 } 732 } 733 break; 734 default: 735 break; 736 } 737 return abi_util::VTableComponentIR(mangled_component_name, kind, value); 738 } 739 740 bool RecordDeclWrapper::SetupTemplateInfo( 741 abi_util::RecordTypeIR *record_declp, 742 const clang::CXXRecordDecl *cxx_record_decl, 743 const std::string &source_file) { 744 assert(cxx_record_decl != nullptr); 745 const clang::ClassTemplateSpecializationDecl *specialization_decl = 746 clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(cxx_record_decl); 747 if (specialization_decl) { 748 const clang::TemplateArgumentList *arg_list = 749 &specialization_decl->getTemplateArgs(); 750 if (arg_list && 751 !SetupTemplateArguments(arg_list, record_declp, source_file)) { 752 return false; 753 } 754 } 755 return true; 756 } 757 758 bool RecordDeclWrapper::SetupRecordInfo(abi_util::RecordTypeIR *record_declp, 759 const std::string &source_file) { 760 if (!record_declp) { 761 return false; 762 } 763 if (record_decl_->isStruct()) { 764 record_declp->SetRecordKind( 765 abi_util::RecordTypeIR::RecordKind::struct_kind); 766 } else if (record_decl_->isClass()) { 767 record_declp->SetRecordKind( 768 abi_util::RecordTypeIR::RecordKind::class_kind); 769 } else { 770 record_declp->SetRecordKind( 771 abi_util::RecordTypeIR::RecordKind::union_kind); 772 } 773 774 const clang::Type *basic_type = nullptr; 775 if (!(basic_type = record_decl_->getTypeForDecl())) { 776 return false; 777 } 778 clang::QualType qual_type = basic_type->getCanonicalTypeInternal(); 779 if (!CreateExtendedType(qual_type, record_declp)) { 780 return false; 781 } 782 record_declp->SetSourceFile(source_file); 783 if (!record_decl_->hasNameForLinkage() || 784 record_decl_->isAnonymousStructOrUnion()) { 785 record_declp->SetAnonymity(true); 786 } 787 record_declp->SetUniqueId(GetTypeUniqueId(record_decl_)); 788 record_declp->SetAccess(AccessClangToIR(record_decl_->getAccess())); 789 return SetupRecordFields(record_declp, source_file) && 790 SetupCXXRecordInfo(record_declp, source_file); 791 } 792 793 bool RecordDeclWrapper::SetupCXXRecordInfo( 794 abi_util::RecordTypeIR *record_declp, const std::string &source_file) { 795 const clang::CXXRecordDecl *cxx_record_decl = 796 clang::dyn_cast<clang::CXXRecordDecl>(record_decl_); 797 if (!cxx_record_decl) { 798 return true; 799 } 800 return SetupTemplateInfo(record_declp, cxx_record_decl, source_file) && 801 SetupCXXBases(record_declp, cxx_record_decl) && 802 SetupRecordVTable(record_declp, cxx_record_decl); 803 } 804 805 // TODO: Can we use clang's ODR hash to do faster ODR checking ? 806 bool RecordDeclWrapper::GetRecordDecl() { 807 auto abi_decl = std::make_unique<abi_util::RecordTypeIR>(); 808 std::string source_file = GetCachedDeclSourceFile(record_decl_, cip_); 809 if (!SetupRecordInfo(abi_decl.get(), source_file)) { 810 llvm::errs() << "Setting up CXX Bases / Template Info failed\n"; 811 return false; 812 } 813 if ((abi_decl->GetReferencedType() == "") || 814 (abi_decl->GetSelfType() == "")) { 815 // The only way to have an empty referenced / self type is when the type was 816 // cached, don't add the record. 817 return true; 818 } 819 return ir_dumper_->AddLinkableMessageIR(abi_decl.get()); 820 } 821 822 EnumDeclWrapper::EnumDeclWrapper( 823 clang::MangleContext *mangle_contextp, 824 clang::ASTContext *ast_contextp, 825 const clang::CompilerInstance *compiler_instance_p, 826 const clang::EnumDecl *decl, abi_util::IRDumper *ir_dumper, 827 ast_util::ASTCaches *ast_caches) 828 : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p, ir_dumper, 829 ast_caches), 830 enum_decl_(decl) { } 831 832 bool EnumDeclWrapper::SetupEnumFields(abi_util::EnumTypeIR *enump) { 833 if (!enump) { 834 return false; 835 } 836 clang::EnumDecl::enumerator_iterator enum_it = enum_decl_->enumerator_begin(); 837 while (enum_it != enum_decl_->enumerator_end()) { 838 std::string name = enum_it->getQualifiedNameAsString(); 839 uint64_t field_value = enum_it->getInitVal().getExtValue(); 840 enump->AddEnumField(abi_util::EnumFieldIR(name, field_value)); 841 enum_it++; 842 } 843 return true; 844 } 845 846 bool EnumDeclWrapper::SetupEnum(abi_util::EnumTypeIR *enum_type, 847 const std::string &source_file) { 848 std::string enum_name = GetTagDeclQualifiedName(enum_decl_); 849 clang::QualType enum_qual_type = 850 enum_decl_->getTypeForDecl()->getCanonicalTypeInternal(); 851 if (!CreateExtendedType(enum_qual_type, enum_type)) { 852 return false; 853 } 854 enum_type->SetSourceFile(source_file); 855 enum_type->SetUnderlyingType( 856 ast_caches_->GetTypeId(GetKeyForTypeId(enum_decl_->getIntegerType()))); 857 enum_type->SetAccess(AccessClangToIR(enum_decl_->getAccess())); 858 enum_type->SetUniqueId(GetTypeUniqueId(enum_decl_)); 859 return SetupEnumFields(enum_type) && 860 CreateBasicNamedAndTypedDecl(enum_decl_->getIntegerType(), ""); 861 } 862 863 bool EnumDeclWrapper::GetEnumDecl() { 864 auto abi_decl = std::make_unique<abi_util::EnumTypeIR>(); 865 std::string source_file = GetCachedDeclSourceFile(enum_decl_, cip_); 866 867 if (!SetupEnum(abi_decl.get(), source_file)) { 868 llvm::errs() << "Setting up Enum failed\n"; 869 return false; 870 } 871 return ir_dumper_->AddLinkableMessageIR(abi_decl.get()); 872 } 873 874 GlobalVarDeclWrapper::GlobalVarDeclWrapper( 875 clang::MangleContext *mangle_contextp, 876 clang::ASTContext *ast_contextp, 877 const clang::CompilerInstance *compiler_instance_p, 878 const clang::VarDecl *decl, abi_util::IRDumper *ir_dumper, 879 ast_util::ASTCaches *ast_caches) 880 : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p, ir_dumper, 881 ast_caches), 882 global_var_decl_(decl) { } 883 884 bool GlobalVarDeclWrapper::SetupGlobalVar( 885 abi_util::GlobalVarIR *global_varp, 886 const std::string &source_file) { 887 // Temporary fix : clang segfaults on trying to mangle global variable which 888 // is a dependent sized array type. 889 std::string mangled_name = 890 GetMangledNameDecl(global_var_decl_, mangle_contextp_); 891 if (!CreateBasicNamedAndTypedDecl(global_var_decl_->getType(), source_file)) { 892 return false; 893 } 894 global_varp->SetSourceFile(source_file); 895 global_varp->SetName(global_var_decl_->getQualifiedNameAsString()); 896 global_varp->SetLinkerSetKey(mangled_name); 897 global_varp->SetAccess(AccessClangToIR(global_var_decl_->getAccess())); 898 global_varp->SetReferencedType( 899 ast_caches_->GetTypeId(GetKeyForTypeId(global_var_decl_->getType()))); 900 return true; 901 } 902 903 bool GlobalVarDeclWrapper::GetGlobalVarDecl() { 904 auto abi_decl = std::make_unique<abi_util::GlobalVarIR>(); 905 std::string source_file = GetCachedDeclSourceFile(global_var_decl_, cip_); 906 return SetupGlobalVar(abi_decl.get(), source_file) && 907 ir_dumper_->AddLinkableMessageIR(abi_decl.get()); 908 } 909