@@ -740,6 +740,23 @@ fn generic_simd_intrinsic(
740
740
llret_ty : & ' ll Type ,
741
741
span : Span ,
742
742
) -> Result < & ' ll Value , ( ) > {
743
+ // Given a SIMD vector type `x` return the element type and the number of
744
+ // elements in the vector.
745
+ fn simd_ty_and_len ( bx : & Builder < ' a , ' ll , ' tcx > , simd_ty : Ty < ' tcx > ) -> ( Ty < ' tcx > , u64 ) {
746
+ let ty = if let ty:: Adt ( _def, _substs) = simd_ty. kind ( ) {
747
+ let f0_ty = bx. layout_of ( simd_ty) . field ( bx, 0 ) . ty ;
748
+ if let ty:: Array ( element_ty, _) = f0_ty. kind ( ) { element_ty } else { f0_ty }
749
+ } else {
750
+ bug ! ( "should only be called with a SIMD type" )
751
+ } ;
752
+ let count = if let abi:: Abi :: Vector { count, .. } = bx. layout_of ( simd_ty) . abi {
753
+ count
754
+ } else {
755
+ bug ! ( "should only be called with a SIMD type" )
756
+ } ;
757
+ ( ty, count)
758
+ }
759
+
743
760
// macros for error handling:
744
761
macro_rules! emit_error {
745
762
( $msg: tt) => {
@@ -792,7 +809,7 @@ fn generic_simd_intrinsic(
792
809
_ => return_error ! ( "`{}` is not an integral type" , in_ty) ,
793
810
} ;
794
811
require_simd ! ( arg_tys[ 1 ] , "argument" ) ;
795
- let v_len = arg_tys[ 1 ] . simd_size ( tcx ) ;
812
+ let ( _ , v_len) = simd_ty_and_len ( bx , arg_tys[ 1 ] ) ;
796
813
require ! (
797
814
// Allow masks for vectors with fewer than 8 elements to be
798
815
// represented with a u8 or i8.
@@ -812,8 +829,6 @@ fn generic_simd_intrinsic(
812
829
// every intrinsic below takes a SIMD vector as its first argument
813
830
require_simd ! ( arg_tys[ 0 ] , "input" ) ;
814
831
let in_ty = arg_tys[ 0 ] ;
815
- let in_elem = arg_tys[ 0 ] . simd_type ( tcx) ;
816
- let in_len = arg_tys[ 0 ] . simd_size ( tcx) ;
817
832
818
833
let comparison = match name {
819
834
sym:: simd_eq => Some ( hir:: BinOpKind :: Eq ) ,
@@ -825,14 +840,15 @@ fn generic_simd_intrinsic(
825
840
_ => None ,
826
841
} ;
827
842
843
+ let ( in_elem, in_len) = simd_ty_and_len ( bx, arg_tys[ 0 ] ) ;
828
844
if let Some ( cmp_op) = comparison {
829
845
require_simd ! ( ret_ty, "return" ) ;
830
846
831
- let out_len = ret_ty . simd_size ( tcx ) ;
847
+ let ( out_ty , out_len) = simd_ty_and_len ( bx , ret_ty ) ;
832
848
require ! (
833
849
in_len == out_len,
834
850
"expected return type with length {} (same as input type `{}`), \
835
- found `{}` with length {}",
851
+ found `{}` with length {}",
836
852
in_len,
837
853
in_ty,
838
854
ret_ty,
@@ -842,7 +858,7 @@ fn generic_simd_intrinsic(
842
858
bx. type_kind( bx. element_type( llret_ty) ) == TypeKind :: Integer ,
843
859
"expected return type with integer elements, found `{}` with non-integer `{}`" ,
844
860
ret_ty,
845
- ret_ty . simd_type ( tcx )
861
+ out_ty
846
862
) ;
847
863
848
864
return Ok ( compare_simd_types (
@@ -862,7 +878,7 @@ fn generic_simd_intrinsic(
862
878
863
879
require_simd ! ( ret_ty, "return" ) ;
864
880
865
- let out_len = ret_ty . simd_size ( tcx ) ;
881
+ let ( out_ty , out_len) = simd_ty_and_len ( bx , ret_ty ) ;
866
882
require ! (
867
883
out_len == n,
868
884
"expected return type of length {}, found `{}` with length {}" ,
@@ -871,13 +887,13 @@ fn generic_simd_intrinsic(
871
887
out_len
872
888
) ;
873
889
require ! (
874
- in_elem == ret_ty . simd_type ( tcx ) ,
890
+ in_elem == out_ty ,
875
891
"expected return element type `{}` (element of input `{}`), \
876
- found `{}` with element type `{}`",
892
+ found `{}` with element type `{}`",
877
893
in_elem,
878
894
in_ty,
879
895
ret_ty,
880
- ret_ty . simd_type ( tcx )
896
+ out_ty
881
897
) ;
882
898
883
899
let total_len = u128:: from ( in_len) * 2 ;
@@ -946,7 +962,7 @@ fn generic_simd_intrinsic(
946
962
let m_elem_ty = in_elem;
947
963
let m_len = in_len;
948
964
require_simd ! ( arg_tys[ 1 ] , "argument" ) ;
949
- let v_len = arg_tys[ 1 ] . simd_size ( tcx ) ;
965
+ let ( _ , v_len) = simd_ty_and_len ( bx , arg_tys[ 1 ] ) ;
950
966
require ! (
951
967
m_len == v_len,
952
968
"mismatched lengths: mask length `{}` != other vector length `{}`" ,
@@ -1171,25 +1187,27 @@ fn generic_simd_intrinsic(
1171
1187
require_simd ! ( ret_ty, "return" ) ;
1172
1188
1173
1189
// Of the same length:
1190
+ let ( _, out_len) = simd_ty_and_len ( bx, arg_tys[ 1 ] ) ;
1191
+ let ( _, out_len2) = simd_ty_and_len ( bx, arg_tys[ 2 ] ) ;
1174
1192
require ! (
1175
- in_len == arg_tys [ 1 ] . simd_size ( tcx ) ,
1193
+ in_len == out_len ,
1176
1194
"expected {} argument with length {} (same as input type `{}`), \
1177
- found `{}` with length {}",
1195
+ found `{}` with length {}",
1178
1196
"second" ,
1179
1197
in_len,
1180
1198
in_ty,
1181
1199
arg_tys[ 1 ] ,
1182
- arg_tys [ 1 ] . simd_size ( tcx )
1200
+ out_len
1183
1201
) ;
1184
1202
require ! (
1185
- in_len == arg_tys [ 2 ] . simd_size ( tcx ) ,
1203
+ in_len == out_len2 ,
1186
1204
"expected {} argument with length {} (same as input type `{}`), \
1187
- found `{}` with length {}",
1205
+ found `{}` with length {}",
1188
1206
"third" ,
1189
1207
in_len,
1190
1208
in_ty,
1191
1209
arg_tys[ 2 ] ,
1192
- arg_tys [ 2 ] . simd_size ( tcx )
1210
+ out_len2
1193
1211
) ;
1194
1212
1195
1213
// The return type must match the first argument type
@@ -1213,39 +1231,40 @@ fn generic_simd_intrinsic(
1213
1231
1214
1232
// The second argument must be a simd vector with an element type that's a pointer
1215
1233
// to the element type of the first argument
1216
- let ( pointer_count , underlying_ty ) = match arg_tys[ 1 ] . simd_type ( tcx ) . kind ( ) {
1217
- ty :: RawPtr ( p ) if p . ty == in_elem => {
1218
- ( ptr_count ( arg_tys [ 1 ] . simd_type ( tcx ) ) , non_ptr ( arg_tys [ 1 ] . simd_type ( tcx ) ) )
1219
- }
1234
+ let ( element_ty0 , _ ) = simd_ty_and_len ( bx , arg_tys[ 0 ] ) ;
1235
+ let ( element_ty1 , _ ) = simd_ty_and_len ( bx , arg_tys [ 1 ] ) ;
1236
+ let ( pointer_count , underlying_ty ) = match element_ty1 . kind ( ) {
1237
+ ty :: RawPtr ( p ) if p . ty == in_elem => ( ptr_count ( element_ty1 ) , non_ptr ( element_ty1 ) ) ,
1220
1238
_ => {
1221
1239
require ! (
1222
1240
false ,
1223
1241
"expected element type `{}` of second argument `{}` \
1224
- to be a pointer to the element type `{}` of the first \
1225
- argument `{}`, found `{}` != `*_ {}`",
1226
- arg_tys [ 1 ] . simd_type ( tcx ) ,
1242
+ to be a pointer to the element type `{}` of the first \
1243
+ argument `{}`, found `{}` != `*_ {}`",
1244
+ element_ty1 ,
1227
1245
arg_tys[ 1 ] ,
1228
1246
in_elem,
1229
1247
in_ty,
1230
- arg_tys [ 1 ] . simd_type ( tcx ) ,
1248
+ element_ty1 ,
1231
1249
in_elem
1232
1250
) ;
1233
1251
unreachable ! ( ) ;
1234
1252
}
1235
1253
} ;
1236
1254
assert ! ( pointer_count > 0 ) ;
1237
- assert_eq ! ( pointer_count - 1 , ptr_count( arg_tys [ 0 ] . simd_type ( tcx ) ) ) ;
1238
- assert_eq ! ( underlying_ty, non_ptr( arg_tys [ 0 ] . simd_type ( tcx ) ) ) ;
1255
+ assert_eq ! ( pointer_count - 1 , ptr_count( element_ty0 ) ) ;
1256
+ assert_eq ! ( underlying_ty, non_ptr( element_ty0 ) ) ;
1239
1257
1240
1258
// The element type of the third argument must be a signed integer type of any width:
1241
- match arg_tys[ 2 ] . simd_type ( tcx) . kind ( ) {
1259
+ let ( element_ty2, _) = simd_ty_and_len ( bx, arg_tys[ 2 ] ) ;
1260
+ match element_ty2. kind ( ) {
1242
1261
ty:: Int ( _) => ( ) ,
1243
1262
_ => {
1244
1263
require ! (
1245
1264
false ,
1246
1265
"expected element type `{}` of third argument `{}` \
1247
1266
to be a signed integer type",
1248
- arg_tys [ 2 ] . simd_type ( tcx ) ,
1267
+ element_ty2 ,
1249
1268
arg_tys[ 2 ]
1250
1269
) ;
1251
1270
}
@@ -1297,25 +1316,27 @@ fn generic_simd_intrinsic(
1297
1316
require_simd ! ( arg_tys[ 2 ] , "third" ) ;
1298
1317
1299
1318
// Of the same length:
1319
+ let ( _, element_len1) = simd_ty_and_len ( bx, arg_tys[ 1 ] ) ;
1320
+ let ( _, element_len2) = simd_ty_and_len ( bx, arg_tys[ 2 ] ) ;
1300
1321
require ! (
1301
- in_len == arg_tys [ 1 ] . simd_size ( tcx ) ,
1322
+ in_len == element_len1 ,
1302
1323
"expected {} argument with length {} (same as input type `{}`), \
1303
- found `{}` with length {}",
1324
+ found `{}` with length {}",
1304
1325
"second" ,
1305
1326
in_len,
1306
1327
in_ty,
1307
1328
arg_tys[ 1 ] ,
1308
- arg_tys [ 1 ] . simd_size ( tcx )
1329
+ element_len1
1309
1330
) ;
1310
1331
require ! (
1311
- in_len == arg_tys [ 2 ] . simd_size ( tcx ) ,
1332
+ in_len == element_len2 ,
1312
1333
"expected {} argument with length {} (same as input type `{}`), \
1313
- found `{}` with length {}",
1334
+ found `{}` with length {}",
1314
1335
"third" ,
1315
1336
in_len,
1316
1337
in_ty,
1317
1338
arg_tys[ 2 ] ,
1318
- arg_tys [ 2 ] . simd_size ( tcx )
1339
+ element_len2
1319
1340
) ;
1320
1341
1321
1342
// This counts how many pointers
@@ -1336,39 +1357,42 @@ fn generic_simd_intrinsic(
1336
1357
1337
1358
// The second argument must be a simd vector with an element type that's a pointer
1338
1359
// to the element type of the first argument
1339
- let ( pointer_count, underlying_ty) = match arg_tys[ 1 ] . simd_type ( tcx) . kind ( ) {
1360
+ let ( element_ty0, _element_len0) = simd_ty_and_len ( bx, arg_tys[ 0 ] ) ;
1361
+ let ( element_ty1, _element_len1) = simd_ty_and_len ( bx, arg_tys[ 1 ] ) ;
1362
+ let ( element_ty2, _element_len2) = simd_ty_and_len ( bx, arg_tys[ 2 ] ) ;
1363
+ let ( pointer_count, underlying_ty) = match element_ty1. kind ( ) {
1340
1364
ty:: RawPtr ( p) if p. ty == in_elem && p. mutbl == hir:: Mutability :: Mut => {
1341
- ( ptr_count ( arg_tys [ 1 ] . simd_type ( tcx ) ) , non_ptr ( arg_tys [ 1 ] . simd_type ( tcx ) ) )
1365
+ ( ptr_count ( element_ty1 ) , non_ptr ( element_ty1 ) )
1342
1366
}
1343
1367
_ => {
1344
1368
require ! (
1345
1369
false ,
1346
1370
"expected element type `{}` of second argument `{}` \
1347
- to be a pointer to the element type `{}` of the first \
1348
- argument `{}`, found `{}` != `*mut {}`",
1349
- arg_tys [ 1 ] . simd_type ( tcx ) ,
1371
+ to be a pointer to the element type `{}` of the first \
1372
+ argument `{}`, found `{}` != `*mut {}`",
1373
+ element_ty1 ,
1350
1374
arg_tys[ 1 ] ,
1351
1375
in_elem,
1352
1376
in_ty,
1353
- arg_tys [ 1 ] . simd_type ( tcx ) ,
1377
+ element_ty1 ,
1354
1378
in_elem
1355
1379
) ;
1356
1380
unreachable ! ( ) ;
1357
1381
}
1358
1382
} ;
1359
1383
assert ! ( pointer_count > 0 ) ;
1360
- assert_eq ! ( pointer_count - 1 , ptr_count( arg_tys [ 0 ] . simd_type ( tcx ) ) ) ;
1361
- assert_eq ! ( underlying_ty, non_ptr( arg_tys [ 0 ] . simd_type ( tcx ) ) ) ;
1384
+ assert_eq ! ( pointer_count - 1 , ptr_count( element_ty0 ) ) ;
1385
+ assert_eq ! ( underlying_ty, non_ptr( element_ty0 ) ) ;
1362
1386
1363
1387
// The element type of the third argument must be a signed integer type of any width:
1364
- match arg_tys [ 2 ] . simd_type ( tcx ) . kind ( ) {
1388
+ match element_ty2 . kind ( ) {
1365
1389
ty:: Int ( _) => ( ) ,
1366
1390
_ => {
1367
1391
require ! (
1368
1392
false ,
1369
1393
"expected element type `{}` of third argument `{}` \
1370
- to be a signed integer type",
1371
- arg_tys [ 2 ] . simd_type ( tcx ) ,
1394
+ be a signed integer type",
1395
+ element_ty2 ,
1372
1396
arg_tys[ 2 ]
1373
1397
) ;
1374
1398
}
@@ -1565,7 +1589,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
1565
1589
1566
1590
if name == sym:: simd_cast {
1567
1591
require_simd ! ( ret_ty, "return" ) ;
1568
- let out_len = ret_ty . simd_size ( tcx ) ;
1592
+ let ( out_elem , out_len) = simd_ty_and_len ( bx , ret_ty ) ;
1569
1593
require ! (
1570
1594
in_len == out_len,
1571
1595
"expected return type with length {} (same as input type `{}`), \
@@ -1576,8 +1600,6 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
1576
1600
out_len
1577
1601
) ;
1578
1602
// casting cares about nominal type, not just structural type
1579
- let out_elem = ret_ty. simd_type ( tcx) ;
1580
-
1581
1603
if in_elem == out_elem {
1582
1604
return Ok ( args[ 0 ] . immediate ( ) ) ;
1583
1605
}
@@ -1693,7 +1715,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
1693
1715
return_error ! (
1694
1716
"expected element type `{}` of vector type `{}` \
1695
1717
to be a signed or unsigned integer type",
1696
- arg_tys[ 0 ] . simd_type ( tcx ) ,
1718
+ simd_ty_and_len ( bx , arg_tys[ 0 ] ) . 0 ,
1697
1719
arg_tys[ 0 ]
1698
1720
) ;
1699
1721
}
0 commit comments