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