diff --git a/lib/ASTGen/CMakeLists.txt b/lib/ASTGen/CMakeLists.txt index eec1a8dea458d..d5c227369439c 100644 --- a/lib/ASTGen/CMakeLists.txt +++ b/lib/ASTGen/CMakeLists.txt @@ -1,10 +1,3 @@ -add_pure_swift_host_library(swiftLLVMJSON STATIC EMIT_MODULE - Sources/LLVMJSON/LLVMJSON.swift - - DEPENDENCIES - swiftBasic -) - set(ASTGen_Swift_dependencies) # If requested, build the regular expression parser into the compiler itself. @@ -61,7 +54,6 @@ add_pure_swift_host_library(swiftASTGen STATIC SwiftSyntaxBuilder SwiftSyntaxMacros SwiftSyntaxMacroExpansion - swiftLLVMJSON ${ASTGen_Swift_dependencies} ) @@ -116,7 +108,7 @@ else() endif() if(SWIFT_BUILD_SWIFT_SYNTAX) - foreach(target swiftASTGen swiftLLVMJSON swiftIDEUtilsBridging) + foreach(target swiftASTGen swiftIDEUtilsBridging) target_compile_options(${target} PRIVATE ${compile_options}) endforeach() endif() diff --git a/lib/ASTGen/Package.swift b/lib/ASTGen/Package.swift index 75435f9b080f9..fb0c263ce1e95 100644 --- a/lib/ASTGen/Package.swift +++ b/lib/ASTGen/Package.swift @@ -49,7 +49,6 @@ let package = Package( ], products: [ .library(name: "swiftASTGen", targets: ["swiftASTGen"]), - .library(name: "swiftLLVMJSON", targets: ["swiftLLVMJSON"]), ], dependencies: [ .package(path: "../../../swift-syntax") @@ -68,7 +67,6 @@ let package = Package( .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), .product(name: "SwiftSyntaxMacroExpansion", package: "swift-syntax"), - "swiftLLVMJSON", "_CompilerRegexParser", ], path: "Sources/ASTGen", @@ -84,12 +82,6 @@ let package = Package( path: "Sources/SwiftIDEUtilsBridging", swiftSettings: swiftSetttings ), - .target( - name: "swiftLLVMJSON", - dependencies: [], - path: "Sources/LLVMJSON", - swiftSettings: swiftSetttings - ), .target( name: "_CompilerRegexParser", dependencies: [], diff --git a/lib/ASTGen/Sources/ASTGen/PluginHost.swift b/lib/ASTGen/Sources/ASTGen/PluginHost.swift index 395bb388b9339..2319d5146a703 100644 --- a/lib/ASTGen/Sources/ASTGen/PluginHost.swift +++ b/lib/ASTGen/Sources/ASTGen/PluginHost.swift @@ -14,7 +14,6 @@ import ASTBridging import BasicBridging @_spi(PluginMessage) import SwiftCompilerPluginMessageHandling import SwiftSyntax -import swiftLLVMJSON enum PluginError: String, Error, CustomStringConvertible { case stalePlugin = "plugin is stale" @@ -117,7 +116,7 @@ struct CompilerPlugin { } private func sendMessage(_ message: HostToPluginMessage) throws { - let hadError = try LLVMJSON.encoding(message) { (data) -> Bool in + let hadError = try JSON.encode(message).withUnsafeBufferPointer { (data) -> Bool in return Plugin_sendMessage(opaqueHandle, BridgedData(baseAddress: data.baseAddress, count: data.count)) } if hadError { @@ -133,7 +132,9 @@ struct CompilerPlugin { throw PluginError.failedToReceiveMessage } let data = UnsafeBufferPointer(start: result.baseAddress, count: result.count) - return try LLVMJSON.decode(PluginToHostMessage.self, from: data) + return try data.withMemoryRebound(to: UInt8.self) { buffer in + try JSON.decode(PluginToHostMessage.self, from: buffer) + } } func sendMessageAndWaitWithoutLock(_ message: HostToPluginMessage) throws -> PluginToHostMessage { diff --git a/lib/ASTGen/Sources/LLVMJSON/LLVMJSON.swift b/lib/ASTGen/Sources/LLVMJSON/LLVMJSON.swift deleted file mode 100644 index 2928a3ffb331c..0000000000000 --- a/lib/ASTGen/Sources/LLVMJSON/LLVMJSON.swift +++ /dev/null @@ -1,874 +0,0 @@ -//===--- LLVMJSON.swift ---------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2023 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -// Building the BasicBridging module requires a bunch of '-Xcc' args, which -// don't currently end up in the module interface. So import as -// @_implementationOnly. -@_implementationOnly import BasicBridging - -extension String { - init(_ data: BridgedData) { - let buffer = UnsafeBufferPointer(start: data.baseAddress, count: data.count) - self = buffer.withMemoryRebound(to: UInt8.self) { buffer in - String(decoding: buffer, as: UTF8.self) - } - } -} - -public struct LLVMJSON { - /// Encode an `Encodable` value to JSON data, and call `body` is the buffer. - /// Note that the buffer is valid onlu in `body`. - public static func encoding(_ value: T, body: (UnsafeBufferPointer) throws -> R) throws -> R { - let valuePtr = JSON_newValue() - defer { JSON_value_delete(valuePtr) } - - let encoder = LLVMJSONEncoding(to: valuePtr) - try value.encode(to: encoder) - - var data: BridgedData = BridgedData() - JSON_value_serialize(valuePtr, &data) - assert(data.baseAddress != nil) - defer { data.free() } - let buffer = UnsafeBufferPointer(start: data.baseAddress, count: data.count) - return try body(buffer) - } - - /// Decode a JSON data to a Swift value. - public static func decode(_ type: T.Type, from json: UnsafeBufferPointer) throws -> T { - let data = BridgedData(baseAddress: json.baseAddress, count: json.count) - let valuePtr = JSON_deserializedValue(data) - defer { JSON_value_delete(valuePtr) } - - let decoder = LLVMJSONDecoding(from: valuePtr) - return try T.init(from: decoder) - } -} - -//===----------------------------------------------------------------------===// -// Decoding -//===----------------------------------------------------------------------===// - -fileprivate struct LLVMJSONDecoding: Decoder { - fileprivate struct KeyedContainer { - var objectPtr: UnsafeMutableRawPointer - var codingPath: [CodingKey] - } - fileprivate struct UnkeyedContainer { - var arrayPtr: UnsafeMutableRawPointer - var currentIndex: Int = 0 - var codingPath: [CodingKey] - } - fileprivate struct SingleValueContainer { - var valuePtr: UnsafeMutableRawPointer - var codingPath: [CodingKey] - } - - var valuePtr: UnsafeMutableRawPointer - var codingPath: [CodingKey] - var userInfo: [CodingUserInfoKey: Any] - - init(from valuePtr: UnsafeMutableRawPointer, codingPath: [CodingKey] = [], userInfo: [CodingUserInfoKey: Any] = [:]) { - self.valuePtr = valuePtr - self.codingPath = codingPath - self.userInfo = userInfo - } - - func container(keyedBy type: Key.Type) throws -> KeyedDecodingContainer where Key: CodingKey { - var objectPtr: UnsafeMutableRawPointer? = nil - if JSON_value_getAsObject(valuePtr, &objectPtr) { - throw DecodingError.typeMismatch( - KeyedContainer.self, - .init(codingPath: codingPath, debugDescription: "type mismatch") - ) - } - return KeyedDecodingContainer(KeyedContainer(objectPtr: objectPtr!, codingPath: codingPath)) - } - - func unkeyedContainer() throws -> UnkeyedDecodingContainer { - var arrayPtr: UnsafeMutableRawPointer? = nil - if JSON_value_getAsArray(valuePtr, &arrayPtr) { - throw DecodingError.typeMismatch( - UnkeyedContainer.self, - .init(codingPath: codingPath, debugDescription: "type mismatch") - ) - } - return UnkeyedContainer(arrayPtr: arrayPtr!, codingPath: codingPath) - } - - func singleValueContainer() throws -> SingleValueDecodingContainer { - return SingleValueContainer(valuePtr: valuePtr, codingPath: codingPath) - } -} - -extension LLVMJSONDecoding.SingleValueContainer: SingleValueDecodingContainer { - private func _typeMismatchError(_ type: Any.Type) -> DecodingError { - DecodingError.typeMismatch(type, .init(codingPath: codingPath, debugDescription: "type misatch")) - } - - func decodeNil() -> Bool { - JSON_value_getAsNull(valuePtr) - } - - func decode(_ type: Bool.Type) throws -> Bool { - var result: Bool = false - if JSON_value_getAsBoolean(valuePtr, &result) { - throw _typeMismatchError(type) - } - return result - } - - func decode(_ type: String.Type) throws -> String { - var result: BridgedData = BridgedData() - - if JSON_value_getAsString(valuePtr, &result) { - throw _typeMismatchError(type) - } - - return String(result) - } - - private func _decodeFloatingPoint(_ type: FP.Type) throws -> FP { - var result: Double = 0 - if JSON_value_getAsDouble(valuePtr, &result) { - throw _typeMismatchError(type) - } - return FP(result); - } - - func decode(_ type: Double.Type) throws -> Double { - try _decodeFloatingPoint(Double.self) - } - - func decode(_ type: Float.Type) throws -> Float { - try _decodeFloatingPoint(Float.self) - } - - private func _decodeInteger(_ type: Integer.Type) throws -> Integer { - var result: Int64 = 0 - if JSON_value_getAsInteger(valuePtr, &result) { - throw _typeMismatchError(type) - } - return Integer(result); - } - - func decode(_ type: Int.Type) throws -> Int { - try _decodeInteger(Int.self) - } - - func decode(_ type: Int8.Type) throws -> Int8 { - try _decodeInteger(Int8.self) - } - - func decode(_ type: Int16.Type) throws -> Int16 { - try _decodeInteger(Int16.self) - } - - func decode(_ type: Int32.Type) throws -> Int32 { - try _decodeInteger(Int32.self) - } - - func decode(_ type: Int64.Type) throws -> Int64 { - try _decodeInteger(Int64.self) - } - - func decode(_ type: UInt.Type) throws -> UInt { - try _decodeInteger(UInt.self) - } - - func decode(_ type: UInt8.Type) throws -> UInt8 { - try _decodeInteger(UInt8.self) - } - - func decode(_ type: UInt16.Type) throws -> UInt16 { - try _decodeInteger(UInt16.self) - } - - func decode(_ type: UInt32.Type) throws -> UInt32 { - try _decodeInteger(UInt32.self) - } - - func decode(_ type: UInt64.Type) throws -> UInt64 { - try _decodeInteger(UInt64.self) - } - - func decode(_ type: T.Type) throws -> T where T: Decodable { - let decoder = LLVMJSONDecoding(from: valuePtr, codingPath: codingPath) - return try T.init(from: decoder) - } -} - -extension LLVMJSONDecoding.KeyedContainer: KeyedDecodingContainerProtocol { - typealias KeyedContainer = LLVMJSONDecoding.KeyedContainer - typealias UnkeyedContainer = LLVMJSONDecoding.UnkeyedContainer - typealias SingleContainer = LLVMJSONDecoding.SingleValueContainer - - var allKeys: [Key] { - var keys: [Key] = [] - let size = JSON_object_getSize(objectPtr) - keys.reserveCapacity(size) - for i in 0.. Bool { - return JSON_object_hasKey(objectPtr, key.stringValue) - } - - private func _getValue(forKey key: Key) -> UnsafeMutableRawPointer? { - guard JSON_object_hasKey(objectPtr, key.stringValue) else { - return nil - } - return JSON_object_getValue(objectPtr, key.stringValue) - } - - private func _getValueOrThrow(forKey key: Key) throws -> UnsafeMutableRawPointer { - guard let valuePtr = _getValue(forKey: key) else { - throw DecodingError.keyNotFound(key, .init(codingPath: codingPath, debugDescription: "key not found")) - } - return valuePtr - } - - private func _getSingle(forKey key: Key) throws -> SingleContainer { - SingleContainer( - valuePtr: try _getValueOrThrow(forKey: key), - codingPath: codingPath + [key] - ) - } - - private func _typeMismatchError(_ type: Any.Type, forKey key: Key) -> DecodingError { - DecodingError.typeMismatch(type, .init(codingPath: codingPath + [key], debugDescription: "type misatch")) - } - - func decodeNil(forKey key: Key) throws -> Bool { - try _getSingle(forKey: key).decodeNil() - } - - func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: String.Type, forKey key: Key) throws -> String { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: Double.Type, forKey key: Key) throws -> Double { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: Float.Type, forKey key: Key) throws -> Float { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: Int.Type, forKey key: Key) throws -> Int { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 { - try _getSingle(forKey: key).decode(type) - } - - func decode(_ type: T.Type, forKey key: Key) throws -> T where T: Decodable { - try _getSingle(forKey: key).decode(type) - } - - func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: Int8.Type, forKey key: Key) throws -> Int8? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: Int16.Type, forKey key: Key) throws -> Int16? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: Int32.Type, forKey key: Key) throws -> Int32? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: UInt.Type, forKey key: Key) throws -> UInt? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: UInt8.Type, forKey key: Key) throws -> UInt8? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: UInt16.Type, forKey key: Key) throws -> UInt16? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: UInt32.Type, forKey key: Key) throws -> UInt32? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: UInt64.Type, forKey key: Key) throws -> UInt64? { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func decodeIfPresent(_ type: T.Type, forKey key: Key) throws -> T? where T: Decodable { - guard contains(key) else { return nil } - return try decode(type, forKey: key) - } - - func nestedContainer( - keyedBy type: NestedKey.Type, - forKey key: Key - ) throws -> KeyedDecodingContainer { - var objectPtr: UnsafeMutableRawPointer? = nil - if JSON_value_getAsObject(try _getValueOrThrow(forKey: key), &objectPtr) { - throw _typeMismatchError(KeyedDecodingContainer.self, forKey: key) - } - - return KeyedDecodingContainer(KeyedContainer(objectPtr: objectPtr!, codingPath: codingPath + [key])) - } - - func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer { - var arrayPtr: UnsafeMutableRawPointer? = nil - if JSON_value_getAsArray(try _getValueOrThrow(forKey: key), &arrayPtr) { - throw _typeMismatchError(UnkeyedContainer.self, forKey: key) - } - - return UnkeyedContainer(arrayPtr: arrayPtr!, codingPath: codingPath + [key]) - } - - func superDecoder() throws -> Decoder { - fatalError("unimplemented") - } - - func superDecoder(forKey key: Key) throws -> Decoder { - fatalError("unimplemented") - } -} - -extension LLVMJSONDecoding.UnkeyedContainer: UnkeyedDecodingContainer { - typealias KeyedContainer = LLVMJSONDecoding.KeyedContainer - typealias UnkeyedContainer = LLVMJSONDecoding.UnkeyedContainer - typealias SingleContainer = LLVMJSONDecoding.SingleValueContainer - - struct IndexKey: CodingKey { - var intValue: Int? - var stringValue: String { intValue!.description } - init(intValue value: Int) { self.intValue = value } - init?(stringValue: String) { - return nil - } - } - - var count: Int? { - Int(JSON_array_getSize(arrayPtr)) - } - - var isAtEnd: Bool { - currentIndex == count - } - - private mutating func _getValueOrThrow() throws -> UnsafeMutableRawPointer { - guard !isAtEnd else { - throw DecodingError.valueNotFound( - Bool.self, - .init(codingPath: codingPath, debugDescription: "tried to decode too many") - ) - } - let index = currentIndex - currentIndex += 1 - return JSON_array_getValue(arrayPtr, numericCast(index)) - } - - private mutating func _getSingle() throws -> SingleContainer { - SingleContainer( - valuePtr: try _getValueOrThrow(), - codingPath: codingPath + [IndexKey(intValue: currentIndex)] - ) - } - - mutating func decodeNil() throws -> Bool { - try _getSingle().decodeNil() - } - - mutating func decode(_ type: Bool.Type) throws -> Bool { - try _getSingle().decode(type) - } - - mutating func decode(_ type: String.Type) throws -> String { - try _getSingle().decode(type) - } - - mutating func decode(_ type: Double.Type) throws -> Double { - try _getSingle().decode(type) - } - - mutating func decode(_ type: Float.Type) throws -> Float { - try _getSingle().decode(type) - } - - mutating func decode(_ type: Int.Type) throws -> Int { - try _getSingle().decode(type) - } - - mutating func decode(_ type: Int8.Type) throws -> Int8 { - try _getSingle().decode(type) - } - - mutating func decode(_ type: Int16.Type) throws -> Int16 { - try _getSingle().decode(type) - } - - mutating func decode(_ type: Int32.Type) throws -> Int32 { - try _getSingle().decode(type) - } - - mutating func decode(_ type: Int64.Type) throws -> Int64 { - try _getSingle().decode(type) - } - - mutating func decode(_ type: UInt.Type) throws -> UInt { - try _getSingle().decode(type) - } - - mutating func decode(_ type: UInt8.Type) throws -> UInt8 { - try _getSingle().decode(type) - } - - mutating func decode(_ type: UInt16.Type) throws -> UInt16 { - try _getSingle().decode(type) - } - - mutating func decode(_ type: UInt32.Type) throws -> UInt32 { - try _getSingle().decode(type) - } - - mutating func decode(_ type: UInt64.Type) throws -> UInt64 { - try _getSingle().decode(type) - } - - mutating func decode(_ type: T.Type) throws -> T where T: Decodable { - try _getSingle().decode(type) - } - - private func _typeMismatchError(_ type: Any.Type) -> DecodingError { - DecodingError.typeMismatch( - type, - .init( - codingPath: codingPath + [IndexKey(intValue: currentIndex)], - debugDescription: "type misatch" - ) - ) - } - - mutating func nestedContainer( - keyedBy type: NestedKey.Type - ) throws -> KeyedDecodingContainer { - var objectPtr: UnsafeMutableRawPointer? = nil - let newPath = codingPath + [IndexKey(intValue: currentIndex)] - if JSON_value_getAsObject(try _getValueOrThrow(), &objectPtr) { - throw _typeMismatchError(KeyedDecodingContainer.self) - } - - return KeyedDecodingContainer(KeyedContainer(objectPtr: objectPtr!, codingPath: newPath)) - } - - mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer { - var arrayPtr: UnsafeMutableRawPointer? = nil - let newPath = codingPath + [IndexKey(intValue: currentIndex)] - if JSON_value_getAsArray(try _getValueOrThrow(), &arrayPtr) { - throw _typeMismatchError(UnkeyedContainer.self) - } - - return UnkeyedContainer(arrayPtr: arrayPtr!, codingPath: newPath) - } - - mutating func superDecoder() throws -> Decoder { - fatalError("unimplemented") - } -} - -//===----------------------------------------------------------------------===// -// Encoding -//===----------------------------------------------------------------------===// - -fileprivate struct LLVMJSONEncoding: Encoder { - fileprivate struct SingleValueContainer { - var valuePtr: UnsafeMutableRawPointer - var codingPath: [CodingKey] - } - fileprivate struct UnkeyedContainer { - var arrayPtr: UnsafeMutableRawPointer - var codingPath: [CodingKey] - } - fileprivate struct KeyedContainer { - var objectPtr: UnsafeMutableRawPointer - var codingPath: [CodingKey] - } - - var valuePtr: UnsafeMutableRawPointer - var codingPath: [CodingKey] - var userInfo: [CodingUserInfoKey: Any] - - init(to valuePtr: UnsafeMutableRawPointer, codingPath: [CodingKey] = [], userInfo: [CodingUserInfoKey: Any] = [:]) { - self.valuePtr = valuePtr - self.codingPath = codingPath - self.userInfo = userInfo - } - - func container(keyedBy type: Key.Type) -> KeyedEncodingContainer where Key: CodingKey { - let objectPtr = JSON_value_emplaceNewObject(valuePtr) - return KeyedEncodingContainer(KeyedContainer(objectPtr: objectPtr, codingPath: codingPath)) - } - - func unkeyedContainer() -> UnkeyedEncodingContainer { - let arrayPtr = JSON_value_emplaceNewArray(valuePtr) - return UnkeyedContainer(arrayPtr: arrayPtr, codingPath: codingPath) - } - - func singleValueContainer() -> SingleValueEncodingContainer { - return SingleValueContainer(valuePtr: valuePtr, codingPath: codingPath) - } -} - -extension LLVMJSONEncoding.KeyedContainer: KeyedEncodingContainerProtocol { - typealias UnkeyedContainer = LLVMJSONEncoding.UnkeyedContainer - typealias KeyedContainer = LLVMJSONEncoding.KeyedContainer - - mutating func encodeNil(forKey key: Key) throws { - JSON_object_setNull(objectPtr, key.stringValue) - } - - mutating func encode(_ value: Bool, forKey key: Key) throws { - JSON_object_setBoolean(objectPtr, key.stringValue, value) - } - - mutating func encode(_ value: String, forKey key: Key) throws { - JSON_object_setString(objectPtr, key.stringValue, value) - } - - mutating func encode(_ value: Double, forKey key: Key) throws { - JSON_object_setDouble(objectPtr, key.stringValue, value) - } - - mutating func encode(_ value: Float, forKey key: Key) throws { - JSON_object_setDouble(objectPtr, key.stringValue, Double(value)) - } - - mutating func encode(_ value: Int, forKey key: Key) throws { - JSON_object_setInteger(objectPtr, key.stringValue, Int64(value)) - } - - mutating func encode(_ value: Int8, forKey key: Key) throws { - JSON_object_setInteger(objectPtr, key.stringValue, Int64(value)) - } - - mutating func encode(_ value: Int16, forKey key: Key) throws { - JSON_object_setInteger(objectPtr, key.stringValue, Int64(value)) - } - - mutating func encode(_ value: Int32, forKey key: Key) throws { - JSON_object_setInteger(objectPtr, key.stringValue, Int64(value)) - } - - mutating func encode(_ value: Int64, forKey key: Key) throws { - JSON_object_setInteger(objectPtr, key.stringValue, Int64(value)) - } - - mutating func encode(_ value: UInt, forKey key: Key) throws { - JSON_object_setInteger(objectPtr, key.stringValue, Int64(value)) - } - - mutating func encode(_ value: UInt8, forKey key: Key) throws { - JSON_object_setInteger(objectPtr, key.stringValue, Int64(value)) - } - - mutating func encode(_ value: UInt16, forKey key: Key) throws { - JSON_object_setInteger(objectPtr, key.stringValue, Int64(value)) - } - - mutating func encode(_ value: UInt32, forKey key: Key) throws { - JSON_object_setInteger(objectPtr, key.stringValue, Int64(value)) - } - - mutating func encode(_ value: UInt64, forKey key: Key) throws { - JSON_object_setInteger(objectPtr, key.stringValue, Int64(value)) - } - - mutating func encode(_ value: T, forKey key: Key) throws where T: Encodable { - let valuePtr = JSON_object_setNewValue(objectPtr, key.stringValue) - let encoder = LLVMJSONEncoding(to: valuePtr, codingPath: codingPath + [key]) - try value.encode(to: encoder) - } - - mutating func nestedContainer( - keyedBy keyType: NestedKey.Type, - forKey key: Key - ) -> KeyedEncodingContainer { - let nestedObjectPtr = JSON_object_setNewObject(objectPtr, key.stringValue) - return KeyedEncodingContainer(KeyedContainer(objectPtr: nestedObjectPtr, codingPath: codingPath + [key])) - } - - mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer { - let nestedArrayPtr = JSON_object_setNewArray(objectPtr, key.stringValue) - return UnkeyedContainer(arrayPtr: nestedArrayPtr, codingPath: codingPath + [key]) - } - - mutating func superEncoder() -> Encoder { - fatalError("unimplemented") - } - - mutating func superEncoder(forKey key: Key) -> Encoder { - fatalError("unimplemented") - } -} - -extension LLVMJSONEncoding.UnkeyedContainer: UnkeyedEncodingContainer { - typealias UnkeyedContainer = LLVMJSONEncoding.UnkeyedContainer - typealias KeyedContainer = LLVMJSONEncoding.KeyedContainer - - struct IndexKey: CodingKey { - var intValue: Int? - var stringValue: String { intValue!.description } - init(intValue value: Int) { self.intValue = value } - init?(stringValue: String) { - return nil - } - } - - var count: Int { - return Int(JSON_array_getSize(arrayPtr)) - } - - mutating func encodeNil() throws { - JSON_array_pushNull(arrayPtr) - } - - mutating func encode(_ value: Bool) throws { - JSON_array_pushBoolean(arrayPtr, value) - } - - mutating func encode(_ value: String) throws { - JSON_array_pushString(arrayPtr, value) - } - - mutating func encode(_ value: Double) throws { - JSON_array_pushDouble(arrayPtr, Double(value)) - } - - mutating func encode(_ value: Float) throws { - JSON_array_pushDouble(arrayPtr, Double(value)) - } - - mutating func encode(_ value: Int) throws { - JSON_array_pushInteger(arrayPtr, Int64(value)) - } - - mutating func encode(_ value: Int8) throws { - JSON_array_pushInteger(arrayPtr, Int64(value)) - } - - mutating func encode(_ value: Int16) throws { - JSON_array_pushInteger(arrayPtr, Int64(value)) - } - - mutating func encode(_ value: Int32) throws { - JSON_array_pushInteger(arrayPtr, Int64(value)) - } - - mutating func encode(_ value: Int64) throws { - JSON_array_pushInteger(arrayPtr, Int64(value)) - } - - mutating func encode(_ value: UInt) throws { - JSON_array_pushInteger(arrayPtr, Int64(value)) - } - - mutating func encode(_ value: UInt8) throws { - JSON_array_pushInteger(arrayPtr, Int64(value)) - } - - mutating func encode(_ value: UInt16) throws { - JSON_array_pushInteger(arrayPtr, Int64(value)) - } - - mutating func encode(_ value: UInt32) throws { - JSON_array_pushInteger(arrayPtr, Int64(value)) - } - - mutating func encode(_ value: UInt64) throws { - JSON_array_pushInteger(arrayPtr, Int64(value)) - } - - mutating func encode(_ value: T) throws where T: Encodable { - let key = IndexKey(intValue: self.count) - let valuePtr = JSON_array_pushNewValue(arrayPtr) - let encoder = LLVMJSONEncoding(to: valuePtr, codingPath: codingPath + [key]) - try value.encode(to: encoder) - } - - mutating func nestedContainer(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer - where NestedKey: CodingKey { - let key = IndexKey(intValue: self.count) - let nestedObjectPtr = JSON_array_pushNewObject(arrayPtr) - return KeyedEncodingContainer( - KeyedContainer( - objectPtr: nestedObjectPtr, - codingPath: codingPath + [key] - ) - ) - } - - mutating func nestedUnkeyedContainer() -> UnkeyedEncodingContainer { - let key = IndexKey(intValue: self.count) - let nestedArrayPtr = JSON_array_pushNewArray(arrayPtr) - return UnkeyedContainer(arrayPtr: nestedArrayPtr, codingPath: codingPath + [key]) - } - - mutating func superEncoder() -> Encoder { - fatalError("unsupported") - } -} - -extension LLVMJSONEncoding.SingleValueContainer: SingleValueEncodingContainer { - mutating func encodeNil() throws { - JSON_value_emplaceNull(valuePtr); - } - - mutating func encode(_ value: Bool) throws { - JSON_value_emplaceBoolean(valuePtr, value); - } - - mutating func encode(_ value: String) throws { - JSON_value_emplaceString(valuePtr, value); - } - - mutating func encode(_ value: Double) throws { - JSON_value_emplaceDouble(valuePtr, Double(value)); - } - - mutating func encode(_ value: Float) throws { - JSON_value_emplaceDouble(valuePtr, Double(value)); - } - - mutating func encode(_ value: Int) throws { - JSON_value_emplaceInteger(valuePtr, Int64(value)); - } - - mutating func encode(_ value: Int8) throws { - JSON_value_emplaceInteger(valuePtr, Int64(value)); - } - - mutating func encode(_ value: Int16) throws { - JSON_value_emplaceInteger(valuePtr, Int64(value)); - } - - mutating func encode(_ value: Int32) throws { - JSON_value_emplaceInteger(valuePtr, Int64(value)); - } - - mutating func encode(_ value: Int64) throws { - JSON_value_emplaceInteger(valuePtr, Int64(value)); - } - - mutating func encode(_ value: UInt) throws { - JSON_value_emplaceInteger(valuePtr, Int64(value)); - } - - mutating func encode(_ value: UInt8) throws { - JSON_value_emplaceInteger(valuePtr, Int64(value)); - } - - mutating func encode(_ value: UInt16) throws { - JSON_value_emplaceInteger(valuePtr, Int64(value)); - } - - mutating func encode(_ value: UInt32) throws { - JSON_value_emplaceInteger(valuePtr, Int64(value)); - } - - mutating func encode(_ value: UInt64) throws { - JSON_value_emplaceInteger(valuePtr, Int64(value)); - } - - mutating func encode(_ value: T) throws where T: Encodable { - let encoder = LLVMJSONEncoding(to: valuePtr, codingPath: codingPath) - try value.encode(to: encoder) - } -} diff --git a/tools/swift-plugin-server/CMakeLists.txt b/tools/swift-plugin-server/CMakeLists.txt index 34e8637089521..71ab672767c50 100644 --- a/tools/swift-plugin-server/CMakeLists.txt +++ b/tools/swift-plugin-server/CMakeLists.txt @@ -1,8 +1,9 @@ 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 OBJECT + add_swift_host_library(_swiftCSwiftPluginServer STATIC Sources/CSwiftPluginServer/PluginServer.cpp + LLVM_LINK_COMPONENTS support ) target_link_libraries(_swiftCSwiftPluginServer PRIVATE swiftDemangling @@ -14,15 +15,13 @@ if (SWIFT_BUILD_SWIFT_SYNTAX) add_pure_swift_host_tool(swift-plugin-server Sources/swift-plugin-server/swift-plugin-server.swift DEPENDENCIES - swiftDemangling - $ + _swiftCSwiftPluginServer SWIFT_COMPONENT compiler SWIFT_DEPENDENCIES SwiftSyntaxMacros SwiftSyntaxMacroExpansion SwiftCompilerPluginMessageHandling - swiftLLVMJSON ) target_include_directories(swift-plugin-server PRIVATE Sources/CSwiftPluginServer/include diff --git a/tools/swift-plugin-server/Package.swift b/tools/swift-plugin-server/Package.swift index 5a4bb6b830ab8..9fee6137adce9 100644 --- a/tools/swift-plugin-server/Package.swift +++ b/tools/swift-plugin-server/Package.swift @@ -9,7 +9,6 @@ let package = Package( ], dependencies: [ .package(path: "../../../swift-syntax"), - .package(path: "../../lib/ASTGen"), ], targets: [ .target( @@ -24,7 +23,6 @@ let package = Package( .executableTarget( name: "swift-plugin-server", dependencies: [ - .product(name: "swiftLLVMJSON", package: "ASTGen"), .product(name: "SwiftCompilerPluginMessageHandling", package: "swift-syntax"), .product(name: "SwiftDiagnostics", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), diff --git a/tools/swift-plugin-server/Sources/CSwiftPluginServer/PluginServer.cpp b/tools/swift-plugin-server/Sources/CSwiftPluginServer/PluginServer.cpp index 11ef8bc5c2ebc..1cd18be9f058d 100644 --- a/tools/swift-plugin-server/Sources/CSwiftPluginServer/PluginServer.cpp +++ b/tools/swift-plugin-server/Sources/CSwiftPluginServer/PluginServer.cpp @@ -22,121 +22,12 @@ #include #endif +#include #include #include using namespace swift; -namespace { -struct ConnectionHandle { - int inputFD; - int outputFD; - - ConnectionHandle(int inputFD, int outputFD) - : inputFD(inputFD), outputFD(outputFD) {} -}; -} // namespace - -const void *PluginServer_createConnection(const char **errorMessage) { -#if defined(_WIN32) - struct unique_fd { - unique_fd(int fd) : fd_(fd) {} - unique_fd(const unique_fd &) = delete; - unique_fd &operator=(const unique_fd &) = delete; - unique_fd &operator=(unique_fd &&) = delete; - unique_fd(unique_fd &&uf) : fd_(uf.fd_) { uf.fd_ = -1; } - ~unique_fd() { if (fd_ > 0) _close(fd_); } - - int operator*() const { return fd_; } - int release() { int fd = fd_; fd_ = -1; return fd; } - - private: - int fd_; - }; - - unique_fd ifd{_dup(_fileno(stdin))}; - if (*ifd < 0) { - *errorMessage = _strerror(nullptr); - return nullptr; - } - - if (_close(_fileno(stdin)) < 0) { - *errorMessage = _strerror(nullptr); - return nullptr; - } - - unique_fd ofd{_dup(_fileno(stdout))}; - if (*ofd < 0) { - *errorMessage = _strerror(nullptr); - return nullptr; - } - - if (_dup2(_fileno(stderr), _fileno(stdout)) < 0) { - *errorMessage = _strerror(nullptr); - return nullptr; - } - - return new ConnectionHandle(ifd.release(), ofd.release()); -#else - // Duplicate the `stdin` file descriptor, which we will then use for - // receiving messages from the plugin host. - auto inputFD = dup(STDIN_FILENO); - if (inputFD < 0) { - *errorMessage = strerror(errno); - return nullptr; - } - - // Having duplicated the original standard-input descriptor, we close - // `stdin` so that attempts by the plugin to read console input (which - // are usually a mistake) return errors instead of blocking. - if (close(STDIN_FILENO) < 0) { - *errorMessage = strerror(errno); - return nullptr; - } - - // Duplicate the `stdout` file descriptor, which we will then use for - // sending messages to the plugin host. - auto outputFD = dup(STDOUT_FILENO); - if (outputFD < 0) { - *errorMessage = strerror(errno); - return nullptr; - } - - // Having duplicated the original standard-output descriptor, redirect - // `stdout` to `stderr` so that all free-form text output goes there. - if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) { - *errorMessage = strerror(errno); - return nullptr; - } - - // Open a message channel for communicating with the plugin host. - return new ConnectionHandle(inputFD, outputFD); -#endif -} - -void PluginServer_destroyConnection(const void *server) { - delete static_cast(server); -} - -ptrdiff_t PluginServer_read(const void *server, void *data, size_t nbyte) { - const auto *connection = static_cast(server); -#if defined(_WIN32) - return _read(connection->inputFD, data, nbyte); -#else - return ::read(connection->inputFD, data, nbyte); -#endif -} - -ptrdiff_t PluginServer_write(const void *server, const void *data, - size_t nbyte) { - const auto *connection = static_cast(server); -#if defined(_WIN32) - return _write(connection->outputFD, data, nbyte); -#else - return ::write(connection->outputFD, data, nbyte); -#endif -} - 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 diff --git a/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/PluginServer.h b/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/PluginServer.h index 75c62e06e1212..a0b9f1b062297 100644 --- a/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/PluginServer.h +++ b/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/PluginServer.h @@ -19,24 +19,6 @@ extern "C" { #endif -//===----------------------------------------------------------------------===// -// Inter-process communication. -//===----------------------------------------------------------------------===// - -/// Create an IPC communication handle. -const void *PluginServer_createConnection(const char **errorMessage); - -/// Destroy an IPC communication handle created by -/// 'PluginServer_createConnection'. -void PluginServer_destroyConnection(const void *connHandle); - -/// Read bytes from the IPC communication handle. -ptrdiff_t PluginServer_read(const void *connHandle, void *data, size_t nbyte); - -/// Write bytes to the IPC communication handle. -ptrdiff_t PluginServer_write(const void *connHandle, const void *data, - size_t nbyte); - //===----------------------------------------------------------------------===// // Dynamic link //===----------------------------------------------------------------------===// 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 9e4bccf8b84ab..61b3663614558 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 @@ -12,7 +12,6 @@ @_spi(PluginMessage) import SwiftCompilerPluginMessageHandling import SwiftSyntaxMacros -import swiftLLVMJSON import CSwiftPluginServer @main @@ -39,7 +38,7 @@ final class SwiftPluginServer { /// @main entry point. static func main() throws { - let connection = try PluginHostConnection() + let connection = try StandardIOMessageConnection() let listener = CompilerPluginMessageListener( connection: connection, provider: self.init() @@ -99,121 +98,6 @@ extension SwiftPluginServer: PluginProvider { } } -final class PluginHostConnection: MessageConnection { - let handle: UnsafeRawPointer - init() throws { - var errorMessage: UnsafePointer? = nil - guard let handle = PluginServer_createConnection(&errorMessage) else { - throw PluginServerError(message: String(cString: errorMessage!)) - } - self.handle = handle - } - - deinit { - PluginServer_destroyConnection(self.handle) - } - - func sendMessage(_ message: TX) throws { - try LLVMJSON.encoding(message) { buffer in - try self.sendMessageData(buffer) - } - } - - func waitForNextMessage(_ type: RX.Type) throws -> RX? { - return try self.withReadingMessageData { jsonData in - try LLVMJSON.decode(RX.self, from: jsonData) - } - } - - /// Send a serialized message to the message channel. - private func sendMessageData(_ data: UnsafeBufferPointer) throws { - // Write the header (a 64-bit length field in little endian byte order). - var header: UInt64 = UInt64(data.count).littleEndian - let writtenSize = try Swift.withUnsafeBytes(of: &header) { buffer in - try self.write(buffer: UnsafeRawBufferPointer(buffer)) - } - guard writtenSize == MemoryLayout.size(ofValue: header) else { - throw PluginServerError(message: "failed to write message header") - } - - // Write the body. - guard try self.write(buffer: UnsafeRawBufferPointer(data)) == data.count else { - throw PluginServerError(message: "failed to write message body") - } - } - - /// Read a serialized message from the message channel and call the 'body' - /// with the data. - private func withReadingMessageData(_ body: (UnsafeBufferPointer) throws -> R) throws -> R? { - // Read the header (a 64-bit length field in little endian byte order). - var header: UInt64 = 0 - let readSize = try Swift.withUnsafeMutableBytes(of: &header) { buffer in - try self.read(into: UnsafeMutableRawBufferPointer(buffer)) - } - guard readSize == MemoryLayout.size(ofValue: header) else { - if readSize == 0 { - // The host closed the pipe. - return nil - } - // Otherwise, some error happened. - throw PluginServerError(message: "failed to read message header") - } - - // Read the body. - let count = Int(UInt64(littleEndian: header)) - let data = UnsafeMutableBufferPointer.allocate(capacity: count) - defer { data.deallocate() } - guard try self.read(into: UnsafeMutableRawBufferPointer(data)) == count else { - throw PluginServerError(message: "failed to read message body") - } - - // Invoke the handler. - return try body(UnsafeBufferPointer(data)) - } - - /// Write the 'buffer' to the message channel. - /// Returns the number of bytes succeeded to write. - private func write(buffer: UnsafeRawBufferPointer) throws -> Int { - var bytesToWrite = buffer.count - guard bytesToWrite > 0 else { - return 0 - } - var ptr = buffer.baseAddress! - - while (bytesToWrite > 0) { - let writtenSize = PluginServer_write(handle, ptr, bytesToWrite) - if (writtenSize <= 0) { - // error e.g. broken pipe. - break - } - ptr = ptr.advanced(by: writtenSize) - bytesToWrite -= Int(writtenSize) - } - return buffer.count - bytesToWrite - } - - /// Read data from the message channel into the 'buffer' up to 'buffer.count' bytes. - /// Returns the number of bytes succeeded to read. - private func read(into buffer: UnsafeMutableRawBufferPointer) throws -> Int { - var bytesToRead = buffer.count - guard bytesToRead > 0 else { - return 0 - } - var ptr = buffer.baseAddress! - - while bytesToRead > 0 { - let readSize = PluginServer_read(handle, ptr, bytesToRead) - if (readSize <= 0) { - // 0: EOF (the host closed), -1: Broken pipe (the host crashed?) - break; - } - ptr = ptr.advanced(by: readSize) - bytesToRead -= readSize - } - return buffer.count - bytesToRead - } -} - struct PluginServerError: Error, CustomStringConvertible { var description: String init(message: String) {