Skip to content

Commit 082e0c5

Browse files
committed
[Macros] Move 'loadExecutablePlugin' logic to 'CompilerPluginLoadRequest'
Separate "load plugin" and "resolve macro" phases. So that the loaded executable plugin is now cached in ASTContext and reused. This saves a 'loadPluginLibrary' IPC messaging when the library provides multiple macros.
1 parent 92e5ad6 commit 082e0c5

File tree

3 files changed

+120
-68
lines changed

3 files changed

+120
-68
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct ExternalMacroDefinition;
4949
class ClosureExpr;
5050
class GenericParamList;
5151
class LabeledStmt;
52+
class LoadedExecutablePlugin;
5253
class MacroDefinition;
5354
class PrecedenceGroupDecl;
5455
class PropertyWrapperInitializerInfo;
@@ -4000,19 +4001,51 @@ class ExpandSynthesizedMemberMacroRequest
40004001
/// Load a plugin module with the given name.
40014002
///
40024003
///
4004+
class LoadedCompilerPlugin {
4005+
enum class PluginKind : uint8_t {
4006+
None,
4007+
InProcess,
4008+
Executable,
4009+
};
4010+
PluginKind kind;
4011+
void *ptr;
4012+
4013+
LoadedCompilerPlugin(PluginKind kind, void *ptr) : kind(kind), ptr(ptr) {
4014+
assert(ptr != nullptr || kind == PluginKind::None);
4015+
}
4016+
4017+
public:
4018+
LoadedCompilerPlugin(std::nullptr_t) : kind(PluginKind::None), ptr(nullptr) {}
4019+
4020+
static LoadedCompilerPlugin inProcess(void *ptr) {
4021+
return {PluginKind::InProcess, ptr};
4022+
}
4023+
static LoadedCompilerPlugin executable(LoadedExecutablePlugin *ptr) {
4024+
return {PluginKind::Executable, ptr};
4025+
}
4026+
4027+
void *getAsInProcessPlugin() const {
4028+
return kind == PluginKind::InProcess ? static_cast<void *>(ptr) : nullptr;
4029+
}
4030+
LoadedExecutablePlugin *getAsExecutablePlugin() const {
4031+
return kind == PluginKind::Executable
4032+
? static_cast<LoadedExecutablePlugin *>(ptr)
4033+
: nullptr;
4034+
}
4035+
};
4036+
40034037
class CompilerPluginLoadRequest
4004-
: public SimpleRequest<CompilerPluginLoadRequest,
4005-
void *(ASTContext *, Identifier),
4006-
RequestFlags::Cached> {
4038+
: public SimpleRequest<CompilerPluginLoadRequest,
4039+
LoadedCompilerPlugin(ASTContext *, Identifier),
4040+
RequestFlags::Cached> {
40074041
public:
40084042
using SimpleRequest::SimpleRequest;
40094043

40104044
private:
40114045
friend SimpleRequest;
40124046

4013-
void *evaluate(
4014-
Evaluator &evaluator, ASTContext *ctx, Identifier moduleName
4015-
) const;
4047+
LoadedCompilerPlugin evaluate(Evaluator &evaluator, ASTContext *ctx,
4048+
Identifier moduleName) const;
40164049

40174050
public:
40184051
// Source location

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ SWIFT_REQUEST(TypeChecker, MacroDefinitionRequest,
431431
MacroDefinition(MacroDecl *),
432432
Cached, NoLocationInfo)
433433
SWIFT_REQUEST(TypeChecker, CompilerPluginLoadRequest,
434-
void *(ASTContext *, Identifier),
434+
LoadedCompilerPlugin(ASTContext *, Identifier),
435435
Cached, NoLocationInfo)
436436
SWIFT_REQUEST(TypeChecker, ExternalMacroDefinitionRequest,
437437
Optional<ExternalMacroDefinition>(ASTContext *, Identifier, Identifier),

lib/Sema/TypeCheckMacros.cpp

Lines changed: 80 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,9 @@ MacroDefinition MacroDefinitionRequest::evaluate(
286286
}
287287

288288
/// Load a plugin library based on a module name.
289-
static void *loadPluginByName(StringRef searchPath,
290-
StringRef moduleName,
291-
llvm::vfs::FileSystem &fs,
292-
PluginRegistry *registry) {
289+
static void *loadLibraryPluginByName(StringRef searchPath, StringRef moduleName,
290+
llvm::vfs::FileSystem &fs,
291+
PluginRegistry *registry) {
293292
SmallString<128> fullPath(searchPath);
294293
llvm::sys::path::append(fullPath, "lib" + moduleName + LTDL_SHLIB_EXT);
295294
if (fs.getRealPath(fullPath, fullPath))
@@ -298,53 +297,12 @@ static void *loadPluginByName(StringRef searchPath,
298297
return loadResult ? *loadResult : nullptr;
299298
}
300299

301-
void *CompilerPluginLoadRequest::evaluate(
302-
Evaluator &evaluator, ASTContext *ctx, Identifier moduleName
303-
) const {
304-
auto fs = ctx->SourceMgr.getFileSystem();
305-
auto &searchPathOpts = ctx->SearchPathOpts;
306-
auto *registry = ctx->getPluginRegistry();
307-
for (const auto &path : searchPathOpts.PluginSearchPaths) {
308-
if (auto found = loadPluginByName(path, moduleName.str(), *fs, registry))
309-
return found;
310-
}
311-
312-
return nullptr;
313-
}
314-
315-
static Optional<ExternalMacroDefinition>
316-
resolveInProcessMacro(
317-
ASTContext &ctx, Identifier moduleName, Identifier typeName,
318-
void *libraryHint = nullptr
319-
) {
320-
#if SWIFT_SWIFT_PARSER
321-
/// Look for the type metadata given the external module and type names.
322-
auto macroMetatype = lookupMacroTypeMetadataByExternalName(
323-
ctx, moduleName.str(), typeName.str(), libraryHint);
324-
if (macroMetatype) {
325-
// Check whether the macro metatype is in-process.
326-
if (auto inProcess = swift_ASTGen_resolveMacroType(macroMetatype)) {
327-
// Make sure we clean up after the macro.
328-
ctx.addCleanup([inProcess]() {
329-
swift_ASTGen_destroyMacro(inProcess);
330-
});
331-
332-
return ExternalMacroDefinition{
333-
ExternalMacroDefinition::PluginKind::InProcess, inProcess};
334-
}
335-
}
336-
#endif
337-
return None;
338-
}
339-
340-
static Optional<ExternalMacroDefinition>
341-
resolveExecutableMacro(ASTContext &ctx, Identifier moduleName,
342-
Identifier typeName) {
343-
#if SWIFT_SWIFT_PARSER
344-
std::string executablePluginPath;
300+
static LoadedExecutablePlugin *
301+
loadExecutablePluginByName(ASTContext &ctx, Identifier moduleName) {
302+
// Find an executable plugin.
345303
std::string libraryPath;
304+
std::string executablePluginPath;
346305

347-
// Find macros in executable plugins.
348306
if (auto found = ctx.lookupExternalLibraryPluginByModuleName(moduleName)) {
349307
// Found in '-external-plugin-path'.
350308
std::tie(libraryPath, executablePluginPath) = found.value();
@@ -353,38 +311,97 @@ resolveExecutableMacro(ASTContext &ctx, Identifier moduleName,
353311
executablePluginPath = found->str();
354312
}
355313
if (executablePluginPath.empty())
356-
return None;
314+
return nullptr;
357315

358316
// Launch the plugin.
359317
LoadedExecutablePlugin *executablePlugin =
360318
ctx.loadExecutablePlugin(executablePluginPath);
361319
if (!executablePlugin)
362-
return None;
320+
return nullptr;
363321

364322
// FIXME: Ideally this should be done right after invoking the plugin.
365323
// But plugin loading is in libAST and it can't link ASTGen symbols.
366324
if (!executablePlugin->isInitialized()) {
325+
#if SWIFT_SWIFT_PARSER
367326
swift_ASTGen_initializePlugin(executablePlugin);
368327
executablePlugin->setCleanup([executablePlugin] {
369328
swift_ASTGen_deinitializePlugin(executablePlugin);
370329
});
330+
#endif
371331
}
372332

373-
// If this is a plugin server. Load the library in that process before
374-
// resolving the macro.
333+
// If this is a plugin server, load the library.
375334
if (!libraryPath.empty()) {
335+
#if SWIFT_SWIFT_PARSER
376336
llvm::SmallString<128> resolvedLibraryPath;
377337
auto fs = ctx.SourceMgr.getFileSystem();
378338
if (fs->getRealPath(libraryPath, resolvedLibraryPath)) {
379-
return None;
339+
return nullptr;
380340
}
381341
bool loaded = swift_ASTGen_pluginServerLoadLibraryPlugin(
382342
executablePlugin, resolvedLibraryPath.c_str(), moduleName.str().data(),
383343
&ctx.Diags);
384344
if (!loaded)
385-
return None;
345+
return nullptr;
346+
#endif
347+
}
348+
349+
return executablePlugin;
350+
}
351+
352+
LoadedCompilerPlugin
353+
CompilerPluginLoadRequest::evaluate(Evaluator &evaluator, ASTContext *ctx,
354+
Identifier moduleName) const {
355+
auto fs = ctx->SourceMgr.getFileSystem();
356+
auto &searchPathOpts = ctx->SearchPathOpts;
357+
auto *registry = ctx->getPluginRegistry();
358+
359+
// First, check '-plugin-path' paths.
360+
for (const auto &path : searchPathOpts.PluginSearchPaths) {
361+
if (auto found =
362+
loadLibraryPluginByName(path, moduleName.str(), *fs, registry))
363+
return LoadedCompilerPlugin::inProcess(found);
364+
}
365+
366+
// Fall back to executable plugins.
367+
// i.e. '-external-plugin-path', and '-load-plugin-executable'.
368+
if (auto *found = loadExecutablePluginByName(*ctx, moduleName)) {
369+
return LoadedCompilerPlugin::executable(found);
386370
}
387371

372+
return nullptr;
373+
}
374+
375+
static Optional<ExternalMacroDefinition>
376+
resolveInProcessMacro(
377+
ASTContext &ctx, Identifier moduleName, Identifier typeName,
378+
void *libraryHint = nullptr
379+
) {
380+
#if SWIFT_SWIFT_PARSER
381+
/// Look for the type metadata given the external module and type names.
382+
auto macroMetatype = lookupMacroTypeMetadataByExternalName(
383+
ctx, moduleName.str(), typeName.str(), libraryHint);
384+
if (macroMetatype) {
385+
// Check whether the macro metatype is in-process.
386+
if (auto inProcess = swift_ASTGen_resolveMacroType(macroMetatype)) {
387+
// Make sure we clean up after the macro.
388+
ctx.addCleanup([inProcess]() {
389+
swift_ASTGen_destroyMacro(inProcess);
390+
});
391+
392+
return ExternalMacroDefinition{
393+
ExternalMacroDefinition::PluginKind::InProcess, inProcess};
394+
}
395+
}
396+
#endif
397+
return None;
398+
}
399+
400+
static Optional<ExternalMacroDefinition>
401+
resolveExecutableMacro(ASTContext &ctx,
402+
LoadedExecutablePlugin *executablePlugin,
403+
Identifier moduleName, Identifier typeName) {
404+
#if SWIFT_SWIFT_PARSER
388405
if (auto *execMacro = swift_ASTGen_resolveExecutableMacro(
389406
moduleName.str().data(), moduleName.str().size(),
390407
typeName.str().data(), typeName.str().size(), executablePlugin)) {
@@ -395,7 +412,6 @@ resolveExecutableMacro(ASTContext &ctx, Identifier moduleName,
395412
ExternalMacroDefinition::PluginKind::Executable, execMacro};
396413
}
397414
#endif
398-
399415
return None;
400416
}
401417

@@ -406,8 +422,9 @@ ExternalMacroDefinitionRequest::evaluate(Evaluator &evaluator, ASTContext *ctx,
406422
// Try to load a plugin module from the plugin search paths. If it
407423
// succeeds, resolve in-process from that plugin
408424
CompilerPluginLoadRequest loadRequest{ctx, moduleName};
409-
if (auto loadedLibrary = evaluateOrDefault(
410-
evaluator, loadRequest, nullptr)) {
425+
LoadedCompilerPlugin loaded =
426+
evaluateOrDefault(evaluator, loadRequest, nullptr);
427+
if (auto loadedLibrary = loaded.getAsInProcessPlugin()) {
411428
if (auto inProcess = resolveInProcessMacro(
412429
*ctx, moduleName, typeName, loadedLibrary))
413430
return *inProcess;
@@ -418,9 +435,11 @@ ExternalMacroDefinitionRequest::evaluate(Evaluator &evaluator, ASTContext *ctx,
418435
return *inProcess;
419436

420437
// Try executable plugins.
421-
if (auto executableMacro =
422-
resolveExecutableMacro(*ctx, moduleName, typeName)) {
423-
return executableMacro;
438+
if (auto *executablePlugin = loaded.getAsExecutablePlugin()) {
439+
if (auto executableMacro = resolveExecutableMacro(*ctx, executablePlugin,
440+
moduleName, typeName)) {
441+
return executableMacro;
442+
}
424443
}
425444

426445
return None;

0 commit comments

Comments
 (0)