15ffd83dbSDimitry Andric //===-- AppleObjCDeclVendor.cpp -------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "AppleObjCDeclVendor.h" 100b57cec5SDimitry Andric 115ffd83dbSDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h" 125ffd83dbSDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangUtil.h" 130b57cec5SDimitry Andric #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" 140b57cec5SDimitry Andric #include "lldb/Core/Module.h" 150b57cec5SDimitry Andric #include "lldb/Target/Process.h" 160b57cec5SDimitry Andric #include "lldb/Target/Target.h" 1781ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 180b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 210b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 22480093f4SDimitry Andric #include "clang/AST/ExternalASTSource.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric using namespace lldb_private; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric class lldb_private::AppleObjCExternalASTSource 27480093f4SDimitry Andric : public clang::ExternalASTSource { 280b57cec5SDimitry Andric public: 290b57cec5SDimitry Andric AppleObjCExternalASTSource(AppleObjCDeclVendor &decl_vendor) 300b57cec5SDimitry Andric : m_decl_vendor(decl_vendor) {} 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric bool FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx, 330b57cec5SDimitry Andric clang::DeclarationName name) override { 340b57cec5SDimitry Andric 3581ad6265SDimitry Andric Log *log(GetLog( 3681ad6265SDimitry Andric LLDBLog::Expressions)); // FIXME - a more appropriate log channel? 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric if (log) { 399dba64beSDimitry Andric LLDB_LOGF(log, 405ffd83dbSDimitry Andric "AppleObjCExternalASTSource::FindExternalVisibleDeclsByName" 415ffd83dbSDimitry Andric " on (ASTContext*)%p Looking for %s in (%sDecl*)%p", 420b57cec5SDimitry Andric static_cast<void *>(&decl_ctx->getParentASTContext()), 430b57cec5SDimitry Andric name.getAsString().c_str(), decl_ctx->getDeclKindName(), 440b57cec5SDimitry Andric static_cast<const void *>(decl_ctx)); 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric do { 480b57cec5SDimitry Andric const clang::ObjCInterfaceDecl *interface_decl = 490b57cec5SDimitry Andric llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx); 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric if (!interface_decl) 520b57cec5SDimitry Andric break; 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric clang::ObjCInterfaceDecl *non_const_interface_decl = 550b57cec5SDimitry Andric const_cast<clang::ObjCInterfaceDecl *>(interface_decl); 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric if (!m_decl_vendor.FinishDecl(non_const_interface_decl)) 580b57cec5SDimitry Andric break; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric clang::DeclContext::lookup_result result = 610b57cec5SDimitry Andric non_const_interface_decl->lookup(name); 620b57cec5SDimitry Andric 63fe6060f1SDimitry Andric return (!result.empty()); 640b57cec5SDimitry Andric } while (false); 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric SetNoExternalVisibleDeclsForName(decl_ctx, name); 670b57cec5SDimitry Andric return false; 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric void CompleteType(clang::TagDecl *tag_decl) override { 710b57cec5SDimitry Andric 7281ad6265SDimitry Andric Log *log(GetLog( 7381ad6265SDimitry Andric LLDBLog::Expressions)); // FIXME - a more appropriate log channel? 740b57cec5SDimitry Andric 759dba64beSDimitry Andric LLDB_LOGF(log, 765ffd83dbSDimitry Andric "AppleObjCExternalASTSource::CompleteType on " 770b57cec5SDimitry Andric "(ASTContext*)%p Completing (TagDecl*)%p named %s", 785ffd83dbSDimitry Andric static_cast<void *>(&tag_decl->getASTContext()), 79480093f4SDimitry Andric static_cast<void *>(tag_decl), tag_decl->getName().str().c_str()); 800b57cec5SDimitry Andric 815ffd83dbSDimitry Andric LLDB_LOG(log, " AOEAS::CT Before:\n{1}", ClangUtil::DumpDecl(tag_decl)); 820b57cec5SDimitry Andric 835ffd83dbSDimitry Andric LLDB_LOG(log, " AOEAS::CT After:{1}", ClangUtil::DumpDecl(tag_decl)); 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric void CompleteType(clang::ObjCInterfaceDecl *interface_decl) override { 870b57cec5SDimitry Andric 8881ad6265SDimitry Andric Log *log(GetLog( 8981ad6265SDimitry Andric LLDBLog::Expressions)); // FIXME - a more appropriate log channel? 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric if (log) { 929dba64beSDimitry Andric LLDB_LOGF(log, 935ffd83dbSDimitry Andric "AppleObjCExternalASTSource::CompleteType on " 940b57cec5SDimitry Andric "(ASTContext*)%p Completing (ObjCInterfaceDecl*)%p named %s", 950b57cec5SDimitry Andric static_cast<void *>(&interface_decl->getASTContext()), 960b57cec5SDimitry Andric static_cast<void *>(interface_decl), 970b57cec5SDimitry Andric interface_decl->getName().str().c_str()); 980b57cec5SDimitry Andric 995ffd83dbSDimitry Andric LLDB_LOGF(log, " AOEAS::CT Before:"); 100480093f4SDimitry Andric LLDB_LOG(log, " [CT] {0}", ClangUtil::DumpDecl(interface_decl)); 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric m_decl_vendor.FinishDecl(interface_decl); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric if (log) { 1069dba64beSDimitry Andric LLDB_LOGF(log, " [CT] After:"); 107480093f4SDimitry Andric LLDB_LOG(log, " [CT] {0}", ClangUtil::DumpDecl(interface_decl)); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric bool layoutRecordType( 1120b57cec5SDimitry Andric const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, 1130b57cec5SDimitry Andric llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, 1140b57cec5SDimitry Andric llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> 1150b57cec5SDimitry Andric &BaseOffsets, 1160b57cec5SDimitry Andric llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> 1170b57cec5SDimitry Andric &VirtualBaseOffsets) override { 1180b57cec5SDimitry Andric return false; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric void StartTranslationUnit(clang::ASTConsumer *Consumer) override { 1220b57cec5SDimitry Andric clang::TranslationUnitDecl *translation_unit_decl = 123bdd1243dSDimitry Andric m_decl_vendor.m_ast_ctx->getASTContext().getTranslationUnitDecl(); 1240b57cec5SDimitry Andric translation_unit_decl->setHasExternalVisibleStorage(); 1250b57cec5SDimitry Andric translation_unit_decl->setHasExternalLexicalStorage(); 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric private: 1290b57cec5SDimitry Andric AppleObjCDeclVendor &m_decl_vendor; 1300b57cec5SDimitry Andric }; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime) 1339dba64beSDimitry Andric : ClangDeclVendor(eAppleObjCDeclVendor), m_runtime(runtime), 1340b57cec5SDimitry Andric m_type_realizer_sp(m_runtime.GetEncodingToType()) { 135bdd1243dSDimitry Andric m_ast_ctx = std::make_shared<TypeSystemClang>( 136bdd1243dSDimitry Andric "AppleObjCDeclVendor AST", 137bdd1243dSDimitry Andric runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple()); 1380b57cec5SDimitry Andric m_external_source = new AppleObjCExternalASTSource(*this); 1390b57cec5SDimitry Andric llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr( 1400b57cec5SDimitry Andric m_external_source); 141bdd1243dSDimitry Andric m_ast_ctx->getASTContext().setExternalSource(external_source_owning_ptr); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric clang::ObjCInterfaceDecl * 1450b57cec5SDimitry Andric AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) { 1460b57cec5SDimitry Andric ISAToInterfaceMap::const_iterator iter = m_isa_to_interface.find(isa); 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric if (iter != m_isa_to_interface.end()) 1490b57cec5SDimitry Andric return iter->second; 1500b57cec5SDimitry Andric 151bdd1243dSDimitry Andric clang::ASTContext &ast_ctx = m_ast_ctx->getASTContext(); 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP descriptor = 1540b57cec5SDimitry Andric m_runtime.GetClassDescriptorFromISA(isa); 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric if (!descriptor) 1570b57cec5SDimitry Andric return nullptr; 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric ConstString name(descriptor->GetClassName()); 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric clang::IdentifierInfo &identifier_info = 162480093f4SDimitry Andric ast_ctx.Idents.get(name.GetStringRef()); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric clang::ObjCInterfaceDecl *new_iface_decl = clang::ObjCInterfaceDecl::Create( 165480093f4SDimitry Andric ast_ctx, ast_ctx.getTranslationUnitDecl(), clang::SourceLocation(), 1660b57cec5SDimitry Andric &identifier_info, nullptr, nullptr); 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric ClangASTMetadata meta_data; 1690b57cec5SDimitry Andric meta_data.SetISAPtr(isa); 170bdd1243dSDimitry Andric m_ast_ctx->SetMetadata(new_iface_decl, meta_data); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric new_iface_decl->setHasExternalVisibleStorage(); 1730b57cec5SDimitry Andric new_iface_decl->setHasExternalLexicalStorage(); 1740b57cec5SDimitry Andric 175480093f4SDimitry Andric ast_ctx.getTranslationUnitDecl()->addDecl(new_iface_decl); 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric m_isa_to_interface[isa] = new_iface_decl; 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric return new_iface_decl; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric class ObjCRuntimeMethodType { 1830b57cec5SDimitry Andric public: 18481ad6265SDimitry Andric ObjCRuntimeMethodType(const char *types) { 1850b57cec5SDimitry Andric const char *cursor = types; 1860b57cec5SDimitry Andric enum ParserState { Start = 0, InType, InPos } state = Start; 1870b57cec5SDimitry Andric const char *type = nullptr; 1880b57cec5SDimitry Andric int brace_depth = 0; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric uint32_t stepsLeft = 256; 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric while (true) { 1930b57cec5SDimitry Andric if (--stepsLeft == 0) { 1940b57cec5SDimitry Andric m_is_valid = false; 1950b57cec5SDimitry Andric return; 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric switch (state) { 1990b57cec5SDimitry Andric case Start: { 2000b57cec5SDimitry Andric switch (*cursor) { 2010b57cec5SDimitry Andric default: 2020b57cec5SDimitry Andric state = InType; 2030b57cec5SDimitry Andric type = cursor; 2040b57cec5SDimitry Andric break; 2050b57cec5SDimitry Andric case '\0': 2060b57cec5SDimitry Andric m_is_valid = true; 2070b57cec5SDimitry Andric return; 2080b57cec5SDimitry Andric case '0': 2090b57cec5SDimitry Andric case '1': 2100b57cec5SDimitry Andric case '2': 2110b57cec5SDimitry Andric case '3': 2120b57cec5SDimitry Andric case '4': 2130b57cec5SDimitry Andric case '5': 2140b57cec5SDimitry Andric case '6': 2150b57cec5SDimitry Andric case '7': 2160b57cec5SDimitry Andric case '8': 2170b57cec5SDimitry Andric case '9': 2180b57cec5SDimitry Andric m_is_valid = false; 2190b57cec5SDimitry Andric return; 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric } break; 2220b57cec5SDimitry Andric case InType: { 2230b57cec5SDimitry Andric switch (*cursor) { 2240b57cec5SDimitry Andric default: 2250b57cec5SDimitry Andric ++cursor; 2260b57cec5SDimitry Andric break; 2270b57cec5SDimitry Andric case '0': 2280b57cec5SDimitry Andric case '1': 2290b57cec5SDimitry Andric case '2': 2300b57cec5SDimitry Andric case '3': 2310b57cec5SDimitry Andric case '4': 2320b57cec5SDimitry Andric case '5': 2330b57cec5SDimitry Andric case '6': 2340b57cec5SDimitry Andric case '7': 2350b57cec5SDimitry Andric case '8': 2360b57cec5SDimitry Andric case '9': 2370b57cec5SDimitry Andric if (!brace_depth) { 2380b57cec5SDimitry Andric state = InPos; 2390b57cec5SDimitry Andric if (type) { 2400b57cec5SDimitry Andric m_type_vector.push_back(std::string(type, (cursor - type))); 2410b57cec5SDimitry Andric } else { 2420b57cec5SDimitry Andric m_is_valid = false; 2430b57cec5SDimitry Andric return; 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric type = nullptr; 2460b57cec5SDimitry Andric } else { 2470b57cec5SDimitry Andric ++cursor; 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric break; 2500b57cec5SDimitry Andric case '[': 2510b57cec5SDimitry Andric case '{': 2520b57cec5SDimitry Andric case '(': 2530b57cec5SDimitry Andric ++brace_depth; 2540b57cec5SDimitry Andric ++cursor; 2550b57cec5SDimitry Andric break; 2560b57cec5SDimitry Andric case ']': 2570b57cec5SDimitry Andric case '}': 2580b57cec5SDimitry Andric case ')': 2590b57cec5SDimitry Andric if (!brace_depth) { 2600b57cec5SDimitry Andric m_is_valid = false; 2610b57cec5SDimitry Andric return; 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric --brace_depth; 2640b57cec5SDimitry Andric ++cursor; 2650b57cec5SDimitry Andric break; 2660b57cec5SDimitry Andric case '\0': 2670b57cec5SDimitry Andric m_is_valid = false; 2680b57cec5SDimitry Andric return; 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric } break; 2710b57cec5SDimitry Andric case InPos: { 2720b57cec5SDimitry Andric switch (*cursor) { 2730b57cec5SDimitry Andric default: 2740b57cec5SDimitry Andric state = InType; 2750b57cec5SDimitry Andric type = cursor; 2760b57cec5SDimitry Andric break; 2770b57cec5SDimitry Andric case '0': 2780b57cec5SDimitry Andric case '1': 2790b57cec5SDimitry Andric case '2': 2800b57cec5SDimitry Andric case '3': 2810b57cec5SDimitry Andric case '4': 2820b57cec5SDimitry Andric case '5': 2830b57cec5SDimitry Andric case '6': 2840b57cec5SDimitry Andric case '7': 2850b57cec5SDimitry Andric case '8': 2860b57cec5SDimitry Andric case '9': 2870b57cec5SDimitry Andric ++cursor; 2880b57cec5SDimitry Andric break; 2890b57cec5SDimitry Andric case '\0': 2900b57cec5SDimitry Andric m_is_valid = true; 2910b57cec5SDimitry Andric return; 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric } break; 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric clang::ObjCMethodDecl * 2995ffd83dbSDimitry Andric BuildMethod(TypeSystemClang &clang_ast_ctxt, 300480093f4SDimitry Andric clang::ObjCInterfaceDecl *interface_decl, const char *name, 3010b57cec5SDimitry Andric bool instance, 3020b57cec5SDimitry Andric ObjCLanguageRuntime::EncodingToTypeSP type_realizer_sp) { 3030b57cec5SDimitry Andric if (!m_is_valid || m_type_vector.size() < 3) 3040b57cec5SDimitry Andric return nullptr; 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric clang::ASTContext &ast_ctx(interface_decl->getASTContext()); 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric const bool isInstance = instance; 3090b57cec5SDimitry Andric const bool isVariadic = false; 310480093f4SDimitry Andric const bool isPropertyAccessor = false; 311480093f4SDimitry Andric const bool isSynthesizedAccessorStub = false; 3120b57cec5SDimitry Andric const bool isImplicitlyDeclared = true; 3130b57cec5SDimitry Andric const bool isDefined = false; 3145f757f3fSDimitry Andric const clang::ObjCImplementationControl impControl = 3155f757f3fSDimitry Andric clang::ObjCImplementationControl::None; 3160b57cec5SDimitry Andric const bool HasRelatedResultType = false; 3170b57cec5SDimitry Andric const bool for_expression = true; 3180b57cec5SDimitry Andric 319*0fca6ea1SDimitry Andric std::vector<const clang::IdentifierInfo *> selector_components; 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric const char *name_cursor = name; 3220b57cec5SDimitry Andric bool is_zero_argument = true; 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric while (*name_cursor != '\0') { 3250b57cec5SDimitry Andric const char *colon_loc = strchr(name_cursor, ':'); 3260b57cec5SDimitry Andric if (!colon_loc) { 3270b57cec5SDimitry Andric selector_components.push_back( 3280b57cec5SDimitry Andric &ast_ctx.Idents.get(llvm::StringRef(name_cursor))); 3290b57cec5SDimitry Andric break; 3300b57cec5SDimitry Andric } else { 3310b57cec5SDimitry Andric is_zero_argument = false; 3320b57cec5SDimitry Andric selector_components.push_back(&ast_ctx.Idents.get( 3330b57cec5SDimitry Andric llvm::StringRef(name_cursor, colon_loc - name_cursor))); 3340b57cec5SDimitry Andric name_cursor = colon_loc + 1; 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric 338*0fca6ea1SDimitry Andric const clang::IdentifierInfo **identifier_infos = selector_components.data(); 3390b57cec5SDimitry Andric if (!identifier_infos) { 3400b57cec5SDimitry Andric return nullptr; 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric clang::Selector sel = ast_ctx.Selectors.getSelector( 3440b57cec5SDimitry Andric is_zero_argument ? 0 : selector_components.size(), 3450b57cec5SDimitry Andric identifier_infos); 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric clang::QualType ret_type = 3480b57cec5SDimitry Andric ClangUtil::GetQualType(type_realizer_sp->RealizeType( 349480093f4SDimitry Andric clang_ast_ctxt, m_type_vector[0].c_str(), for_expression)); 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric if (ret_type.isNull()) 3520b57cec5SDimitry Andric return nullptr; 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric clang::ObjCMethodDecl *ret = clang::ObjCMethodDecl::Create( 3550b57cec5SDimitry Andric ast_ctx, clang::SourceLocation(), clang::SourceLocation(), sel, 3560b57cec5SDimitry Andric ret_type, nullptr, interface_decl, isInstance, isVariadic, 357480093f4SDimitry Andric isPropertyAccessor, isSynthesizedAccessorStub, isImplicitlyDeclared, 358480093f4SDimitry Andric isDefined, impControl, HasRelatedResultType); 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric std::vector<clang::ParmVarDecl *> parm_vars; 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric for (size_t ai = 3, ae = m_type_vector.size(); ai != ae; ++ai) { 3630b57cec5SDimitry Andric const bool for_expression = true; 3640b57cec5SDimitry Andric clang::QualType arg_type = 3650b57cec5SDimitry Andric ClangUtil::GetQualType(type_realizer_sp->RealizeType( 366480093f4SDimitry Andric clang_ast_ctxt, m_type_vector[ai].c_str(), for_expression)); 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric if (arg_type.isNull()) 3690b57cec5SDimitry Andric return nullptr; // well, we just wasted a bunch of time. Wish we could 3700b57cec5SDimitry Andric // delete the stuff we'd just made! 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric parm_vars.push_back(clang::ParmVarDecl::Create( 3730b57cec5SDimitry Andric ast_ctx, ret, clang::SourceLocation(), clang::SourceLocation(), 3740b57cec5SDimitry Andric nullptr, arg_type, nullptr, clang::SC_None, nullptr)); 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric ret->setMethodParams(ast_ctx, 3780b57cec5SDimitry Andric llvm::ArrayRef<clang::ParmVarDecl *>(parm_vars), 3790b57cec5SDimitry Andric llvm::ArrayRef<clang::SourceLocation>()); 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric return ret; 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric explicit operator bool() { return m_is_valid; } 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric size_t GetNumTypes() { return m_type_vector.size(); } 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric const char *GetTypeAtIndex(size_t idx) { return m_type_vector[idx].c_str(); } 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric private: 3910b57cec5SDimitry Andric typedef std::vector<std::string> TypeVector; 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric TypeVector m_type_vector; 39481ad6265SDimitry Andric bool m_is_valid = false; 3950b57cec5SDimitry Andric }; 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { 39881ad6265SDimitry Andric Log *log( 39981ad6265SDimitry Andric GetLog(LLDBLog::Expressions)); // FIXME - a more appropriate log channel? 4000b57cec5SDimitry Andric 401bdd1243dSDimitry Andric ClangASTMetadata *metadata = m_ast_ctx->GetMetadata(interface_decl); 4020b57cec5SDimitry Andric ObjCLanguageRuntime::ObjCISA objc_isa = 0; 4030b57cec5SDimitry Andric if (metadata) 4040b57cec5SDimitry Andric objc_isa = metadata->GetISAPtr(); 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric if (!objc_isa) 4070b57cec5SDimitry Andric return false; 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric if (!interface_decl->hasExternalVisibleStorage()) 4100b57cec5SDimitry Andric return true; 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric interface_decl->startDefinition(); 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric interface_decl->setHasExternalVisibleStorage(false); 4150b57cec5SDimitry Andric interface_decl->setHasExternalLexicalStorage(false); 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP descriptor = 4180b57cec5SDimitry Andric m_runtime.GetClassDescriptorFromISA(objc_isa); 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric if (!descriptor) 4210b57cec5SDimitry Andric return false; 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric auto superclass_func = [interface_decl, 4240b57cec5SDimitry Andric this](ObjCLanguageRuntime::ObjCISA isa) { 4250b57cec5SDimitry Andric clang::ObjCInterfaceDecl *superclass_decl = GetDeclForISA(isa); 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric if (!superclass_decl) 4280b57cec5SDimitry Andric return; 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric FinishDecl(superclass_decl); 431bdd1243dSDimitry Andric clang::ASTContext &context = m_ast_ctx->getASTContext(); 432480093f4SDimitry Andric interface_decl->setSuperClass(context.getTrivialTypeSourceInfo( 433480093f4SDimitry Andric context.getObjCInterfaceType(superclass_decl))); 4340b57cec5SDimitry Andric }; 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric auto instance_method_func = 4370b57cec5SDimitry Andric [log, interface_decl, this](const char *name, const char *types) -> bool { 4380b57cec5SDimitry Andric if (!name || !types) 4390b57cec5SDimitry Andric return false; // skip this one 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric ObjCRuntimeMethodType method_type(types); 4420b57cec5SDimitry Andric 443480093f4SDimitry Andric clang::ObjCMethodDecl *method_decl = method_type.BuildMethod( 444bdd1243dSDimitry Andric *m_ast_ctx, interface_decl, name, true, m_type_realizer_sp); 4450b57cec5SDimitry Andric 4469dba64beSDimitry Andric LLDB_LOGF(log, "[ AOTV::FD] Instance method [%s] [%s]", name, types); 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric if (method_decl) 4490b57cec5SDimitry Andric interface_decl->addDecl(method_decl); 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric return false; 4520b57cec5SDimitry Andric }; 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric auto class_method_func = [log, interface_decl, 4550b57cec5SDimitry Andric this](const char *name, const char *types) -> bool { 4560b57cec5SDimitry Andric if (!name || !types) 4570b57cec5SDimitry Andric return false; // skip this one 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric ObjCRuntimeMethodType method_type(types); 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric clang::ObjCMethodDecl *method_decl = method_type.BuildMethod( 462bdd1243dSDimitry Andric *m_ast_ctx, interface_decl, name, false, m_type_realizer_sp); 4630b57cec5SDimitry Andric 4649dba64beSDimitry Andric LLDB_LOGF(log, "[ AOTV::FD] Class method [%s] [%s]", name, types); 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric if (method_decl) 4670b57cec5SDimitry Andric interface_decl->addDecl(method_decl); 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric return false; 4700b57cec5SDimitry Andric }; 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric auto ivar_func = [log, interface_decl, 4730b57cec5SDimitry Andric this](const char *name, const char *type, 4740b57cec5SDimitry Andric lldb::addr_t offset_ptr, uint64_t size) -> bool { 4750b57cec5SDimitry Andric if (!name || !type) 4760b57cec5SDimitry Andric return false; 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric const bool for_expression = false; 4790b57cec5SDimitry Andric 4809dba64beSDimitry Andric LLDB_LOGF(log, 4819dba64beSDimitry Andric "[ AOTV::FD] Instance variable [%s] [%s], offset at %" PRIx64, 4829dba64beSDimitry Andric name, type, offset_ptr); 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric CompilerType ivar_type = m_runtime.GetEncodingToType()->RealizeType( 485bdd1243dSDimitry Andric *m_ast_ctx, type, for_expression); 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric if (ivar_type.IsValid()) { 4880b57cec5SDimitry Andric clang::TypeSourceInfo *const type_source_info = nullptr; 4890b57cec5SDimitry Andric const bool is_synthesized = false; 4900b57cec5SDimitry Andric clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create( 491bdd1243dSDimitry Andric m_ast_ctx->getASTContext(), interface_decl, clang::SourceLocation(), 492bdd1243dSDimitry Andric clang::SourceLocation(), &m_ast_ctx->getASTContext().Idents.get(name), 4930b57cec5SDimitry Andric ClangUtil::GetQualType(ivar_type), 4940b57cec5SDimitry Andric type_source_info, // TypeSourceInfo * 4950b57cec5SDimitry Andric clang::ObjCIvarDecl::Public, nullptr, is_synthesized); 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric if (ivar_decl) { 4980b57cec5SDimitry Andric interface_decl->addDecl(ivar_decl); 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric } 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric return false; 5030b57cec5SDimitry Andric }; 5040b57cec5SDimitry Andric 50506c3fb27SDimitry Andric LLDB_LOGF(log, 5069dba64beSDimitry Andric "[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C " 5070b57cec5SDimitry Andric "interface for %s", 5080b57cec5SDimitry Andric descriptor->GetClassName().AsCString()); 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric if (!descriptor->Describe(superclass_func, instance_method_func, 5110b57cec5SDimitry Andric class_method_func, ivar_func)) 5120b57cec5SDimitry Andric return false; 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andric if (log) { 5159dba64beSDimitry Andric LLDB_LOGF( 5169dba64beSDimitry Andric log, 5170b57cec5SDimitry Andric "[AppleObjCDeclVendor::FinishDecl] Finished Objective-C interface"); 5180b57cec5SDimitry Andric 519480093f4SDimitry Andric LLDB_LOG(log, " [AOTV::FD] {0}", ClangUtil::DumpDecl(interface_decl)); 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric return true; 5230b57cec5SDimitry Andric } 5240b57cec5SDimitry Andric 525480093f4SDimitry Andric uint32_t AppleObjCDeclVendor::FindDecls(ConstString name, bool append, 5260b57cec5SDimitry Andric uint32_t max_matches, 527480093f4SDimitry Andric std::vector<CompilerDecl> &decls) { 5280b57cec5SDimitry Andric 52981ad6265SDimitry Andric Log *log( 53081ad6265SDimitry Andric GetLog(LLDBLog::Expressions)); // FIXME - a more appropriate log channel? 5310b57cec5SDimitry Andric 5325ffd83dbSDimitry Andric LLDB_LOGF(log, "AppleObjCDeclVendor::FindDecls ('%s', %s, %u, )", 5335ffd83dbSDimitry Andric (const char *)name.AsCString(), append ? "true" : "false", 5345ffd83dbSDimitry Andric max_matches); 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric if (!append) 5370b57cec5SDimitry Andric decls.clear(); 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric uint32_t ret = 0; 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric do { 5420b57cec5SDimitry Andric // See if the type is already in our ASTContext. 5430b57cec5SDimitry Andric 544bdd1243dSDimitry Andric clang::ASTContext &ast_ctx = m_ast_ctx->getASTContext(); 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric clang::IdentifierInfo &identifier_info = 547480093f4SDimitry Andric ast_ctx.Idents.get(name.GetStringRef()); 5480b57cec5SDimitry Andric clang::DeclarationName decl_name = 549480093f4SDimitry Andric ast_ctx.DeclarationNames.getIdentifier(&identifier_info); 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric clang::DeclContext::lookup_result lookup_result = 552480093f4SDimitry Andric ast_ctx.getTranslationUnitDecl()->lookup(decl_name); 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric if (!lookup_result.empty()) { 5550b57cec5SDimitry Andric if (clang::ObjCInterfaceDecl *result_iface_decl = 556fe6060f1SDimitry Andric llvm::dyn_cast<clang::ObjCInterfaceDecl>(*lookup_result.begin())) { 5570b57cec5SDimitry Andric if (log) { 5580b57cec5SDimitry Andric clang::QualType result_iface_type = 559480093f4SDimitry Andric ast_ctx.getObjCInterfaceType(result_iface_decl); 5600b57cec5SDimitry Andric 5610b57cec5SDimitry Andric uint64_t isa_value = LLDB_INVALID_ADDRESS; 562bdd1243dSDimitry Andric ClangASTMetadata *metadata = m_ast_ctx->GetMetadata(result_iface_decl); 5630b57cec5SDimitry Andric if (metadata) 5640b57cec5SDimitry Andric isa_value = metadata->GetISAPtr(); 5650b57cec5SDimitry Andric 56606c3fb27SDimitry Andric LLDB_LOGF(log, 5675ffd83dbSDimitry Andric "AOCTV::FT Found %s (isa 0x%" PRIx64 ") in the ASTContext", 56806c3fb27SDimitry Andric result_iface_type.getAsString().data(), isa_value); 5690b57cec5SDimitry Andric } 5700b57cec5SDimitry Andric 571bdd1243dSDimitry Andric decls.push_back(m_ast_ctx->GetCompilerDecl(result_iface_decl)); 5720b57cec5SDimitry Andric ret++; 5730b57cec5SDimitry Andric break; 5740b57cec5SDimitry Andric } else { 5755ffd83dbSDimitry Andric LLDB_LOGF(log, "AOCTV::FT There's something in the ASTContext, but " 5765ffd83dbSDimitry Andric "it's not something we know about"); 5770b57cec5SDimitry Andric break; 5780b57cec5SDimitry Andric } 5790b57cec5SDimitry Andric } else if (log) { 5805ffd83dbSDimitry Andric LLDB_LOGF(log, "AOCTV::FT Couldn't find %s in the ASTContext", 5815ffd83dbSDimitry Andric name.AsCString()); 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric // It's not. If it exists, we have to put it into our ASTContext. 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name); 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric if (!isa) { 5895ffd83dbSDimitry Andric LLDB_LOGF(log, "AOCTV::FT Couldn't find the isa"); 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric break; 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric clang::ObjCInterfaceDecl *iface_decl = GetDeclForISA(isa); 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric if (!iface_decl) { 5979dba64beSDimitry Andric LLDB_LOGF(log, 5985ffd83dbSDimitry Andric "AOCTV::FT Couldn't get the Objective-C interface for " 5990b57cec5SDimitry Andric "isa 0x%" PRIx64, 6005ffd83dbSDimitry Andric (uint64_t)isa); 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric break; 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric if (log) { 606480093f4SDimitry Andric clang::QualType new_iface_type = ast_ctx.getObjCInterfaceType(iface_decl); 607480093f4SDimitry Andric 6085ffd83dbSDimitry Andric LLDB_LOG(log, "AOCTV::FT Created {1} (isa 0x{2:x})", 609480093f4SDimitry Andric new_iface_type.getAsString(), (uint64_t)isa); 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric 612bdd1243dSDimitry Andric decls.push_back(m_ast_ctx->GetCompilerDecl(iface_decl)); 6130b57cec5SDimitry Andric ret++; 6140b57cec5SDimitry Andric break; 6150b57cec5SDimitry Andric } while (false); 6160b57cec5SDimitry Andric 6170b57cec5SDimitry Andric return ret; 6180b57cec5SDimitry Andric } 619