@@ -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