@@ -597,6 +597,27 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
597597 self . pointercast ( val, self . type_ptr ( ) )
598598 }
599599
600+ sym:: sve_cast => {
601+ let Some ( ( in_cnt, in_elem, in_num_vecs) ) =
602+ args[ 0 ] . layout . ty . scalable_vector_parts ( self . cx . tcx )
603+ else {
604+ bug ! ( "input parameter to `sve_cast` was not scalable vector" ) ;
605+ } ;
606+ let out_layout = self . layout_of ( fn_args. type_at ( 1 ) ) ;
607+ let Some ( ( out_cnt, out_elem, out_num_vecs) ) =
608+ out_layout. ty . scalable_vector_parts ( self . cx . tcx )
609+ else {
610+ bug ! ( "output parameter to `sve_cast` was not scalable vector" ) ;
611+ } ;
612+ assert_eq ! ( in_cnt, out_cnt) ;
613+ assert_eq ! ( in_num_vecs, out_num_vecs) ;
614+ let out_llty = self . backend_type ( out_layout) ;
615+ match simd_cast ( self , sym:: simd_cast, args, out_llty, in_elem, out_elem) {
616+ Some ( val) => val,
617+ _ => bug ! ( "could not cast scalable vectors" ) ,
618+ }
619+ }
620+
600621 sym:: sve_tuple_create2 => {
601622 assert_matches ! (
602623 self . layout_of( fn_args. type_at( 0 ) ) . backend_repr,
@@ -2763,96 +2784,17 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
27632784 out_len
27642785 }
27652786 ) ;
2766- // casting cares about nominal type, not just structural type
2767- if in_elem == out_elem {
2768- return Ok ( args[ 0 ] . immediate ( ) ) ;
2769- }
2770-
2771- #[ derive( Copy , Clone ) ]
2772- enum Sign {
2773- Unsigned ,
2774- Signed ,
2775- }
2776- use Sign :: * ;
2777-
2778- enum Style {
2779- Float ,
2780- Int ( Sign ) ,
2781- Unsupported ,
2782- }
2783-
2784- let ( in_style, in_width) = match in_elem. kind ( ) {
2785- // vectors of pointer-sized integers should've been
2786- // disallowed before here, so this unwrap is safe.
2787- ty:: Int ( i) => (
2788- Style :: Int ( Signed ) ,
2789- i. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
2790- ) ,
2791- ty:: Uint ( u) => (
2792- Style :: Int ( Unsigned ) ,
2793- u. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
2794- ) ,
2795- ty:: Float ( f) => ( Style :: Float , f. bit_width ( ) ) ,
2796- _ => ( Style :: Unsupported , 0 ) ,
2797- } ;
2798- let ( out_style, out_width) = match out_elem. kind ( ) {
2799- ty:: Int ( i) => (
2800- Style :: Int ( Signed ) ,
2801- i. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
2802- ) ,
2803- ty:: Uint ( u) => (
2804- Style :: Int ( Unsigned ) ,
2805- u. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
2806- ) ,
2807- ty:: Float ( f) => ( Style :: Float , f. bit_width ( ) ) ,
2808- _ => ( Style :: Unsupported , 0 ) ,
2809- } ;
2810-
2811- match ( in_style, out_style) {
2812- ( Style :: Int ( sign) , Style :: Int ( _) ) => {
2813- return Ok ( match in_width. cmp ( & out_width) {
2814- Ordering :: Greater => bx. trunc ( args[ 0 ] . immediate ( ) , llret_ty) ,
2815- Ordering :: Equal => args[ 0 ] . immediate ( ) ,
2816- Ordering :: Less => match sign {
2817- Sign :: Signed => bx. sext ( args[ 0 ] . immediate ( ) , llret_ty) ,
2818- Sign :: Unsigned => bx. zext ( args[ 0 ] . immediate ( ) , llret_ty) ,
2819- } ,
2820- } ) ;
2821- }
2822- ( Style :: Int ( Sign :: Signed ) , Style :: Float ) => {
2823- return Ok ( bx. sitofp ( args[ 0 ] . immediate ( ) , llret_ty) ) ;
2824- }
2825- ( Style :: Int ( Sign :: Unsigned ) , Style :: Float ) => {
2826- return Ok ( bx. uitofp ( args[ 0 ] . immediate ( ) , llret_ty) ) ;
2827- }
2828- ( Style :: Float , Style :: Int ( sign) ) => {
2829- return Ok ( match ( sign, name == sym:: simd_as) {
2830- ( Sign :: Unsigned , false ) => bx. fptoui ( args[ 0 ] . immediate ( ) , llret_ty) ,
2831- ( Sign :: Signed , false ) => bx. fptosi ( args[ 0 ] . immediate ( ) , llret_ty) ,
2832- ( _, true ) => bx. cast_float_to_int (
2833- matches ! ( sign, Sign :: Signed ) ,
2834- args[ 0 ] . immediate ( ) ,
2835- llret_ty,
2836- ) ,
2837- } ) ;
2838- }
2839- ( Style :: Float , Style :: Float ) => {
2840- return Ok ( match in_width. cmp ( & out_width) {
2841- Ordering :: Greater => bx. fptrunc ( args[ 0 ] . immediate ( ) , llret_ty) ,
2842- Ordering :: Equal => args[ 0 ] . immediate ( ) ,
2843- Ordering :: Less => bx. fpext ( args[ 0 ] . immediate ( ) , llret_ty) ,
2844- } ) ;
2845- }
2846- _ => { /* Unsupported. Fallthrough. */ }
2787+ match simd_cast ( bx, name, args, llret_ty, in_elem, out_elem) {
2788+ Some ( val) => return Ok ( val) ,
2789+ None => return_error ! ( InvalidMonomorphization :: UnsupportedCast {
2790+ span,
2791+ name,
2792+ in_ty,
2793+ in_elem,
2794+ ret_ty,
2795+ out_elem
2796+ } ) ,
28472797 }
2848- return_error ! ( InvalidMonomorphization :: UnsupportedCast {
2849- span,
2850- name,
2851- in_ty,
2852- in_elem,
2853- ret_ty,
2854- out_elem
2855- } ) ;
28562798 }
28572799 macro_rules! arith_binary {
28582800 ( $( $name: ident: $( $( $p: ident) ,* => $call: ident) ,* ; ) * ) => {
@@ -3026,3 +2968,86 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
30262968
30272969 span_bug ! ( span, "unknown SIMD intrinsic" ) ;
30282970}
2971+
2972+ /// Implementation of `core::intrinsics::simd_cast`, re-used by `core::scalable::sve_cast`.
2973+ fn simd_cast < ' ll , ' tcx > (
2974+ bx : & mut Builder < ' _ , ' ll , ' tcx > ,
2975+ name : Symbol ,
2976+ args : & [ OperandRef < ' tcx , & ' ll Value > ] ,
2977+ llret_ty : & ' ll Type ,
2978+ in_elem : Ty < ' tcx > ,
2979+ out_elem : Ty < ' tcx > ,
2980+ ) -> Option < & ' ll Value > {
2981+ // Casting cares about nominal type, not just structural type
2982+ if in_elem == out_elem {
2983+ return Some ( args[ 0 ] . immediate ( ) ) ;
2984+ }
2985+
2986+ #[ derive( Copy , Clone ) ]
2987+ enum Sign {
2988+ Unsigned ,
2989+ Signed ,
2990+ }
2991+ use Sign :: * ;
2992+
2993+ enum Style {
2994+ Float ,
2995+ Int ( Sign ) ,
2996+ Unsupported ,
2997+ }
2998+
2999+ let ( in_style, in_width) = match in_elem. kind ( ) {
3000+ // vectors of pointer-sized integers should've been
3001+ // disallowed before here, so this unwrap is safe.
3002+ ty:: Int ( i) => (
3003+ Style :: Int ( Signed ) ,
3004+ i. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
3005+ ) ,
3006+ ty:: Uint ( u) => (
3007+ Style :: Int ( Unsigned ) ,
3008+ u. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
3009+ ) ,
3010+ ty:: Float ( f) => ( Style :: Float , f. bit_width ( ) ) ,
3011+ _ => ( Style :: Unsupported , 0 ) ,
3012+ } ;
3013+ let ( out_style, out_width) = match out_elem. kind ( ) {
3014+ ty:: Int ( i) => (
3015+ Style :: Int ( Signed ) ,
3016+ i. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
3017+ ) ,
3018+ ty:: Uint ( u) => (
3019+ Style :: Int ( Unsigned ) ,
3020+ u. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
3021+ ) ,
3022+ ty:: Float ( f) => ( Style :: Float , f. bit_width ( ) ) ,
3023+ _ => ( Style :: Unsupported , 0 ) ,
3024+ } ;
3025+
3026+ match ( in_style, out_style) {
3027+ ( Style :: Int ( sign) , Style :: Int ( _) ) => Some ( match in_width. cmp ( & out_width) {
3028+ Ordering :: Greater => bx. trunc ( args[ 0 ] . immediate ( ) , llret_ty) ,
3029+ Ordering :: Equal => args[ 0 ] . immediate ( ) ,
3030+ Ordering :: Less => match sign {
3031+ Sign :: Signed => bx. sext ( args[ 0 ] . immediate ( ) , llret_ty) ,
3032+ Sign :: Unsigned => bx. zext ( args[ 0 ] . immediate ( ) , llret_ty) ,
3033+ } ,
3034+ } ) ,
3035+ ( Style :: Int ( Sign :: Signed ) , Style :: Float ) => Some ( bx. sitofp ( args[ 0 ] . immediate ( ) , llret_ty) ) ,
3036+ ( Style :: Int ( Sign :: Unsigned ) , Style :: Float ) => {
3037+ Some ( bx. uitofp ( args[ 0 ] . immediate ( ) , llret_ty) )
3038+ }
3039+ ( Style :: Float , Style :: Int ( sign) ) => Some ( match ( sign, name == sym:: simd_as) {
3040+ ( Sign :: Unsigned , false ) => bx. fptoui ( args[ 0 ] . immediate ( ) , llret_ty) ,
3041+ ( Sign :: Signed , false ) => bx. fptosi ( args[ 0 ] . immediate ( ) , llret_ty) ,
3042+ ( _, true ) => {
3043+ bx. cast_float_to_int ( matches ! ( sign, Sign :: Signed ) , args[ 0 ] . immediate ( ) , llret_ty)
3044+ }
3045+ } ) ,
3046+ ( Style :: Float , Style :: Float ) => Some ( match in_width. cmp ( & out_width) {
3047+ Ordering :: Greater => bx. fptrunc ( args[ 0 ] . immediate ( ) , llret_ty) ,
3048+ Ordering :: Equal => args[ 0 ] . immediate ( ) ,
3049+ Ordering :: Less => bx. fpext ( args[ 0 ] . immediate ( ) , llret_ty) ,
3050+ } ) ,
3051+ _ => None ,
3052+ }
3053+ }
0 commit comments