Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Macros] In-process plugin server #73725

Merged
merged 2 commits into from
Jun 26, 2024
Merged

Conversation

rintaro
Copy link
Member

@rintaro rintaro commented May 17, 2024

Separate swift-syntax libs for the compiler and for the library plugins. Compiler communicates with library plugins using serialized messages just like executable plugins.

  • lib/swift/host/compiler/lib_Compiler*.dylib(source lib/CompilerSwiftSyntax): swift-syntax libraries for compiler. Library evolution is disabled.

  • Compiler (ASTGen and swiftIDEUtilsBridging) only depends on lib/swift/host/compiler libraries.

  • lib/swift/host/libSwiftInProcPluginServer.dylib (source tools/swift-plugin-server/Sources/SwiftInProcPluginServer): In-process plugin server shared library. This has one swift_inproc_plugins_handle_message entry point that receives a message and return the response.

  • In the compiler:

    • Add -in-process-plugin-server-path front-end option, which specifies the SwiftInProcPluginServer shared library path.
    • Remove LoadedLibraryPlugin, because all library plugins are managed by SwiftInProcPluginServer
    • Introduce abstract CompilerPlugin class that has 2 subclasses:
      • LoadedExecutablePlugin existing class that represents an executable plugin
      • InProcessPlugins wraps dlopened SwiftInProcPluginServer and communicate with it via the swift_inproc_plugins_handle_message
    • Unified the code path in TypeCheckMacros.cpp and ASTGen, the difference between executable plugins and library plugins are now abstracted by CompilerPlugin

Comment on lines 28 to 47
# Make unified swift-syntax shared library.
add_pure_swift_host_library(swiftSyntaxUnified SHARED)
set_target_properties(swiftSyntaxUnified PROPERTIES LINKER_LANGUAGE Swift)

macro(target_link_libraries_whole_archive target)
foreach(lib ${ARGN})
target_compile_options(${lib} PRIVATE "SHELL:-module-link-name ${target}")
target_sources(${target} PRIVATE $<TARGET_OBJECTS:${lib}>)
# Workaround for CMake doesn't recognize '.o' files as sources.
target_link_options(${target} PRIVATE $<TARGET_OBJECTS:${lib}>)
set_property(TARGET ${target} APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:${lib},INTERFACE_INCLUDE_DIRECTORIES>"
)
Copy link
Member Author

@rintaro rintaro May 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of making an aggregated swift-syntax libraries, can we link those static libraries with ASTGen and make libASTGen.dylib?

edit: no because ASTGen depends on C++ code.

