Skip to content

Commit 587d531

Browse files
committed
[Macros] Load '-load-plugin-library' plugins lazily
Load '-load-plugin-library' libraries lazily until resolving macros.
1 parent 2a7f985 commit 587d531

File tree

8 files changed

+101
-77
lines changed

8 files changed

+101
-77
lines changed

include/swift/AST/ASTContext.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,10 +1461,6 @@ class ASTContext final {
14611461
/// The declared interface type of Builtin.TheTupleType.
14621462
BuiltinTupleType *getBuiltinTupleType();
14631463

1464-
/// Finds the address of the given symbol. If `libraryHandleHint` is non-null,
1465-
/// search within the library.
1466-
void *getAddressOfSymbol(const char *name, void *libraryHandleHint = nullptr);
1467-
14681464
Type getNamedSwiftType(ModuleDecl *module, StringRef name);
14691465

14701466
/// Lookup an executable plugin that is declared to handle \p moduleName
@@ -1506,7 +1502,7 @@ class ASTContext final {
15061502
Optional<StringRef> getBriefComment(const Decl *D);
15071503
void setBriefComment(const Decl *D, StringRef Comment);
15081504

1509-
void loadCompilerPlugins();
1505+
void createModuleToExecutablePluginMap();
15101506

15111507
friend TypeBase;
15121508
friend ArchetypeType;

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ ERROR(error_invalid_source_location_str,none,
128128
ERROR(error_no_source_location_scope_map,none,
129129
"-dump-scope-maps argument must be 'expanded' or a list of "
130130
"source locations", ())
131+
ERROR(error_load_plugin_executable,none,
132+
"invalid value '%0' in '-load-plugin-executable'; "
133+
"make sure to use format '<plugin path>#<module names>'", (StringRef))
131134

132135
NOTE(note_valid_swift_versions, none,
133136
"valid arguments to '-swift-version' are %0", (StringRef))

include/swift/AST/SearchPathOptions.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,13 @@ class ModuleSearchPathLookup {
174174
llvm::vfs::FileSystem *FS, bool IsOSDarwin);
175175
};
176176

177+
/// Pair of a plugin search and the corresponding plugin server executable
178+
/// path.
179+
struct PluginExecutablePathAndModuleNames {
180+
std::string ExecutablePath;
181+
std::vector<std::string> ModuleNames;
182+
};
183+
177184
/// Pair of a plugin search path and the corresponding plugin server executable
178185
/// path.
179186
struct ExternalPluginSearchPathAndServerPath {
@@ -242,8 +249,7 @@ class SearchPathOptions {
242249
std::vector<std::string> CompilerPluginLibraryPaths;
243250

244251
/// Compiler plugin executable paths and providing module names.
245-
/// Format: '<path>#<module names>'
246-
std::vector<std::string> CompilerPluginExecutablePaths;
252+
std::vector<PluginExecutablePathAndModuleNames> CompilerPluginExecutablePaths;
247253

248254
/// Add a single import search path. Must only be called from
249255
/// \c ASTContext::addSearchPath.
@@ -361,12 +367,13 @@ class SearchPathOptions {
361367
}
362368

363369
void setCompilerPluginExecutablePaths(
364-
std::vector<std::string> NewCompilerPluginExecutablePaths) {
365-
CompilerPluginExecutablePaths = NewCompilerPluginExecutablePaths;
370+
std::vector<PluginExecutablePathAndModuleNames> &&newValue) {
371+
CompilerPluginExecutablePaths = std::move(newValue);
366372
Lookup.searchPathsDidChange();
367373
}
368374

369-
ArrayRef<std::string> getCompilerPluginExecutablePaths() const {
375+
ArrayRef<PluginExecutablePathAndModuleNames>
376+
getCompilerPluginExecutablePaths() const {
370377
return CompilerPluginExecutablePaths;
371378
}
372379

include/swift/AST/TypeCheckRequests.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4054,6 +4054,27 @@ class CompilerPluginLoadRequest
40544054
bool isCached() const { return true; }
40554055
};
40564056

4057+
/// Load a plugin library specified by '-load-plugin-library'.
4058+
class LoadPluginLibraryRequest
4059+
: public SimpleRequest<LoadPluginLibraryRequest,
4060+
LoadedCompilerPlugin(ASTContext *, std::string path),
4061+
RequestFlags::Cached> {
4062+
public:
4063+
using SimpleRequest::SimpleRequest;
4064+
4065+
private:
4066+
friend SimpleRequest;
4067+
4068+
LoadedCompilerPlugin evaluate(Evaluator &evaluator, ASTContext *ctx,
4069+
std::string path) const;
4070+
4071+
public:
4072+
// Source location
4073+
SourceLoc getNearestLoc() const { return SourceLoc(); }
4074+
4075+
bool isCached() const { return true; }
4076+
};
4077+
40574078
/// Expand peer macros attached to the given declaration.
40584079
class ExpandPeerMacroRequest
40594080
: public SimpleRequest<ExpandPeerMacroRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,9 @@ SWIFT_REQUEST(TypeChecker, MacroDefinitionRequest,
433433
SWIFT_REQUEST(TypeChecker, CompilerPluginLoadRequest,
434434
LoadedCompilerPlugin(ASTContext *, Identifier),
435435
Cached, NoLocationInfo)
436+
SWIFT_REQUEST(TypeChecker, LoadPluginLibraryRequest,
437+
LoadedCompilerPlugin(ASTContext *, std::string),
438+
Cached, NoLocationInfo)
436439
SWIFT_REQUEST(TypeChecker, ExternalMacroDefinitionRequest,
437440
Optional<ExternalMacroDefinition>(ASTContext *, Identifier, Identifier),
438441
Cached, NoLocationInfo)

lib/AST/ASTContext.cpp

Lines changed: 5 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -531,9 +531,6 @@ struct ASTContext::Implementation {
531531
/// `Plugins` storage if this ASTContext owns it.
532532
std::unique_ptr<PluginRegistry> OwnedPluginRegistry = nullptr;
533533

534-
/// Cache of loaded symbols.
535-
llvm::StringMap<void *> LoadedSymbols;
536-
537534
/// Map a module name to an executable plugin path that provides the module.
538535
llvm::DenseMap<Identifier, StringRef> ExecutablePluginPaths;
539536

@@ -707,8 +704,7 @@ ASTContext::ASTContext(
707704
registerAccessRequestFunctions(evaluator);
708705
registerNameLookupRequestFunctions(evaluator);
709706

710-
// FIXME: Delay this so the client e.g. SourceKit can inject plugin registry.
711-
loadCompilerPlugins();
707+
createModuleToExecutablePluginMap();
712708
}
713709

714710
ASTContext::~ASTContext() {
@@ -6264,66 +6260,17 @@ PluginRegistry *ASTContext::getPluginRegistry() const {
62646260
return registry;
62656261
}
62666262

6267-
void ASTContext::loadCompilerPlugins() {
6268-
auto fs = this->SourceMgr.getFileSystem();
6269-
for (auto &path : SearchPathOpts.getCompilerPluginLibraryPaths()) {
6270-
SmallString<128> resolvedPath;
6271-
if (auto err = fs->getRealPath(path, resolvedPath)) {
6272-
Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded, path,
6273-
err.message());
6274-
continue;
6275-
}
6276-
auto loaded = getPluginRegistry()->loadLibraryPlugin(resolvedPath);
6277-
if (!loaded) {
6278-
Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded, path,
6279-
llvm::toString(loaded.takeError()));
6280-
}
6281-
}
6282-
6263+
void ASTContext::createModuleToExecutablePluginMap() {
62836264
for (auto &arg : SearchPathOpts.getCompilerPluginExecutablePaths()) {
6284-
// 'arg' is '<path to executable>#<module names>' where the module names are
6285-
// comma separated.
6286-
62876265
// Create a moduleName -> pluginPath mapping.
6288-
StringRef path;
6289-
StringRef modulesStr;
6290-
std::tie(path, modulesStr) = StringRef(arg).rsplit('#');
6291-
SmallVector<StringRef, 1> modules;
6292-
modulesStr.split(modules, ',');
6293-
6294-
if (modules.empty() || path.empty()) {
6295-
// TODO: Error messsage.
6296-
Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded, arg, "");
6297-
}
6298-
auto pathStr = AllocateCopy(path);
6299-
for (auto moduleName : modules) {
6266+
assert(!arg.ExecutablePath.empty() && "empty plugin path");
6267+
auto pathStr = AllocateCopy(arg.ExecutablePath);
6268+
for (auto moduleName : arg.ModuleNames) {
63006269
getImpl().ExecutablePluginPaths[getIdentifier(moduleName)] = pathStr;
63016270
}
63026271
}
63036272
}
63046273

6305-
void *ASTContext::getAddressOfSymbol(const char *name,
6306-
void *libraryHandleHint) {
6307-
auto lookup = getImpl().LoadedSymbols.try_emplace(name, nullptr);
6308-
void *&address = lookup.first->getValue();
6309-
#if !defined(_WIN32)
6310-
if (lookup.second) {
6311-
auto *handle = libraryHandleHint ? libraryHandleHint : RTLD_DEFAULT;
6312-
address = dlsym(handle, name);
6313-
6314-
// If we didn't know where to look, look specifically in each plugin.
6315-
if (!address && !libraryHandleHint) {
6316-
for (const auto &plugin : getPluginRegistry()->getLoadedLibraryPlugins()) {
6317-
address = dlsym(plugin.second, name);
6318-
if (address)
6319-
break;
6320-
}
6321-
}
6322-
}
6323-
#endif
6324-
return address;
6325-
}
6326-
63276274
Type ASTContext::getNamedSwiftType(ModuleDecl *module, StringRef name) {
63286275
if (!module)
63296276
return Type();

lib/Frontend/CompilerInvocation.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,14 +1564,28 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts,
15641564
}
15651565
Opts.setCompilerPluginLibraryPaths(CompilerPluginLibraryPaths);
15661566

1567-
std::vector<std::string> CompilerPluginExecutablePaths(
1567+
std::vector<PluginExecutablePathAndModuleNames> CompilerPluginExecutablePaths(
15681568
Opts.getCompilerPluginExecutablePaths());
15691569
for (const Arg *A : Args.filtered(OPT_load_plugin_executable)) {
1570-
// NOTE: The value has '#<module names>' after the path.
1571-
// But resolveSearchPath() works as long as the value starts with a path.
1572-
CompilerPluginExecutablePaths.push_back(resolveSearchPath(A->getValue()));
1570+
// 'A' is '<path to executable>#<module names>' where the module names are
1571+
// comma separated.
1572+
StringRef path;
1573+
StringRef modulesStr;
1574+
std::tie(path, modulesStr) = StringRef(A->getValue()).rsplit('#');
1575+
std::vector<std::string> moduleNames;
1576+
for (auto name : llvm::split(modulesStr, ',')) {
1577+
moduleNames.emplace_back(name);
1578+
}
1579+
if (path.empty() || moduleNames.empty()) {
1580+
Diags.diagnose(SourceLoc(), diag::error_load_plugin_executable,
1581+
A->getValue());
1582+
} else {
1583+
CompilerPluginExecutablePaths.push_back(
1584+
{resolveSearchPath(path), std::move(moduleNames)});
1585+
}
15731586
}
1574-
Opts.setCompilerPluginExecutablePaths(CompilerPluginExecutablePaths);
1587+
Opts.setCompilerPluginExecutablePaths(
1588+
std::move(CompilerPluginExecutablePaths));
15751589

15761590
return false;
15771591
}

lib/Sema/TypeCheckMacros.cpp

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/ASTContext.h"
2121
#include "swift/AST/ASTMangler.h"
2222
#include "swift/AST/ASTNode.h"
23+
#include "swift/AST/DiagnosticsFrontend.h"
2324
#include "swift/AST/Expr.h"
2425
#include "swift/AST/MacroDefinition.h"
2526
#include "swift/AST/NameLookupRequests.h"
@@ -93,7 +94,9 @@ static void const *lookupMacroTypeMetadataByExternalName(
9394
for (auto typeKind : typeKinds) {
9495
auto symbolName = Demangle::mangledNameForTypeMetadataAccessor(
9596
moduleName, typeName, typeKind);
96-
accessorAddr = ctx.getAddressOfSymbol(symbolName.c_str(), libraryHint);
97+
#if !defined(_WIN32)
98+
accessorAddr = dlsym(libraryHint, symbolName.c_str());
99+
#endif
97100
if (accessorAddr)
98101
break;
99102
}
@@ -396,6 +399,26 @@ CompilerPluginLoadRequest::evaluate(Evaluator &evaluator, ASTContext *ctx,
396399
return nullptr;
397400
}
398401

402+
LoadedCompilerPlugin
403+
LoadPluginLibraryRequest::evaluate(Evaluator &evaluator, ASTContext *ctx,
404+
std::string path) const {
405+
auto fs = ctx->SourceMgr.getFileSystem();
406+
auto *registry = ctx->getPluginRegistry();
407+
auto &diags = ctx->Diags;
408+
409+
SmallString<128> resolvedPath;
410+
if (fs->getRealPath(path, resolvedPath))
411+
return nullptr;
412+
auto loaded = registry->loadLibraryPlugin(resolvedPath);
413+
if (!loaded) {
414+
diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded, path,
415+
llvm::toString(loaded.takeError()));
416+
return nullptr;
417+
}
418+
419+
return LoadedCompilerPlugin::inProcess(loaded.get());
420+
}
421+
399422
static Optional<ExternalMacroDefinition>
400423
resolveInProcessMacro(
401424
ASTContext &ctx, Identifier moduleName, Identifier typeName,
@@ -448,15 +471,25 @@ ExternalMacroDefinitionRequest::evaluate(Evaluator &evaluator, ASTContext *ctx,
448471
CompilerPluginLoadRequest loadRequest{ctx, moduleName};
449472
LoadedCompilerPlugin loaded =
450473
evaluateOrDefault(evaluator, loadRequest, nullptr);
474+
475+
// Loaded in '-plugin-path'?
451476
if (auto loadedLibrary = loaded.getAsInProcessPlugin()) {
452477
if (auto inProcess = resolveInProcessMacro(
453478
*ctx, moduleName, typeName, loadedLibrary))
454479
return *inProcess;
455480
}
456481

457-
// Try to resolve in-process.
458-
if (auto inProcess = resolveInProcessMacro(*ctx, moduleName, typeName))
459-
return *inProcess;
482+
// Try to resolve in '-load-plugin-library' plugins.
483+
for (auto &path : ctx->SearchPathOpts.getCompilerPluginLibraryPaths()) {
484+
LoadPluginLibraryRequest loadRequest{ctx, path};
485+
LoadedCompilerPlugin loaded =
486+
evaluateOrDefault(evaluator, loadRequest, nullptr);
487+
if (auto loadedLibrary = loaded.getAsInProcessPlugin()) {
488+
if (auto inProcess =
489+
resolveInProcessMacro(*ctx, moduleName, typeName, loadedLibrary))
490+
return *inProcess;
491+
}
492+
}
460493

461494
// Try executable plugins.
462495
if (auto *executablePlugin = loaded.getAsExecutablePlugin()) {

0 commit comments

Comments
 (0)