From a3a43d46c5cf430803c292b02f87ad30088fb1e5 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 5 May 2023 15:51:08 -0700 Subject: [PATCH] [Serialization] Teach ASTSectionImporter to filter by triple. On macOS it is possible for one application to contain Swift modules compiled for different triples that are incompatible as far as the Swift compiler is concerned. Examples include an iOS simulator application hunning on a macOS host, or a macCatalyst application running on macOS. A debugger might see .swift_ast sections for all triples at the same time. This patch adds an interface to let the client provide a triple to filter Swift modules in an ASTSection. rdar://107869141 --- .../swift/ASTSectionImporter/ASTSectionImporter.h | 6 +++++- include/swift/Serialization/Validation.h | 9 +++++++++ lib/ASTSectionImporter/ASTSectionImporter.cpp | 12 ++++++++++-- lib/Serialization/ModuleFile.cpp | 13 +++++++++++-- test/DebugInfo/ASTSection.swift | 1 + .../lldb-moduleimport-test.cpp | 7 ++++++- 6 files changed, 42 insertions(+), 6 deletions(-) diff --git a/include/swift/ASTSectionImporter/ASTSectionImporter.h b/include/swift/ASTSectionImporter/ASTSectionImporter.h index 94c7cbabf8ca6..aebeb301b5233 100644 --- a/include/swift/ASTSectionImporter/ASTSectionImporter.h +++ b/include/swift/ASTSectionImporter/ASTSectionImporter.h @@ -20,6 +20,9 @@ #include "swift/Basic/LLVM.h" #include +namespace llvm { +class Triple; +} namespace swift { class MemoryBufferSerializedModuleLoader; @@ -28,9 +31,10 @@ namespace swift { /// registers them using registerMemoryBuffer() so they can be found by /// loadModule(). The access path of all modules found in the section is /// appended to the vector foundModules. + /// \param filter If fully specified, only matching modules are registered. /// \return true if successful. bool parseASTSection(MemoryBufferSerializedModuleLoader &Loader, - StringRef Data, + StringRef Data, const llvm::Triple &filter, SmallVectorImpl &foundModules); } #endif diff --git a/include/swift/Serialization/Validation.h b/include/swift/Serialization/Validation.h index 83373234bd2e7..b2404b8516579 100644 --- a/include/swift/Serialization/Validation.h +++ b/include/swift/Serialization/Validation.h @@ -19,6 +19,10 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +namespace llvm { +class Triple; +} + namespace swift { class ModuleFile; @@ -302,6 +306,11 @@ void diagnoseSerializedASTLoadFailureTransitive( ASTContext &Ctx, SourceLoc diagLoc, const serialization::Status status, ModuleFile *loadedModuleFile, Identifier ModuleName, bool forTestable); +/// Determine whether two triples are considered to be compatible for module +/// serialization purposes. +bool areCompatible(const llvm::Triple &moduleTarget, + const llvm::Triple &ctxTarget); + } // end namespace serialization } // end namespace swift diff --git a/lib/ASTSectionImporter/ASTSectionImporter.cpp b/lib/ASTSectionImporter/ASTSectionImporter.cpp index 71f1f4fc87ebf..ddb55c4a66691 100644 --- a/lib/ASTSectionImporter/ASTSectionImporter.cpp +++ b/lib/ASTSectionImporter/ASTSectionImporter.cpp @@ -28,10 +28,13 @@ using namespace swift; bool swift::parseASTSection(MemoryBufferSerializedModuleLoader &Loader, StringRef buf, + const llvm::Triple &filter, SmallVectorImpl &foundModules) { if (!serialization::isSerializedAST(buf)) return false; + bool haveFilter = filter.getOS() != llvm::Triple::UnknownOS && + filter.getArch() != llvm::Triple::UnknownArch; // An AST section consists of one or more AST modules, optionally with // headers. Iterate over all AST modules. while (!buf.empty()) { @@ -43,10 +46,15 @@ bool swift::parseASTSection(MemoryBufferSerializedModuleLoader &Loader, if (info.status == serialization::Status::Valid) { assert(info.bytes != 0); - if (!info.name.empty()) { + bool selected = true; + if (haveFilter) { + llvm::Triple moduleTriple(info.targetTriple); + selected = serialization::areCompatible(moduleTriple, filter); + } + if (!info.name.empty() && selected) { StringRef moduleData = buf.substr(0, info.bytes); std::unique_ptr bitstream( - llvm::MemoryBuffer::getMemBuffer(moduleData, info.name, false)); + llvm::MemoryBuffer::getMemBuffer(moduleData, info.name, false)); // Register the memory buffer. Loader.registerMemoryBuffer(info.name, std::move(bitstream), diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index 6a83a40f4752c..132d1901ecd85 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -91,6 +91,16 @@ static bool isTargetTooNew(const llvm::Triple &moduleTarget, return ctxTarget.isOSVersionLT(moduleTarget); } +namespace swift { +namespace serialization { +bool areCompatible(const llvm::Triple &moduleTarget, + const llvm::Triple &ctxTarget) { + return areCompatibleArchitectures(moduleTarget, ctxTarget) && + areCompatibleOSs(moduleTarget, ctxTarget); +} +} // namespace serialization +} // namespace swift + ModuleFile::ModuleFile(std::shared_ptr core) : Core(core) { assert(!core->hasError()); @@ -249,8 +259,7 @@ Status ModuleFile::associateWithFileContext(FileUnit *file, SourceLoc diagLoc, ASTContext &ctx = getContext(); llvm::Triple moduleTarget(llvm::Triple::normalize(Core->TargetTriple)); - if (!areCompatibleArchitectures(moduleTarget, ctx.LangOpts.Target) || - !areCompatibleOSs(moduleTarget, ctx.LangOpts.Target)) { + if (!areCompatible(moduleTarget, ctx.LangOpts.Target)) { status = Status::TargetIncompatible; if (!recoverFromIncompatibility) return error(status); diff --git a/test/DebugInfo/ASTSection.swift b/test/DebugInfo/ASTSection.swift index 008597b4cfb85..b55b5faedd31a 100644 --- a/test/DebugInfo/ASTSection.swift +++ b/test/DebugInfo/ASTSection.swift @@ -2,6 +2,7 @@ // RUN: %target-build-swift -emit-executable %s -g -o %t/ASTSection -emit-module // RUN: %lldb-moduleimport-test -verbose %t/ASTSection | %FileCheck %s +// RUN: %lldb-moduleimport-test -filter mips64-unknown-hurd -verbose %t/ASTSection | %FileCheck %s --check-prefix=LINETABLE-CHECK // REQUIRES: executable_test // REQUIRES: swift_tools_extra diff --git a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp index d7649134818d6..6d9314b3ecd3a 100644 --- a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp +++ b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp @@ -239,6 +239,9 @@ int main(int argc, char **argv) { opt Verbose("verbose", desc("Dump informations on the loaded module"), cat(Visible)); + opt Filter("filter", desc("triple for filtering modules"), + cat(Visible)); + opt ModuleCachePath( "module-cache-path", desc("Clang module cache path"), cat(Visible)); @@ -351,9 +354,11 @@ int main(int argc, char **argv) { ClangImporter->setDWARFImporterDelegate(dummyDWARFImporter); } + llvm::Triple filter(Filter); for (auto &Module : Modules) if (!parseASTSection(*CI.getMemoryBufferSerializedModuleLoader(), - StringRef(Module.first, Module.second), modules)) { + StringRef(Module.first, Module.second), filter, + modules)) { llvm::errs() << "error: Failed to parse AST section!\n"; return 1; }