@@ -319,7 +319,7 @@ class PluginDiagnosticsEngine {
messageSuffix: String? = nil
) {
for diagnostic in diagnostics {
self.emit(diagnostic)
self.emit(diagnostic, messageSuffix: messageSuffix)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had a bug in executable plugins where (from macro '\(macroName)') suffix wasn't added in the diagnostics from executable plugins 😞

include/swift/AST/PluginRegistry.h Outdated Show resolved Hide resolved
lib/AST/PluginRegistry.cpp Outdated Show resolved Hide resolved
lib/AST/PluginRegistry.cpp Outdated Show resolved Hide resolved
lib/AST/PluginRegistry.cpp Outdated Show resolved Hide resolved
lib/ASTGen/Sources/ASTGen/PluginHost.swift Outdated Show resolved Hide resolved
tools/libSwiftScan/CMakeLists.txt Outdated Show resolved Hide resolved
@rintaro rintaro force-pushed the macros-inproc-plugin branch 2 times, most recently from 1d223b1 to 8e7b75e Compare May 24, 2024 04:16
Swift_MODULE_NAME ${name}
Swift_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set(module_file "${CMAKE_CURRENT_BINARY_DIR}/${name}.swiftmodule")
set(module_dir "${CMAKE_CURRENT_BINARY_DIR}/modules")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fragile modules are now created in ${CMAKE_CURRENT_BINARY_DIR}/modules. This is to avoid PR testing failures in incremental bots. This PR changes _CompilerRegexParser to fragile, if we create ${CMAKE_CURRENT_BINARY_DIR}/_CompilerRegexParser.swiftmodule , subsequent PR testings will be confused because -I ${CMAKE_CURRENT_BINARY_DIR} is added by CMake. Pre-patch #73799 can avoid that, but just in case.

@@ -629,8 +629,8 @@ struct HasNestedType {
#if TEST_DIAGNOSTICS
@freestanding(expression)
macro missingMacro() = #externalMacro(module: "MacroDefinition", type: "BluhBlah")
// expected-warning@-1 {{external macro implementation type 'MacroDefinition.BluhBlah' could not be found for macro 'missingMacro()'; 'MacroDefinition.BluhBlah' could not be found in library plugin '}}
// FIXME: xpected-warning@-1 {{external macro implementation type 'MacroDefinition.BluhBlah' could not be found for macro 'missingMacro()'; 'MacroDefinition.BluhBlah' could not be found in library plugin '}}
Copy link
Member Author

@rintaro rintaro May 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because the plugin message facilities (i.e. executable plugins) doesn't support "resolve macro type" at this point. Expansions would just fail and be diagnosed if the type is not found or not a macro type.

Maybe we can introduce case resolveMacroType(module: String, type: String) plugin message to recover this.

@rintaro rintaro force-pushed the macros-inproc-plugin branch 4 times, most recently from e64de00 to 9be379a Compare May 25, 2024 06:24
@kabiroberai
Copy link
Contributor

kabiroberai commented May 29, 2024

👋 does this PR remove support for the loadPluginLibrary approach entirely? Worth noting that we're relying on this mechanism in #73031 in order to enable support for WebAssembly-based plugins. We could move these in-process but I think it would be preferable to keep third-party Wasm plugins out-of-process for defence-in-depth/isolation reasons (especially if we eventually want to execute them with JIT), so IMO it's worth keeping the library plugin mechanism for that. Also, IIUC one of the ways we could improve macro performance is to reuse a single plugin library/executable across swiftc invocations. Would this PR preclude that change for library-based plugins?

I should mention that I don't fully understand the implications of this PR so please do correct me if I'm mistaken. In general, in-process execution for first-party plugins during one-off swiftc invocation does seem like a nice improvement!

@rintaro
Copy link
Member Author

rintaro commented May 30, 2024

does this PR remove support for the loadPluginLibrary approach entirely?

I'm not 100% sure what "loadPluginLibrary approach" you mean, but either it's about -load-plugin-library compiler option or loadPluginLibrary plugin message, this PR doesn't remove them.

Since we need to keep supporting "in-process" plugins (i.e. -load-plugin-library and -plugin-path compiler options) for various reasons, we've been suffered by some limitations from that. The main intent of this PR is that separating swift-syntax libraries for the compiler and swift-syntax libraries for those "in-process" plugins. By that

  • We can unify the code path between in-process and out-of-process plugins
  • We can use different swift-syntax between the compiler and the in-process plugins. That let us compiling swift-syntax for the compiler without library-evolution, for the compiler performance

This PR doesn't have any intent of removing or deprecating out-of-process plugin mechanism.

IIUC one of the ways we could improve macro performance is to reuse a single plugin library/executable across swiftc invocations. Would this PR preclude that change for library-based plugins?

Yes, reusing plugin processes across multiple swift-frontend invocations is probably what we need to tackle on next. This PR does not preclude that approach.

I'm not sure I entirely understand your concerns. Let me know if you still have any questions!

@kabiroberai
Copy link
Contributor

kabiroberai commented May 31, 2024

Ah I was under the impression that this removed support for external plugin servers in favour of in-process plugins, but looks like I was confused. Thanks for the clarification!

Separate swift-syntax libs for the compiler and for the library plugins.
Compiler communicates with library plugins using serialized messages
just like executable plugins.

* `lib/swift/host/compiler/lib_Compiler*.dylib`(`lib/CompilerSwiftSyntax`):
  swift-syntax libraries for compiler. Library evolution is disabled.
* Compiler (`ASTGen` and `swiftIDEUtilsBridging`) only depends on
  `lib/swift/host/compiler` libraries.
* `SwiftInProcPluginServer`: In-process plugin server shared library.
  This has one `swift_inproc_plugins_handle_message` entry point that
  receives a message and return the response.
* In the compiler
  * Add `-in-process-plugin-server-path` front-end option, which specifies
    the `SwiftInProcPluginServer` shared library path.
  * Remove `LoadedLibraryPlugin`, because all library plugins are managed
    by `SwiftInProcPluginServer`
  * Introduce abstract `CompilerPlugin` class that has 2 subclasses:
    * `LoadedExecutablePlugin` existing class that represents an
      executable plugin
    * `InProcessPlugins` wraps `dlopen`ed `SwiftInProcPluginServer`
  * Unified the code path in `TypeCheckMacros.cpp` and `ASTGen`, the
    difference between executable plugins and library plugins are now
    abstracted by `CompilerPlugin`
@rintaro
Copy link
Member Author

rintaro commented Jun 17, 2024

@rintaro
Copy link
Member Author

rintaro commented Jun 20, 2024

@rintaro
Copy link
Member Author

rintaro commented Jun 20, 2024

@rintaro
Copy link
Member Author

rintaro commented Jun 20, 2024

@rintaro
Copy link
Member Author

rintaro commented Jun 20, 2024

Not all driver can send '-in-process-plugin-server-path'. To keep
existing '-plugin-path' working, infer default server path in the
frontend.
@rintaro
Copy link
Member Author

rintaro commented Jun 22, 2024

1 similar comment
@rintaro
Copy link
Member Author

rintaro commented Jun 24, 2024

@rintaro
Copy link
Member Author

rintaro commented Jun 25, 2024

@rintaro rintaro merged commit 5ebd715 into swiftlang:main Jun 26, 2024
7 checks passed
drodriguez added a commit to drodriguez/swift that referenced this pull request Jun 27, 2024
…target

PR swiftlang#73725 introduced the in-process plugin server library, but the
selection of the library depends on the selected toolchain, which
depends on the compiler target, not the host. When cross-compiling (for
example from macOS to a embedded Unix target), the compiler will
incorrectly chose the `.so` file, not find it, and fail to compile
things like the `@debugDescription` macro.

Move the in-process plugin server library code from the platform
toolchains into the parent type, and code it so it uses the right name
depending on the compiler host at compilation time. This discards the
target and only relies on the compiler host for selecting the right
library.
drodriguez added a commit to drodriguez/swift that referenced this pull request Jun 27, 2024
…target

PR swiftlang#73725 introduced the in-process plugin server library, but the
selection of the library depends on the selected toolchain, which
depends on the compiler target, not the host. When cross-compiling (for
example from macOS to a embedded Unix target), the compiler will
incorrectly chose the `.so` file, not find it, and fail to compile
things like the `@debugDescription` macro.

Move the in-process plugin server library code from the platform
toolchains into the parent type, and code it so it uses the right name
depending on the compiler host at compilation time. This discards the
target and only relies on the compiler host for selecting the right
library.
drodriguez added a commit to drodriguez/swift that referenced this pull request Jun 28, 2024
…target

PR swiftlang#73725 introduced the in-process plugin server library, but the
selection of the library depends on the selected toolchain, which
depends on the compiler target, not the host. When cross-compiling (for
example from macOS to a embedded Unix target), the compiler will
incorrectly chose the `.so` file, not find it, and fail to compile
things like the `@debugDescription` macro.

Move the in-process plugin server library code from the platform
toolchains into the parent type, and code it so it uses the right name
depending on the compiler host at compilation time. This discards the
target and only relies on the compiler host for selecting the right
library.
drodriguez added a commit to drodriguez/swift that referenced this pull request Jun 29, 2024
…target

PR swiftlang#73725 introduced the in-process plugin server library, but the
selection of the library depends on the selected toolchain, which
depends on the compiler target, not the host. When cross-compiling (for
example from macOS to a embedded Unix target), the compiler will
incorrectly chose the `.so` file, not find it, and fail to compile
things like the `@debugDescription` macro.

Move the in-process plugin server library code from the platform
toolchains into the parent type, and code it so it uses the right name
depending on the compiler host at compilation time. This discards the
target and only relies on the compiler host for selecting the right
library.
drodriguez added a commit to drodriguez/swift that referenced this pull request Jun 29, 2024
…target

PR swiftlang#73725 introduced the in-process plugin server library, but the
selection of the library depends on the selected toolchain, which
depends on the compiler target, not the host. When cross-compiling (for
example from macOS to a embedded Unix target), the compiler will
incorrectly chose the `.so` file, not find it, and fail to compile
things like the `@debugDescription` macro.

Move the in-process plugin server library code from the platform
toolchains into the parent type, and code it so it uses the right name
depending on the compiler host at compilation time. This discards the
target and only relies on the compiler host for selecting the right
library.
drodriguez added a commit to drodriguez/swift that referenced this pull request Jun 30, 2024
…target

PR swiftlang#73725 introduced the in-process plugin server library, but the
selection of the library depends on the selected toolchain, which
depends on the compiler target, not the host. When cross-compiling (for
example from macOS to a embedded Unix target), the compiler will
incorrectly chose the `.so` file, not find it, and fail to compile
things like the `@debugDescription` macro.

Move the in-process plugin server library code from the platform
toolchains into the parent type, and code it so it uses the right name
depending on the compiler host at compilation time. This discards the
target and only relies on the compiler host for selecting the right
library.
drodriguez added a commit to drodriguez/swift that referenced this pull request Jul 1, 2024
…target

PR swiftlang#73725 introduced the in-process plugin server library, but the
selection of the library depends on the selected toolchain, which
depends on the compiler target, not the host. When cross-compiling (for
example from macOS to a embedded Unix target), the compiler will
incorrectly chose the `.so` file, not find it, and fail to compile
things like the `@debugDescription` macro.

Move the in-process plugin server library code from the platform
toolchains into the parent type, and code it so it uses the right name
depending on the compiler host at compilation time. This discards the
target and only relies on the compiler host for selecting the right
library.
drodriguez added a commit that referenced this pull request Jul 1, 2024
…target (#74785)

PR #73725 introduced the in-process plugin server library, but the
selection of the library depends on the selected toolchain, which
depends on the compiler target, not the host. When cross-compiling (for
example from macOS to a embedded Unix target), the compiler will
incorrectly chose the `.so` file, not find it, and fail to compile
things like the `@debugDescription` macro.

Move the in-process plugin server library code from the platform
toolchains into the parent type, and code it so it uses the right name
depending on the compiler host at compilation time. This discards the
target and only relies on the compiler host for selecting the right
library.
rintaro pushed a commit to rintaro/swift that referenced this pull request Jul 1, 2024
…target

PR swiftlang#73725 introduced the in-process plugin server library, but the
selection of the library depends on the selected toolchain, which
depends on the compiler target, not the host. When cross-compiling (for
example from macOS to a embedded Unix target), the compiler will
incorrectly chose the `.so` file, not find it, and fail to compile
things like the `@debugDescription` macro.

Move the in-process plugin server library code from the platform
toolchains into the parent type, and code it so it uses the right name
depending on the compiler host at compilation time. This discards the
target and only relies on the compiler host for selecting the right
library.

(cherry picked from commit 55d9e74)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants