@@ -921,6 +921,8 @@ SwiftASTContext::~SwiftASTContext() {
921
921
}
922
922
}
923
923
924
+ const std::string &SwiftASTContext::GetDescription () const { return m_description; }
925
+
924
926
ConstString SwiftASTContext::GetPluginNameStatic () {
925
927
return ConstString (" swift" );
926
928
}
@@ -3163,6 +3165,11 @@ class StoringDiagnosticConsumer : public swift::DiagnosticConsumer {
3163
3165
// / Clang AST to ClangImporter to import the type into Swift.
3164
3166
class SwiftDWARFImporterDelegate : public swift ::DWARFImporterDelegate {
3165
3167
SwiftASTContext &m_swift_ast_ctx;
3168
+ using ModuleAndName = std::pair<const char *, const char *>;
3169
+ // / Caches successful lookups for the scratch context.
3170
+ llvm::DenseMap<ModuleAndName, llvm::SmallVector<clang::QualType, 1 >>
3171
+ m_decl_cache;
3172
+ std::string m_description;
3166
3173
3167
3174
// / Used to filter out types with mismatching kinds.
3168
3175
bool HasTypeKind (TypeSP clang_type_sp, swift::ClangTypeKind kind) {
@@ -3230,9 +3237,42 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate {
3230
3237
}
3231
3238
}
3232
3239
3240
+ // / Import \p qual_type from one clang ASTContext to another and
3241
+ // / add it to \p results if successful.
3242
+ void importType (clang::QualType qual_type, clang::ASTContext &from_ctx,
3243
+ clang::ASTContext &to_ctx,
3244
+ llvm::Optional<swift::ClangTypeKind> kind,
3245
+ llvm::SmallVectorImpl<clang::Decl *> &results) {
3246
+ clang::FileSystemOptions file_system_options;
3247
+ clang::FileManager file_manager (
3248
+ file_system_options, FileSystem::Instance ().GetVirtualFileSystem ());
3249
+ clang::ASTImporter importer (to_ctx, file_manager, from_ctx, file_manager,
3250
+ false );
3251
+ llvm::Expected<clang::QualType> clang_type (importer.Import (qual_type));
3252
+ if (!clang_type) {
3253
+ llvm::consumeError (clang_type.takeError ());
3254
+ return ;
3255
+ }
3256
+
3257
+ // Retrieve the imported type's Decl.
3258
+ if (kind) {
3259
+ if (clang::Decl *clang_decl = GetDeclForTypeAndKind (*clang_type, *kind))
3260
+ results.push_back (clang_decl);
3261
+ } else {
3262
+ swift::ClangTypeKind kinds[] = {
3263
+ swift::ClangTypeKind::Typedef, // =swift::ClangTypeKind::ObjCClass,
3264
+ swift::ClangTypeKind::Tag, swift::ClangTypeKind::ObjCProtocol};
3265
+ for (auto kind : kinds)
3266
+ if (clang::Decl *clang_decl = GetDeclForTypeAndKind (*clang_type, kind))
3267
+ results.push_back (clang_decl);
3268
+ }
3269
+ }
3270
+
3233
3271
public:
3234
3272
SwiftDWARFImporterDelegate (SwiftASTContext &swift_ast_ctx)
3235
- : m_swift_ast_ctx(swift_ast_ctx) {}
3273
+ : m_swift_ast_ctx(swift_ast_ctx),
3274
+ m_description (swift_ast_ctx.GetDescription() +
3275
+ "::SwiftDWARFImporterDelegate") {}
3236
3276
3237
3277
// / Look up a clang::Decl by name.
3238
3278
// /
@@ -3291,6 +3331,8 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate {
3291
3331
void lookupValue (StringRef name, llvm::Optional<swift::ClangTypeKind> kind,
3292
3332
StringRef inModule,
3293
3333
llvm::SmallVectorImpl<clang::Decl *> &results) override {
3334
+ LOG_PRINTF (LIBLLDB_LOG_TYPES, " (\" %s\" )" , name.str ().c_str ());
3335
+
3294
3336
// We will not find any Swift types in the Clang compile units.
3295
3337
if (SwiftLanguageRuntime::IsSwiftMangledName (name.str ().c_str ()))
3296
3338
return ;
@@ -3301,15 +3343,16 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate {
3301
3343
3302
3344
// Find the type in the debug info.
3303
3345
TypeMap clang_types;
3346
+ ConstString name_cs (name);
3347
+ ConstString module_cs (inModule);
3304
3348
3305
3349
llvm::SmallVector<CompilerContext, 3 > decl_context;
3306
3350
// Perform a lookup in a specific module, if requested.
3307
3351
if (!inModule.empty ())
3308
- decl_context.push_back (
3309
- {CompilerContextKind::Module, ConstString (inModule)});
3352
+ decl_context.push_back ({CompilerContextKind::Module, module_cs});
3310
3353
// Swift doesn't keep track of submodules.
3311
3354
decl_context.push_back ({CompilerContextKind::AnyModule, ConstString ()});
3312
- decl_context.push_back ({GetCompilerContextKind (kind), ConstString (name) });
3355
+ decl_context.push_back ({GetCompilerContextKind (kind), name_cs });
3313
3356
auto search = [&](Module &module ) {
3314
3357
return module .FindTypes (decl_context,
3315
3358
ClangASTContext::GetSupportedLanguagesForTypes (),
@@ -3318,16 +3361,46 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate {
3318
3361
if (Module *module = m_swift_ast_ctx.GetModule ())
3319
3362
search (*module );
3320
3363
else if (TargetSP target_sp = m_swift_ast_ctx.GetTarget ().lock ()) {
3321
- // In a scratch context, search everywhere.
3364
+ // In a scratch context, check the module's DWARFImporterDelegates first.
3365
+ //
3366
+ // It's a common pattern that a type is revisited immediately
3367
+ // after looking it up in a per-module context in the scratch
3368
+ // context for dynamic type resolution.
3322
3369
auto images = target_sp->GetImages ();
3323
- for (size_t i = 0 ; i != images.GetSize (); ++i)
3324
- if (search (*images.GetModuleAtIndex (i)))
3325
- break ;
3370
+ for (size_t i = 0 ; i != images.GetSize (); ++i) {
3371
+ auto module_sp = images.GetModuleAtIndex (i);
3372
+ auto ts = module_sp->GetTypeSystemForLanguage (lldb::eLanguageTypeSwift);
3373
+ if (!ts) {
3374
+ llvm::consumeError (ts.takeError ());
3375
+ continue ;
3376
+ }
3377
+ auto *swift_ast_ctx = static_cast <SwiftASTContext *>(&*ts);
3378
+ auto *dwarf_imp = static_cast <SwiftDWARFImporterDelegate *>(
3379
+ swift_ast_ctx->GetDWARFImporterDelegate ());
3380
+ if (!dwarf_imp)
3381
+ continue ;
3382
+ auto it = dwarf_imp->m_decl_cache .find (
3383
+ {module_cs.GetCString (), name_cs.GetCString ()});
3384
+ if (it == dwarf_imp->m_decl_cache .end ())
3385
+ continue ;
3386
+
3387
+ auto *from_clang_importer = swift_ast_ctx->GetClangImporter ();
3388
+ if (!from_clang_importer)
3389
+ continue ;
3390
+ auto &from_ctx = from_clang_importer->getClangASTContext ();
3391
+ auto &to_ctx = clang_importer->getClangASTContext ();
3392
+ for (clang::QualType qual_type : it->second )
3393
+ importType (qual_type, from_ctx, to_ctx, kind, results);
3394
+ }
3395
+ LOG_PRINTF (LIBLLDB_LOG_TYPES, " %d types found in cache." , results.size ());
3396
+
3397
+ // TODO: Otherwise, the correct thing to do is to invoke
3398
+ // search() on all modules. In practice, however, this is
3399
+ // prohibitively expensive, so we need to do something
3400
+ // more targeted.
3401
+ return ;
3326
3402
}
3327
3403
3328
- clang::FileSystemOptions file_system_options;
3329
- clang::FileManager file_manager (
3330
- file_system_options, FileSystem::Instance ().GetVirtualFileSystem ());
3331
3404
clang_types.ForEach ([&](lldb::TypeSP &clang_type_sp) {
3332
3405
if (!clang_type_sp)
3333
3406
return true ;
@@ -3350,29 +3423,19 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate {
3350
3423
clang::ASTContext *from_ctx = type_system->getASTContext ();
3351
3424
if (!from_ctx)
3352
3425
return true ;
3353
- clang::ASTImporter importer (to_ctx, file_manager, *from_ctx, file_manager,
3354
- false );
3355
- llvm::Expected<clang::QualType> clang_type (
3356
- importer.Import (ClangUtil::GetQualType (compiler_type)));
3357
- if (!clang_type) {
3358
- llvm::consumeError (clang_type.takeError ());
3359
- return true ;
3360
- }
3361
3426
3362
- // Retrieve the imported type's Decl.
3363
- if (kind) {
3364
- if (clang::Decl *clang_decl = GetDeclForTypeAndKind (*clang_type, *kind))
3365
- results.push_back (clang_decl);
3366
- } else {
3367
- swift::ClangTypeKind kinds[] = {
3368
- swift::ClangTypeKind::Typedef, // =swift::ClangTypeKind::ObjCClass,
3369
- swift::ClangTypeKind::Tag, swift::ClangTypeKind::ObjCProtocol};
3370
- for (auto kind : kinds)
3371
- if (clang::Decl *clang_decl = GetDeclForTypeAndKind (*clang_type, kind))
3372
- results.push_back (clang_decl);
3373
- }
3427
+ clang::QualType qual_type = ClangUtil::GetQualType (compiler_type);
3428
+ importType (qual_type, *from_ctx, to_ctx, kind, results);
3429
+
3430
+ // If this is a module context, cache the result for the scratch context.
3431
+ if (m_swift_ast_ctx.GetModule ())
3432
+ m_decl_cache[{module_cs.GetCString (), name_cs.GetCString ()}].push_back (
3433
+ qual_type);
3434
+
3374
3435
return true ;
3375
3436
});
3437
+
3438
+ LOG_PRINTF (LIBLLDB_LOG_TYPES, " %d types from debug info." , results.size ());
3376
3439
}
3377
3440
};
3378
3441
} // namespace lldb_private
@@ -3552,6 +3615,12 @@ swift::ClangImporter *SwiftASTContext::GetClangImporter() {
3552
3615
return m_clang_importer;
3553
3616
}
3554
3617
3618
+ swift::DWARFImporterDelegate *SwiftASTContext::GetDWARFImporterDelegate () {
3619
+ VALID_OR_RETURN (nullptr );
3620
+
3621
+ return m_dwarf_importer_delegate_up.get ();
3622
+ }
3623
+
3555
3624
bool SwiftASTContext::AddClangArgument (std::string clang_arg, bool unique) {
3556
3625
if (clang_arg.empty ())
3557
3626
return false ;
0 commit comments