Skip to content

Commit 0a1d14a

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 (cherry picked from commit a551c01)
1 parent f256b28 commit 0a1d14a

File tree

13 files changed

+420
-160
lines changed

13 files changed

+420
-160
lines changed

include/swift/AST/ASTContext.h

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ namespace swift {
9393
class ModuleDependencyInfo;
9494
class PatternBindingDecl;
9595
class PatternBindingInitializer;
96-
class PluginRegistry;
96+
class PluginLoader;
9797
class SourceFile;
9898
class SourceLoc;
9999
class Type;
@@ -1477,6 +1477,12 @@ class ASTContext final {
14771477

14781478
Type getNamedSwiftType(ModuleDecl *module, StringRef name);
14791479

1480+
/// Set the plugin loader.
1481+
void setPluginLoader(std::unique_ptr<PluginLoader> loader);
1482+
1483+
/// Get the plugin loader.
1484+
PluginLoader &getPluginLoader();
1485+
14801486
/// Lookup a library plugin that can handle \p moduleName and return the path
14811487
/// to it.
14821488
/// The path is valid within the VFS, use `FS.getRealPath()` for the
@@ -1510,15 +1516,6 @@ class ASTContext final {
15101516
/// instance is simply returned.
15111517
LoadedExecutablePlugin *loadExecutablePlugin(StringRef path);
15121518

1513-
/// Get the plugin registry this ASTContext is using.
1514-
PluginRegistry *getPluginRegistry() const;
1515-
1516-
/// Set the plugin registory this ASTContext should use.
1517-
/// This should be called before any plugin is loaded.
1518-
void setPluginRegistry(PluginRegistry *newValue);
1519-
1520-
const llvm::StringSet<> &getLoadedPluginLibraryPaths() const;
1521-
15221519
private:
15231520
friend Decl;
15241521

@@ -1531,8 +1528,6 @@ class ASTContext final {
15311528
Optional<StringRef> getBriefComment(const Decl *D);
15321529
void setBriefComment(const Decl *D, StringRef Comment);
15331530

1534-
void createModuleToExecutablePluginMap();
1535-
15361531
friend TypeBase;
15371532
friend ArchetypeType;
15381533
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
@@ -625,6 +625,7 @@ class CompilerInstance {
625625
void setUpLLVMArguments();
626626
void setUpDiagnosticOptions();
627627
bool setUpModuleLoaders();
628+
bool setUpPluginLoader();
628629
bool setUpInputs();
629630
bool setUpASTContextIfNeeded();
630631
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"
@@ -524,17 +523,8 @@ struct ASTContext::Implementation {
524523

525524
llvm::StringMap<OptionSet<SearchPathKind>> SearchPathsSet;
526525

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

539529
/// The permanent arena.
540530
Arena Permanent;
@@ -705,8 +695,6 @@ ASTContext::ASTContext(
705695
// Register any request-evaluator functions available at the AST layer.
706696
registerAccessRequestFunctions(evaluator);
707697
registerNameLookupRequestFunctions(evaluator);
708-
709-
createModuleToExecutablePluginMap();
710698
}
711699

712700
ASTContext::~ASTContext() {
@@ -6266,34 +6254,33 @@ BuiltinTupleType *ASTContext::getBuiltinTupleType() {
62666254
return result;
62676255
}
62686256

6269-
void ASTContext::setPluginRegistry(PluginRegistry *newValue) {
6270-
assert(getImpl().Plugins == nullptr &&
6271-
"Too late to set a new plugin registry");
6272-
getImpl().Plugins = newValue;
6257+
void ASTContext::setPluginLoader(std::unique_ptr<PluginLoader> loader) {
6258+
getImpl().Plugins = std::move(loader);
62736259
}
62746260

6275-
PluginRegistry *ASTContext::getPluginRegistry() const {
6276-
PluginRegistry *&registry = getImpl().Plugins;
6261+
PluginLoader &ASTContext::getPluginLoader() { return *getImpl().Plugins; }
62776262

6278-
// Create a new one if it hasn't been set.
6279-
if (!registry) {
6280-
registry = new PluginRegistry();
6281-
getImpl().OwnedPluginRegistry.reset(registry);
6282-
}
6263+
Optional<std::string>
6264+
ASTContext::lookupLibraryPluginByModuleName(Identifier moduleName) {
6265+
return getImpl().Plugins->lookupLibraryPluginByModuleName(moduleName);
6266+
}
62836267

6284-
assert(registry != nullptr);
6285-
return registry;
6268+
Optional<StringRef>
6269+
ASTContext::lookupExecutablePluginByModuleName(Identifier moduleName) {
6270+
return getImpl().Plugins->lookupExecutablePluginByModuleName(moduleName);
62866271
}
62876272

6288-
void ASTContext::createModuleToExecutablePluginMap() {
6289-
for (auto &arg : SearchPathOpts.getCompilerPluginExecutablePaths()) {
6290-
// Create a moduleName -> pluginPath mapping.
6291-
assert(!arg.ExecutablePath.empty() && "empty plugin path");
6292-
auto pathStr = AllocateCopy(arg.ExecutablePath);
6293-
for (auto moduleName : arg.ModuleNames) {
6294-
getImpl().ExecutablePluginPaths[getIdentifier(moduleName)] = pathStr;
6295-
}
6296-
}
6273+
Optional<std::pair<std::string, std::string>>
6274+
ASTContext::lookupExternalLibraryPluginByModuleName(Identifier moduleName) {
6275+
return getImpl().Plugins->lookupExternalLibraryPluginByModuleName(moduleName);
6276+
}
6277+
6278+
LoadedLibraryPlugin *ASTContext::loadLibraryPlugin(StringRef path) {
6279+
return getImpl().Plugins->loadLibraryPlugin(path);
6280+
}
6281+
6282+
LoadedExecutablePlugin *ASTContext::loadExecutablePlugin(StringRef path) {
6283+
return getImpl().Plugins->loadExecutablePlugin(path);
62976284
}
62986285

62996286
Type ASTContext::getNamedSwiftType(ModuleDecl *module, StringRef name) {
@@ -6331,105 +6318,6 @@ Type ASTContext::getNamedSwiftType(ModuleDecl *module, StringRef name) {
63316318
return decl->getDeclaredInterfaceType();
63326319
}
63336320

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