Skip to content

Commit 4181f7a

Browse files
committed
[Macros] Track plugin dependencies
* Factor out ASTContext plugin loading to newly introduced 'PluginLoader' * Insert 'DependencyTracker' to 'PluginLoader' * Add dependencies right before loading the plugins rdar://104938481
1 parent f1b8d9d commit 4181f7a

File tree

13 files changed

+397
-160
lines changed

13 files changed

+397
-160
lines changed

include/swift/AST/ASTContext.h

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ namespace swift {
9595
class ModuleDependencyInfo;
9696
class PatternBindingDecl;
9797
class PatternBindingInitializer;
98-
class PluginRegistry;
98+
class PluginLoader;
9999
class SourceFile;
100100
class SourceLoc;
101101
class Type;
@@ -1488,6 +1488,12 @@ class ASTContext final {
14881488

14891489
Type getNamedSwiftType(ModuleDecl *module, StringRef name);
14901490

1491+
/// Set the plugin loader.
1492+
void setPluginLoader(std::unique_ptr<PluginLoader> loader);
1493+
1494+
/// Get the plugin loader.
1495+
PluginLoader &getPluginLoader();
1496+
14911497
/// Lookup a library plugin that can handle \p moduleName and return the path
14921498
/// to it.
14931499
/// The path is valid within the VFS, use `FS.getRealPath()` for the
@@ -1521,15 +1527,6 @@ class ASTContext final {
15211527
/// instance is simply returned.
15221528
LoadedExecutablePlugin *loadExecutablePlugin(StringRef path);
15231529

1524-
/// Get the plugin registry this ASTContext is using.
1525-
PluginRegistry *getPluginRegistry() const;
1526-
1527-
/// Set the plugin registory this ASTContext should use.
1528-
/// This should be called before any plugin is loaded.
1529-
void setPluginRegistry(PluginRegistry *newValue);
1530-
1531-
const llvm::StringSet<> &getLoadedPluginLibraryPaths() const;
1532-
15331530
/// Get the output backend. The output backend needs to be initialized via
15341531
/// constructor or `setOutputBackend`.
15351532
llvm::vfs::OutputBackend &getOutputBackend() const {
@@ -1554,8 +1551,6 @@ class ASTContext final {
15541551
Optional<StringRef> getBriefComment(const Decl *D);
15551552
void setBriefComment(const Decl *D, StringRef Comment);
15561553

1557-
void createModuleToExecutablePluginMap();
1558-
15591554
friend TypeBase;
15601555
friend ArchetypeType;
15611556
friend OpaqueTypeDecl;

include/swift/AST/PluginLoader.h

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//===--- PluginLoader.h -----------------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
#ifndef SWIFT_AST_PLUGIN_LOADER_H
13+
#define SWIFT_AST_PLUGIN_LOADER_H
14+
15+
#include "swift/AST/ModuleLoader.h"
16+
#include "swift/AST/PluginRegistry.h"
17+
#include "llvm/ADT/ArrayRef.h"
18+
#include "llvm/ADT/Optional.h"
19+
#include "llvm/ADT/StringMap.h"
20+
#include "llvm/ADT/StringRef.h"
21+
22+
namespace swift {
23+
24+
class ASTContext;
25+
26+
/// Compiler plugin loader tied to an ASTContext. This is responsible for:
27+
/// * Find plugins based on the module name
28+
/// * Load plugins resolving VFS paths
29+
/// * Track plugin dependencies
30+
class PluginLoader {
31+
/// Plugin registry. Lazily populated by get/setRegistry().
32+
/// NOTE: Do not reference this directly. Use getRegistry().
33+
PluginRegistry *Registry = nullptr;
34+
35+
/// `Registry` storage if this owns it.
36+
std::unique_ptr<PluginRegistry> OwnedRegistry = nullptr;
37+
38+
ASTContext &Ctx;
39+
DependencyTracker *DepTracker;
40+
41+
/// Map a module name to an executable plugin path that provides the module.
42+
llvm::DenseMap<swift::Identifier, llvm::StringRef> ExecutablePluginPaths;
43+
44+
void createModuleToExecutablePluginMap();
45+
46+
public:
47+
PluginLoader(ASTContext &Ctx, DependencyTracker *DepTracker)
48+
: Ctx(Ctx), DepTracker(DepTracker) {
49+
createModuleToExecutablePluginMap();
50+
}
51+
52+
void setRegistry(PluginRegistry *newValue);
53+
PluginRegistry *getRegistry();
54+
55+
/// Lookup a library plugin that can handle \p moduleName and return the path
56+
/// to it from `-plugin-path` or `-load-plugin-library`.
57+
/// The path returned can be loaded by 'loadLibraryPlugin' method.
58+
llvm::Optional<std::string>
59+
lookupLibraryPluginByModuleName(Identifier moduleName);
60+
61+
/// Lookup an executable plugin that is declared to handle \p moduleName
62+
/// module by '-load-plugin-executable'.
63+
/// The path returned can be loaded by 'loadExecutablePlugin' method.
64+
llvm::Optional<StringRef>
65+
lookupExecutablePluginByModuleName(Identifier moduleName);
66+
67+
/// Look for dynamic libraries in paths from `-external-plugin-path` and
68+
/// return a pair of `(library path, plugin server executable)` if found.
69+
/// These paths are valid within the VFS, use `FS.getRealPath()` for their
70+
/// underlying path.
71+
llvm::Optional<std::pair<std::string, std::string>>
72+
lookupExternalLibraryPluginByModuleName(Identifier moduleName);
73+
74+
/// Load the specified dylib plugin path resolving the path with the
75+
/// current VFS. If it fails to load the plugin, a diagnostic is emitted, and
76+
/// returns a nullptr.
77+
/// NOTE: This method is idempotent. If the plugin is already loaded, the same
78+
/// instance is simply returned.
79+
LoadedLibraryPlugin *loadLibraryPlugin(llvm::StringRef path);
80+
81+
/// Launch the specified executable plugin path resolving the path with the
82+
/// current VFS. If it fails to load the plugin, a diagnostic is emitted, and
83+
/// returns a nullptr.
84+
/// NOTE: This method is idempotent. If the plugin is already loaded, the same
85+
/// instance is simply returned.
86+
LoadedExecutablePlugin *loadExecutablePlugin(llvm::StringRef path);
87+
};
88+
89+
} // namespace swift
90+
91+
#endif // SWIFT_AST_PLUGIN_LOADER_H

include/swift/Frontend/Frontend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,7 @@ class CompilerInstance {
663663
void setUpLLVMArguments();
664664
void setUpDiagnosticOptions();
665665
bool setUpModuleLoaders();
666+
bool setUpPluginLoader();
666667
bool setUpInputs();
667668
bool setUpASTContextIfNeeded();
668669
void setupStatsReporter();

lib/AST/ASTContext.cpp

Lines changed: 24 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
#include "swift/AST/NameLookup.h"
4242
#include "swift/AST/PackConformance.h"
4343
#include "swift/AST/ParameterList.h"
44-
#include "swift/AST/PluginRegistry.h"
44+
#include "swift/AST/PluginLoader.h"
4545
#include "swift/AST/PrettyStackTrace.h"
4646
#include "swift/AST/PropertyWrappers.h"
4747
#include "swift/AST/ProtocolConformance.h"
@@ -67,7 +67,6 @@
6767
#include "llvm/ADT/Statistic.h"
6868
#include "llvm/ADT/StringMap.h"
6969
#include "llvm/ADT/StringSwitch.h"
70-
#include "llvm/Config/config.h"
7170
#include "llvm/IR/LLVMContext.h"
7271
#include "llvm/Support/Allocator.h"
7372
#include "llvm/Support/Compiler.h"
@@ -526,17 +525,8 @@ struct ASTContext::Implementation {
526525

527526
llvm::StringMap<OptionSet<SearchPathKind>> SearchPathsSet;
528527

529-
/// Plugin registry. Lazily populated by get/setPluginRegistry().
530-
/// NOTE: Do not reference this directly. Use ASTContext::getPluginRegistry().
531-
PluginRegistry *Plugins = nullptr;
532-
533-
/// `Plugins` storage if this ASTContext owns it.
534-
std::unique_ptr<PluginRegistry> OwnedPluginRegistry = nullptr;
535-
536-
/// Map a module name to an executable plugin path that provides the module.
537-
llvm::DenseMap<Identifier, StringRef> ExecutablePluginPaths;
538-
539-
llvm::StringSet<> LoadedPluginLibraryPaths;
528+
/// Plugin loader.
529+
std::unique_ptr<swift::PluginLoader> Plugins;
540530

541531
/// The permanent arena.
542532
Arena Permanent;
@@ -712,8 +702,6 @@ ASTContext::ASTContext(
712702
registerAccessRequestFunctions(evaluator);
713703
registerNameLookupRequestFunctions(evaluator);
714704

715-
createModuleToExecutablePluginMap();
716-
717705
// Provide a default OnDiskOutputBackend if user didn't supply one.
718706
if (!OutputBackend)
719707
OutputBackend = llvm::makeIntrusiveRefCnt<llvm::vfs::OnDiskOutputBackend>();
@@ -6280,34 +6268,33 @@ BuiltinTupleType *ASTContext::getBuiltinTupleType() {
62806268
return result;
62816269
}
62826270

6283-
void ASTContext::setPluginRegistry(PluginRegistry *newValue) {
6284-
assert(getImpl().Plugins == nullptr &&
6285-
"Too late to set a new plugin registry");
6286-
getImpl().Plugins = newValue;
6271+
void ASTContext::setPluginLoader(std::unique_ptr<PluginLoader> loader) {
6272+
getImpl().Plugins = std::move(loader);
62876273
}
62886274

6289-
PluginRegistry *ASTContext::getPluginRegistry() const {
6290-
PluginRegistry *&registry = getImpl().Plugins;
6275+
PluginLoader &ASTContext::getPluginLoader() { return *getImpl().Plugins; }
62916276

6292-
// Create a new one if it hasn't been set.
6293-
if (!registry) {
6294-
registry = new PluginRegistry();
6295-
getImpl().OwnedPluginRegistry.reset(registry);
6296-
}
6277+
Optional<std::string>
6278+
ASTContext::lookupLibraryPluginByModuleName(Identifier moduleName) {
6279+
return getImpl().Plugins->lookupLibraryPluginByModuleName(moduleName);
6280+
}
62976281

6298-
assert(registry != nullptr);
6299-
return registry;
6282+
Optional<StringRef>
6283+
ASTContext::lookupExecutablePluginByModuleName(Identifier moduleName) {
6284+
return getImpl().Plugins->lookupExecutablePluginByModuleName(moduleName);
63006285
}
63016286

6302-
void ASTContext::createModuleToExecutablePluginMap() {
6303-
for (auto &arg : SearchPathOpts.getCompilerPluginExecutablePaths()) {
6304-
// Create a moduleName -> pluginPath mapping.
6305-
assert(!arg.ExecutablePath.empty() && "empty plugin path");
6306-
auto pathStr = AllocateCopy(arg.ExecutablePath);
6307-
for (auto moduleName : arg.ModuleNames) {
6308-
getImpl().ExecutablePluginPaths[getIdentifier(moduleName)] = pathStr;
6309-
}
6310-
}
6287+
Optional<std::pair<std::string, std::string>>
6288+
ASTContext::lookupExternalLibraryPluginByModuleName(Identifier moduleName) {
6289+
return getImpl().Plugins->lookupExternalLibraryPluginByModuleName(moduleName);
6290+
}
6291+
6292+
LoadedLibraryPlugin *ASTContext::loadLibraryPlugin(StringRef path) {
6293+
return getImpl().Plugins->loadLibraryPlugin(path);
6294+
}
6295+
6296+
LoadedExecutablePlugin *ASTContext::loadExecutablePlugin(StringRef path) {
6297+
return getImpl().Plugins->loadExecutablePlugin(path);
63116298
}
63126299

63136300
Type ASTContext::getNamedSwiftType(ModuleDecl *module, StringRef name) {
@@ -6345,105 +6332,6 @@ Type ASTContext::getNamedSwiftType(ModuleDecl *module, StringRef name) {
63456332
return decl->getDeclaredInterfaceType();
63466333
}
63476334

6348-
Optional<std::string>
6349-
ASTContext::lookupLibraryPluginByModuleName(Identifier moduleName) {
6350-
auto fs = SourceMgr.getFileSystem();
6351-
6352-
// Look for 'lib${module name}(.dylib|.so)'.
6353-
SmallString<64> expectedBasename;
6354-
expectedBasename.append("lib");
6355-
expectedBasename.append(moduleName.str());
6356-
expectedBasename.append(LTDL_SHLIB_EXT);
6357-
6358-
// Try '-plugin-path'.
6359-
for (const auto &searchPath : SearchPathOpts.PluginSearchPaths) {
6360-
SmallString<128> fullPath(searchPath);
6361-
llvm::sys::path::append(fullPath, expectedBasename);
6362-
if (fs->exists(fullPath)) {
6363-
return std::string(fullPath);
6364-
}
6365-
}
6366-
6367-
// Try '-load-plugin-library'.
6368-
for (const auto &libPath : SearchPathOpts.getCompilerPluginLibraryPaths()) {
6369-
if (llvm::sys::path::filename(libPath) == expectedBasename) {
6370-
return libPath;
6371-
}
6372-
}
6373-
6374-
return None;
6375-
}
6376-
6377-
Optional<StringRef>
6378-
ASTContext::lookupExecutablePluginByModuleName(Identifier moduleName) {
6379-
auto &execPluginPaths = getImpl().ExecutablePluginPaths;
6380-
auto found = execPluginPaths.find(moduleName);
6381-
if (found == execPluginPaths.end())
6382-
return None;
6383-
return found->second;
6384-
}
6385-
6386-
Optional<std::pair<std::string, std::string>>
6387-
ASTContext::lookupExternalLibraryPluginByModuleName(Identifier moduleName) {
6388-
auto fs = this->SourceMgr.getFileSystem();
6389-
for (auto &pair : SearchPathOpts.ExternalPluginSearchPaths) {
6390-
SmallString<128> fullPath(pair.SearchPath);
6391-
llvm::sys::path::append(fullPath, "lib" + moduleName.str() + LTDL_SHLIB_EXT);
6392-
6393-
if (fs->exists(fullPath)) {
6394-
return {{std::string(fullPath), pair.ServerPath}};
6395-
}
6396-
}
6397-
return None;
6398-
}
6399-
6400-
LoadedExecutablePlugin *ASTContext::loadExecutablePlugin(StringRef path) {
6401-
SmallString<128> resolvedPath;
6402-
auto fs = this->SourceMgr.getFileSystem();
6403-
if (auto err = fs->getRealPath(path, resolvedPath)) {
6404-
Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded, path,
6405-
err.message());
6406-
return nullptr;
6407-
}
6408-
6409-
// Load the plugin.
6410-
auto plugin = getPluginRegistry()->loadExecutablePlugin(resolvedPath);
6411-
if (!plugin) {
6412-
Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded, path,
6413-
llvm::toString(plugin.takeError()));
6414-
return nullptr;
6415-
}
6416-
6417-
return plugin.get();
6418-
}
6419-
6420-
LoadedLibraryPlugin *ASTContext::loadLibraryPlugin(StringRef path) {
6421-
// Remember the path (even if it fails to load.)
6422-
getImpl().LoadedPluginLibraryPaths.insert(path);
6423-
6424-
SmallString<128> resolvedPath;
6425-
auto fs = this->SourceMgr.getFileSystem();
6426-
if (auto err = fs->getRealPath(path, resolvedPath)) {
6427-
Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded, path,
6428-
err.message());
6429-
return nullptr;
6430-
}
6431-
6432-
// Load the plugin.
6433-
auto plugin = getPluginRegistry()->loadLibraryPlugin(resolvedPath);
6434-
if (!plugin) {
6435-
Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded, path,
6436-
llvm::toString(plugin.takeError()));
6437-
return nullptr;
6438-
}
6439-
6440-
return plugin.get();
6441-
}
6442-
6443-
const llvm::StringSet<> &ASTContext::getLoadedPluginLibraryPaths() const {
6444-
return getImpl().LoadedPluginLibraryPaths;
6445-
}
6446-
64476335
bool ASTContext::supportsMoveOnlyTypes() const {
64486336
// currently the only thing holding back whether the types can appear is this.
64496337
return SILOpts.LexicalLifetimes != LexicalLifetimesOption::Off;

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ add_swift_host_library(swiftAST STATIC
7272
Parameter.cpp
7373
Pattern.cpp
7474
PlatformKind.cpp
75+
PluginLoader.cpp
7576
PluginRegistry.cpp
7677
PrettyStackTrace.cpp
7778
ProtocolConformance.cpp

0 commit comments

Comments
 (0)