Skip to content

Commit 7e3357a

Browse files
Merge pull request swiftlang#22313 from adrian-prantl/47600180
Cache clang ASTFile information in swift::Module (NFC from the outside).
2 parents f07dec6 + 761e9a0 commit 7e3357a

File tree

4 files changed

+73
-12
lines changed

4 files changed

+73
-12
lines changed

include/swift/ClangImporter/ClangModule.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "swift/AST/Module.h"
2020
#include "swift/ClangImporter/ClangImporter.h"
21+
#include "clang/AST/ExternalASTSource.h"
2122

2223
namespace clang {
2324
class ASTContext;
@@ -35,6 +36,8 @@ class ClangModuleUnit final : public LoadedFile {
3536
const clang::Module *clangModule;
3637
llvm::PointerIntPair<ModuleDecl *, 1, bool> adapterModule;
3738
mutable ArrayRef<ModuleDecl::ImportedModule> importedModulesForLookup;
39+
/// The metadata of the underlying Clang module.
40+
clang::ExternalASTSource::ASTSourceDescriptor ASTSourceDescriptor;
3841

3942
~ClangModuleUnit() = default;
4043

@@ -113,6 +116,11 @@ class ClangModuleUnit final : public LoadedFile {
113116

114117
clang::ASTContext &getClangASTContext() const;
115118

119+
/// Returns the ASTSourceDescriptor of the associated Clang module if one
120+
/// exists.
121+
Optional<clang::ExternalASTSource::ASTSourceDescriptor>
122+
getASTSourceDescriptor() const;
123+
116124
static bool classof(const FileUnit *file) {
117125
return file->getKind() == FileUnitKind::ClangModule;
118126
}

lib/ClangImporter/ClangImporter.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3075,6 +3075,18 @@ ClangModuleUnit::ClangModuleUnit(ModuleDecl &M,
30753075
const clang::Module *clangModule)
30763076
: LoadedFile(FileUnitKind::ClangModule, M), owner(owner),
30773077
clangModule(clangModule) {
3078+
// Capture the file metadata before it goes away.
3079+
if (clangModule)
3080+
ASTSourceDescriptor = {*clangModule};
3081+
}
3082+
3083+
Optional<clang::ExternalASTSource::ASTSourceDescriptor>
3084+
ClangModuleUnit::getASTSourceDescriptor() const {
3085+
if (clangModule) {
3086+
assert(ASTSourceDescriptor.getModuleOrNull() == clangModule);
3087+
return ASTSourceDescriptor;
3088+
}
3089+
return None;
30783090
}
30793091

30803092
bool ClangModuleUnit::hasClangModule(ModuleDecl *M) {

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
#include "swift/Basic/SourceManager.h"
2929
#include "swift/Basic/Version.h"
3030
#include "swift/ClangImporter/ClangImporter.h"
31+
#include "swift/ClangImporter/ClangModule.h"
3132
#include "swift/Demangling/ManglingMacros.h"
33+
#include "swift/Serialization/SerializedModuleLoader.h"
3234
#include "swift/SIL/SILArgument.h"
3335
#include "swift/SIL/SILBasicBlock.h"
3436
#include "swift/SIL/SILDebugScope.h"
@@ -582,14 +584,18 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
582584
}
583585

584586
StringRef Sysroot = IGM.Context.SearchPathOpts.SDKPath;
585-
auto M =
587+
llvm::DIModule *M =
586588
DBuilder.createModule(Parent, Name, ConfigMacros, IncludePath, Sysroot);
587589
DIModuleCache.insert({Key, llvm::TrackingMDNodeRef(M)});
588590
return M;
589591
}
590592

591-
llvm::DIModule *
592-
getOrCreateModule(clang::ExternalASTSource::ASTSourceDescriptor Desc) {
593+
using ASTSourceDescriptor = clang::ExternalASTSource::ASTSourceDescriptor;
594+
/// Create a DIModule from a clang module or PCH.
595+
/// The clang::Module pointer is passed separately because the recursive case
596+
/// needs to fudge the AST descriptor.
597+
llvm::DIModule *getOrCreateModule(ASTSourceDescriptor Desc,
598+
const clang::Module *ClangModule) {
593599
// PCH files don't have a signature field in the control block,
594600
// but LLVM detects skeleton CUs by looking for a non-zero DWO id.
595601
// We use the lower 64 bits for debug info.
@@ -599,10 +605,24 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
599605
: ~1ULL;
600606

601607
// Handle Clang modules.
602-
if (const clang::Module *ClangModule = Desc.getModuleOrNull()) {
608+
if (ClangModule) {
603609
llvm::DIModule *Parent = nullptr;
604-
if (ClangModule->Parent)
605-
Parent = getOrCreateModule(*ClangModule->Parent);
610+
if (ClangModule->Parent) {
611+
// The loading of additional modules by Sema may trigger an out-of-date
612+
// PCM rebuild in the Clang module dependencies of the additional
613+
// module. A PCM rebuild causes the ModuleManager to unload previously
614+
// loaded ASTFiles. For this reason we must use the cached ASTFile
615+
// information here instead of the potentially dangling pointer to the
616+
// ASTFile that is stored in the clang::Module object.
617+
//
618+
// Note: The implementation here assumes that all clang submodules
619+
// belong to the same PCM file.
620+
ASTSourceDescriptor ParentDescriptor(*ClangModule->Parent);
621+
Parent = getOrCreateModule({ParentDescriptor.getModuleName(),
622+
ParentDescriptor.getPath(),
623+
Desc.getASTFile(), Desc.getSignature()},
624+
ClangModule->Parent);
625+
}
606626
return getOrCreateModule(ClangModule, Parent, Desc.getModuleName(),
607627
Desc.getPath(), Signature, Desc.getASTFile());
608628
}
@@ -612,10 +632,18 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
612632
Desc.getASTFile());
613633
};
614634

635+
static Optional<ASTSourceDescriptor> getClangModule(const ModuleDecl &M) {
636+
for (auto *FU : M.getFiles())
637+
if (auto *CMU = dyn_cast_or_null<ClangModuleUnit>(FU))
638+
if (auto Desc = CMU->getASTSourceDescriptor())
639+
return Desc;
640+
return None;
641+
}
642+
615643
llvm::DIModule *getOrCreateModule(ModuleDecl::ImportedModule IM) {
616644
ModuleDecl *M = IM.second;
617-
if (auto *ClangModule = M->findUnderlyingClangModule())
618-
return getOrCreateModule(*ClangModule);
645+
if (Optional<ASTSourceDescriptor> ModuleDesc = getClangModule(*M))
646+
return getOrCreateModule(*ModuleDesc, ModuleDesc->getModuleOrNull());
619647

620648
StringRef Path = getFilenameFromDC(M);
621649
StringRef Name = M->getName().str();
@@ -1457,8 +1485,18 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
14571485
if (auto *ClangDecl = D->getClangDecl()) {
14581486
clang::ASTReader &Reader = *CI.getClangInstance().getModuleManager();
14591487
auto Idx = ClangDecl->getOwningModuleID();
1460-
if (auto Info = Reader.getSourceDescriptor(Idx))
1461-
Scope = getOrCreateModule(*Info);
1488+
auto SubModuleDesc = Reader.getSourceDescriptor(Idx);
1489+
auto TopLevelModuleDesc = getClangModule(*D->getModuleContext());
1490+
if (SubModuleDesc && TopLevelModuleDesc) {
1491+
// Describe the submodule, but substitute the cached ASTFile from
1492+
// the toplevel module. The ASTFile pointer in SubModule may be
1493+
// dangling and cant be trusted.
1494+
Scope = getOrCreateModule({SubModuleDesc->getModuleName(),
1495+
SubModuleDesc->getPath(),
1496+
TopLevelModuleDesc->getASTFile(),
1497+
TopLevelModuleDesc->getSignature()},
1498+
SubModuleDesc->getModuleOrNull());
1499+
}
14621500
}
14631501
Context = Context->getParent();
14641502
}

test/DebugInfo/test-foundation.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@ class MyObject : NSObject {
1818
// LOC-CHECK: ret
1919
@objc var MyArr = NSArray()
2020
// IMPORT-CHECK: filename: "test-foundation.swift"
21-
// IMPORT-CHECK-DAG: [[FOUNDATION:[0-9]+]] = !DIModule({{.*}} name: "Foundation",{{.*}} includePath:
21+
// IMPORT-CHECK-DAG: [[FOUNDATION:[0-9]+]] = !DIModule({{.*}} name: "Foundation",{{.*}} includePath: {{.*}}Foundation.framework
22+
// IMPORT-CHECK-DAG: [[OVERLAY:[0-9]+]] = !DIModule({{.*}} name: "Foundation",{{.*}} includePath: {{.*}}Foundation.swiftmodule
2223
// IMPORT-CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "NSArray", scope: ![[NSARRAY:[0-9]+]]
2324
// IMPORT-CHECK-DAG: ![[NSARRAY]] = !DIModule(scope: ![[FOUNDATION:[0-9]+]], name: "NSArray"
24-
// IMPORT-CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_module, {{.*}}entity: ![[FOUNDATION]]
25+
// We actually imported the Foundation SDK overlay and not the Clang module
26+
// directly.
27+
// IMPORT-CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_module, {{.*}}entity: ![[OVERLAY]]
2528

2629
// ALLOCCTOR-CHECK: ![[F:.*]] = !DIFile(filename: "<compiler-generated>",
2730
// ALLOCCTOR-CHECK: distinct !DISubprogram(name: "init",

0 commit comments

Comments
 (0)