Skip to content

Commit 158ddd5

Browse files
committed
Rebase
1 parent a7d8cbe commit 158ddd5

File tree

5 files changed

+96
-4
lines changed

5 files changed

+96
-4
lines changed

Sources/SwiftCompilerPlugin/CompilerPlugin.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,45 @@ extension CompilerPlugin {
112112
let connection = try StandardIOMessageConnection()
113113
let provider = MacroProviderAdapter(plugin: Self())
114114
let impl = CompilerPluginMessageListener(connection: connection, provider: provider)
115+
#if os(WASI)
116+
// Rather than blocking on read(), let the host tell us when there's data.
117+
readabilityHandler = {
118+
do {
119+
_ = try impl.handleNextMessage()
120+
} catch {
121+
internalError("\(error)")
122+
}
123+
}
124+
#else
115125
do {
116126
try impl.main()
117127
} catch {
118128
// Emit a diagnostic and indicate failure to the plugin host,
119129
// and exit with an error code.
120130
fatalError("Internal Error: \(error)")
121131
}
132+
#endif
122133
}
123134
}
135+
136+
#if os(WASI)
137+
138+
/// A callback invoked by the Wasm Host when new data is available on `stdin`.
139+
///
140+
/// This is safe to access without serialization as Wasm plugins are single-threaded.
141+
nonisolated(unsafe) private var readabilityHandler: () -> Void = {
142+
internalError("""
143+
CompilerPlugin.main wasn't called. Did you annotate your plugin with '@main'?
144+
""")
145+
}
146+
147+
// We can use @_expose(wasm, ...) with compiler >= 6.0
148+
// but it causes build errors with older compilers.
149+
// Instead, we export from wasm_support.c and trampoline
150+
// to this method.
151+
@_cdecl("_swift_wasm_macro_pump")
152+
func wasmPump() {
153+
readabilityHandler()
154+
}
155+
156+
#endif

Sources/SwiftCompilerPluginMessageHandling/CompilerPluginMessageHandler.swift

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,20 @@ public class CompilerPluginMessageListener<Connection: MessageConnection, Provid
8686
/// Throws an error when it failed to send/receive the message, or failed
8787
/// to serialize/deserialize the message.
8888
public func main() throws {
89-
while let message = try connection.waitForNextMessage(HostToPluginMessage.self) {
90-
let result = handler.handleMessage(message)
91-
try connection.sendMessage(result)
89+
while try handleNextMessage() {}
90+
}
91+
92+
/// Receives and handles a single message from the plugin host.
93+
///
94+
/// - Returns: `true` if there was a message to read, `false`
95+
/// if the end-of-file was reached.
96+
public func handleNextMessage() throws -> Bool {
97+
guard let message = try connection.waitForNextMessage(HostToPluginMessage.self) else {
98+
return false
9299
}
100+
let result = handler.handleMessage(message)
101+
try connection.sendMessage(result)
102+
return true
93103
}
94104
}
95105

Sources/SwiftCompilerPluginMessageHandling/StandardIOMessageConnection.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ public struct StandardIOMessageConnection: MessageConnection {
4848
/// - Duplicate the original `stdin` and `stdout` for use as messaging
4949
/// pipes, and are not directly used by the plugin logic
5050
public init() throws {
51+
#if os(WASI)
52+
// Wasm doesn't support dup{,2} so we use the original file descriptors.
53+
let inputFD = fileno(_stdin)
54+
let outputFD = fileno(_stdout)
55+
#else
5156
// Duplicate the `stdin` file descriptor, which we will then use for
5257
// receiving messages from the plugin host.
5358
let inputFD = dup(fileno(_stdin))
@@ -80,6 +85,7 @@ public struct StandardIOMessageConnection: MessageConnection {
8085
_ = _setmode(inputFD, _O_BINARY)
8186
_ = _setmode(outputFD, _O_BINARY)
8287
#endif
88+
#endif
8389

8490
self.init(inputFileDescriptor: inputFD, outputFileDescriptor: outputFD)
8591
}
@@ -146,6 +152,15 @@ public struct StandardIOMessageConnection: MessageConnection {
146152
}
147153
}
148154

155+
#if os(WASI)
156+
// fatalError writes to stdout, which is the message
157+
// output stream under WASI
158+
public func internalError(_ message: String) -> Never {
159+
fputs("Internal Error: \(message)\n", _stderr)
160+
exit(1)
161+
}
162+
#endif
163+
149164
private enum IOError: Error, CustomStringConvertible {
150165
case readReachedEndOfInput
151166
case systemError(function: String, errno: CInt)

Sources/_SwiftSyntaxCShims/dummy.c

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#if defined(__wasm32__)
14+
15+
// uint32_t
16+
#define SWIFT_WASM_MACRO_ABI 1
17+
18+
#define _STR(X) #X
19+
#define STR(X) _STR(X)
20+
21+
// LLVM has special-cased handling to map .custom_section.foo to
22+
// Wasm Custom Section "foo". this must be a metadata section rather
23+
// than a data section so we can't use __attribute__((section)) for it.
24+
// See: https://reviews.llvm.org/D43097
25+
__asm__("\t.section .custom_section.swift_wasm_macro_abi,\"\",@\n\t.4byte " STR(SWIFT_WASM_MACRO_ABI) "\n");
26+
27+
// defined in CompilerPlugin.swift
28+
void _swift_wasm_macro_pump(void);
29+
30+
__attribute__((export_name("swift_wasm_macro_pump")))
31+
void swift_wasm_macro_pump(void) {
32+
_swift_wasm_macro_pump();
33+
}
34+
35+
#endif

0 commit comments

Comments
 (0)