@@ -3,6 +3,7 @@ use std::assert_matches::debug_assert_matches;
3
3
use rustc_abi:: FieldIdx ;
4
4
use rustc_ast:: InlineAsmTemplatePiece ;
5
5
use rustc_data_structures:: fx:: FxIndexSet ;
6
+ use rustc_hir:: def_id:: DefId ;
6
7
use rustc_hir:: { self as hir, LangItem } ;
7
8
use rustc_middle:: bug;
8
9
use rustc_middle:: ty:: { self , FloatTy , IntTy , Ty , TyCtxt , TypeVisitableExt , UintTy } ;
@@ -21,6 +22,12 @@ pub struct InlineAsmCtxt<'a, 'tcx> {
21
22
get_operand_ty : Box < dyn Fn ( & ' tcx hir:: Expr < ' tcx > ) -> Ty < ' tcx > + ' a > ,
22
23
}
23
24
25
+ enum NonAsmTypeReason < ' tcx > {
26
+ UnevaluatedSIMDArrayLength ( DefId , ty:: Const < ' tcx > ) ,
27
+ Invalid ( Ty < ' tcx > ) ,
28
+ InvalidElement ( DefId , Ty < ' tcx > ) ,
29
+ }
30
+
24
31
impl < ' a , ' tcx > InlineAsmCtxt < ' a , ' tcx > {
25
32
pub fn new_global_asm ( tcx : TyCtxt < ' tcx > ) -> Self {
26
33
InlineAsmCtxt {
@@ -56,7 +63,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
56
63
false
57
64
}
58
65
59
- fn get_asm_ty ( & self , ty : Ty < ' tcx > ) -> Option < InlineAsmType > {
66
+ fn get_asm_ty ( & self , ty : Ty < ' tcx > ) -> Result < InlineAsmType , NonAsmTypeReason < ' tcx > > {
60
67
let asm_ty_isize = match self . tcx . sess . target . pointer_width {
61
68
16 => InlineAsmType :: I16 ,
62
69
32 => InlineAsmType :: I32 ,
@@ -65,64 +72,62 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
65
72
} ;
66
73
67
74
match * ty. kind ( ) {
68
- ty:: Int ( IntTy :: I8 ) | ty:: Uint ( UintTy :: U8 ) => Some ( InlineAsmType :: I8 ) ,
69
- ty:: Int ( IntTy :: I16 ) | ty:: Uint ( UintTy :: U16 ) => Some ( InlineAsmType :: I16 ) ,
70
- ty:: Int ( IntTy :: I32 ) | ty:: Uint ( UintTy :: U32 ) => Some ( InlineAsmType :: I32 ) ,
71
- ty:: Int ( IntTy :: I64 ) | ty:: Uint ( UintTy :: U64 ) => Some ( InlineAsmType :: I64 ) ,
72
- ty:: Int ( IntTy :: I128 ) | ty:: Uint ( UintTy :: U128 ) => Some ( InlineAsmType :: I128 ) ,
73
- ty:: Int ( IntTy :: Isize ) | ty:: Uint ( UintTy :: Usize ) => Some ( asm_ty_isize) ,
74
- ty:: Float ( FloatTy :: F16 ) => Some ( InlineAsmType :: F16 ) ,
75
- ty:: Float ( FloatTy :: F32 ) => Some ( InlineAsmType :: F32 ) ,
76
- ty:: Float ( FloatTy :: F64 ) => Some ( InlineAsmType :: F64 ) ,
77
- ty:: Float ( FloatTy :: F128 ) => Some ( InlineAsmType :: F128 ) ,
78
- ty:: FnPtr ( ..) => Some ( asm_ty_isize) ,
79
- ty:: RawPtr ( ty, _) if self . is_thin_ptr_ty ( ty) => Some ( asm_ty_isize) ,
75
+ ty:: Int ( IntTy :: I8 ) | ty:: Uint ( UintTy :: U8 ) => Ok ( InlineAsmType :: I8 ) ,
76
+ ty:: Int ( IntTy :: I16 ) | ty:: Uint ( UintTy :: U16 ) => Ok ( InlineAsmType :: I16 ) ,
77
+ ty:: Int ( IntTy :: I32 ) | ty:: Uint ( UintTy :: U32 ) => Ok ( InlineAsmType :: I32 ) ,
78
+ ty:: Int ( IntTy :: I64 ) | ty:: Uint ( UintTy :: U64 ) => Ok ( InlineAsmType :: I64 ) ,
79
+ ty:: Int ( IntTy :: I128 ) | ty:: Uint ( UintTy :: U128 ) => Ok ( InlineAsmType :: I128 ) ,
80
+ ty:: Int ( IntTy :: Isize ) | ty:: Uint ( UintTy :: Usize ) => Ok ( asm_ty_isize) ,
81
+ ty:: Float ( FloatTy :: F16 ) => Ok ( InlineAsmType :: F16 ) ,
82
+ ty:: Float ( FloatTy :: F32 ) => Ok ( InlineAsmType :: F32 ) ,
83
+ ty:: Float ( FloatTy :: F64 ) => Ok ( InlineAsmType :: F64 ) ,
84
+ ty:: Float ( FloatTy :: F128 ) => Ok ( InlineAsmType :: F128 ) ,
85
+ ty:: FnPtr ( ..) => Ok ( asm_ty_isize) ,
86
+ ty:: RawPtr ( ty, _) if self . is_thin_ptr_ty ( ty) => Ok ( asm_ty_isize) ,
80
87
ty:: Adt ( adt, args) if adt. repr ( ) . simd ( ) => {
81
88
let fields = & adt. non_enum_variant ( ) . fields ;
82
- let elem_ty = fields[ FieldIdx :: ZERO ] . ty ( self . tcx , args) ;
89
+ let field = & fields[ FieldIdx :: ZERO ] ;
90
+ let elem_ty = field. ty ( self . tcx , args) ;
83
91
84
92
let ( size, ty) = match elem_ty. kind ( ) {
85
93
ty:: Array ( ty, len) => {
94
+ let len = self . tcx . normalize_erasing_regions ( self . typing_env , * len) ;
86
95
if let Some ( len) = len. try_to_target_usize ( self . tcx ) {
87
96
( len, * ty)
88
97
} else {
89
- return None ;
98
+ return Err ( NonAsmTypeReason :: UnevaluatedSIMDArrayLength (
99
+ field. did , len,
100
+ ) ) ;
90
101
}
91
102
}
92
103
_ => ( fields. len ( ) as u64 , elem_ty) ,
93
104
} ;
94
105
95
106
match ty. kind ( ) {
96
- ty:: Int ( IntTy :: I8 ) | ty:: Uint ( UintTy :: U8 ) => Some ( InlineAsmType :: VecI8 ( size) ) ,
97
- ty:: Int ( IntTy :: I16 ) | ty:: Uint ( UintTy :: U16 ) => {
98
- Some ( InlineAsmType :: VecI16 ( size) )
99
- }
100
- ty:: Int ( IntTy :: I32 ) | ty:: Uint ( UintTy :: U32 ) => {
101
- Some ( InlineAsmType :: VecI32 ( size) )
102
- }
103
- ty:: Int ( IntTy :: I64 ) | ty:: Uint ( UintTy :: U64 ) => {
104
- Some ( InlineAsmType :: VecI64 ( size) )
105
- }
107
+ ty:: Int ( IntTy :: I8 ) | ty:: Uint ( UintTy :: U8 ) => Ok ( InlineAsmType :: VecI8 ( size) ) ,
108
+ ty:: Int ( IntTy :: I16 ) | ty:: Uint ( UintTy :: U16 ) => Ok ( InlineAsmType :: VecI16 ( size) ) ,
109
+ ty:: Int ( IntTy :: I32 ) | ty:: Uint ( UintTy :: U32 ) => Ok ( InlineAsmType :: VecI32 ( size) ) ,
110
+ ty:: Int ( IntTy :: I64 ) | ty:: Uint ( UintTy :: U64 ) => Ok ( InlineAsmType :: VecI64 ( size) ) ,
106
111
ty:: Int ( IntTy :: I128 ) | ty:: Uint ( UintTy :: U128 ) => {
107
- Some ( InlineAsmType :: VecI128 ( size) )
112
+ Ok ( InlineAsmType :: VecI128 ( size) )
108
113
}
109
114
ty:: Int ( IntTy :: Isize ) | ty:: Uint ( UintTy :: Usize ) => {
110
- Some ( match self . tcx . sess . target . pointer_width {
115
+ Ok ( match self . tcx . sess . target . pointer_width {
111
116
16 => InlineAsmType :: VecI16 ( size) ,
112
117
32 => InlineAsmType :: VecI32 ( size) ,
113
118
64 => InlineAsmType :: VecI64 ( size) ,
114
119
width => bug ! ( "unsupported pointer width: {width}" ) ,
115
120
} )
116
121
}
117
- ty:: Float ( FloatTy :: F16 ) => Some ( InlineAsmType :: VecF16 ( size) ) ,
118
- ty:: Float ( FloatTy :: F32 ) => Some ( InlineAsmType :: VecF32 ( size) ) ,
119
- ty:: Float ( FloatTy :: F64 ) => Some ( InlineAsmType :: VecF64 ( size) ) ,
120
- ty:: Float ( FloatTy :: F128 ) => Some ( InlineAsmType :: VecF128 ( size) ) ,
121
- _ => None ,
122
+ ty:: Float ( FloatTy :: F16 ) => Ok ( InlineAsmType :: VecF16 ( size) ) ,
123
+ ty:: Float ( FloatTy :: F32 ) => Ok ( InlineAsmType :: VecF32 ( size) ) ,
124
+ ty:: Float ( FloatTy :: F64 ) => Ok ( InlineAsmType :: VecF64 ( size) ) ,
125
+ ty:: Float ( FloatTy :: F128 ) => Ok ( InlineAsmType :: VecF128 ( size) ) ,
126
+ _ => Err ( NonAsmTypeReason :: InvalidElement ( field . did , ty ) ) ,
122
127
}
123
128
}
124
129
ty:: Infer ( _) => bug ! ( "unexpected infer ty in asm operand" ) ,
125
- _ => None ,
130
+ _ => Err ( NonAsmTypeReason :: Invalid ( ty ) ) ,
126
131
}
127
132
}
128
133
@@ -163,17 +168,42 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
163
168
}
164
169
_ => self . get_asm_ty ( ty) ,
165
170
} ;
166
- let Some ( asm_ty) = asm_ty else {
167
- let msg = format ! ( "cannot use value of type `{ty}` for inline assembly" ) ;
168
- self . tcx
169
- . dcx ( )
170
- . struct_span_err ( expr. span , msg)
171
- . with_note (
172
- "only integers, floats, SIMD vectors, pointers and function pointers \
173
- can be used as arguments for inline assembly",
174
- )
175
- . emit ( ) ;
176
- return None ;
171
+ let asm_ty = match asm_ty {
172
+ Ok ( asm_ty) => asm_ty,
173
+ Err ( reason) => {
174
+ match reason {
175
+ NonAsmTypeReason :: UnevaluatedSIMDArrayLength ( did, len) => {
176
+ let msg = format ! ( "cannot evaluate SIMD vector length `{len}`" ) ;
177
+ self . tcx
178
+ . dcx ( )
179
+ . struct_span_err ( self . tcx . def_span ( did) , msg)
180
+ . with_span_note (
181
+ expr. span ,
182
+ "SIMD vector length needs to be known statically for use in `asm!`" ,
183
+ )
184
+ . emit ( ) ;
185
+ }
186
+ NonAsmTypeReason :: Invalid ( ty) => {
187
+ let msg = format ! ( "cannot use value of type `{ty}` for inline assembly" ) ;
188
+ self . tcx . dcx ( ) . struct_span_err ( expr. span , msg) . with_note (
189
+ "only integers, floats, SIMD vectors, pointers and function pointers \
190
+ can be used as arguments for inline assembly",
191
+ ) . emit ( ) ;
192
+ }
193
+ NonAsmTypeReason :: InvalidElement ( did, ty) => {
194
+ let msg = format ! (
195
+ "cannot use SIMD vector with element type `{ty}` for inline assembly"
196
+ ) ;
197
+ self . tcx . dcx ( )
198
+ . struct_span_err ( self . tcx . def_span ( did) , msg) . with_span_note (
199
+ expr. span ,
200
+ "only integers, floats, SIMD vectors, pointers and function pointers \
201
+ can be used as arguments for inline assembly",
202
+ ) . emit ( ) ;
203
+ }
204
+ }
205
+ return None ;
206
+ }
177
207
} ;
178
208
179
209
// Check that the type implements Copy. The only case where this can
0 commit comments