99//
1010//===----------------------------------------------------------------------===//
1111
12+ @_implementationOnly import _RegexParser
13+
1214extension Instruction {
1315 /// An instruction's payload packs operands and destination
1416 /// registers.
@@ -330,7 +332,9 @@ extension Instruction.Payload {
330332 ) {
331333 interpretPair ( )
332334 }
335+
333336 // MARK: Struct payloads
337+
334338 init ( _ model: _CharacterClassModel ) {
335339 self . init ( CharacterClassPayload ( model) . rawValue)
336340 }
@@ -342,11 +346,169 @@ extension Instruction.Payload {
342346 self . init ( rawValue: payload. rawValue)
343347 }
344348 var assertion : AssertionPayload {
345- AssertionPayload . init ( rawValue: self . rawValue & _payloadMask)
349+ AssertionPayload . init ( rawValue: rawValue & _payloadMask)
350+ }
351+ init ( quantify: QuantifyPayload ) {
352+ self . init ( quantify. rawValue)
353+ }
354+ var quantify : QuantifyPayload {
355+ return QuantifyPayload ( rawValue: rawValue & _payloadMask)
346356 }
347357}
348358
349359// MARK: Struct definitions
360+ struct QuantifyPayload : RawRepresentable {
361+ let rawValue : UInt64
362+ enum PayloadType : UInt64 {
363+ case bitset = 0
364+ case asciiChar = 1
365+ case any = 2
366+ case builtin = 4
367+ }
368+
369+ // Future work: optimize this layout -> payload type should be a fast switch
370+ // The top 8 bits are reserved for the opcode so we have 56 bits to work with
371+ // b55-b38 - Unused
372+ // b38-b35 - Payload type (one of 4 types, stored on 3 bits)
373+ // b35-b27 - minTrips (8 bit int)
374+ // b27-b18 - extraTrips (8 bit value, one bit for nil)
375+ // b18-b16 - Quantification type (one of three types)
376+ // b16-b0 - Payload value (depends on payload type)
377+ static var quantKindShift : UInt64 { 16 }
378+ static var extraTripsShift : UInt64 { 18 }
379+ static var minTripsShift : UInt64 { 27 }
380+ static var typeShift : UInt64 { 35 }
381+ static var maxStorableTrips : UInt64 { ( 1 << 8 ) - 1 }
382+
383+ var quantKindMask : UInt64 { 3 }
384+ var extraTripsMask : UInt64 { 0x1FF }
385+ var minTripsMask : UInt64 { 0xFF }
386+ var typeMask : UInt64 { 7 }
387+ var payloadMask : UInt64 { 0xFF_FF }
388+
389+ static func packInfoValues(
390+ _ kind: AST . Quantification . Kind ,
391+ _ minTrips: Int ,
392+ _ extraTrips: Int ? ,
393+ _ type: PayloadType
394+ ) -> UInt64 {
395+ let kindVal : UInt64
396+ switch kind {
397+ case . eager:
398+ kindVal = 0
399+ case . reluctant:
400+ kindVal = 1
401+ case . possessive:
402+ kindVal = 2
403+ }
404+ let extraTripsVal : UInt64 = extraTrips == nil ? 1 : UInt64 ( extraTrips!) << 1
405+ return ( kindVal << QuantifyPayload . quantKindShift) +
406+ ( extraTripsVal << QuantifyPayload . extraTripsShift) +
407+ ( UInt64 ( minTrips) << QuantifyPayload . minTripsShift) +
408+ ( type. rawValue << QuantifyPayload . typeShift)
409+ }
410+
411+ init ( rawValue: UInt64 ) {
412+ self . rawValue = rawValue
413+ assert ( rawValue & _opcodeMask == 0 )
414+ }
415+
416+ init (
417+ bitset: AsciiBitsetRegister ,
418+ _ kind: AST . Quantification . Kind ,
419+ _ minTrips: Int ,
420+ _ extraTrips: Int ?
421+ ) {
422+ assert ( bitset. bits <= _payloadMask)
423+ self . rawValue = bitset. bits
424+ + QuantifyPayload. packInfoValues ( kind, minTrips, extraTrips, . bitset)
425+ }
426+
427+ init (
428+ asciiChar: UInt8 ,
429+ _ kind: AST . Quantification . Kind ,
430+ _ minTrips: Int ,
431+ _ extraTrips: Int ?
432+ ) {
433+ self . rawValue = UInt64 ( asciiChar)
434+ + QuantifyPayload. packInfoValues ( kind, minTrips, extraTrips, . asciiChar)
435+ }
436+
437+ init (
438+ matchesNewlines: Bool ,
439+ _ kind: AST . Quantification . Kind ,
440+ _ minTrips: Int ,
441+ _ extraTrips: Int ?
442+ ) {
443+ self . rawValue = ( matchesNewlines ? 1 : 0 )
444+ + QuantifyPayload. packInfoValues ( kind, minTrips, extraTrips, . any)
445+ }
446+
447+ init (
448+ model: _CharacterClassModel ,
449+ _ kind: AST . Quantification . Kind ,
450+ _ minTrips: Int ,
451+ _ extraTrips: Int ?
452+ ) {
453+ assert ( model. cc. rawValue < 0xFF )
454+ assert ( model. matchLevel != . unicodeScalar)
455+ let packedModel = model. cc. rawValue
456+ + ( model. isInverted ? 1 << 9 : 0 )
457+ + ( model. isStrictASCII ? 1 << 10 : 0 )
458+ self . rawValue = packedModel
459+ + QuantifyPayload. packInfoValues ( kind, minTrips, extraTrips, . builtin)
460+ }
461+
462+ var type : PayloadType {
463+ PayloadType ( rawValue: ( self . rawValue >> QuantifyPayload . typeShift) & 7 ) !
464+ }
465+
466+ var quantKind : AST . Quantification . Kind {
467+ switch ( self . rawValue >> QuantifyPayload . quantKindShift) & quantKindMask {
468+ case 0 : return . eager
469+ case 1 : return . reluctant
470+ case 2 : return . possessive
471+ default :
472+ fatalError ( " Unreachable " )
473+ }
474+ }
475+
476+ var minTrips : UInt64 {
477+ ( self . rawValue >> QuantifyPayload . minTripsShift) & minTripsMask
478+ }
479+
480+ var extraTrips : UInt64 ? {
481+ let val = ( self . rawValue >> QuantifyPayload . extraTripsShift) & extraTripsMask
482+ if val == 1 {
483+ return nil
484+ } else {
485+ return val >> 1
486+ }
487+ }
488+
489+ var bitset : AsciiBitsetRegister {
490+ TypedInt ( self . rawValue & payloadMask)
491+ }
492+
493+ var asciiChar : UInt8 {
494+ UInt8 ( asserting: self . rawValue & payloadMask)
495+ }
496+
497+ var anyMatchesNewline : Bool {
498+ ( self . rawValue & 1 ) == 1
499+ }
500+
501+ var builtin : _CharacterClassModel . Representation {
502+ _CharacterClassModel. Representation ( rawValue: self . rawValue & 0xFF ) !
503+ }
504+ var builtinIsInverted : Bool {
505+ ( self . rawValue >> 9 ) & 1 == 1
506+ }
507+ var builtinIsStrict : Bool {
508+ ( self . rawValue >> 10 ) & 1 == 1
509+ }
510+ }
511+
350512struct CharacterClassPayload : RawRepresentable {
351513 let rawValue : UInt64
352514 // Layout:
0 commit comments