Skip to content

Commit b876369

Browse files
committed
swift-plugin-server: adjust API for portability
This begins reworking the API to be less POSIX centric and more generally usable. The API was defined in terms of `dlopen`/`dlsym` rather than the better suited `llvm::sys::DynamicLibrary` APIs which would avoid most of the work that needs to be done here for platform specifics. Prefer to guard that with `_WIN32` until this is fully tested on Windows.
1 parent 5422f9a commit b876369

File tree

4 files changed

+82
-20
lines changed

4 files changed

+82
-20
lines changed

lib/ASTGen/Sources/ASTGen/PluginHost.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ struct CompilerPlugin {
121121

122122
private func sendMessage(_ message: HostToPluginMessage) throws {
123123
let hadError = try LLVMJSON.encoding(message) { (data) -> Bool in
124-
return Plugin_sendMessage(opaqueHandle, BridgedData(baseAddress: data.baseAddress, size: UInt(data.count)))
124+
return Plugin_sendMessage(opaqueHandle, BridgedData(baseAddress: data.baseAddress, size: Int(data.count)))
125125
}
126126
if hadError {
127127
throw PluginError.failedToSendMessage

tools/swift-plugin-server/Sources/CSwiftPluginServer/PluginServer.cpp

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,47 @@
1313
#include "PluginServer.h"
1414
#include "swift/ABI/MetadataValues.h"
1515
#include "swift/Demangling/Demangle.h"
16+
#include "llvm/Support/ConvertUTF.h"
17+
#include "llvm/Support/DynamicLibrary.h"
1618

19+
#if defined(_WIN32)
20+
#define WIN32_LEAN_AND_MEAN
21+
#include <Windows.h>
22+
#elif defined(__unix__) || defined(__APPLE__)
1723
#include <dlfcn.h>
24+
#include <unistd.h>
25+
#endif
26+
1827
#include <errno.h>
1928
#include <string.h>
20-
#include <unistd.h>
2129

2230
using namespace swift;
2331

2432
namespace {
33+
#if defined(_WIN32)
34+
struct ConnectionHandle {
35+
HANDLE hInput;
36+
HANDLE hOutput;
37+
38+
ConnectionHandle(HANDLE hInput, HANDLE hOutput)
39+
: hInput(hInput), hOutput(hOutput) {}
40+
};
41+
#else
2542
struct ConnectionHandle {
2643
int inputFD;
2744
int outputFD;
2845

2946
ConnectionHandle(int inputFD, int outputFD)
3047
: inputFD(inputFD), outputFD(outputFD) {}
3148
};
49+
#endif
3250
} // namespace
3351

3452
const void *PluginServer_createConnection(const char **errorMessage) {
53+
#if defined(_WIN32)
54+
return new ConnectionHandle(GetStdHandle(STD_INPUT_HANDLE),
55+
GetStdHandle(STD_OUTPUT_HANDLE));
56+
#else
3557
// Duplicate the `stdin` file descriptor, which we will then use for
3658
// receiving messages from the plugin host.
3759
auto inputFD = dup(STDIN_FILENO);
@@ -65,37 +87,73 @@ const void *PluginServer_createConnection(const char **errorMessage) {
6587

6688
// Open a message channel for communicating with the plugin host.
6789
return new ConnectionHandle(inputFD, outputFD);
90+
#endif
6891
}
6992

70-
void PluginServer_destroyConnection(const void *connHandle) {
71-
const auto *conn = static_cast<const ConnectionHandle *>(connHandle);
72-
delete conn;
93+
void PluginServer_destroyConnection(const void *server) {
94+
delete static_cast<const ConnectionHandle *>(server);
7395
}
7496

75-
long PluginServer_read(const void *connHandle, void *data,
76-
unsigned long nbyte) {
77-
const auto *conn = static_cast<const ConnectionHandle *>(connHandle);
97+
size_t PluginServer_read(const void *server, void *data, size_t nbyte) {
98+
const auto *connection = static_cast<const ConnectionHandle *>(server);
99+
#if defined(_WIN32)
100+
DWORD NumberOfBytesRead;
101+
llvm::SmallVector<wchar_t> buffer(nbyte);
102+
if (!ReadFile(connection->hInput, buffer.data(),
103+
buffer.size() * sizeof(wchar_t), &NumberOfBytesRead, NULL))
104+
return 0;
105+
106+
llvm::SmallVector<char> converted;
107+
if (llvm::sys::windows::UTF16ToUTF8(buffer.data(), buffer.size(), converted))
108+
return 0;
109+
memcpy(data, converted.data(), min(nbyte, converted.size()));
110+
return min(nbyte, converted.size());
111+
#else
78112
return ::read(conn->inputFD, data, nbyte);
113+
#endif
79114
}
80115

81-
long PluginServer_write(const void *connHandle, const void *data,
82-
unsigned long nbyte) {
83-
const auto *conn = static_cast<const ConnectionHandle *>(connHandle);
116+
size_t PluginServer_write(const void *server, const void *data, size_t nbyte) {
117+
const auto *connection = static_cast<const ConnectionHandle *>(server);
118+
#if defined(_WIN32)
119+
using namespace llvm;
120+
121+
SmallVector<wchar_t> buffer;
122+
if (sys::windows::UTF8ToUTF16(StringRef{static_cast<const char *>(data),
123+
static_cast<size_t>(nbyte)}, buffer))
124+
return 0;
125+
126+
DWORD NumberOfBytesWritten;
127+
if (!WriteFile(connection->hOutput, buffer.data(),
128+
buffer.size() * sizeof(wchar_t), &NumberOfBytesWritten, NULL))
129+
return 0;
130+
return NumberOfBytesWritten;
131+
#else
84132
return ::write(conn->outputFD, data, nbyte);
133+
#endif
85134
}
86135

87-
void *PluginServer_dlopen(const char *filename, const char **errorMessage) {
136+
void *PluginServer_load(const char *filename, const char **errorMessage) {
137+
#if defined(_WIN32)
138+
std::string error;
139+
llvm::sys::DynamicLibrary library =
140+
llvm::sys::DynamicLibrary::getLibrary(filename, &error);
141+
if (library.isValid())
142+
return library.getOSSpecificHandle();
143+
*errorMessage = ::strdup(error.c_str());
144+
return nullptr;
145+
#else
88146
auto *handle = ::dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
89147
if (!handle) {
90148
*errorMessage = dlerror();
91149
}
92150
return handle;
151+
#endif
93152
}
94153

95154
const void *PluginServer_lookupMacroTypeMetadataByExternalName(
96155
const char *moduleName, const char *typeName, void *libraryHint,
97156
const char **errorMessage) {
98-
99157
// Look up the type metadata accessor as a struct, enum, or class.
100158
const Demangle::Node::Kind typeKinds[] = {
101159
Demangle::Node::Kind::Structure,
@@ -108,8 +166,13 @@ const void *PluginServer_lookupMacroTypeMetadataByExternalName(
108166
auto symbolName =
109167
mangledNameForTypeMetadataAccessor(moduleName, typeName, typeKind);
110168

169+
#if defined(_WIN32)
170+
accessorAddr = llvm::sys::DynamicLibrary{libraryHint}
171+
.getAddressOfSymbol(symbolName.c_str());
172+
#else
111173
auto *handle = libraryHint ? libraryHint : RTLD_DEFAULT;
112174
accessorAddr = ::dlsym(handle, symbolName.c_str());
175+
#endif
113176
if (accessorAddr)
114177
break;
115178
}

tools/swift-plugin-server/Sources/CSwiftPluginServer/include/PluginServer.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,17 @@ const void *PluginServer_createConnection(const char **errorMessage);
2929
void PluginServer_destroyConnection(const void *connHandle);
3030

3131
/// Read bytes from the IPC communication handle.
32-
long PluginServer_read(const void *connHandle, void *data, unsigned long nbyte);
32+
size_t PluginServer_read(const void *connHandle, void *data, size_t nbyte);
3333

3434
/// Write bytes to the IPC communication handle.
35-
long PluginServer_write(const void *connHandle, const void *data,
36-
unsigned long nbyte);
35+
size_t PluginServer_write(const void *connHandle, const void *data, size_t nbyte);
3736

3837
//===----------------------------------------------------------------------===//
3938
// Dynamic link
4039
//===----------------------------------------------------------------------===//
4140

4241
/// Load a dynamic link library, and return the handle.
43-
void *PluginServer_dlopen(const char *filename, const char **errorMessage);
42+
void *PluginServer_load(const char *filename, const char **errorMessage);
4443

4544
/// Resolve a type metadata by a pair of the module name and the type name.
4645
/// 'libraryHint' is a

tools/swift-plugin-server/Sources/swift-plugin-server/swift-plugin-server.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ extension SwiftPluginServer: PluginProvider {
4747
/// Load a macro implementation from the dynamic link library.
4848
func loadPluginLibrary(libraryPath: String, moduleName: String) throws {
4949
var errorMessage: UnsafePointer<CChar>?
50-
guard let dlHandle = PluginServer_dlopen(libraryPath, &errorMessage) else {
50+
guard let dlHandle = PluginServer_load(libraryPath, &errorMessage) else {
5151
throw PluginServerError(message: String(cString: errorMessage!))
5252
}
5353
loadedLibraryPlugins[moduleName] = dlHandle
@@ -172,7 +172,7 @@ final class PluginHostConnection: MessageConnection {
172172
var ptr = buffer.baseAddress!
173173

174174
while (bytesToWrite > 0) {
175-
let writtenSize = PluginServer_write(handle, ptr, UInt(bytesToWrite))
175+
let writtenSize = PluginServer_write(handle, ptr, Int(bytesToWrite))
176176
if (writtenSize <= 0) {
177177
// error e.g. broken pipe.
178178
break
@@ -193,7 +193,7 @@ final class PluginHostConnection: MessageConnection {
193193
var ptr = buffer.baseAddress!
194194

195195
while bytesToRead > 0 {
196-
let readSize = PluginServer_read(handle, ptr, UInt(bytesToRead))
196+
let readSize = PluginServer_read(handle, ptr, Int(bytesToRead))
197197
if (readSize <= 0) {
198198
// 0: EOF (the host closed), -1: Broken pipe (the host crashed?)
199199
break;

0 commit comments

Comments
 (0)