From 26dbe2f8a1f9e1e870a7fce0b76eb361d0d690a1 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 11 Oct 2023 15:13:29 -0700 Subject: [PATCH] [Macros] Use 'LibraryPluginProvider' in swift-plugin-server Move 'PluginProvider' logic to 'SwiftLibraryPluginProvider' module so the compiler can reuse that logic for the actual in-process plugins. --- test/Macros/macro_plugin_server.swift | 2 +- tools/swift-plugin-server/CMakeLists.txt | 21 +---- tools/swift-plugin-server/Package.swift | 15 ---- .../CSwiftPluginServer/PluginServer.cpp | 77 ----------------- .../CSwiftPluginServer/include/PluginServer.h | 39 --------- .../include/module.modulemap | 4 - .../swift-plugin-server.swift | 86 +------------------ 7 files changed, 5 insertions(+), 239 deletions(-) delete mode 100644 tools/swift-plugin-server/Sources/CSwiftPluginServer/PluginServer.cpp delete mode 100644 tools/swift-plugin-server/Sources/CSwiftPluginServer/include/PluginServer.h delete mode 100644 tools/swift-plugin-server/Sources/CSwiftPluginServer/include/module.modulemap diff --git a/test/Macros/macro_plugin_server.swift b/test/Macros/macro_plugin_server.swift index 85c641f0e20b3..0a51ff3e758af 100644 --- a/test/Macros/macro_plugin_server.swift +++ b/test/Macros/macro_plugin_server.swift @@ -87,7 +87,7 @@ func testStringify(a: Int, b: Int) { let s3: String = #stringify(b + a).1 print(s3) - // expected-error @+1 {{macro implementation type 'MacroDefinition.TypeDoesNotExist' could not be found in library plugin '}} + // expected-error @+1 {{type 'MacroDefinition.TypeDoesNotExist' could not be found in library plugin '}} _ = #missing() // expected-error @+1 {{type 'MacroDefinition.NotMacroStruct' is not a valid macro implementation type in library plugin '}} diff --git a/tools/swift-plugin-server/CMakeLists.txt b/tools/swift-plugin-server/CMakeLists.txt index 71ab672767c50..e1e7ffc6f93b5 100644 --- a/tools/swift-plugin-server/CMakeLists.txt +++ b/tools/swift-plugin-server/CMakeLists.txt @@ -1,29 +1,10 @@ if (SWIFT_BUILD_SWIFT_SYNTAX) - # _swiftCSwiftPluginServer is just a C support library for swift-plugin-server - # Don't bother to create '.a' for that. - add_swift_host_library(_swiftCSwiftPluginServer STATIC - Sources/CSwiftPluginServer/PluginServer.cpp - LLVM_LINK_COMPONENTS support - ) - target_link_libraries(_swiftCSwiftPluginServer PRIVATE - swiftDemangling - ) - target_include_directories(_swiftCSwiftPluginServer PUBLIC - Sources/CSwiftPluginServer/include - ) - add_pure_swift_host_tool(swift-plugin-server Sources/swift-plugin-server/swift-plugin-server.swift - DEPENDENCIES - _swiftCSwiftPluginServer SWIFT_COMPONENT compiler SWIFT_DEPENDENCIES - SwiftSyntaxMacros - SwiftSyntaxMacroExpansion SwiftCompilerPluginMessageHandling - ) - target_include_directories(swift-plugin-server PRIVATE - Sources/CSwiftPluginServer/include + SwiftLibraryPluginProvider ) endif() diff --git a/tools/swift-plugin-server/Package.swift b/tools/swift-plugin-server/Package.swift index 9fee6137adce9..a30a97a118bbf 100644 --- a/tools/swift-plugin-server/Package.swift +++ b/tools/swift-plugin-server/Package.swift @@ -11,25 +11,10 @@ let package = Package( .package(path: "../../../swift-syntax"), ], targets: [ - .target( - name: "CSwiftPluginServer", - cxxSettings: [ - .unsafeFlags([ - "-I", "../../include", - "-I", "../../../llvm-project/llvm/include", - ]) - ] - ), .executableTarget( name: "swift-plugin-server", dependencies: [ .product(name: "SwiftCompilerPluginMessageHandling", package: "swift-syntax"), - .product(name: "SwiftDiagnostics", package: "swift-syntax"), - .product(name: "SwiftSyntax", package: "swift-syntax"), - .product(name: "SwiftOperators", package: "swift-syntax"), - .product(name: "SwiftParser", package: "swift-syntax"), - .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), - "CSwiftPluginServer" ] ), ], diff --git a/tools/swift-plugin-server/Sources/CSwiftPluginServer/PluginServer.cpp b/tools/swift-plugin-server/Sources/CSwiftPluginServer/PluginServer.cpp deleted file mode 100644 index 1cd18be9f058d..0000000000000 --- a/tools/swift-plugin-server/Sources/CSwiftPluginServer/PluginServer.cpp +++ /dev/null @@ -1,77 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift open source project -// -// Copyright (c) 2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See http://swift.org/LICENSE.txt for license information -// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#include "PluginServer.h" -#include "swift/ABI/MetadataValues.h" -#include "swift/Demangling/Demangle.h" -#include "llvm/Support/DynamicLibrary.h" - -#if defined(_WIN32) -#include -#elif defined(__unix__) || defined(__APPLE__) -#include -#include -#endif - -#include -#include -#include - -using namespace swift; - -void *PluginServer_load(const char *plugin, const char **errorMessage) { - // Use a static allocation for the error as the client will not release the - // string. POSIX 2008 (IEEE-1003.1-2008) specifies that it is implementation - // defined if `dlerror` is re-entrant. Take advantage of that and make it - // thread-unsafe. This ensures that the string outlives the call permitting - // the client to duplicate it. - static std::string error; - auto library = llvm::sys::DynamicLibrary::getLibrary(plugin, &error); - if (library.isValid()) - return library.getOSSpecificHandle(); - *errorMessage = error.c_str(); - return nullptr; -} - -const void *PluginServer_lookupMacroTypeMetadataByExternalName( - const char *moduleName, const char *typeName, void *libraryHint, - const char **errorMessage) { - // Look up the type metadata accessor as a struct, enum, or class. - const Demangle::Node::Kind typeKinds[] = { - Demangle::Node::Kind::Structure, - Demangle::Node::Kind::Enum, - Demangle::Node::Kind::Class, - }; - - void *accessorAddr = nullptr; - for (auto typeKind : typeKinds) { - auto symbolName = - mangledNameForTypeMetadataAccessor(moduleName, typeName, typeKind); - -#if !defined(_WIN32) - if (libraryHint == nullptr) - libraryHint = RTLD_DEFAULT; -#endif - accessorAddr = llvm::sys::DynamicLibrary{libraryHint} - .getAddressOfSymbol(symbolName.c_str()); - if (accessorAddr) - break; - } - - if (!accessorAddr) - return nullptr; - - // Call the accessor to form type metadata. - using MetadataAccessFunc = const void *(MetadataRequest); - auto accessor = reinterpret_cast(accessorAddr); - return accessor(MetadataRequest(MetadataState::Complete)); -} diff --git a/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/PluginServer.h b/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/PluginServer.h deleted file mode 100644 index a0b9f1b062297..0000000000000 --- a/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/PluginServer.h +++ /dev/null @@ -1,39 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift open source project -// -// Copyright (c) 2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See http://swift.org/LICENSE.txt for license information -// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_PLUGINSERVER_PLUGINSERVER_H -#define SWIFT_PLUGINSERVER_PLUGINSERVER_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -//===----------------------------------------------------------------------===// -// Dynamic link -//===----------------------------------------------------------------------===// - -/// Load a dynamic link library, and return the handle. -void *PluginServer_load(const char *filename, const char **errorMessage); - -/// Resolve a type metadata by a pair of the module name and the type name. -/// 'libraryHint' is a -const void *PluginServer_lookupMacroTypeMetadataByExternalName( - const char *moduleName, const char *typeName, void *libraryHint, - const char **errorMessage); - -#ifdef __cplusplus -} -#endif - -#endif /* SWIFT_PLUGINSERVER_PLUGINSERVER_H */ diff --git a/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/module.modulemap b/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/module.modulemap deleted file mode 100644 index 0f3ca3686e5b4..0000000000000 --- a/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module CSwiftPluginServer { - header "PluginServer.h" - export * -} diff --git a/tools/swift-plugin-server/Sources/swift-plugin-server/swift-plugin-server.swift b/tools/swift-plugin-server/Sources/swift-plugin-server/swift-plugin-server.swift index 61b3663614558..1b97b4fd0af17 100644 --- a/tools/swift-plugin-server/Sources/swift-plugin-server/swift-plugin-server.swift +++ b/tools/swift-plugin-server/Sources/swift-plugin-server/swift-plugin-server.swift @@ -11,96 +11,16 @@ //===----------------------------------------------------------------------===// @_spi(PluginMessage) import SwiftCompilerPluginMessageHandling -import SwiftSyntaxMacros -import CSwiftPluginServer +@_spi(PluginMessage) import SwiftLibraryPluginProvider @main final class SwiftPluginServer { - struct MacroRef: Hashable { - var moduleName: String - var typeName: String - init(_ moduleName: String, _ typeName: String) { - self.moduleName = moduleName - self.typeName = typeName - } - } - - struct LoadedLibraryPlugin { - var libraryPath: String - var handle: UnsafeMutableRawPointer - } - - /// Loaded dylib handles associated with the module name. - var loadedLibraryPlugins: [String: LoadedLibraryPlugin] = [:] - - /// Resolved cached macros. - var resolvedMacros: [MacroRef: Macro.Type] = [:] - - /// @main entry point. static func main() throws { let connection = try StandardIOMessageConnection() let listener = CompilerPluginMessageListener( connection: connection, - provider: self.init() + provider: LibraryPluginProvider.shared ) - try listener.main() - } -} - -extension SwiftPluginServer: PluginProvider { - /// Load a macro implementation from the dynamic link library. - func loadPluginLibrary(libraryPath: String, moduleName: String) throws { - var errorMessage: UnsafePointer? - guard let dlHandle = PluginServer_load(libraryPath, &errorMessage) else { - throw PluginServerError(message: "loader error: " + String(cString: errorMessage!)) - } - loadedLibraryPlugins[moduleName] = LoadedLibraryPlugin( - libraryPath: libraryPath, - handle: dlHandle - ) - } - - /// Lookup a loaded macro by a pair of module name and type name. - func resolveMacro(moduleName: String, typeName: String) throws -> Macro.Type { - if let resolved = resolvedMacros[.init(moduleName, typeName)] { - return resolved - } - - // Find 'dlopen'ed library for the module name. - guard let plugin = loadedLibraryPlugins[moduleName] else { - // NOTE: This should be unreachable. Compiler should not use this server - // unless the plugin loading succeeded. - throw PluginServerError(message: "(plugin-server) plugin not loaded for module '\(moduleName)'") - } - - // Lookup the type metadata. - var errorMessage: UnsafePointer? - guard let macroTypePtr = PluginServer_lookupMacroTypeMetadataByExternalName( - moduleName, typeName, plugin.handle, &errorMessage - ) else { - throw PluginServerError(message: "macro implementation type '\(moduleName).\(typeName)' could not be found in library plugin '\(plugin.libraryPath)'") - } - - // THe type must be a 'Macro' type. - let macroType = unsafeBitCast(macroTypePtr, to: Any.Type.self) - guard let macro = macroType as? Macro.Type else { - throw PluginServerError(message: "type '\(moduleName).\(typeName)' is not a valid macro implementation type in library plugin '\(plugin.libraryPath)'") - } - - // Cache the resolved type. - resolvedMacros[.init(moduleName, typeName)] = macro - return macro - } - - /// This 'PluginProvider' implements 'loadLibraryMacro()'. - var features: [SwiftCompilerPluginMessageHandling.PluginFeature] { - [.loadPluginLibrary] - } -} - -struct PluginServerError: Error, CustomStringConvertible { - var description: String - init(message: String) { - self.description = message + listener.main() } }