@@ -163,12 +163,6 @@ enum AggregateTy<'tcx> {
163
163
Array ,
164
164
Tuple ,
165
165
Def ( DefId , ty:: GenericArgsRef < ' tcx > ) ,
166
- RawPtr {
167
- /// Needed for cast propagation.
168
- data_pointer_ty : Ty < ' tcx > ,
169
- /// The data pointer can be anything thin, so doesn't determine the output.
170
- output_pointer_ty : Ty < ' tcx > ,
171
- } ,
172
166
}
173
167
174
168
#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
@@ -194,6 +188,17 @@ enum Value<'tcx> {
194
188
/// An aggregate value, either tuple/closure/struct/enum.
195
189
/// This does not contain unions, as we cannot reason with the value.
196
190
Aggregate ( AggregateTy < ' tcx > , VariantIdx , Vec < VnIndex > ) ,
191
+ /// A raw pointer aggregate built from a thin pointer and metadata.
192
+ RawPtr {
193
+ /// Thin pointer component. This is field 0 in MIR.
194
+ pointer : VnIndex ,
195
+ /// Metadata component. This is field 1 in MIR.
196
+ metadata : VnIndex ,
197
+ /// Needed for cast propagation.
198
+ data_pointer_ty : Ty < ' tcx > ,
199
+ /// The data pointer can be anything thin, so doesn't determine the output.
200
+ output_pointer_ty : Ty < ' tcx > ,
201
+ } ,
197
202
/// This corresponds to a `[value; count]` expression.
198
203
Repeat ( VnIndex , ty:: Const < ' tcx > ) ,
199
204
/// The address of a place.
@@ -402,22 +407,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
402
407
AggregateTy :: Def ( def_id, args) => {
403
408
self . tcx . type_of ( def_id) . instantiate ( self . tcx , args)
404
409
}
405
- AggregateTy :: RawPtr { output_pointer_ty, .. } => output_pointer_ty,
406
410
} ;
407
411
let variant = if ty. is_enum ( ) { Some ( variant) } else { None } ;
408
412
let ty = self . ecx . layout_of ( ty) . ok ( ) ?;
409
413
if ty. is_zst ( ) {
410
414
ImmTy :: uninit ( ty) . into ( )
411
- } else if matches ! ( kind, AggregateTy :: RawPtr { .. } ) {
412
- // Pointers don't have fields, so don't `project_field` them.
413
- let data = self . ecx . read_pointer ( fields[ 0 ] ) . discard_err ( ) ?;
414
- let meta = if fields[ 1 ] . layout . is_zst ( ) {
415
- MemPlaceMeta :: None
416
- } else {
417
- MemPlaceMeta :: Meta ( self . ecx . read_scalar ( fields[ 1 ] ) . discard_err ( ) ?)
418
- } ;
419
- let ptr_imm = Immediate :: new_pointer_with_meta ( data, meta, & self . ecx ) ;
420
- ImmTy :: from_immediate ( ptr_imm, ty) . into ( )
421
415
} else if matches ! (
422
416
ty. backend_repr,
423
417
BackendRepr :: Scalar ( ..) | BackendRepr :: ScalarPair ( ..)
@@ -446,6 +440,22 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
446
440
return None ;
447
441
}
448
442
}
443
+ RawPtr { pointer, metadata, output_pointer_ty, data_pointer_ty : _ } => {
444
+ let pointer = self . evaluated [ pointer] . as_ref ( ) ?;
445
+ let metadata = self . evaluated [ metadata] . as_ref ( ) ?;
446
+ let output_pointer_ty = self . ecx . layout_of ( output_pointer_ty) . ok ( ) ?;
447
+ debug_assert ! ( !output_pointer_ty. is_zst( ) ) ;
448
+
449
+ // Pointers don't have fields, so don't `project_field` them.
450
+ let data = self . ecx . read_pointer ( pointer) . discard_err ( ) ?;
451
+ let meta = if metadata. layout . is_zst ( ) {
452
+ MemPlaceMeta :: None
453
+ } else {
454
+ MemPlaceMeta :: Meta ( self . ecx . read_scalar ( metadata) . discard_err ( ) ?)
455
+ } ;
456
+ let ptr_imm = Immediate :: new_pointer_with_meta ( data, meta, & self . ecx ) ;
457
+ ImmTy :: from_immediate ( ptr_imm, output_pointer_ty) . into ( )
458
+ }
449
459
450
460
Projection ( base, elem) => {
451
461
let value = self . evaluated [ base] . as_ref ( ) ?;
@@ -1026,7 +1036,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1026
1036
}
1027
1037
}
1028
1038
1029
- let ( mut ty, variant_index) = match * kind {
1039
+ let fields: Vec < _ > = field_ops
1040
+ . iter_mut ( )
1041
+ . map ( |op| self . simplify_operand ( op, location) . unwrap_or_else ( || self . new_opaque ( ) ) )
1042
+ . collect ( ) ;
1043
+
1044
+ let ( ty, variant_index) = match * kind {
1030
1045
AggregateKind :: Array ( ..) => {
1031
1046
assert ! ( !field_ops. is_empty( ) ) ;
1032
1047
( AggregateTy :: Array , FIRST_VARIANT )
@@ -1045,41 +1060,41 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1045
1060
AggregateKind :: Adt ( _, _, _, _, Some ( _) ) => return None ,
1046
1061
AggregateKind :: RawPtr ( pointee_ty, mtbl) => {
1047
1062
assert_eq ! ( field_ops. len( ) , 2 ) ;
1048
- let data_pointer_ty = field_ops[ FieldIdx :: ZERO ] . ty ( self . local_decls , self . tcx ) ;
1063
+ let mut data_pointer_ty = field_ops[ FieldIdx :: ZERO ] . ty ( self . local_decls , self . tcx ) ;
1049
1064
let output_pointer_ty = Ty :: new_ptr ( self . tcx , pointee_ty, mtbl) ;
1050
- ( AggregateTy :: RawPtr { data_pointer_ty, output_pointer_ty } , FIRST_VARIANT )
1051
- }
1052
- } ;
1053
-
1054
- let mut fields: Vec < _ > = field_ops
1055
- . iter_mut ( )
1056
- . map ( |op| self . simplify_operand ( op, location) . unwrap_or_else ( || self . new_opaque ( ) ) )
1057
- . collect ( ) ;
1058
1065
1059
- if let AggregateTy :: RawPtr { data_pointer_ty, output_pointer_ty } = & mut ty {
1060
- let mut was_updated = false ;
1066
+ let [ mut pointer, metadata] = fields. try_into ( ) . unwrap ( ) ;
1067
+
1068
+ // Any thin pointer of matching mutability is fine as the data pointer.
1069
+ let mut was_updated = false ;
1070
+ while let Value :: Cast {
1071
+ kind : CastKind :: PtrToPtr ,
1072
+ value : cast_value,
1073
+ from : cast_from,
1074
+ to : _,
1075
+ } = self . get ( pointer)
1076
+ && let ty:: RawPtr ( from_pointee_ty, from_mtbl) = cast_from. kind ( )
1077
+ && let ty:: RawPtr ( _, output_mtbl) = output_pointer_ty. kind ( )
1078
+ && from_mtbl == output_mtbl
1079
+ && from_pointee_ty. is_sized ( self . tcx , self . typing_env ( ) )
1080
+ {
1081
+ pointer = * cast_value;
1082
+ data_pointer_ty = * cast_from;
1083
+ was_updated = true ;
1084
+ }
1061
1085
1062
- // Any thin pointer of matching mutability is fine as the data pointer.
1063
- while let Value :: Cast {
1064
- kind : CastKind :: PtrToPtr ,
1065
- value : cast_value,
1066
- from : cast_from,
1067
- to : _,
1068
- } = self . get ( fields[ 0 ] )
1069
- && let ty:: RawPtr ( from_pointee_ty, from_mtbl) = cast_from. kind ( )
1070
- && let ty:: RawPtr ( _, output_mtbl) = output_pointer_ty. kind ( )
1071
- && from_mtbl == output_mtbl
1072
- && from_pointee_ty. is_sized ( self . tcx , self . typing_env ( ) )
1073
- {
1074
- fields[ 0 ] = * cast_value;
1075
- * data_pointer_ty = * cast_from;
1076
- was_updated = true ;
1077
- }
1086
+ if was_updated && let Some ( op) = self . try_as_operand ( pointer, location) {
1087
+ field_ops[ FieldIdx :: ZERO ] = op;
1088
+ }
1078
1089
1079
- if was_updated && let Some ( op) = self . try_as_operand ( fields[ 0 ] , location) {
1080
- field_ops[ FieldIdx :: ZERO ] = op;
1090
+ return Some ( self . insert ( Value :: RawPtr {
1091
+ output_pointer_ty,
1092
+ data_pointer_ty,
1093
+ pointer,
1094
+ metadata,
1095
+ } ) ) ;
1081
1096
}
1082
- }
1097
+ } ;
1083
1098
1084
1099
if let AggregateTy :: Array = ty
1085
1100
&& fields. len ( ) > 4
@@ -1165,9 +1180,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1165
1180
( UnOp :: Not , Value :: BinaryOp ( BinOp :: Ne , lhs, rhs) ) => {
1166
1181
Value :: BinaryOp ( BinOp :: Eq , * lhs, * rhs)
1167
1182
}
1168
- ( UnOp :: PtrMetadata , Value :: Aggregate ( AggregateTy :: RawPtr { .. } , _, fields) ) => {
1169
- return Some ( fields[ 1 ] ) ;
1170
- }
1183
+ ( UnOp :: PtrMetadata , Value :: RawPtr { metadata, .. } ) => return Some ( * metadata) ,
1171
1184
// We have an unsizing cast, which assigns the length to wide pointer metadata.
1172
1185
(
1173
1186
UnOp :: PtrMetadata ,
@@ -1399,16 +1412,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1399
1412
// If a cast just casts away the metadata again, then we can get it by
1400
1413
// casting the original thin pointer passed to `from_raw_parts`
1401
1414
if let PtrToPtr = kind
1402
- && let Value :: Aggregate ( AggregateTy :: RawPtr { data_pointer_ty, .. } , _, fields) =
1403
- self . get ( value)
1415
+ && let Value :: RawPtr { data_pointer_ty, pointer, .. } = self . get ( value)
1404
1416
&& let ty:: RawPtr ( to_pointee, _) = to. kind ( )
1405
1417
&& to_pointee. is_sized ( self . tcx , self . typing_env ( ) )
1406
1418
{
1407
1419
from = * data_pointer_ty;
1408
- value = fields [ 0 ] ;
1420
+ value = * pointer ;
1409
1421
was_updated_this_iteration = true ;
1410
1422
if * data_pointer_ty == to {
1411
- return Some ( fields [ 0 ] ) ;
1423
+ return Some ( * pointer ) ;
1412
1424
}
1413
1425
}
1414
1426
0 commit comments