@@ -200,6 +200,33 @@ public enum OptionalConvention: Sendable, Equatable {
200200 case sideChannelReturn
201201}
202202
203+ /// A bit pattern that is never a valid value for a type, usable to represent `nil`
204+ /// without an extra `isSome` flag. Inspired by Swift's "extra inhabitant" concept.
205+ ///
206+ /// Types with a nil sentinel can encode Optional<T> in T's own return slot:
207+ /// the sentinel value means absent, any other value means present.
208+ /// Types without a sentinel need either an inline isSome flag or a side channel.
209+ public enum NilSentinel : Sendable , Equatable {
210+ /// No sentinel exists - all bit patterns are valid values.
211+ case none
212+ /// A specific i32 value is never valid (e.g. 0 for object IDs, -1 for enum tags).
213+ case i32 ( Int32 )
214+ /// A null pointer (0) is the sentinel.
215+ case pointer
216+
217+ public var jsLiteral : String {
218+ switch self {
219+ case . none : fatalError ( " No sentinel value for .none " )
220+ case . i32 ( let value ) : return " \( value ) "
221+ case . pointer : return " 0 "
222+ }
223+ }
224+
225+ public var hasSentinel : Bool {
226+ self != . none
227+ }
228+ }
229+
203230/// Captures the WASM ABI shape for a ``BridgeType`` so codegen can read descriptor fields
204231/// instead of switching on every concrete type.
205232///
@@ -208,33 +235,32 @@ public enum OptionalConvention: Sendable, Equatable {
208235/// import side returns a pointer/ID while the export side uses the stack.
209236public struct BridgeTypeDescriptor : Sendable {
210237 public let wasmParams : [ ( name : String , type : WasmCoreType ) ]
238+ public let importParams : [ ( name : String , type : WasmCoreType ) ]
211239 public let wasmReturnType : WasmCoreType ?
212240 public let importReturnType : WasmCoreType ?
213241 public let optionalConvention : OptionalConvention
242+ public let nilSentinel : NilSentinel
214243 public let usesStackLifting : Bool
215244 public let accessorTransform : AccessorTransform
216245 public let lowerMethod : LowerMethod
217246
218- /// Creates a descriptor with an explicitly specified optional convention.
219- ///
220- /// When `optionalConvention` is nil, it is derived from `wasmParams`:
221- /// - Empty `wasmParams` (stack-based types) default to `.stackABI`
222- /// - Non-empty `wasmParams` (scalar types) default to `.inlineFlag`
223- ///
224- /// Only `.sideChannelReturn` needs to be explicitly specified.
225247 public init (
226248 wasmParams : [ ( name : String , type : WasmCoreType ) ] ,
249+ importParams : [ ( name : String , type : WasmCoreType ) ] ? = nil ,
227250 wasmReturnType : WasmCoreType ? ,
228251 importReturnType : WasmCoreType ?? = nil ,
229252 optionalConvention : OptionalConvention ? = nil ,
253+ nilSentinel : NilSentinel = . none ,
230254 usesStackLifting : Bool = false ,
231255 accessorTransform : AccessorTransform ,
232256 lowerMethod : LowerMethod
233257 ) {
234258 self . wasmParams = wasmParams
259+ self . importParams = importParams ?? wasmParams
235260 self . wasmReturnType = wasmReturnType
236261 self . importReturnType = importReturnType ?? wasmReturnType
237262 self . optionalConvention = optionalConvention ?? ( wasmParams . isEmpty ? . stackABI : . inlineFlag )
263+ self . nilSentinel = nilSentinel
238264 self . usesStackLifting = usesStackLifting
239265 self . accessorTransform = accessorTransform
240266 self . lowerMethod = lowerMethod
@@ -356,6 +382,7 @@ extension BridgeType {
356382 case . string :
357383 return BridgeTypeDescriptor (
358384 wasmParams : [ ( " bytes " , . i32 ) , ( " length " , . i32 ) ] ,
385+ importParams : [ ( " value " , . i32 ) ] ,
359386 wasmReturnType : nil ,
360387 importReturnType : . i32 ,
361388 optionalConvention : . sideChannelReturn ,
@@ -369,6 +396,7 @@ extension BridgeType {
369396 wasmParams : [ ( " value " , . i32 ) ] ,
370397 wasmReturnType : . i32 ,
371398 optionalConvention : . sideChannelReturn ,
399+ nilSentinel : . i32 ( 0 ) ,
372400 accessorTransform : transform ,
373401 lowerMethod : . stackReturn
374402 )
@@ -383,6 +411,7 @@ extension BridgeType {
383411 return BridgeTypeDescriptor (
384412 wasmParams : [ ( " pointer " , . pointer ) ] ,
385413 wasmReturnType : . pointer ,
414+ nilSentinel : . pointer ,
386415 accessorTransform : . identity ,
387416 lowerMethod : . stackReturn
388417 )
@@ -398,13 +427,15 @@ extension BridgeType {
398427 wasmParams : [ ( " value " , . i32 ) ] ,
399428 wasmReturnType : . i32 ,
400429 optionalConvention : . sideChannelReturn ,
430+ nilSentinel : . i32 ( 0 ) ,
401431 accessorTransform : . cast ( " Any \( protocolName ) " ) ,
402432 lowerMethod : . stackReturn
403433 )
404434 case . caseEnum :
405435 return BridgeTypeDescriptor (
406436 wasmParams : [ ( " value " , . i32 ) ] ,
407437 wasmReturnType : . i32 ,
438+ nilSentinel : . i32 ( - 1 ) ,
408439 accessorTransform : . identity ,
409440 lowerMethod : . stackReturn
410441 )
@@ -413,6 +444,7 @@ extension BridgeType {
413444 case . string :
414445 return BridgeTypeDescriptor (
415446 wasmParams : [ ( " bytes " , . i32 ) , ( " length " , . i32 ) ] ,
447+ importParams : [ ( " value " , . i32 ) ] ,
416448 wasmReturnType : nil ,
417449 importReturnType : . some ( . i32 ) ,
418450 optionalConvention : . sideChannelReturn ,
@@ -456,6 +488,7 @@ extension BridgeType {
456488 wasmParams : [ ( " caseId " , . i32 ) ] ,
457489 wasmReturnType : nil ,
458490 importReturnType : . i32 ,
491+ nilSentinel : . i32 ( - 1 ) ,
459492 usesStackLifting : true ,
460493 accessorTransform : . identity ,
461494 lowerMethod : . pushParameter
@@ -470,7 +503,9 @@ extension BridgeType {
470503 case . swiftStruct :
471504 return BridgeTypeDescriptor (
472505 wasmParams : [ ] ,
506+ importParams : [ ( " objectId " , . i32 ) ] ,
473507 wasmReturnType : nil ,
508+ importReturnType : . i32 ,
474509 usesStackLifting : true ,
475510 accessorTransform : . identity ,
476511 lowerMethod : . fullReturn
0 commit comments