[Macros] Support user-defined macros as compiler plugins (#61734)

Allow user-defined macros to be loaded from dynamic libraries and evaluated.

- Introduce a _CompilerPluginSupport module installed into the toolchain. Its `_CompilerPlugin` protocol acts as a stable interface between the compiler and user-defined macros.
- Introduce a `-load-plugin-library <path>` attribute which allows users to specify dynamic libraries to be loaded into the compiler.

A macro library must declare a public top-level computed property `public var allMacros: [Any.Type]` and be compiled to a dynamic library. The compiler will call the getter of this property to obtain and register all macros.

Known issues:
- We current do not have a way to strip out unnecessary symbols from the plugin dylib, i.e. produce a plugin library that does not contain SwiftSyntax symbols that will collide with the compiler itself.
- `MacroExpansionExpr`'s type is hard-coded as `(Int, String)`. It should instead be specified by the macro via protocol requirements such as `signature` and `genericSignature`. We need more protocol requirements in `_CompilerPlugin` to handle this.
- `dlopen` is not secure and is only for prototyping use here.

Friend PR: apple/swift-syntax#1022
This commit is contained in:
Richard Wei
2022-10-31 14:03:25 -07:00
committed by GitHub
parent 0fff782e09
commit 4ce1ebb120
31 changed files with 855 additions and 23 deletions

View File

@@ -203,7 +203,8 @@ void SerializedModuleLoaderBase::collectVisibleTopLevelModuleNamesImpl(
});
return None;
}
case ModuleSearchPathKind::RuntimeLibrary: {
case ModuleSearchPathKind::RuntimeLibrary:
case ModuleSearchPathKind::CompilerPlugin: {
// Look for:
// (Darwin OS) $PATH/{name}.swiftmodule/{arch}.{extension}
// (Other OS) $PATH/{name}.{extension}
@@ -613,7 +614,8 @@ SerializedModuleLoaderBase::findModule(ImportPath::Element moduleID,
switch (searchPath->getKind()) {
case ModuleSearchPathKind::Import:
case ModuleSearchPathKind::RuntimeLibrary: {
case ModuleSearchPathKind::RuntimeLibrary:
case ModuleSearchPathKind::CompilerPlugin: {
isFramework = false;
// On Apple platforms, we can assume that the runtime libraries use