1313#include " PluginServer.h"
1414#include " swift/ABI/MetadataValues.h"
1515#include " swift/Demangling/Demangle.h"
16+ #include " llvm/Support/DynamicLibrary.h"
1617
18+ #if defined(_WIN32)
19+ #include < io.h>
20+ #elif defined(__unix__) || defined(__APPLE__)
1721#include < dlfcn.h>
22+ #include < unistd.h>
23+ #endif
24+
1825#include < errno.h>
1926#include < string.h>
20- #include < unistd.h>
2127
2228using namespace swift ;
2329
@@ -32,6 +38,46 @@ struct ConnectionHandle {
3238} // namespace
3339
3440const void *PluginServer_createConnection (const char **errorMessage) {
41+ #if defined(_WIN32)
42+ struct unique_fd {
43+ unique_fd (int fd) : fd_(fd) {}
44+ unique_fd (const unique_fd &) = delete ;
45+ unique_fd &operator =(const unique_fd &) = delete ;
46+ unique_fd &operator =(unique_fd &&) = delete ;
47+ unique_fd (unique_fd &&uf) : fd_(uf.fd_) { uf.fd_ = -1 ; }
48+ ~unique_fd () { if (fd_ > 0 ) _close (fd_); }
49+
50+ int operator *() const { return fd_; }
51+ int release () { int fd = fd_; fd_ = -1 ; return fd; }
52+
53+ private:
54+ int fd_;
55+ };
56+
57+ unique_fd ifd{_dup (_fileno (stdin))};
58+ if (*ifd < 0 ) {
59+ *errorMessage = _strerror (nullptr );
60+ return nullptr ;
61+ }
62+
63+ if (_close (_fileno (stdin)) < 0 ) {
64+ *errorMessage = _strerror (nullptr );
65+ return nullptr ;
66+ }
67+
68+ unique_fd ofd{_dup (_fileno (stdout))};
69+ if (*ofd < 0 ) {
70+ *errorMessage = _strerror (nullptr );
71+ return nullptr ;
72+ }
73+
74+ if (_dup2 (_fileno (stderr), _fileno (stdout)) < 0 ) {
75+ *errorMessage = _strerror (nullptr );
76+ return nullptr ;
77+ }
78+
79+ return new ConnectionHandle (ifd.release (), ofd.release ());
80+ #else
3581 // Duplicate the `stdin` file descriptor, which we will then use for
3682 // receiving messages from the plugin host.
3783 auto inputFD = dup (STDIN_FILENO);
@@ -65,37 +111,48 @@ const void *PluginServer_createConnection(const char **errorMessage) {
65111
66112 // Open a message channel for communicating with the plugin host.
67113 return new ConnectionHandle (inputFD, outputFD);
114+ #endif
68115}
69116
70- void PluginServer_destroyConnection (const void *connHandle) {
71- const auto *conn = static_cast <const ConnectionHandle *>(connHandle);
72- delete conn;
117+ void PluginServer_destroyConnection (const void *server) {
118+ delete static_cast <const ConnectionHandle *>(server);
73119}
74120
75- long PluginServer_read (const void *connHandle, void *data,
76- unsigned long nbyte) {
77- const auto *conn = static_cast <const ConnectionHandle *>(connHandle);
78- return ::read (conn->inputFD , data, nbyte);
121+ size_t PluginServer_read (const void *server, void *data, size_t nbyte) {
122+ const auto *connection = static_cast <const ConnectionHandle *>(server);
123+ #if defined(_WIN32)
124+ return _read (connection->inputFD , data, nbyte);
125+ #else
126+ return ::read (connection->inputFD , data, nbyte);
127+ #endif
79128}
80129
81- long PluginServer_write (const void *connHandle, const void *data,
82- unsigned long nbyte) {
83- const auto *conn = static_cast <const ConnectionHandle *>(connHandle);
84- return ::write (conn->outputFD , data, nbyte);
130+ size_t PluginServer_write (const void *server, const void *data, size_t nbyte) {
131+ const auto *connection = static_cast <const ConnectionHandle *>(server);
132+ #if defined(_WIN32)
133+ return _write (connection->outputFD , data, nbyte);
134+ #else
135+ return ::write (connection->outputFD , data, nbyte);
136+ #endif
85137}
86138
87- void *PluginServer_dlopen (const char *filename, const char **errorMessage) {
88- auto *handle = ::dlopen (filename, RTLD_LAZY | RTLD_LOCAL);
89- if (!handle) {
90- *errorMessage = dlerror ();
91- }
92- return handle;
139+ void *PluginServer_load (const char *plugin, const char **errorMessage) {
140+ // Use a static allocation for the error as the client will not release the
141+ // string. POSIX 2008 (IEEE-1003.1-2008) specifies that it is implementation
142+ // defined if `dlerror` is re-entrant. Take advantage of that and make it
143+ // thread-unsafe. This ensures that the string outlives the call permitting
144+ // the client to duplicate it.
145+ static std::string error;
146+ auto library = llvm::sys::DynamicLibrary::getLibrary (plugin, &error);
147+ if (library.isValid ())
148+ return library.getOSSpecificHandle ();
149+ *errorMessage = error.c_str ();
150+ return nullptr ;
93151}
94152
95153const void *PluginServer_lookupMacroTypeMetadataByExternalName (
96154 const char *moduleName, const char *typeName, void *libraryHint,
97155 const char **errorMessage) {
98-
99156 // Look up the type metadata accessor as a struct, enum, or class.
100157 const Demangle::Node::Kind typeKinds[] = {
101158 Demangle::Node::Kind::Structure,
@@ -108,8 +165,12 @@ const void *PluginServer_lookupMacroTypeMetadataByExternalName(
108165 auto symbolName =
109166 mangledNameForTypeMetadataAccessor (moduleName, typeName, typeKind);
110167
111- auto *handle = libraryHint ? libraryHint : RTLD_DEFAULT;
112- accessorAddr = ::dlsym (handle, symbolName.c_str ());
168+ #if !defined(_WIN32)
169+ if (libraryHint == nullptr )
170+ libraryHint = RTLD_DEFAULT;
171+ #endif
172+ accessorAddr = llvm::sys::DynamicLibrary{libraryHint}
173+ .getAddressOfSymbol (symbolName.c_str ());
113174 if (accessorAddr)
114175 break ;
115176 }
0 commit comments