1
1
use rustc_middle:: mir:: interpret:: ErrorHandled ;
2
2
use rustc_middle:: ty:: layout:: HasTyCtxt ;
3
- use rustc_middle:: ty:: { self , Ty } ;
3
+ use rustc_middle:: ty:: { self , Ty , ValTree } ;
4
4
use rustc_middle:: { bug, mir, span_bug} ;
5
5
use rustc_target:: abi:: Abi ;
6
6
@@ -28,7 +28,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
28
28
. expect ( "erroneous constant missed by mono item collection" )
29
29
}
30
30
31
- /// This is a convenience helper for `simd_shuffle_indices `. It has the precondition
31
+ /// This is a convenience helper for `immediate_const_vector `. It has the precondition
32
32
/// that the given `constant` is an `Const::Unevaluated` and must be convertible to
33
33
/// a `ValTree`. If you want a more general version of this, talk to `wg-const-eval` on zulip.
34
34
///
@@ -59,23 +59,42 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
59
59
self . cx . tcx ( ) . const_eval_resolve_for_typeck ( ty:: ParamEnv :: reveal_all ( ) , uv, constant. span )
60
60
}
61
61
62
- /// process constant containing SIMD shuffle indices
63
- pub fn simd_shuffle_indices (
62
+ /// process constant containing SIMD shuffle indices & constant vectors
63
+ pub fn immediate_const_vector (
64
64
& mut self ,
65
65
bx : & Bx ,
66
66
constant : & mir:: ConstOperand < ' tcx > ,
67
67
) -> ( Bx :: Value , Ty < ' tcx > ) {
68
68
let ty = self . monomorphize ( constant. ty ( ) ) ;
69
+ let ty_is_simd = ty. is_simd ( ) ;
70
+ // FIXME: ideally we'd assert that this is a SIMD type, but simd_shuffle
71
+ // in its current form relies on a regular array being passed as an
72
+ // immediate argument. This hack can be removed once that is fixed.
73
+ let field_ty = if ty_is_simd {
74
+ ty. simd_size_and_type ( bx. tcx ( ) ) . 1
75
+ } else {
76
+ ty. builtin_index ( ) . unwrap ( )
77
+ } ;
78
+
69
79
let val = self
70
80
. eval_unevaluated_mir_constant_to_valtree ( constant)
71
81
. ok ( )
72
82
. map ( |x| x. ok ( ) )
73
83
. flatten ( )
74
84
. map ( |val| {
75
- let field_ty = ty. builtin_index ( ) . unwrap ( ) ;
76
- let values: Vec < _ > = val
77
- . unwrap_branch ( )
78
- . iter ( )
85
+ // Depending on whether this is a SIMD type with an array field
86
+ // or a type with many fields (one for each elements), the valtree
87
+ // is either a single branch with N children, or a root node
88
+ // with exactly one child which then in turn has many children.
89
+ // So we look at the first child to determine whether it is a
90
+ // leaf or whether we have to go one more layer down.
91
+ let branch_or_leaf = val. unwrap_branch ( ) ;
92
+ let first = branch_or_leaf. get ( 0 ) . unwrap ( ) ;
93
+ let field_iter = match first {
94
+ ValTree :: Branch ( _) => first. unwrap_branch ( ) . iter ( ) ,
95
+ ValTree :: Leaf ( _) => branch_or_leaf. iter ( ) ,
96
+ } ;
97
+ let values: Vec < _ > = field_iter
79
98
. map ( |field| {
80
99
if let Some ( prim) = field. try_to_scalar ( ) {
81
100
let layout = bx. layout_of ( field_ty) ;
@@ -84,11 +103,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
84
103
} ;
85
104
bx. scalar_to_backend ( prim, scalar, bx. immediate_backend_type ( layout) )
86
105
} else {
87
- bug ! ( "simd shuffle field {:?}" , field)
106
+ bug ! ( "field is not a scalar {:?}" , field)
88
107
}
89
108
} )
90
109
. collect ( ) ;
91
- bx. const_struct ( & values, false )
110
+ if ty_is_simd { bx. const_vector ( & values ) } else { bx . const_struct ( & values, false ) }
92
111
} )
93
112
. unwrap_or_else ( || {
94
113
bx. tcx ( ) . dcx ( ) . emit_err ( errors:: ShuffleIndicesEvaluation { span : constant. span } ) ;
0 commit comments