@@ -920,6 +920,8 @@ SwiftASTContext::~SwiftASTContext() {
920
920
}
921
921
}
922
922
923
+ const std::string &SwiftASTContext::GetDescription () const { return m_description; }
924
+
923
925
ConstString SwiftASTContext::GetPluginNameStatic () {
924
926
return ConstString (" swift" );
925
927
}
@@ -3103,6 +3105,11 @@ class StoringDiagnosticConsumer : public swift::DiagnosticConsumer {
3103
3105
// / Clang AST to ClangImporter to import the type into Swift.
3104
3106
class SwiftDWARFImporterDelegate : public swift ::DWARFImporterDelegate {
3105
3107
SwiftASTContext &m_swift_ast_ctx;
3108
+ using ModuleAndName = std::pair<const char *, const char *>;
3109
+ // / Caches successful lookups for the scratch context.
3110
+ llvm::DenseMap<ModuleAndName, llvm::SmallVector<clang::QualType, 1 >>
3111
+ m_decl_cache;
3112
+ std::string m_description;
3106
3113
3107
3114
// / Used to filter out types with mismatching kinds.
3108
3115
bool HasTypeKind (TypeSP clang_type_sp, swift::ClangTypeKind kind) {
@@ -3170,9 +3177,42 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate {
3170
3177
}
3171
3178
}
3172
3179
3180
+ // / Import \p qual_type from one clang ASTContext to another and
3181
+ // / add it to \p results if successful.
3182
+ void importType (clang::QualType qual_type, clang::ASTContext &from_ctx,
3183
+ clang::ASTContext &to_ctx,
3184
+ llvm::Optional<swift::ClangTypeKind> kind,
3185
+ llvm::SmallVectorImpl<clang::Decl *> &results) {
3186
+ clang::FileSystemOptions file_system_options;
3187
+ clang::FileManager file_manager (
3188
+ file_system_options, FileSystem::Instance ().GetVirtualFileSystem ());
3189
+ clang::ASTImporter importer (to_ctx, file_manager, from_ctx, file_manager,
3190
+ false );
3191
+ llvm::Expected<clang::QualType> clang_type (importer.Import (qual_type));
3192
+ if (!clang_type) {
3193
+ llvm::consumeError (clang_type.takeError ());
3194
+ return ;
3195
+ }
3196
+
3197
+ // Retrieve the imported type's Decl.
3198
+ if (kind) {
3199
+ if (clang::Decl *clang_decl = GetDeclForTypeAndKind (*clang_type, *kind))
3200
+ results.push_back (clang_decl);
3201
+ } else {
3202
+ swift::ClangTypeKind kinds[] = {
3203
+ swift::ClangTypeKind::Typedef, // =swift::ClangTypeKind::ObjCClass,
3204
+ swift::ClangTypeKind::Tag, swift::ClangTypeKind::ObjCProtocol};
3205
+ for (auto kind : kinds)
3206
+ if (clang::Decl *clang_decl = GetDeclForTypeAndKind (*clang_type, kind))
3207
+ results.push_back (clang_decl);
3208
+ }
3209
+ }
3210
+
3173
3211
public:
3174
3212
SwiftDWARFImporterDelegate (SwiftASTContext &swift_ast_ctx)
3175
- : m_swift_ast_ctx(swift_ast_ctx) {}
3213
+ : m_swift_ast_ctx(swift_ast_ctx),
3214
+ m_description (swift_ast_ctx.GetDescription() +
3215
+ "::SwiftDWARFImporterDelegate") {}
3176
3216
3177
3217
// / Look up a clang::Decl by name.
3178
3218
// /
@@ -3231,6 +3271,8 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate {
3231
3271
void lookupValue (StringRef name, llvm::Optional<swift::ClangTypeKind> kind,
3232
3272
StringRef inModule,
3233
3273
llvm::SmallVectorImpl<clang::Decl *> &results) override {
3274
+ LOG_PRINTF (LIBLLDB_LOG_TYPES, " (\" %s\" )" , name.str ().c_str ());
3275
+
3234
3276
// We will not find any Swift types in the Clang compile units.
3235
3277
if (SwiftLanguageRuntime::IsSwiftMangledName (name.str ().c_str ()))
3236
3278
return ;
@@ -3241,15 +3283,16 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate {
3241
3283
3242
3284
// Find the type in the debug info.
3243
3285
TypeMap clang_types;
3286
+ ConstString name_cs (name);
3287
+ ConstString module_cs (inModule);
3244
3288
3245
3289
llvm::SmallVector<CompilerContext, 3 > decl_context;
3246
3290
// Perform a lookup in a specific module, if requested.
3247
3291
if (!inModule.empty ())
3248
- decl_context.push_back (
3249
- {CompilerContextKind::Module, ConstString (inModule)});
3292
+ decl_context.push_back ({CompilerContextKind::Module, module_cs});
3250
3293
// Swift doesn't keep track of submodules.
3251
3294
decl_context.push_back ({CompilerContextKind::AnyModule, ConstString ()});
3252
- decl_context.push_back ({GetCompilerContextKind (kind), ConstString (name) });
3295
+ decl_context.push_back ({GetCompilerContextKind (kind), name_cs });
3253
3296
auto search = [&](Module &module ) {
3254
3297
return module .FindTypes (decl_context,
3255
3298
ClangASTContext::GetSupportedLanguagesForTypes (),
@@ -3258,16 +3301,46 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate {
3258
3301
if (Module *module = m_swift_ast_ctx.GetModule ())
3259
3302
search (*module );
3260
3303
else if (TargetSP target_sp = m_swift_ast_ctx.GetTarget ().lock ()) {
3261
- // In a scratch context, search everywhere.
3304
+ // In a scratch context, check the module's DWARFImporterDelegates first.
3305
+ //
3306
+ // It's a common pattern that a type is revisited immediately
3307
+ // after looking it up in a per-module context in the scratch
3308
+ // context for dynamic type resolution.
3262
3309
auto images = target_sp->GetImages ();
3263
- for (size_t i = 0 ; i != images.GetSize (); ++i)
3264
- if (search (*images.GetModuleAtIndex (i)))
3265
- break ;
3310
+ for (size_t i = 0 ; i != images.GetSize (); ++i) {
3311
+ auto module_sp = images.GetModuleAtIndex (i);
3312
+ auto ts = module_sp->GetTypeSystemForLanguage (lldb::eLanguageTypeSwift);
3313
+ if (!ts) {
3314
+ llvm::consumeError (ts.takeError ());
3315
+ continue ;
3316
+ }
3317
+ auto *swift_ast_ctx = static_cast <SwiftASTContext *>(&*ts);
3318
+ auto *dwarf_imp = static_cast <SwiftDWARFImporterDelegate *>(
3319
+ swift_ast_ctx->GetDWARFImporterDelegate ());
3320
+ if (!dwarf_imp)
3321
+ continue ;
3322
+ auto it = dwarf_imp->m_decl_cache .find (
3323
+ {module_cs.GetCString (), name_cs.GetCString ()});
3324
+ if (it == dwarf_imp->m_decl_cache .end ())
3325
+ continue ;
3326
+
3327
+ auto *from_clang_importer = swift_ast_ctx->GetClangImporter ();
3328
+ if (!from_clang_importer)
3329
+ continue ;
3330
+ auto &from_ctx = from_clang_importer->getClangASTContext ();
3331
+ auto &to_ctx = clang_importer->getClangASTContext ();
3332
+ for (clang::QualType qual_type : it->second )
3333
+ importType (qual_type, from_ctx, to_ctx, kind, results);
3334
+ }
3335
+ LOG_PRINTF (LIBLLDB_LOG_TYPES, " %d types found in cache." , results.size ());
3336
+
3337
+ // TODO: Otherwise, the correct thing to do is to invoke
3338
+ // search() on all modules. In practice, however, this is
3339
+ // prohibitively expensive, so we need to do something
3340
+ // more targeted.
3341
+ return ;
3266
3342
}
3267
3343
3268
- clang::FileSystemOptions file_system_options;
3269
- clang::FileManager file_manager (
3270
- file_system_options, FileSystem::Instance ().GetVirtualFileSystem ());
3271
3344
clang_types.ForEach ([&](lldb::TypeSP &clang_type_sp) {
3272
3345
if (!clang_type_sp)
3273
3346
return true ;
@@ -3290,29 +3363,19 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate {
3290
3363
clang::ASTContext *from_ctx = type_system->getASTContext ();
3291
3364
if (!from_ctx)
3292
3365
return true ;
3293
- clang::ASTImporter importer (to_ctx, file_manager, *from_ctx, file_manager,
3294
- false );
3295
- llvm::Expected<clang::QualType> clang_type (
3296
- importer.Import (ClangUtil::GetQualType (compiler_type)));
3297
- if (!clang_type) {
3298
- llvm::consumeError (clang_type.takeError ());
3299
- return true ;
3300
- }
3301
3366
3302
- // Retrieve the imported type's Decl.
3303
- if (kind) {
3304
- if (clang::Decl *clang_decl = GetDeclForTypeAndKind (*clang_type, *kind))
3305
- results.push_back (clang_decl);
3306
- } else {
3307
- swift::ClangTypeKind kinds[] = {
3308
- swift::ClangTypeKind::Typedef, // =swift::ClangTypeKind::ObjCClass,
3309
- swift::ClangTypeKind::Tag, swift::ClangTypeKind::ObjCProtocol};
3310
- for (auto kind : kinds)
3311
- if (clang::Decl *clang_decl = GetDeclForTypeAndKind (*clang_type, kind))
3312
- results.push_back (clang_decl);
3313
- }
3367
+ clang::QualType qual_type = ClangUtil::GetQualType (compiler_type);
3368
+ importType (qual_type, *from_ctx, to_ctx, kind, results);
3369
+
3370
+ // If this is a module context, cache the result for the scratch context.
3371
+ if (m_swift_ast_ctx.GetModule ())
3372
+ m_decl_cache[{module_cs.GetCString (), name_cs.GetCString ()}].push_back (
3373
+ qual_type);
3374
+
3314
3375
return true ;
3315
3376
});
3377
+
3378
+ LOG_PRINTF (LIBLLDB_LOG_TYPES, " %d types from debug info." , results.size ());
3316
3379
}
3317
3380
};
3318
3381
} // namespace lldb_private
@@ -3492,6 +3555,12 @@ swift::ClangImporter *SwiftASTContext::GetClangImporter() {
3492
3555
return m_clang_importer;
3493
3556
}
3494
3557
3558
+ swift::DWARFImporterDelegate *SwiftASTContext::GetDWARFImporterDelegate () {
3559
+ VALID_OR_RETURN (nullptr );
3560
+
3561
+ return m_dwarf_importer_delegate_up.get ();
3562
+ }
3563
+
3495
3564
bool SwiftASTContext::AddClangArgument (std::string clang_arg, bool unique) {
3496
3565
if (clang_arg.empty ())
3497
3566
return false ;
0 commit comments