|
28 | 28 | #include "swift/Basic/SourceManager.h"
|
29 | 29 | #include "swift/Basic/Version.h"
|
30 | 30 | #include "swift/ClangImporter/ClangImporter.h"
|
| 31 | +#include "swift/ClangImporter/ClangModule.h" |
31 | 32 | #include "swift/Demangling/ManglingMacros.h"
|
| 33 | +#include "swift/Serialization/SerializedModuleLoader.h" |
32 | 34 | #include "swift/SIL/SILArgument.h"
|
33 | 35 | #include "swift/SIL/SILBasicBlock.h"
|
34 | 36 | #include "swift/SIL/SILDebugScope.h"
|
@@ -566,35 +568,63 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
|
566 | 568 | return cast<llvm::DIModule>(Val->second);
|
567 | 569 |
|
568 | 570 | StringRef Sysroot = IGM.Context.SearchPathOpts.SDKPath;
|
569 |
| - auto M = DBuilder.createModule( |
570 |
| - Parent, Name, ConfigMacros, DebugPrefixMap.remapPath(IncludePath), |
571 |
| - Sysroot); |
| 571 | + llvm::DIModule *M = |
| 572 | + DBuilder.createModule(Parent, Name, ConfigMacros, IncludePath, Sysroot); |
572 | 573 | DIModuleCache.insert({Key, llvm::TrackingMDNodeRef(M)});
|
573 | 574 | return M;
|
574 | 575 | }
|
575 | 576 |
|
576 |
| - llvm::DIModule * |
577 |
| - getOrCreateModule(clang::ExternalASTSource::ASTSourceDescriptor Desc) { |
| 577 | + using ASTSourceDescriptor = clang::ExternalASTSource::ASTSourceDescriptor; |
| 578 | + /// Create a DIModule from a clang module or PCH. |
| 579 | + /// The clang::Module pointer is passed separately because the recursive case |
| 580 | + /// needs to fudge the AST descriptor. |
| 581 | + llvm::DIModule *getOrCreateModule(ASTSourceDescriptor Desc, |
| 582 | + const clang::Module *ClangModule) { |
578 | 583 | // Handle Clang modules.
|
579 |
| - if (const clang::Module *ClangModule = Desc.getModuleOrNull()) { |
| 584 | + if (ClangModule) { |
580 | 585 | llvm::DIModule *Parent = nullptr;
|
581 |
| - if (ClangModule->Parent) |
582 |
| - Parent = getOrCreateModule(*ClangModule->Parent); |
583 |
| - |
584 |
| - return getOrCreateModule(ClangModule, Parent, |
585 |
| - Desc.getModuleName(), Desc.getPath(), |
586 |
| - ConfigMacros); |
| 586 | + if (ClangModule->Parent) { |
| 587 | + // The loading of additional modules by Sema may trigger an out-of-date |
| 588 | + // PCM rebuild in the Clang module dependencies of the additional |
| 589 | + // module. A PCM rebuild causes the ModuleManager to unload previously |
| 590 | + // loaded ASTFiles. For this reason we must use the cached ASTFile |
| 591 | + // information here instead of the potentially dangling pointer to the |
| 592 | + // ASTFile that is stored in the clang::Module object. |
| 593 | + // |
| 594 | + // Note: The implementation here assumes that all clang submodules |
| 595 | + // belong to the same PCM file. |
| 596 | + ASTSourceDescriptor ParentDescriptor(*ClangModule->Parent); |
| 597 | + Parent = getOrCreateModule({ParentDescriptor.getModuleName(), |
| 598 | + ParentDescriptor.getPath(), |
| 599 | + Desc.getASTFile(), Desc.getSignature()}, |
| 600 | + ClangModule->Parent); |
| 601 | + } |
| 602 | + return getOrCreateModule(ClangModule, Parent, Desc.getModuleName(), |
| 603 | + Desc.getPath(), ConfigMacros); |
587 | 604 | }
|
588 | 605 | // Handle PCH.
|
589 | 606 | return getOrCreateModule(Desc.getASTFile().bytes_begin(), nullptr,
|
590 | 607 | Desc.getModuleName(), Desc.getPath(),
|
591 | 608 | ConfigMacros);
|
592 | 609 | };
|
593 | 610 |
|
| 611 | + static Optional<ASTSourceDescriptor> getClangModule(const ModuleDecl &M) { |
| 612 | + for (auto *FU : M.getFiles()) { |
| 613 | + if (auto *SAF = dyn_cast_or_null<SerializedASTFile>(FU)) { |
| 614 | + if (auto *ShadowedModule = SAF->getShadowedModule()) |
| 615 | + if (auto Desc = getClangModule(*ShadowedModule)) |
| 616 | + return Desc; |
| 617 | + } else if (auto *CMU = dyn_cast_or_null<ClangModuleUnit>(FU)) |
| 618 | + if (auto Desc = CMU->getASTSourceDescriptor()) |
| 619 | + return Desc; |
| 620 | + } |
| 621 | + return {}; |
| 622 | + } |
| 623 | + |
594 | 624 | llvm::DIModule *getOrCreateModule(ModuleDecl::ImportedModule IM) {
|
595 | 625 | ModuleDecl *M = IM.second;
|
596 |
| - if (auto *ClangModule = M->findUnderlyingClangModule()) |
597 |
| - return getOrCreateModule(*ClangModule); |
| 626 | + if (Optional<ASTSourceDescriptor> ModuleDesc = getClangModule(*M)) |
| 627 | + return getOrCreateModule(*ModuleDesc, ModuleDesc->getModuleOrNull()); |
598 | 628 |
|
599 | 629 | StringRef Path = getFilenameFromDC(M);
|
600 | 630 | StringRef Name = M->getName().str();
|
@@ -1431,8 +1461,18 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
|
1431 | 1461 | if (auto *ClangDecl = D->getClangDecl()) {
|
1432 | 1462 | clang::ASTReader &Reader = *CI.getClangInstance().getModuleManager();
|
1433 | 1463 | auto Idx = ClangDecl->getOwningModuleID();
|
1434 |
| - if (auto Info = Reader.getSourceDescriptor(Idx)) |
1435 |
| - Scope = getOrCreateModule(*Info); |
| 1464 | + auto SubModuleDesc = Reader.getSourceDescriptor(Idx); |
| 1465 | + auto TopLevelModuleDesc = getClangModule(*D->getModuleContext()); |
| 1466 | + if (SubModuleDesc && TopLevelModuleDesc) { |
| 1467 | + // Describe the submodule, but substitute the cached ASTFile from |
| 1468 | + // the toplevel module. The ASTFile pointer in SubModule may be |
| 1469 | + // dangling and cant be trusted. |
| 1470 | + Scope = getOrCreateModule({SubModuleDesc->getModuleName(), |
| 1471 | + SubModuleDesc->getPath(), |
| 1472 | + TopLevelModuleDesc->getASTFile(), |
| 1473 | + TopLevelModuleDesc->getSignature()}, |
| 1474 | + SubModuleDesc->getModuleOrNull()); |
| 1475 | + } |
1436 | 1476 | }
|
1437 | 1477 | Context = Context->getParent();
|
1438 | 1478 | }
|
|
0 commit comments