@@ -67,7 +67,7 @@ static TUPLE: Type = Type::Tuple;
6767static CPUID : Type = Type :: CpuidResult ;
6868static NEVER : Type = Type :: Never ;
6969
70- #[ derive( Debug ) ]
70+ #[ derive( Debug , PartialEq , Copy , Clone ) ]
7171enum Type {
7272 PrimFloat ( u8 ) ,
7373 PrimSigned ( u8 ) ,
@@ -520,7 +520,7 @@ fn matches(rust: &Function, intel: &Intrinsic) -> Result<(), String> {
520520
521521 // Make sure we've got the right return type.
522522 if let Some ( t) = rust. ret {
523- equate ( t, & intel. return_ . type_ , "" , rust . name , false ) ?;
523+ equate ( t, & intel. return_ . type_ , "" , intel , false ) ?;
524524 } else if !intel. return_ . type_ . is_empty ( ) && intel. return_ . type_ != "void" {
525525 bail ! (
526526 "{} returns `{}` with intel, void in rust" ,
@@ -542,7 +542,7 @@ fn matches(rust: &Function, intel: &Intrinsic) -> Result<(), String> {
542542 }
543543 for ( i, ( a, b) ) in intel. parameters . iter ( ) . zip ( rust. arguments ) . enumerate ( ) {
544544 let is_const = rust. required_const . contains ( & i) ;
545- equate ( b, & a. type_ , & a. etype , & intel. name , is_const) ?;
545+ equate ( b, & a. type_ , & a. etype , & intel, is_const) ?;
546546 }
547547 }
548548
@@ -655,11 +655,59 @@ fn matches(rust: &Function, intel: &Intrinsic) -> Result<(), String> {
655655 Ok ( ( ) )
656656}
657657
658+ fn pointed_type ( intrinsic : & Intrinsic ) -> Result < Type , String > {
659+ Ok (
660+ if intrinsic. tech == "AMX"
661+ || intrinsic
662+ . cpuid
663+ . iter ( )
664+ . any ( |cpuid| matches ! ( & * * cpuid, "KEYLOCKER" | "KEYLOCKER_WIDE" | "XSAVE" | "FXSR" ) )
665+ {
666+ // AMX, KEYLOCKER and XSAVE intrinsics should take `*u8`
667+ U8
668+ } else if intrinsic. name == "_mm_clflush" {
669+ // Just a false match in the following logic
670+ U8
671+ } else if [ "_mm_storeu_si" , "_mm_loadu_si" ]
672+ . iter ( )
673+ . any ( |x| intrinsic. name . starts_with ( x) )
674+ {
675+ // These have already been stabilized, so cannot be changed anymore
676+ U8
677+ } else if intrinsic. name . ends_with ( "i8" ) {
678+ I8
679+ } else if intrinsic. name . ends_with ( "i16" ) {
680+ I16
681+ } else if intrinsic. name . ends_with ( "i32" ) {
682+ I32
683+ } else if intrinsic. name . ends_with ( "i64" ) {
684+ I64
685+ } else if intrinsic. name . ends_with ( "i128" ) {
686+ M128I
687+ } else if intrinsic. name . ends_with ( "i256" ) {
688+ M256I
689+ } else if intrinsic. name . ends_with ( "i512" ) {
690+ M512I
691+ } else if intrinsic. name . ends_with ( "h" ) {
692+ F16
693+ } else if intrinsic. name . ends_with ( "s" ) {
694+ F32
695+ } else if intrinsic. name . ends_with ( "d" ) {
696+ F64
697+ } else {
698+ bail ! (
699+ "Don't know what type of *void to use for {}" ,
700+ intrinsic. name
701+ ) ;
702+ } ,
703+ )
704+ }
705+
658706fn equate (
659707 t : & Type ,
660708 intel : & str ,
661709 etype : & str ,
662- intrinsic : & str ,
710+ intrinsic : & Intrinsic ,
663711 is_const : bool ,
664712) -> Result < ( ) , String > {
665713 // Make pointer adjacent to the type: float * foo => float* foo
@@ -676,7 +724,7 @@ fn equate(
676724 if etype == "IMM" || intel == "constexpr int" {
677725 // The _bittest intrinsics claim to only accept immediates but actually
678726 // accept run-time values as well.
679- if !is_const && !intrinsic. starts_with ( "_bittest" ) {
727+ if !is_const && !intrinsic. name . starts_with ( "_bittest" ) {
680728 bail ! ( "argument required to be const but isn't" ) ;
681729 }
682730 } else {
@@ -723,7 +771,16 @@ fn equate(
723771 ( & Type :: MMASK16 , "__mmask16" ) => { }
724772 ( & Type :: MMASK8 , "__mmask8" ) => { }
725773
726- ( & Type :: MutPtr ( _) , "void*" ) => { }
774+ ( & Type :: MutPtr ( _type) , "void*" ) | ( & Type :: ConstPtr ( _type) , "void const*" ) => {
775+ let pointed_type = pointed_type ( intrinsic) ?;
776+ if _type != & pointed_type {
777+ bail ! (
778+ "incorrect void pointer type {_type:?} in {}, should be pointer to {pointed_type:?}" ,
779+ intrinsic. name,
780+ ) ;
781+ }
782+ }
783+
727784 ( & Type :: MutPtr ( & Type :: PrimFloat ( 32 ) ) , "float*" ) => { }
728785 ( & Type :: MutPtr ( & Type :: PrimFloat ( 64 ) ) , "double*" ) => { }
729786 ( & Type :: MutPtr ( & Type :: PrimSigned ( 8 ) ) , "char*" ) => { }
@@ -752,7 +809,6 @@ fn equate(
752809 ( & Type :: MutPtr ( & Type :: M512I ) , "__m512i*" ) => { }
753810 ( & Type :: MutPtr ( & Type :: M512D ) , "__m512d*" ) => { }
754811
755- ( & Type :: ConstPtr ( _) , "void const*" ) => { }
756812 ( & Type :: ConstPtr ( & Type :: PrimFloat ( 16 ) ) , "_Float16 const*" ) => { }
757813 ( & Type :: ConstPtr ( & Type :: PrimFloat ( 32 ) ) , "float const*" ) => { }
758814 ( & Type :: ConstPtr ( & Type :: PrimFloat ( 64 ) ) , "double const*" ) => { }
@@ -792,34 +848,32 @@ fn equate(
792848 // This is a macro (?) in C which seems to mutate its arguments, but
793849 // that means that we're taking pointers to arguments in rust
794850 // as we're not exposing it as a macro.
795- ( & Type :: MutPtr ( & Type :: M128 ) , "__m128" ) if intrinsic == "_MM_TRANSPOSE4_PS" => { }
851+ ( & Type :: MutPtr ( & Type :: M128 ) , "__m128" ) if intrinsic. name == "_MM_TRANSPOSE4_PS" => { }
796852
797853 // The _rdtsc intrinsic uses a __int64 return type, but this is a bug in
798854 // the intrinsics guide: https://github.com/rust-lang/stdarch/issues/559
799855 // We have manually fixed the bug by changing the return type to `u64`.
800- ( & Type :: PrimUnsigned ( 64 ) , "__int64" ) if intrinsic == "_rdtsc" => { }
856+ ( & Type :: PrimUnsigned ( 64 ) , "__int64" ) if intrinsic. name == "_rdtsc" => { }
801857
802858 // The _bittest and _bittest64 intrinsics takes a mutable pointer in the
803859 // intrinsics guide even though it never writes through the pointer:
804- ( & Type :: ConstPtr ( & Type :: PrimSigned ( 32 ) ) , "__int32*" ) if intrinsic == "_bittest" => { }
805- ( & Type :: ConstPtr ( & Type :: PrimSigned ( 64 ) ) , "__int64*" ) if intrinsic == "_bittest64" => { }
860+ ( & Type :: ConstPtr ( & Type :: PrimSigned ( 32 ) ) , "__int32*" ) if intrinsic. name == "_bittest" => { }
861+ ( & Type :: ConstPtr ( & Type :: PrimSigned ( 64 ) ) , "__int64*" ) if intrinsic. name == "_bittest64" => { }
806862 // The _xrstor, _fxrstor, _xrstor64, _fxrstor64 intrinsics take a
807863 // mutable pointer in the intrinsics guide even though they never write
808864 // through the pointer:
809865 ( & Type :: ConstPtr ( & Type :: PrimUnsigned ( 8 ) ) , "void*" )
810- if intrinsic == "_xrstor"
811- || intrinsic == "_xrstor64"
812- || intrinsic == "_fxrstor"
813- || intrinsic == "_fxrstor64" => { }
866+ if matches ! (
867+ & * intrinsic. name ,
868+ "_xrstor" | "_xrstor64" | "_fxrstor" | "_fxrstor64 "
869+ ) => { }
814870 // The _mm_stream_load_si128 intrinsic take a mutable pointer in the intrinsics
815871 // guide even though they never write through the pointer
816- ( & Type :: ConstPtr ( & Type :: M128I ) , "void*" ) if intrinsic == "_mm_stream_load_si128" => { }
872+ ( & Type :: ConstPtr ( & Type :: M128I ) , "void*" ) if intrinsic. name == "_mm_stream_load_si128" => { }
817873
818874 _ => bail ! (
819- "failed to equate: `{}` and {:?} for {}" ,
820- intel,
821- t,
822- intrinsic
875+ "failed to equate: `{intel}` and {t:?} for {}" ,
876+ intrinsic. name
823877 ) ,
824878 }
825879 Ok ( ( ) )
0 commit comments