83
83
//! that contain `AllocId`s.
84
84
85
85
use rustc_const_eval:: const_eval:: DummyMachine ;
86
- use rustc_const_eval:: interpret:: { intern_const_alloc_for_constprop, MemoryKind } ;
87
- use rustc_const_eval:: interpret:: { ImmTy , InterpCx , OpTy , Projectable , Scalar } ;
86
+ use rustc_const_eval:: interpret:: { intern_const_alloc_for_constprop, MemPlaceMeta , MemoryKind } ;
87
+ use rustc_const_eval:: interpret:: { ImmTy , Immediate , InterpCx , OpTy , Projectable , Scalar } ;
88
88
use rustc_data_structures:: fx:: FxIndexSet ;
89
89
use rustc_data_structures:: graph:: dominators:: Dominators ;
90
90
use rustc_hir:: def:: DefKind ;
@@ -99,7 +99,7 @@ use rustc_middle::ty::layout::LayoutOf;
99
99
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
100
100
use rustc_span:: def_id:: DefId ;
101
101
use rustc_span:: DUMMY_SP ;
102
- use rustc_target:: abi:: { self , Abi , Size , VariantIdx , FIRST_VARIANT } ;
102
+ use rustc_target:: abi:: { self , Abi , FieldIdx , Size , VariantIdx , FIRST_VARIANT } ;
103
103
use smallvec:: SmallVec ;
104
104
use std:: borrow:: Cow ;
105
105
@@ -177,6 +177,11 @@ enum AggregateTy<'tcx> {
177
177
Array ,
178
178
Tuple ,
179
179
Def ( DefId , ty:: GenericArgsRef < ' tcx > ) ,
180
+ /// Neither of these types can be recovered from the other
181
+ RawPtr {
182
+ input_thin_pointer_ty : Ty < ' tcx > ,
183
+ output_pointer_ty : Ty < ' tcx > ,
184
+ } ,
180
185
}
181
186
182
187
#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
@@ -386,11 +391,22 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
386
391
AggregateTy :: Def ( def_id, args) => {
387
392
self . tcx . type_of ( def_id) . instantiate ( self . tcx , args)
388
393
}
394
+ AggregateTy :: RawPtr { output_pointer_ty, .. } => output_pointer_ty,
389
395
} ;
390
396
let variant = if ty. is_enum ( ) { Some ( variant) } else { None } ;
391
397
let ty = self . ecx . layout_of ( ty) . ok ( ) ?;
392
398
if ty. is_zst ( ) {
393
399
ImmTy :: uninit ( ty) . into ( )
400
+ } else if matches ! ( kind, AggregateTy :: RawPtr { .. } ) {
401
+ // Pointers don't have fields, so don't `project_field` them.
402
+ let data = self . ecx . read_pointer ( fields[ 0 ] ) . ok ( ) ?;
403
+ let meta = if fields[ 1 ] . layout . is_zst ( ) {
404
+ MemPlaceMeta :: None
405
+ } else {
406
+ MemPlaceMeta :: Meta ( self . ecx . read_scalar ( fields[ 1 ] ) . ok ( ) ?)
407
+ } ;
408
+ let ptr_imm = Immediate :: new_pointer_with_meta ( data, meta, & self . ecx ) ;
409
+ ImmTy :: from_immediate ( ptr_imm, ty) . into ( )
394
410
} else if matches ! ( ty. abi, Abi :: Scalar ( ..) | Abi :: ScalarPair ( ..) ) {
395
411
let dest = self . ecx . allocate ( ty, MemoryKind :: Stack ) . ok ( ) ?;
396
412
let variant_dest = if let Some ( variant) = variant {
@@ -920,8 +936,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
920
936
}
921
937
// Do not track unions.
922
938
AggregateKind :: Adt ( _, _, _, _, Some ( _) ) => return None ,
923
- // FIXME: Do the extra work to GVN `from_raw_parts`
924
- AggregateKind :: RawPtr ( ..) => return None ,
939
+ AggregateKind :: RawPtr ( pointee_ty, mtbl) => {
940
+ assert_eq ! ( fields. len( ) , 2 ) ;
941
+ let output_pointer_ty = Ty :: new_ptr ( self . tcx , pointee_ty, mtbl) ;
942
+ let input_thin_pointer_ty = fields[ FieldIdx :: ZERO ] . ty ( self . local_decls , self . tcx ) ;
943
+ ( AggregateTy :: RawPtr { input_thin_pointer_ty, output_pointer_ty } , FIRST_VARIANT )
944
+ }
925
945
} ;
926
946
927
947
let fields: Option < Vec < _ > > = fields
@@ -960,6 +980,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
960
980
( UnOp :: Not , Value :: BinaryOp ( BinOp :: Ne , lhs, rhs) ) => {
961
981
Value :: BinaryOp ( BinOp :: Eq , * lhs, * rhs)
962
982
}
983
+ ( UnOp :: PtrMetadata , Value :: Aggregate ( AggregateTy :: RawPtr { .. } , _, fields) ) => {
984
+ return Some ( fields[ 1 ] ) ;
985
+ }
963
986
_ => return None ,
964
987
} ;
965
988
@@ -1082,6 +1105,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1082
1105
return self . new_opaque ( ) ;
1083
1106
}
1084
1107
1108
+ if let PtrToPtr = kind
1109
+ && let Value :: Aggregate ( AggregateTy :: RawPtr { input_thin_pointer_ty, .. } , _, fields) =
1110
+ self . get ( value)
1111
+ && to == * input_thin_pointer_ty
1112
+ {
1113
+ return Some ( fields[ 0 ] ) ;
1114
+ }
1115
+
1085
1116
if let PtrToPtr | PointerCoercion ( MutToConstPointer ) = kind
1086
1117
&& let Value :: Cast { kind : inner_kind, value : inner_value, from : inner_from, to : _ } =
1087
1118
* self . get ( value)
0 commit comments