1
1
pub mod llvm;
2
+ mod simd;
2
3
3
4
use crate :: prelude:: * ;
4
5
@@ -70,7 +71,7 @@ macro intrinsic_match {
70
71
}
71
72
}
72
73
73
- macro_rules! call_intrinsic_match {
74
+ macro call_intrinsic_match {
74
75
( $fx: expr, $intrinsic: expr, $substs: expr, $ret: expr, $destination: expr, $args: expr, $(
75
76
$name: ident( $( $arg: ident) , * ) -> $ty: ident => $func: ident,
76
77
) * ) => {
@@ -102,32 +103,28 @@ macro_rules! call_intrinsic_match {
102
103
}
103
104
}
104
105
105
- macro_rules! atomic_binop_return_old {
106
- ( $fx: expr, $op: ident<$T: ident>( $ptr: ident, $src: ident) -> $ret: ident) => {
107
- let clif_ty = $fx. clif_type( $T) . unwrap( ) ;
108
- let old = $fx. bcx. ins( ) . load( clif_ty, MemFlags :: new( ) , $ptr, 0 ) ;
109
- let new = $fx. bcx. ins( ) . $op( old, $src) ;
110
- $fx. bcx. ins( ) . store( MemFlags :: new( ) , new, $ptr, 0 ) ;
111
- $ret. write_cvalue( $fx, CValue :: by_val( old, $fx. layout_of( $T) ) ) ;
112
- } ;
106
+ macro atomic_binop_return_old ( $fx: expr, $op: ident<$T: ident>( $ptr: ident, $src: ident) -> $ret: ident) {
107
+ let clif_ty = $fx. clif_type ( $T) . unwrap ( ) ;
108
+ let old = $fx. bcx . ins ( ) . load ( clif_ty, MemFlags :: new ( ) , $ptr, 0 ) ;
109
+ let new = $fx. bcx . ins ( ) . $op( old, $src) ;
110
+ $fx. bcx . ins ( ) . store ( MemFlags :: new ( ) , new, $ptr, 0 ) ;
111
+ $ret. write_cvalue ( $fx, CValue :: by_val ( old, $fx. layout_of ( $T) ) ) ;
113
112
}
114
113
115
- macro_rules! atomic_minmax {
116
- ( $fx: expr, $cc: expr, <$T: ident> ( $ptr: ident, $src: ident) -> $ret: ident) => {
117
- // Read old
118
- let clif_ty = $fx. clif_type( $T) . unwrap( ) ;
119
- let old = $fx. bcx. ins( ) . load( clif_ty, MemFlags :: new( ) , $ptr, 0 ) ;
114
+ macro atomic_minmax( $fx: expr, $cc: expr, <$T: ident> ( $ptr: ident, $src: ident) -> $ret: ident) {
115
+ // Read old
116
+ let clif_ty = $fx. clif_type ( $T) . unwrap ( ) ;
117
+ let old = $fx. bcx . ins ( ) . load ( clif_ty, MemFlags :: new ( ) , $ptr, 0 ) ;
120
118
121
- // Compare
122
- let is_eq = codegen_icmp( $fx, IntCC :: SignedGreaterThan , old, $src) ;
123
- let new = $fx. bcx. ins( ) . select( is_eq, old, $src) ;
119
+ // Compare
120
+ let is_eq = codegen_icmp ( $fx, IntCC :: SignedGreaterThan , old, $src) ;
121
+ let new = $fx. bcx . ins ( ) . select ( is_eq, old, $src) ;
124
122
125
- // Write new
126
- $fx. bcx. ins( ) . store( MemFlags :: new( ) , new, $ptr, 0 ) ;
123
+ // Write new
124
+ $fx. bcx . ins ( ) . store ( MemFlags :: new ( ) , new, $ptr, 0 ) ;
127
125
128
- let ret_val = CValue :: by_val( old, $ret. layout( ) ) ;
129
- $ret. write_cvalue( $fx, ret_val) ;
130
- } ;
126
+ let ret_val = CValue :: by_val ( old, $ret. layout ( ) ) ;
127
+ $ret. write_cvalue ( $fx, ret_val) ;
131
128
}
132
129
133
130
fn lane_type_and_count<' tcx>(
@@ -206,7 +203,7 @@ fn bool_to_zero_or_max_uint<'tcx>(
206
203
CValue :: by_val ( res, layout)
207
204
}
208
205
209
- macro_rules! simd_cmp {
206
+ macro simd_cmp {
210
207
( $fx: expr, $intrinsic: expr, $cc: ident( $x: ident, $y: ident) -> $ret: ident) => {
211
208
simd_for_each_lane (
212
209
$fx,
@@ -222,7 +219,7 @@ macro_rules! simd_cmp {
222
219
bool_to_zero_or_max_uint ( fx, res_lane_layout, res_lane)
223
220
} ,
224
221
) ;
225
- } ;
222
+ } ,
226
223
( $fx: expr, $intrinsic: expr, $cc_u: ident|$cc_s: ident( $x: ident, $y: ident) -> $ret: ident) => {
227
224
simd_for_each_lane (
228
225
$fx,
@@ -239,10 +236,10 @@ macro_rules! simd_cmp {
239
236
bool_to_zero_or_max_uint ( fx, res_lane_layout, res_lane)
240
237
} ,
241
238
) ;
242
- } ;
239
+ } ,
243
240
}
244
241
245
- macro_rules! simd_int_binop {
242
+ macro simd_int_binop {
246
243
( $fx: expr, $intrinsic: expr, $op: ident( $x: ident, $y: ident) -> $ret: ident) => {
247
244
simd_for_each_lane (
248
245
$fx,
@@ -258,7 +255,7 @@ macro_rules! simd_int_binop {
258
255
CValue :: by_val ( res_lane, ret_lane_layout)
259
256
} ,
260
257
) ;
261
- } ;
258
+ } ,
262
259
( $fx: expr, $intrinsic: expr, $op_u: ident|$op_s: ident( $x: ident, $y: ident) -> $ret: ident) => {
263
260
simd_for_each_lane (
264
261
$fx,
@@ -275,10 +272,10 @@ macro_rules! simd_int_binop {
275
272
CValue :: by_val ( res_lane, ret_lane_layout)
276
273
} ,
277
274
) ;
278
- } ;
275
+ } ,
279
276
}
280
277
281
- macro_rules! simd_int_flt_binop {
278
+ macro simd_int_flt_binop {
282
279
( $fx: expr, $intrinsic: expr, $op: ident|$op_f: ident ( $x: ident , $y: ident ) -> $ret: ident) => {
283
280
simd_for_each_lane(
284
281
$fx,
@@ -295,7 +292,7 @@ macro_rules! simd_int_flt_binop {
295
292
CValue :: by_val( res_lane, ret_lane_layout)
296
293
} ,
297
294
) ;
298
- } ;
295
+ } ,
299
296
( $fx: expr, $intrinsic: expr, $op_u: ident|$op_s: ident |$op_f: ident( $x: ident, $y: ident) -> $ret: ident) => {
300
297
simd_for_each_lane(
301
298
$fx,
@@ -313,26 +310,24 @@ macro_rules! simd_int_flt_binop {
313
310
CValue :: by_val( res_lane, ret_lane_layout)
314
311
} ,
315
312
) ;
316
- } ;
313
+ } ,
317
314
}
318
315
319
- macro_rules! simd_flt_binop {
320
- ( $fx: expr, $intrinsic: expr, $op: ident( $x: ident, $y: ident) -> $ret: ident) => {
321
- simd_for_each_lane(
322
- $fx,
323
- $intrinsic,
324
- $x,
325
- $y,
326
- $ret,
327
- |fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
328
- let res_lane = match lane_layout. ty. kind {
329
- ty : : Float ( _) => fx. bcx. ins( ) . $op( x_lane, y_lane) ,
330
- _ => unreachable ! ( "{:?}" , lane_layout. ty) ,
331
- } ;
332
- CValue :: by_val( res_lane, ret_lane_layout)
333
- } ,
334
- ) ;
335
- } ;
316
+ macro simd_flt_binop( $fx: expr, $intrinsic: expr, $op: ident( $x: ident, $y: ident) -> $ret: ident) {
317
+ simd_for_each_lane(
318
+ $fx,
319
+ $intrinsic,
320
+ $x,
321
+ $y,
322
+ $ret,
323
+ |fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
324
+ let res_lane = match lane_layout. ty. kind {
325
+ ty : : Float ( _) => fx. bcx. ins( ) . $op( x_lane, y_lane) ,
326
+ _ => unreachable ! ( "{:?}" , lane_layout. ty) ,
327
+ } ;
328
+ CValue :: by_val( res_lane, ret_lane_layout)
329
+ } ,
330
+ ) ;
336
331
}
337
332
338
333
pub fn codegen_intrinsic_call < ' tcx > (
@@ -371,6 +366,13 @@ pub fn codegen_intrinsic_call<'tcx>(
371
366
}
372
367
} ;
373
368
369
+ if intrinsic. starts_with( "simd_" ) {
370
+ self :: simd:: codegen_simd_intrinsic_call( fx, instance, args, ret, span) ;
371
+ let ret_ebb = fx. get_ebb( destination. expect( "SIMD intrinsics don't diverge" ) . 1 ) ;
372
+ fx. bcx. ins( ) . jump( ret_ebb, & [ ] ) ;
373
+ return ;
374
+ }
375
+
374
376
let usize_layout = fx. layout_of( fx. tcx. types. usize) ;
375
377
376
378
call_intrinsic_match ! {
@@ -944,154 +946,6 @@ pub fn codegen_intrinsic_call<'tcx>(
944
946
ret. write_cvalue( fx, val) ;
945
947
} ;
946
948
947
- simd_cast, ( c a) {
948
- let ( lane_layout, lane_count) = lane_type_and_count( fx, a. layout( ) , intrinsic) ;
949
- let ( ret_lane_layout, ret_lane_count) = lane_type_and_count( fx, ret. layout( ) , intrinsic) ;
950
- assert_eq!( lane_count, ret_lane_count) ;
951
-
952
- let ret_lane_ty = fx. clif_type( ret_lane_layout. ty) . unwrap( ) ;
953
-
954
- let from_signed = type_sign( lane_layout. ty) ;
955
- let to_signed = type_sign( ret_lane_layout. ty) ;
956
-
957
- for lane in 0 ..lane_count {
958
- let lane = mir:: Field :: new( lane. try_into( ) . unwrap( ) ) ;
959
-
960
- let a_lane = a. value_field( fx, lane) . load_scalar( fx) ;
961
- let res = clif_int_or_float_cast( fx, a_lane, from_signed, ret_lane_ty, to_signed) ;
962
- ret. place_field( fx, lane) . write_cvalue( fx, CValue :: by_val( res, ret_lane_layout) ) ;
963
- }
964
- } ;
965
-
966
- simd_eq, ( c x, c y) {
967
- simd_cmp!( fx, intrinsic, Equal ( x, y) -> ret) ;
968
- } ;
969
- simd_ne, ( c x, c y) {
970
- simd_cmp!( fx, intrinsic, NotEqual ( x, y) -> ret) ;
971
- } ;
972
- simd_lt, ( c x, c y) {
973
- simd_cmp!( fx, intrinsic, UnsignedLessThan |SignedLessThan ( x, y) -> ret) ;
974
- } ;
975
- simd_le, ( c x, c y) {
976
- simd_cmp!( fx, intrinsic, UnsignedLessThanOrEqual |SignedLessThanOrEqual ( x, y) -> ret) ;
977
- } ;
978
- simd_gt, ( c x, c y) {
979
- simd_cmp!( fx, intrinsic, UnsignedGreaterThan |SignedGreaterThan ( x, y) -> ret) ;
980
- } ;
981
- simd_ge, ( c x, c y) {
982
- simd_cmp!( fx, intrinsic, UnsignedGreaterThanOrEqual |SignedGreaterThanOrEqual ( x, y) -> ret) ;
983
- } ;
984
-
985
- // simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U
986
- _ if intrinsic. starts_with( "simd_shuffle" ) , ( c x, c y, o idx) {
987
- let n: u32 = intrinsic[ "simd_shuffle" . len( ) ..] . parse( ) . unwrap( ) ;
988
-
989
- assert_eq!( x. layout( ) , y. layout( ) ) ;
990
- let layout = x. layout( ) ;
991
-
992
- let ( lane_type, lane_count) = lane_type_and_count( fx, layout, intrinsic) ;
993
- let ( ret_lane_type, ret_lane_count) = lane_type_and_count( fx, ret. layout( ) , intrinsic) ;
994
-
995
- assert_eq!( lane_type, ret_lane_type) ;
996
- assert_eq!( n, ret_lane_count) ;
997
-
998
- let total_len = lane_count * 2 ;
999
-
1000
- let indexes = {
1001
- use rustc:: mir:: interpret:: * ;
1002
- let idx_const = crate :: constant:: mir_operand_get_const_val( fx, idx) . expect( "simd_shuffle* idx not const" ) ;
1003
-
1004
- let idx_bytes = match idx_const. val {
1005
- ty:: ConstKind :: Value ( ConstValue :: ByRef { alloc, offset } ) => {
1006
- let ptr = Pointer :: new( AllocId ( 0 /* dummy */ ) , offset) ;
1007
- let size = Size :: from_bytes( 4 * u64 :: from( ret_lane_count) /* size_of([u32; ret_lane_count]) */ ) ;
1008
- alloc. get_bytes( fx, ptr, size) . unwrap( )
1009
- }
1010
- _ => unreachable!( "{:?}" , idx_const) ,
1011
- } ;
1012
-
1013
- ( 0 ..ret_lane_count) . map( |i| {
1014
- let i = usize :: try_from( i) . unwrap( ) ;
1015
- let idx = rustc:: mir:: interpret:: read_target_uint(
1016
- fx. tcx. data_layout. endian,
1017
- & idx_bytes[ 4 * i.. 4 * i + 4 ] ,
1018
- ) . expect( "read_target_uint" ) ;
1019
- u32 :: try_from( idx) . expect( "try_from u32" )
1020
- } ) . collect:: <Vec <u32 >>( )
1021
- } ;
1022
-
1023
- for & idx in & indexes {
1024
- assert!( idx < total_len, "idx {} out of range 0..{}" , idx, total_len) ;
1025
- }
1026
-
1027
- for ( out_idx, in_idx) in indexes. into_iter( ) . enumerate( ) {
1028
- let in_lane = if in_idx < lane_count {
1029
- x. value_field( fx, mir:: Field :: new( in_idx. try_into( ) . unwrap( ) ) )
1030
- } else {
1031
- y. value_field( fx, mir:: Field :: new( ( in_idx - lane_count) . try_into( ) . unwrap( ) ) )
1032
- } ;
1033
- let out_lane = ret. place_field( fx, mir:: Field :: new( out_idx) ) ;
1034
- out_lane. write_cvalue( fx, in_lane) ;
1035
- }
1036
- } ;
1037
-
1038
- simd_extract, ( c v, o idx) {
1039
- let idx_const = if let Some ( idx_const) = crate :: constant:: mir_operand_get_const_val( fx, idx) {
1040
- idx_const
1041
- } else {
1042
- fx. tcx. sess. span_warn(
1043
- fx. mir. span,
1044
- "`#[rustc_arg_required_const(..)]` is not yet supported. Calling this function will panic." ,
1045
- ) ;
1046
- crate :: trap:: trap_panic( fx, "`#[rustc_arg_required_const(..)]` is not yet supported." ) ;
1047
- return ;
1048
- } ;
1049
-
1050
- let idx = idx_const. val. try_to_bits( Size :: from_bytes( 4 /* u32*/ ) ) . expect( & format!( "kind not scalar: {:?}" , idx_const) ) ;
1051
- let ( _lane_type, lane_count) = lane_type_and_count( fx, v. layout( ) , intrinsic) ;
1052
- if idx >= lane_count. into( ) {
1053
- fx. tcx. sess. span_fatal( fx. mir. span, & format!( "[simd_extract] idx {} >= lane_count {}" , idx, lane_count) ) ;
1054
- }
1055
-
1056
- let ret_lane = v. value_field( fx, mir:: Field :: new( idx. try_into( ) . unwrap( ) ) ) ;
1057
- ret. write_cvalue( fx, ret_lane) ;
1058
- } ;
1059
-
1060
- simd_add, ( c x, c y) {
1061
- simd_int_flt_binop!( fx, intrinsic, iadd|fadd( x, y) -> ret) ;
1062
- } ;
1063
- simd_sub, ( c x, c y) {
1064
- simd_int_flt_binop!( fx, intrinsic, isub|fsub( x, y) -> ret) ;
1065
- } ;
1066
- simd_mul, ( c x, c y) {
1067
- simd_int_flt_binop!( fx, intrinsic, imul|fmul( x, y) -> ret) ;
1068
- } ;
1069
- simd_div, ( c x, c y) {
1070
- simd_int_flt_binop!( fx, intrinsic, udiv|sdiv|fdiv( x, y) -> ret) ;
1071
- } ;
1072
- simd_shl, ( c x, c y) {
1073
- simd_int_binop!( fx, intrinsic, ishl( x, y) -> ret) ;
1074
- } ;
1075
- simd_shr, ( c x, c y) {
1076
- simd_int_binop!( fx, intrinsic, ushr|sshr( x, y) -> ret) ;
1077
- } ;
1078
- simd_and, ( c x, c y) {
1079
- simd_int_binop!( fx, intrinsic, band( x, y) -> ret) ;
1080
- } ;
1081
- simd_or, ( c x, c y) {
1082
- simd_int_binop!( fx, intrinsic, bor( x, y) -> ret) ;
1083
- } ;
1084
- simd_xor, ( c x, c y) {
1085
- simd_int_binop!( fx, intrinsic, bxor( x, y) -> ret) ;
1086
- } ;
1087
-
1088
- simd_fmin, ( c x, c y) {
1089
- simd_flt_binop!( fx, intrinsic, fmin( x, y) -> ret) ;
1090
- } ;
1091
- simd_fmax, ( c x, c y) {
1092
- simd_flt_binop!( fx, intrinsic, fmax( x, y) -> ret) ;
1093
- } ;
1094
-
1095
949
try, ( v f, v data, v _local_ptr) {
1096
950
// FIXME once unwinding is supported, change this to actually catch panics
1097
951
let f_sig = fx. bcx. func. import_signature( Signature {
0 commit comments