Skip to content

Commit 5eb769e

Browse files
authored
Merge pull request #65421 from rintaro/5.9-plugin-loader-swiftdeps
[5.9][Macros] Track plugin dependencies
2 parents 3f2737c + 0a1d14a commit 5eb769e

File tree

17 files changed

+491
-233
lines changed

17 files changed

+491
-233
lines changed

include/swift/AST/ASTContext.h

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ namespace swift {
8080
class ExtensionDecl;
8181
struct ExternalSourceLocs;
8282
class LoadedExecutablePlugin;
83+
class LoadedLibraryPlugin;
8384
class ForeignRepresentationInfo;
8485
class FuncDecl;
8586
class GenericContext;
@@ -92,7 +93,7 @@ namespace swift {
9293
class ModuleDependencyInfo;
9394
class PatternBindingDecl;
9495
class PatternBindingInitializer;
95-
class PluginRegistry;
96+
class PluginLoader;
9697
class SourceFile;
9798
class SourceLoc;
9899
class Type;
@@ -1476,6 +1477,12 @@ class ASTContext final {
14761477

14771478
Type getNamedSwiftType(ModuleDecl *module, StringRef name);
14781479

1480+
/// Set the plugin loader.
1481+
void setPluginLoader(std::unique_ptr<PluginLoader> loader);
1482+
1483+
/// Get the plugin loader.
1484+
PluginLoader &getPluginLoader();
1485+
14791486
/// Lookup a library plugin that can handle \p moduleName and return the path
14801487
/// to it.
14811488
/// The path is valid within the VFS, use `FS.getRealPath()` for the
@@ -1487,7 +1494,7 @@ class ASTContext final {
14871494
/// returns a nullptr.
14881495
/// NOTE: This method is idempotent. If the plugin is already loaded, the same
14891496
/// instance is simply returned.
1490-
void *loadLibraryPlugin(StringRef path);
1497+
LoadedLibraryPlugin *loadLibraryPlugin(StringRef path);
14911498

14921499
/// Lookup an executable plugin that is declared to handle \p moduleName
14931500
/// module by '-load-plugin-executable'.
@@ -1509,15 +1516,6 @@ class ASTContext final {
15091516
/// instance is simply returned.
15101517
LoadedExecutablePlugin *loadExecutablePlugin(StringRef path);
15111518

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

@@ -1530,8 +1528,6 @@ class ASTContext final {
15301528
Optional<StringRef> getBriefComment(const Decl *D);
15311529
void setBriefComment(const Decl *D, StringRef Comment);
15321530

1533-
void createModuleToExecutablePluginMap();
1534-
15351531
friend TypeBase;
15361532
friend ArchetypeType;
15371533
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/AST/PluginRegistry.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
1010
//
1111
//===----------------------------------------------------------------------===//
12+
#ifndef SWIFT_PLUGIN_REGISTRY_H
13+
#define SWIFT_PLUGIN_REGISTRY_H
1214

1315
#include "llvm/ADT/ArrayRef.h"
1416
#include "llvm/ADT/StringMap.h"
@@ -22,6 +24,21 @@
2224

2325
namespace swift {
2426

27+
/// Represent a 'dlopen'ed plugin library.
28+
class LoadedLibraryPlugin {
29+
// Opaque handle used to interface with OS-specific dynamic library.
30+
void *handle;
31+
32+
/// Cache of loaded symbols.
33+
llvm::StringMap<void *> resolvedSymbols;
34+
35+
public:
36+
LoadedLibraryPlugin(void *handle) : handle(handle) {}
37+
38+
/// Finds the address of the given symbol within the library.
39+
void *getAddressOfSymbol(const char *symbolName);
40+
};
41+
2542
/// Represent a "resolved" exectuable plugin.
2643
///
2744
/// Plugin clients usually deal with this object to communicate with the actual
@@ -130,7 +147,7 @@ class LoadedExecutablePlugin {
130147

131148
class PluginRegistry {
132149
/// Record of loaded plugin library modules.
133-
llvm::StringMap<void *> LoadedPluginLibraries;
150+
llvm::StringMap<std::unique_ptr<LoadedLibraryPlugin>> LoadedPluginLibraries;
134151

135152
/// Record of loaded plugin executables.
136153
llvm::StringMap<std::unique_ptr<LoadedExecutablePlugin>>
@@ -146,7 +163,7 @@ class PluginRegistry {
146163

147164
/// Load a dynamic link library specified by \p path.
148165
/// If \p path plugin is already loaded, this returns the cached object.
149-
llvm::Expected<void *> loadLibraryPlugin(llvm::StringRef path);
166+
llvm::Expected<LoadedLibraryPlugin *> loadLibraryPlugin(llvm::StringRef path);
150167

151168
/// Load an executable plugin specified by \p path .
152169
/// If \p path plugin is already loaded, this returns the cached object.
@@ -155,3 +172,5 @@ class PluginRegistry {
155172
};
156173

157174
} // namespace swift
175+
176+
#endif // SWIFT_PLUGIN_REGISTRY_H

include/swift/AST/TypeCheckRequests.h

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/AST/Type.h"
2727
#include "swift/AST/Evaluator.h"
2828
#include "swift/AST/Pattern.h"
29+
#include "swift/AST/PluginRegistry.h"
2930
#include "swift/AST/ProtocolConformance.h"
3031
#include "swift/AST/SimpleRequest.h"
3132
#include "swift/AST/SourceFile.h"
@@ -49,7 +50,6 @@ struct ExternalMacroDefinition;
4950
class ClosureExpr;
5051
class GenericParamList;
5152
class LabeledStmt;
52-
class LoadedExecutablePlugin;
5353
class MacroDefinition;
5454
class PrecedenceGroupDecl;
5555
class PropertyWrapperInitializerInfo;
@@ -4017,39 +4017,20 @@ class ExpandSynthesizedMemberMacroRequest
40174017
void noteCycleStep(DiagnosticEngine &diags) const;
40184018
};
40194019

4020-
/// Load a plugin module with the given name.
4021-
///
4022-
///
4020+
/// Represent a loaded plugin either an in-process library or an executable.
40234021
class LoadedCompilerPlugin {
4024-
enum class PluginKind : uint8_t {
4025-
None,
4026-
InProcess,
4027-
Executable,
4028-
};
4029-
PluginKind kind;
4030-
void *ptr;
4031-
4032-
LoadedCompilerPlugin(PluginKind kind, void *ptr) : kind(kind), ptr(ptr) {
4033-
assert(ptr != nullptr || kind == PluginKind::None);
4034-
}
4022+
llvm::PointerUnion<LoadedLibraryPlugin *, LoadedExecutablePlugin *> ptr;
40354023

40364024
public:
4037-
LoadedCompilerPlugin(std::nullptr_t) : kind(PluginKind::None), ptr(nullptr) {}
4038-
4039-
static LoadedCompilerPlugin inProcess(void *ptr) {
4040-
return {PluginKind::InProcess, ptr};
4041-
}
4042-
static LoadedCompilerPlugin executable(LoadedExecutablePlugin *ptr) {
4043-
return {PluginKind::Executable, ptr};
4044-
}
4025+
LoadedCompilerPlugin(std::nullptr_t) : ptr(nullptr) {}
4026+
LoadedCompilerPlugin(LoadedLibraryPlugin *ptr) : ptr(ptr){};
4027+
LoadedCompilerPlugin(LoadedExecutablePlugin *ptr) : ptr(ptr){};
40454028

4046-
void *getAsInProcessPlugin() const {
4047-
return kind == PluginKind::InProcess ? ptr : nullptr;
4029+
LoadedLibraryPlugin *getAsLibraryPlugin() const {
4030+
return ptr.dyn_cast<LoadedLibraryPlugin *>();
40484031
}
40494032
LoadedExecutablePlugin *getAsExecutablePlugin() const {
4050-
return kind == PluginKind::Executable
4051-
? static_cast<LoadedExecutablePlugin *>(ptr)
4052-
: nullptr;
4033+
return ptr.dyn_cast<LoadedExecutablePlugin *>();
40534034
}
40544035
};
40554036

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();

0 commit comments

Comments
 (0)