Skip to content

Commit fad0f90

Browse files
authored
Merge pull request swiftlang#63558 from DougGregor/plugin-search-paths
2 parents eb69afc + 4705183 commit fad0f90

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
@@ -3860,6 +3860,30 @@ class ExpandSynthesizedMemberMacroRequest
38603860
bool isCached() const { return true; }
38613861
};
38623862

3863+
/// Load a plugin module with the given name.
3864+
///
3865+
///
3866+
class CompilerPluginLoadRequest
3867+
: public SimpleRequest<CompilerPluginLoadRequest,
3868+
void *(ASTContext *, Identifier),
3869+
RequestFlags::Cached> {
3870+
public:
3871+
using SimpleRequest::SimpleRequest;
3872+
3873+
private:
3874+
friend SimpleRequest;
3875+
3876+
void *evaluate(
3877+
Evaluator &evaluator, ASTContext *ctx, Identifier moduleName
3878+
) const;
3879+
3880+
public:
3881+
// Source location
3882+
SourceLoc getNearestLoc() const { return SourceLoc(); }
3883+
3884+
bool isCached() const { return true; }
3885+
};
3886+
38633887
/// Resolve an external macro given its module and type name.
38643888
class ExternalMacroDefinitionRequest
38653889
: public SimpleRequest<ExternalMacroDefinitionRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,9 @@ SWIFT_REQUEST(TypeChecker, IsSingleValueStmtRequest,
422422
SWIFT_REQUEST(TypeChecker, MacroDefinitionRequest,
423423
MacroDefinition(MacroDecl *),
424424
Cached, NoLocationInfo)
425+
SWIFT_REQUEST(TypeChecker, CompilerPluginLoadRequest,
426+
void *(ASTContext *, Identifier),
427+
Cached, NoLocationInfo)
425428
SWIFT_REQUEST(TypeChecker, ExternalMacroDefinitionRequest,
426429
ExternalMacroDefinition(ASTContext *, Identifier, Identifier),
427430
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)