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