@@ -5,13 +5,13 @@ use super::{CachedLlbb, FunctionCx, LocalRef};
5
5
6
6
use crate :: base:: { self , is_call_from_compiler_builtins_to_upstream_monomorphization} ;
7
7
use crate :: common:: { self , IntPredicate } ;
8
- use crate :: errors:: CompilerBuiltinsCannotCall ;
8
+ use crate :: errors;
9
9
use crate :: meth;
10
10
use crate :: traits:: * ;
11
11
use crate :: MemFlags ;
12
12
13
13
use rustc_ast as ast;
14
- use rustc_ast:: { InlineAsmOptions , InlineAsmTemplatePiece } ;
14
+ use rustc_ast:: { InlineAsmOptions , InlineAsmTemplatePiece , LitKind , MetaItemLit , NestedMetaItem } ;
15
15
use rustc_hir:: lang_items:: LangItem ;
16
16
use rustc_middle:: mir:: { self , AssertKind , BasicBlock , SwitchTargets , UnwindTerminateReason } ;
17
17
use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , ValidityRequirement } ;
@@ -925,7 +925,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
925
925
// checked by the type-checker.
926
926
if i == 2 && intrinsic. name == sym:: simd_shuffle {
927
927
if let mir:: Operand :: Constant ( constant) = & arg. node {
928
- let ( llval, ty) = self . simd_shuffle_indices ( bx, constant) ;
928
+ let ( llval, ty) = self . early_evaluate_const_vector ( bx, constant) ;
929
+ let llval = llval. unwrap_or_else ( || {
930
+ bx. tcx ( ) . sess . emit_err ( errors:: ShuffleIndicesEvaluation {
931
+ span : constant. span ,
932
+ } ) ;
933
+ // We've errored, so we don't have to produce working code.
934
+ let llty = bx. backend_type ( bx. layout_of ( ty) ) ;
935
+ bx. const_undef ( llty)
936
+ } ) ;
929
937
return OperandRef {
930
938
val : Immediate ( llval) ,
931
939
layout : bx. layout_of ( ty) ,
@@ -1003,9 +1011,49 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1003
1011
( args, None )
1004
1012
} ;
1005
1013
1014
+ let const_vec_arg_indexes = ( || {
1015
+ if let Some ( def) = def
1016
+ && let Some ( attr) =
1017
+ bx. tcx ( ) . get_attr ( def. def_id ( ) , sym:: rustc_intrinsic_const_vector_arg)
1018
+ {
1019
+ attr. meta_item_list ( )
1020
+ . iter ( )
1021
+ . flatten ( )
1022
+ . map ( |item : & NestedMetaItem | match item {
1023
+ NestedMetaItem :: Lit ( MetaItemLit {
1024
+ kind : LitKind :: Int ( index, _) , ..
1025
+ } ) => * index as usize ,
1026
+ _ => span_bug ! ( item. span( ) , "attribute argument must be an integer" ) ,
1027
+ } )
1028
+ . collect ( )
1029
+ } else {
1030
+ Vec :: < usize > :: new ( )
1031
+ }
1032
+ } ) ( ) ;
1033
+
1006
1034
let mut copied_constant_arguments = vec ! [ ] ;
1007
1035
' make_args: for ( i, arg) in first_args. iter ( ) . enumerate ( ) {
1008
- let mut op = self . codegen_operand ( bx, & arg. node ) ;
1036
+ let mut op = if const_vec_arg_indexes. contains ( & i) {
1037
+ // Force the specified argument to be constant by using const-qualification to promote any complex rvalues to constant.
1038
+ if let mir:: Operand :: Constant ( constant) = & arg. node
1039
+ && constant. ty ( ) . is_simd ( )
1040
+ {
1041
+ let ( llval, ty) = self . early_evaluate_const_vector ( bx, & constant) ;
1042
+ let llval = llval. unwrap_or_else ( || {
1043
+ bx. tcx ( )
1044
+ . sess
1045
+ . emit_err ( errors:: ConstVectorEvaluation { span : constant. span } ) ;
1046
+ // We've errored, so we don't have to produce working code.
1047
+ let llty = bx. backend_type ( bx. layout_of ( ty) ) ;
1048
+ bx. const_undef ( llty)
1049
+ } ) ;
1050
+ OperandRef { val : Immediate ( llval) , layout : bx. layout_of ( ty) }
1051
+ } else {
1052
+ span_bug ! ( span, "argument at {i} must be a constant vector" ) ;
1053
+ }
1054
+ } else {
1055
+ self . codegen_operand ( bx, & arg. node )
1056
+ } ;
1009
1057
1010
1058
if let ( 0 , Some ( ty:: InstanceKind :: Virtual ( _, idx) ) ) = ( i, def) {
1011
1059
match op. val {
0 commit comments