@@ -992,6 +992,140 @@ impl Step for StdarchVerify {
992992 }
993993}
994994
995+ /// Runs stdarch's intrinsic-test binary crate to verify that Rust's `core::arch`
996+ /// SIMD intrinsics produce the same results as their C counterparts.
997+ ///
998+ /// First runs the `intrinsic-test` binary, which generates C wrapper programs
999+ /// and a Rust Cargo workspace. Then runs `cargo test` on that workspace
1000+ /// which compiles both versions and compares their outputs on random inputs.
1001+ #[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
1002+ pub struct IntrinsicTest {
1003+ host : TargetSelection ,
1004+ }
1005+
1006+ impl Step for IntrinsicTest {
1007+ type Output = ( ) ;
1008+ const IS_HOST : bool = true ;
1009+
1010+ fn should_run ( run : ShouldRun < ' _ > ) -> ShouldRun < ' _ > {
1011+ run. path ( "library/stdarch/crates/intrinsic-test" )
1012+ }
1013+
1014+ fn make_run ( run : RunConfig < ' _ > ) {
1015+ let target = run. target ;
1016+ if !target. contains ( "aarch64-unknown-linux" ) && !target. contains ( "x86_64-unknown-linux" ) {
1017+ return ;
1018+ }
1019+ run. builder . ensure ( IntrinsicTest { host : target } ) ;
1020+ }
1021+
1022+ fn run ( self , builder : & Builder < ' _ > ) {
1023+ let host = self . host ;
1024+
1025+ let ( input_file, skip_file, cflags, sde_runner) = if host. contains ( "x86_64-unknown-linux" ) {
1026+ let cpuid_def =
1027+ builder. src . join ( "library/stdarch/ci/docker/x86_64-unknown-linux-gnu/cpuid.def" ) ;
1028+ let sde_runner = format ! (
1029+ "/intel-sde/sde64 -cpuid-in {} -rtm-mode full -tsx --" ,
1030+ cpuid_def. display( )
1031+ ) ;
1032+ (
1033+ builder. src . join ( "library/stdarch/intrinsics_data/x86-intel.xml" ) ,
1034+ [
1035+ builder
1036+ . src
1037+ . join ( "library/stdarch/crates/intrinsic-test/missing_x86_common.txt" ) ,
1038+ builder. src . join ( "library/stdarch/crates/intrinsic-test/missing_x86_gcc.txt" ) ,
1039+ ] ,
1040+ "-I/usr/include/x86_64-linux-gnu/" ,
1041+ Some ( sde_runner) ,
1042+ )
1043+ } else if host. contains ( "aarch64-unknown-linux" ) {
1044+ (
1045+ builder. src . join ( "library/stdarch/intrinsics_data/arm_intrinsics.json" ) ,
1046+ [
1047+ builder
1048+ . src
1049+ . join ( "library/stdarch/crates/intrinsic-test/missing_aarch64_common.txt" ) ,
1050+ builder
1051+ . src
1052+ . join ( "library/stdarch/crates/intrinsic-test/missing_aarch64_gcc.txt" ) ,
1053+ ] ,
1054+ "-I/usr/aarch64-linux-gnu/include/" ,
1055+ None ,
1056+ )
1057+ } else {
1058+ panic ! ( "intrinsic-test only supports aarch64/x86_64 Linux, got {host}" ) ;
1059+ } ;
1060+
1061+ let out_dir = builder. out . join ( host) . join ( "intrinsic-test" ) ;
1062+ t ! ( fs:: create_dir_all( & out_dir) ) ;
1063+
1064+ let crates_link = out_dir. join ( "crates" ) ;
1065+ if !crates_link. exists ( ) {
1066+ t ! (
1067+ helpers:: symlink_dir(
1068+ & builder. config,
1069+ & builder. src. join( "library/stdarch/crates" ) ,
1070+ & crates_link
1071+ ) ,
1072+ format!( "failed to symlink stdarch crates into {}" , crates_link. display( ) )
1073+ ) ;
1074+ }
1075+
1076+ let mut cmd = builder. tool_cmd ( Tool :: IntrinsicTest ) ;
1077+ cmd. current_dir ( & out_dir) ;
1078+ cmd. arg ( & input_file) ;
1079+ cmd. arg ( "--target" ) . arg ( & * host. triple ) ;
1080+ for skip in & skip_file {
1081+ cmd. arg ( "--skip" ) . arg ( skip) ;
1082+ }
1083+ cmd. arg ( "--sample-percentage" ) . arg ( "10" ) ;
1084+ cmd. arg ( "--cc-arg-style" ) . arg ( "gcc" ) ;
1085+ cmd. env ( "CC" , builder. cc ( host) ) ;
1086+ cmd. env ( "CFLAGS" , cflags) ;
1087+ // intrinsic-test shells out to `cargo` and `rustfmt` make bootstrap's
1088+ // managed binaries findable by prepending their dirs to PATH.
1089+ let rustfmt_path = builder. config . initial_rustfmt . clone ( ) . unwrap_or_else ( || {
1090+ eprintln ! ( "intrinsic-test: rustfmt is required but not available on this channel" ) ;
1091+ crate :: exit!( 1 ) ;
1092+ } ) ;
1093+
1094+ let mut path_dirs: Vec < PathBuf > = Vec :: new ( ) ;
1095+ if let Some ( cargo_dir) = builder. initial_cargo . parent ( ) {
1096+ path_dirs. push ( cargo_dir. to_path_buf ( ) ) ;
1097+ }
1098+ if let Some ( rustfmt_dir) = rustfmt_path. parent ( ) {
1099+ path_dirs. push ( rustfmt_dir. to_path_buf ( ) ) ;
1100+ }
1101+ let old_path = env:: var_os ( "PATH" ) . unwrap_or_default ( ) ;
1102+ let new_path = env:: join_paths ( path_dirs. into_iter ( ) . chain ( env:: split_paths ( & old_path) ) )
1103+ . expect ( "could not build PATH for intrinsic-test" ) ;
1104+ cmd. env ( "PATH" , new_path) ;
1105+ cmd. run ( builder) ;
1106+
1107+ let tested_compiler = builder. compiler ( builder. top_stage , host) ;
1108+ builder. std ( tested_compiler, host) ;
1109+ let rustc = builder. rustc ( tested_compiler) ;
1110+
1111+ let manifest = out_dir. join ( "rust_programs/Cargo.toml" ) ;
1112+ let mut cargo = command ( & builder. initial_cargo ) ;
1113+ cargo. arg ( "test" ) ;
1114+ cargo. arg ( "--tests" ) ;
1115+ cargo. arg ( "--manifest-path" ) . arg ( & manifest) ;
1116+ cargo. arg ( "--target" ) . arg ( & * host. triple ) ;
1117+ cargo. arg ( "--profile" ) . arg ( "release" ) ;
1118+ cargo. env ( "CC" , builder. cc ( host) ) ;
1119+ cargo. env ( "CFLAGS" , cflags) ;
1120+ cargo. env ( "RUSTC" , rustc) ;
1121+ cargo. env ( "RUSTC_BOOTSTRAP" , "1" ) ;
1122+ if let Some ( runner) = sde_runner {
1123+ cargo. env ( "CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER" , runner) ;
1124+ }
1125+ cargo. run ( builder) ;
1126+ }
1127+ }
1128+
9951129#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
9961130pub struct Clippy {
9971131 compilers : RustcPrivateCompilers ,
0 commit comments