Skip to content

Commit 4705183

Browse files
committed
[Macros] Add plugin search paths to load plugin modules by name.
Introduce `-plugin-path <path>` to add a search path where we will look for compiler plugins. When resolving an external macro definition, look for libraries in these search paths whose names match the module name of the macro. Implements rdar://105095761.
1 parent c085f5a commit 4705183

File tree

8 files changed

+107
-9
lines changed

8 files changed

+107
-9
lines changed

include/swift/AST/SearchPathOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,10 @@ class SearchPathOptions {
339339
/// preference.
340340
std::vector<std::string> RuntimeLibraryPaths;
341341

342+
/// Paths that contain compiler plugins loaded on demand for, e.g.,
343+
/// macro implementations.
344+
std::vector<std::string> PluginSearchPaths;
345+
342346
/// Don't look in for compiler-provided modules.
343347
bool SkipRuntimeLibraryImportPaths = false;
344348

include/swift/AST/TypeCheckRequests.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4048,6 +4048,30 @@ class ExpandSynthesizedMemberMacroRequest
40484048
bool isCached() const { return true; }
40494049
};
40504050

4051+
/// Load a plugin module with the given name.
4052+
///
4053+
///
4054+
class CompilerPluginLoadRequest
4055+
: public SimpleRequest<CompilerPluginLoadRequest,
4056+
void *(ASTContext *, Identifier),
4057+
RequestFlags::Cached> {
4058+
public:
4059+
using SimpleRequest::SimpleRequest;
4060+
4061+
private:
4062+
friend SimpleRequest;
4063+
4064+
void *evaluate(
4065+
Evaluator &evaluator, ASTContext *ctx, Identifier moduleName
4066+
) const;
4067+
4068+
public:
4069+
// Source location
4070+
SourceLoc getNearestLoc() const { return SourceLoc(); }
4071+
4072+
bool isCached() const { return true; }
4073+
};
4074+
40514075
/// Resolve an external macro given its module and type name.
40524076
class ExternalMacroDefinitionRequest
40534077
: public SimpleRequest<ExternalMacroDefinitionRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,9 @@ SWIFT_REQUEST(TypeChecker, GetTypeWrapperInitializer,
455455
SWIFT_REQUEST(TypeChecker, MacroDefinitionRequest,
456456
MacroDefinition(MacroDecl *),
457457
Cached, NoLocationInfo)
458+
SWIFT_REQUEST(TypeChecker, CompilerPluginLoadRequest,
459+
void *(ASTContext *, Identifier),
460+
Cached, NoLocationInfo)
458461
SWIFT_REQUEST(TypeChecker, ExternalMacroDefinitionRequest,
459462
ExternalMacroDefinition(ASTContext *, Identifier, Identifier),
460463
Cached, NoLocationInfo)

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ def I : JoinedOrSeparate<["-"], "I">,
271271
def I_EQ : Joined<["-"], "I=">, Flags<[FrontendOption, ArgumentIsPath]>,
272272
Alias<I>;
273273

274+
def plugin_path : Separate<["-"], "plugin-path">,
275+
Flags<[FrontendOption, ArgumentIsPath, SwiftAPIExtractOption, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
276+
HelpText<"Add directory to the plugin search path">;
277+
274278
def import_underlying_module : Flag<["-"], "import-underlying-module">,
275279
Flags<[FrontendOption, NoInteractiveOption]>,
276280
HelpText<"Implicitly imports the Objective-C half of a module">;

lib/Driver/ToolChains.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
218218
inputArgs.AddAllArgs(arguments, options::OPT_I);
219219
inputArgs.AddAllArgs(arguments, options::OPT_F, options::OPT_Fsystem);
220220
inputArgs.AddAllArgs(arguments, options::OPT_vfsoverlay);
221+
inputArgs.AddAllArgs(arguments, options::OPT_plugin_path);
221222

222223
inputArgs.AddLastArg(arguments, options::OPT_AssertConfig);
223224
inputArgs.AddLastArg(arguments, options::OPT_autolink_force_load);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,10 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts,
14131413
}
14141414
Opts.setFrameworkSearchPaths(FrameworkSearchPaths);
14151415

1416+
for (const Arg *A : Args.filtered(OPT_plugin_path)) {
1417+
Opts.PluginSearchPaths.push_back(resolveSearchPath(A->getValue()));
1418+
}
1419+
14161420
for (const Arg *A : Args.filtered(OPT_L)) {
14171421
Opts.LibrarySearchPaths.push_back(resolveSearchPath(A->getValue()));
14181422
}

lib/Sema/TypeCheckMacros.cpp

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@
3232
#include "swift/Demangling/ManglingMacros.h"
3333
#include "swift/Parse/Lexer.h"
3434
#include "swift/Subsystems.h"
35+
#include "llvm/Config/config.h"
36+
37+
#if defined(_WIN32)
38+
#define WIN32_LEAN_AND_MEAN
39+
#define NOMINMAX
40+
#include <windows.h>
41+
#else
42+
#include <dlfcn.h>
43+
#endif
3544

3645
using namespace swift;
3746

@@ -100,7 +109,9 @@ static std::string mangledNameForTypeMetadataAccessor(
100109
#if SWIFT_SWIFT_PARSER
101110
/// Look for macro's type metadata given its external module and type name.
102111
static void const *lookupMacroTypeMetadataByExternalName(
103-
ASTContext &ctx, StringRef moduleName, StringRef typeName) {
112+
ASTContext &ctx, StringRef moduleName, StringRef typeName,
113+
void *libraryHint = nullptr
114+
) {
104115
// Look up the type metadata accessor as a struct, enum, or class.
105116
const Demangle::Node::Kind typeKinds[] = {
106117
Demangle::Node::Kind::Structure,
@@ -111,8 +122,8 @@ static void const *lookupMacroTypeMetadataByExternalName(
111122
void *accessorAddr = nullptr;
112123
for (auto typeKind : typeKinds) {
113124
auto symbolName = mangledNameForTypeMetadataAccessor(
114-
moduleName, typeName, typeKind);
115-
accessorAddr = ctx.getAddressOfSymbol(symbolName.c_str());
125+
moduleName, typeName, typeKind);
126+
accessorAddr = ctx.getAddressOfSymbol(symbolName.c_str(), libraryHint);
116127
if (accessorAddr)
117128
break;
118129
}
@@ -289,20 +300,43 @@ MacroDefinition MacroDefinitionRequest::evaluate(
289300
return MacroDefinition::forExternal(*moduleName, *typeName);
290301
}
291302

292-
ExternalMacroDefinition
293-
ExternalMacroDefinitionRequest::evaluate(
294-
Evaluator &evaluator, ASTContext *ctx,
295-
Identifier moduleName, Identifier typeName
303+
/// Load a plugin library based on a module name.
304+
static void *loadPluginByName(StringRef searchPath, StringRef moduleName) {
305+
SmallString<128> fullPath(searchPath);
306+
llvm::sys::path::append(fullPath, "lib" + moduleName + LTDL_SHLIB_EXT);
307+
#if defined(_WIN32)
308+
return LoadLibraryA(fullPath.c_str());
309+
#else
310+
return dlopen(fullPath.c_str(), RTLD_LAZY);
311+
#endif
312+
}
313+
314+
void *CompilerPluginLoadRequest::evaluate(
315+
Evaluator &evaluator, ASTContext *ctx, Identifier moduleName
296316
) const {
317+
auto &searchPathOpts = ctx->SearchPathOpts;
318+
for (const auto &path : searchPathOpts.PluginSearchPaths) {
319+
if (auto found = loadPluginByName(path, moduleName.str()))
320+
return found;
321+
}
322+
323+
return nullptr;
324+
}
325+
326+
static Optional<ExternalMacroDefinition>
327+
resolveInProcessMacro(
328+
ASTContext &ctx, Identifier moduleName, Identifier typeName,
329+
void *libraryHint = nullptr
330+
) {
297331
#if SWIFT_SWIFT_PARSER
298332
/// Look for the type metadata given the external module and type names.
299333
auto macroMetatype = lookupMacroTypeMetadataByExternalName(
300-
*ctx, moduleName.str(), typeName.str());
334+
ctx, moduleName.str(), typeName.str(), libraryHint);
301335
if (macroMetatype) {
302336
// Check whether the macro metatype is in-process.
303337
if (auto inProcess = swift_ASTGen_resolveMacroType(macroMetatype)) {
304338
// Make sure we clean up after the macro.
305-
ctx->addCleanup([inProcess]() {
339+
ctx.addCleanup([inProcess]() {
306340
swift_ASTGen_destroyMacro(inProcess);
307341
});
308342

@@ -311,6 +345,28 @@ ExternalMacroDefinitionRequest::evaluate(
311345
}
312346
#endif
313347

348+
return None;
349+
}
350+
351+
ExternalMacroDefinition
352+
ExternalMacroDefinitionRequest::evaluate(
353+
Evaluator &evaluator, ASTContext *ctx,
354+
Identifier moduleName, Identifier typeName
355+
) const {
356+
// Try to load a plugin module from the plugin search paths. If it
357+
// succeeds, resolve in-process from that plugin
358+
CompilerPluginLoadRequest loadRequest{ctx, moduleName};
359+
if (auto loadedLibrary = evaluateOrDefault(
360+
evaluator, loadRequest, nullptr)) {
361+
if (auto inProcess = resolveInProcessMacro(
362+
*ctx, moduleName, typeName, loadedLibrary))
363+
return *inProcess;
364+
}
365+
366+
// Try to resolve in-process.
367+
if (auto inProcess = resolveInProcessMacro(*ctx, moduleName, typeName))
368+
return *inProcess;
369+
314370
return ExternalMacroDefinition{nullptr};
315371
}
316372

test/Macros/macro_expand.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
// Diagnostics testing
66
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -module-name MacroUser -DTEST_DIAGNOSTICS
77

8+
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature Macros -plugin-path %t -I %swift-host-lib-dir -module-name MacroUser -DTEST_DIAGNOSTICS
9+
810
// RUN: not %target-swift-frontend -swift-version 5 -typecheck -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -module-name MacroUser -DTEST_DIAGNOSTICS -serialize-diagnostics-path %t/macro_expand.dia %s -emit-macro-expansion-files no-diagnostics > %t/macro-printing.txt
911
// RUN: c-index-test -read-diagnostics %t/macro_expand.dia 2>&1 | %FileCheck -check-prefix CHECK-DIAGS %s
1012

0 commit comments

Comments
 (0)