@@ -16,6 +16,7 @@ struct Function {
1616 doc : & ' static str ,
1717}
1818
19+ static BOOL : Type = Type :: PrimBool ;
1920static F16 : Type = Type :: PrimFloat ( 16 ) ;
2021static F32 : Type = Type :: PrimFloat ( 32 ) ;
2122static F64 : Type = Type :: PrimFloat ( 64 ) ;
@@ -28,6 +29,7 @@ static U32: Type = Type::PrimUnsigned(32);
2829static U64 : Type = Type :: PrimUnsigned ( 64 ) ;
2930static U8 : Type = Type :: PrimUnsigned ( 8 ) ;
3031static NEVER : Type = Type :: Never ;
32+ static VOID : Type = Type :: Void ;
3133static GENERICT : Type = Type :: GenericParam ( "T" ) ;
3234static GENERICU : Type = Type :: GenericParam ( "U" ) ;
3335
@@ -151,19 +153,78 @@ static U8X8X2: Type = Type::U(8, 8, 2);
151153static U8X8X3 : Type = Type :: U ( 8 , 8 , 3 ) ;
152154static U8X8X4 : Type = Type :: U ( 8 , 8 , 4 ) ;
153155
156+ static SVBOOL : Type = Type :: Pred ( 1 ) ;
157+ static SVBOOLX2 : Type = Type :: Pred ( 2 ) ;
158+ static SVBOOLX3 : Type = Type :: Pred ( 3 ) ;
159+ static SVBOOLX4 : Type = Type :: Pred ( 4 ) ;
160+ static SVCOUNT : Type = Type :: Pred ( 1 ) ;
161+ static SVF16 : Type = Type :: SVF ( 16 , 1 ) ;
162+ static SVF16X2 : Type = Type :: SVF ( 16 , 2 ) ;
163+ static SVF16X3 : Type = Type :: SVF ( 16 , 3 ) ;
164+ static SVF16X4 : Type = Type :: SVF ( 16 , 4 ) ;
165+ static SVF32 : Type = Type :: SVF ( 32 , 1 ) ;
166+ static SVF32X2 : Type = Type :: SVF ( 32 , 2 ) ;
167+ static SVF32X3 : Type = Type :: SVF ( 32 , 3 ) ;
168+ static SVF32X4 : Type = Type :: SVF ( 32 , 4 ) ;
169+ static SVF64 : Type = Type :: SVF ( 64 , 1 ) ;
170+ static SVF64X2 : Type = Type :: SVF ( 64 , 2 ) ;
171+ static SVF64X3 : Type = Type :: SVF ( 64 , 3 ) ;
172+ static SVF64X4 : Type = Type :: SVF ( 64 , 4 ) ;
173+ static SVI8 : Type = Type :: SVI ( 8 , 1 ) ;
174+ static SVI8X2 : Type = Type :: SVI ( 8 , 2 ) ;
175+ static SVI8X3 : Type = Type :: SVI ( 8 , 3 ) ;
176+ static SVI8X4 : Type = Type :: SVI ( 8 , 4 ) ;
177+ static SVI16 : Type = Type :: SVI ( 16 , 1 ) ;
178+ static SVI16X2 : Type = Type :: SVI ( 16 , 2 ) ;
179+ static SVI16X3 : Type = Type :: SVI ( 16 , 3 ) ;
180+ static SVI16X4 : Type = Type :: SVI ( 16 , 4 ) ;
181+ static SVI32 : Type = Type :: SVI ( 32 , 1 ) ;
182+ static SVI32X2 : Type = Type :: SVI ( 32 , 2 ) ;
183+ static SVI32X3 : Type = Type :: SVI ( 32 , 3 ) ;
184+ static SVI32X4 : Type = Type :: SVI ( 32 , 4 ) ;
185+ static SVI64 : Type = Type :: SVI ( 64 , 1 ) ;
186+ static SVI64X2 : Type = Type :: SVI ( 64 , 2 ) ;
187+ static SVI64X3 : Type = Type :: SVI ( 64 , 3 ) ;
188+ static SVI64X4 : Type = Type :: SVI ( 64 , 4 ) ;
189+ static SVU8 : Type = Type :: SVU ( 8 , 1 ) ;
190+ static SVU8X2 : Type = Type :: SVU ( 8 , 2 ) ;
191+ static SVU8X3 : Type = Type :: SVU ( 8 , 3 ) ;
192+ static SVU8X4 : Type = Type :: SVU ( 8 , 4 ) ;
193+ static SVU16 : Type = Type :: SVU ( 16 , 1 ) ;
194+ static SVU16X2 : Type = Type :: SVU ( 16 , 2 ) ;
195+ static SVU16X3 : Type = Type :: SVU ( 16 , 3 ) ;
196+ static SVU16X4 : Type = Type :: SVU ( 16 , 4 ) ;
197+ static SVU32 : Type = Type :: SVU ( 32 , 1 ) ;
198+ static SVU32X2 : Type = Type :: SVU ( 32 , 2 ) ;
199+ static SVU32X3 : Type = Type :: SVU ( 32 , 3 ) ;
200+ static SVU32X4 : Type = Type :: SVU ( 32 , 4 ) ;
201+ static SVU64 : Type = Type :: SVU ( 64 , 1 ) ;
202+ static SVU64X2 : Type = Type :: SVU ( 64 , 2 ) ;
203+ static SVU64X3 : Type = Type :: SVU ( 64 , 3 ) ;
204+ static SVU64X4 : Type = Type :: SVU ( 64 , 4 ) ;
205+ static SVPRFOP : Type = Type :: Enum ( "svprfop" ) ;
206+ static SVPATTERN : Type = Type :: Enum ( "svpattern" ) ;
207+
154208#[ derive( Debug , Copy , Clone , PartialEq ) ]
155209enum Type {
210+ Void ,
211+ PrimBool ,
156212 PrimFloat ( u8 ) ,
157213 PrimSigned ( u8 ) ,
158214 PrimUnsigned ( u8 ) ,
159215 PrimPoly ( u8 ) ,
160216 MutPtr ( & ' static Type ) ,
161217 ConstPtr ( & ' static Type ) ,
218+ Enum ( & ' static str ) ,
162219 GenericParam ( & ' static str ) ,
163220 I ( u8 , u8 , u8 ) ,
164221 U ( u8 , u8 , u8 ) ,
165222 P ( u8 , u8 , u8 ) ,
166223 F ( u8 , u8 , u8 ) ,
224+ Pred ( u8 ) ,
225+ SVI ( u8 , u8 ) ,
226+ SVU ( u8 , u8 ) ,
227+ SVF ( u8 , u8 ) ,
167228 Never ,
168229}
169230
@@ -182,19 +243,18 @@ fn verify_all_signatures() {
182243
183244 let mut all_valid = true ;
184245 for rust in FUNCTIONS {
246+ // Most SVE intrinsics just rely on the intrinsics test tool for validation
185247 if !rust. has_test {
186- if !SKIP_RUNTIME_TESTS . contains ( & rust. name ) {
187- println ! (
188- "missing run-time test named `test_{}` for `{}`" ,
189- {
190- let mut id = rust. name;
191- while id. starts_with( '_' ) {
192- id = & id[ 1 ..] ;
193- }
194- id
195- } ,
196- rust. name
197- ) ;
248+ if !SKIP_RUNTIME_TESTS . contains ( & rust. name )
249+ // Most run-time tests are handled by the intrinsic-test tool, except for
250+ // load/stores (which have generated tests)
251+ && ( !rust. name . starts_with ( "sv" ) || rust. name . starts_with ( "svld" )
252+ || rust. name . starts_with ( "svst" ) )
253+ // The load/store test generator can't handle these cases yet
254+ && ( !rust. name . contains ( "_u32base_" ) || rust. name . contains ( "index" ) || rust. name . contains ( "offset" ) )
255+ && !( rust. name . starts_with ( "svldff1" ) && rust. name . contains ( "gather" ) )
256+ {
257+ println ! ( "missing run-time test for `{}`" , rust. name) ;
198258 all_valid = false ;
199259 }
200260 }
@@ -269,12 +329,21 @@ fn matches(rust: &Function, arm: &Intrinsic) -> Result<(), String> {
269329 let mut nconst = 0 ;
270330 let iter = rust. arguments . iter ( ) . zip ( & arm. arguments ) . enumerate ( ) ;
271331 for ( i, ( rust_ty, ( arm, arm_const) ) ) in iter {
272- if * rust_ty != arm {
273- bail ! ( "mismatched arguments: {rust_ty:?} != {arm:?}" )
332+ match ( * rust_ty, arm) {
333+ // SVE uses generic type parameters to handle void pointers
334+ ( Type :: ConstPtr ( Type :: GenericParam ( "T" ) ) , Type :: ConstPtr ( Type :: Void ) ) => ( ) ,
335+ // SVE const generics use i32 over u64 for usability reasons
336+ ( Type :: PrimSigned ( 32 ) , Type :: PrimUnsigned ( 64 ) ) if rust. required_const . contains ( & i) => {
337+ ( )
338+ }
339+ // svset doesn't have its const argument last as we assumed when building the Function
340+ _ if rust. name . starts_with ( "svset" ) => ( ) ,
341+ ( x, y) if x == y => ( ) ,
342+ _ => bail ! ( "mismatched arguments: {rust_ty:?} != {arm:?}" ) ,
274343 }
275344 if * arm_const {
276345 nconst += 1 ;
277- if !rust. required_const . contains ( & i) {
346+ if !rust. required_const . contains ( & i) && !rust . name . starts_with ( "svset" ) {
278347 bail ! ( "argument const mismatch" ) ;
279348 }
280349 }
@@ -283,7 +352,7 @@ fn matches(rust: &Function, arm: &Intrinsic) -> Result<(), String> {
283352 bail ! ( "wrong number of const arguments" ) ;
284353 }
285354
286- if rust. instrs . is_empty ( ) {
355+ if rust. instrs . is_empty ( ) && arm . instruction != "" {
287356 bail ! (
288357 "instruction not listed for `{}`, but arm lists {:?}" ,
289358 rust. name,
@@ -322,7 +391,7 @@ fn matches(rust: &Function, arm: &Intrinsic) -> Result<(), String> {
322391 Ok ( ( ) )
323392}
324393
325- #[ derive( PartialEq ) ]
394+ #[ derive( Debug , PartialEq ) ]
326395struct Intrinsic {
327396 name : String ,
328397 ret : Option < Type > ,
@@ -337,7 +406,7 @@ struct JsonIntrinsic {
337406 arguments : Vec < String > ,
338407 return_type : ReturnType ,
339408 #[ serde( default ) ]
340- instructions : Vec < Vec < String > > ,
409+ instructions : Option < Vec < Vec < String > > > ,
341410}
342411
343412#[ derive( Deserialize , Debug ) ]
@@ -356,6 +425,8 @@ fn parse_intrinsics(intrinsics: Vec<JsonIntrinsic>) -> HashMap<String, Intrinsic
356425
357426fn parse_intrinsic ( mut intr : JsonIntrinsic ) -> Intrinsic {
358427 let name = intr. name ;
428+ // Remove '[' and ']' so that intrinsics of the form `svwhilerw[_s16]` becomes `svwhilerw_s16`.
429+ let name = name. replace ( '[' , "" ) . replace ( ']' , "" ) ;
359430 let ret = if intr. return_type . value == "void" {
360431 None
361432 } else {
@@ -364,18 +435,24 @@ fn parse_intrinsic(mut intr: JsonIntrinsic) -> Intrinsic {
364435
365436 // This ignores multiple instructions and different optional sequences for now to mimic
366437 // the old HTML scraping behaviour
367- let instruction = intr. instructions . swap_remove ( 0 ) . swap_remove ( 0 ) ;
438+ let instruction = intr
439+ . instructions
440+ . map_or ( String :: new ( ) , |mut i| i. swap_remove ( 0 ) . swap_remove ( 0 ) ) ;
368441
369442 let arguments = intr
370443 . arguments
371444 . iter ( )
372445 . map ( |s| {
373- let ( ty, konst) = match s. strip_prefix ( "const" ) {
374- Some ( stripped) => ( stripped. trim_start ( ) , true ) ,
375- None => ( s. as_str ( ) , false ) ,
446+ let ty = if let Some ( i) = s. find ( '*' ) {
447+ & s[ ..i + 1 ]
448+ } else {
449+ s. rsplit_once ( ' ' ) . unwrap ( ) . 0 . trim_start_matches ( "const " )
376450 } ;
377- let ty = ty. rsplit_once ( ' ' ) . unwrap ( ) . 0 ;
378- ( parse_ty ( ty) , konst)
451+ let ty = parse_ty ( ty) ;
452+ let konst = s. contains ( "const" ) && !matches ! ( ty, Type :: ConstPtr ( _) )
453+ || s. starts_with ( "enum" )
454+ || s. rsplit_once ( " " ) . unwrap ( ) . 1 . starts_with ( "imm" ) ;
455+ ( ty, konst)
379456 } )
380457 . collect :: < Vec < _ > > ( ) ;
381458
@@ -388,18 +465,27 @@ fn parse_intrinsic(mut intr: JsonIntrinsic) -> Intrinsic {
388465}
389466
390467fn parse_ty ( s : & str ) -> Type {
391- let suffix = " const *" ;
392- if let Some ( base) = s. strip_suffix ( suffix) {
393- Type :: ConstPtr ( parse_ty_base ( base) )
394- } else if let Some ( base) = s. strip_suffix ( " *" ) {
395- Type :: MutPtr ( parse_ty_base ( base) )
468+ if let Some ( ty) = s. strip_suffix ( "*" ) {
469+ let ty = ty. trim ( ) ;
470+ if let Some ( ty) = ty. strip_prefix ( "const" ) {
471+ // SVE intrinsics are west-const (`const int8_t *`)
472+ Type :: ConstPtr ( parse_ty_base ( ty) )
473+ } else if let Some ( ty) = ty. strip_suffix ( "const" ) {
474+ // Neon intrinsics are east-const (`int8_t const *`)
475+ Type :: ConstPtr ( parse_ty_base ( ty) )
476+ } else {
477+ Type :: MutPtr ( parse_ty_base ( ty) )
478+ }
396479 } else {
397480 * parse_ty_base ( s)
398481 }
399482}
400483
401484fn parse_ty_base ( s : & str ) -> & ' static Type {
485+ let s = s. trim ( ) ;
402486 match s {
487+ "bool" => & BOOL ,
488+ "void" => & VOID ,
403489 "float16_t" => & F16 ,
404490 "float16x4_t" => & F16X4 ,
405491 "float16x4x2_t" => & F16X4X2 ,
@@ -529,6 +615,57 @@ fn parse_ty_base(s: &str) -> &'static Type {
529615 "uint8x8x2_t" => & U8X8X2 ,
530616 "uint8x8x3_t" => & U8X8X3 ,
531617 "uint8x8x4_t" => & U8X8X4 ,
618+ "svbool_t" => & SVBOOL ,
619+ "svboolx2_t" => & SVBOOLX2 ,
620+ "svboolx3_t" => & SVBOOLX3 ,
621+ "svboolx4_t" => & SVBOOLX4 ,
622+ "svcount_t" => & SVCOUNT ,
623+ "svfloat16_t" => & SVF16 ,
624+ "svfloat16x2_t" => & SVF16X2 ,
625+ "svfloat16x3_t" => & SVF16X3 ,
626+ "svfloat16x4_t" => & SVF16X4 ,
627+ "svfloat32_t" => & SVF32 ,
628+ "svfloat32x2_t" => & SVF32X2 ,
629+ "svfloat32x3_t" => & SVF32X3 ,
630+ "svfloat32x4_t" => & SVF32X4 ,
631+ "svfloat64_t" => & SVF64 ,
632+ "svfloat64x2_t" => & SVF64X2 ,
633+ "svfloat64x3_t" => & SVF64X3 ,
634+ "svfloat64x4_t" => & SVF64X4 ,
635+ "svint8_t" => & SVI8 ,
636+ "svint8x2_t" => & SVI8X2 ,
637+ "svint8x3_t" => & SVI8X3 ,
638+ "svint8x4_t" => & SVI8X4 ,
639+ "svint16_t" => & SVI16 ,
640+ "svint16x2_t" => & SVI16X2 ,
641+ "svint16x3_t" => & SVI16X3 ,
642+ "svint16x4_t" => & SVI16X4 ,
643+ "svint32_t" => & SVI32 ,
644+ "svint32x2_t" => & SVI32X2 ,
645+ "svint32x3_t" => & SVI32X3 ,
646+ "svint32x4_t" => & SVI32X4 ,
647+ "svint64_t" => & SVI64 ,
648+ "svint64x2_t" => & SVI64X2 ,
649+ "svint64x3_t" => & SVI64X3 ,
650+ "svint64x4_t" => & SVI64X4 ,
651+ "svuint8_t" => & SVU8 ,
652+ "svuint8x2_t" => & SVU8X2 ,
653+ "svuint8x3_t" => & SVU8X3 ,
654+ "svuint8x4_t" => & SVU8X4 ,
655+ "svuint16_t" => & SVU16 ,
656+ "svuint16x2_t" => & SVU16X2 ,
657+ "svuint16x3_t" => & SVU16X3 ,
658+ "svuint16x4_t" => & SVU16X4 ,
659+ "svuint32_t" => & SVU32 ,
660+ "svuint32x2_t" => & SVU32X2 ,
661+ "svuint32x3_t" => & SVU32X3 ,
662+ "svuint32x4_t" => & SVU32X4 ,
663+ "svuint64_t" => & SVU64 ,
664+ "svuint64x2_t" => & SVU64X2 ,
665+ "svuint64x3_t" => & SVU64X3 ,
666+ "svuint64x4_t" => & SVU64X4 ,
667+ "enum svprfop" => & SVPRFOP ,
668+ "enum svpattern" => & SVPATTERN ,
532669
533670 _ => panic ! ( "failed to parse json type {s:?}" ) ,
534671 }
0 commit comments