@@ -10,12 +10,15 @@ use rustc_middle::mir;
1010use rustc_middle:: mir:: tcx:: PlaceTy ;
1111use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , TyAndLayout } ;
1212use rustc_middle:: ty:: { self , Ty } ;
13- use rustc_target:: abi:: { Align , FieldsShape , Int , Pointer , TagEncoding } ;
13+ use rustc_target:: abi:: { Align , FieldsShape , Int , Pointer , Size , TagEncoding } ;
1414use rustc_target:: abi:: { VariantIdx , Variants } ;
1515
1616/// The location and extra runtime properties of the place.
1717///
1818/// Typically found in a [`PlaceRef`] or an [`OperandValue::Ref`].
19+ ///
20+ /// As a location in memory, this has no specific type. If you want to
21+ /// load or store it using a typed operation, use [`Self::with_type`].
1922#[ derive( Copy , Clone , Debug ) ]
2023pub struct PlaceValue < V > {
2124 /// A pointer to the contents of the place.
@@ -35,6 +38,41 @@ impl<V: CodegenObject> PlaceValue<V> {
3538 pub fn new_sized ( llval : V , align : Align ) -> PlaceValue < V > {
3639 PlaceValue { llval, llextra : None , align }
3740 }
41+
42+ /// Allocates a stack slot in the function for a value
43+ /// of the specified size and alignment.
44+ ///
45+ /// The allocation itself is untyped.
46+ pub fn alloca < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
47+ bx : & mut Bx ,
48+ size : Size ,
49+ align : Align ,
50+ ) -> PlaceValue < V > {
51+ let llval = bx. alloca ( size, align) ;
52+ PlaceValue :: new_sized ( llval, align)
53+ }
54+
55+ /// Creates a `PlaceRef` to this location with the given type.
56+ pub fn with_type < ' tcx > ( self , layout : TyAndLayout < ' tcx > ) -> PlaceRef < ' tcx , V > {
57+ debug_assert ! (
58+ layout. is_unsized( ) || layout. abi. is_uninhabited( ) || self . llextra. is_none( ) ,
59+ "Had pointer metadata {:?} for sized type {layout:?}" ,
60+ self . llextra,
61+ ) ;
62+ PlaceRef { val : self , layout }
63+ }
64+
65+ /// Gets the pointer to this place as an [`OperandValue::Immediate`]
66+ /// or, for those needing metadata, an [`OperandValue::Pair`].
67+ ///
68+ /// This is the inverse of [`OperandValue::deref`].
69+ pub fn address ( self ) -> OperandValue < V > {
70+ if let Some ( llextra) = self . llextra {
71+ OperandValue :: Pair ( self . llval , llextra)
72+ } else {
73+ OperandValue :: Immediate ( self . llval )
74+ }
75+ }
3876}
3977
4078#[ derive( Copy , Clone , Debug ) ]
@@ -52,9 +90,7 @@ pub struct PlaceRef<'tcx, V> {
5290
5391impl < ' a , ' tcx , V : CodegenObject > PlaceRef < ' tcx , V > {
5492 pub fn new_sized ( llval : V , layout : TyAndLayout < ' tcx > ) -> PlaceRef < ' tcx , V > {
55- assert ! ( layout. is_sized( ) ) ;
56- let val = PlaceValue :: new_sized ( llval, layout. align . abi ) ;
57- PlaceRef { val, layout }
93+ PlaceRef :: new_sized_aligned ( llval, layout, layout. align . abi )
5894 }
5995
6096 pub fn new_sized_aligned (
@@ -63,27 +99,17 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
6399 align : Align ,
64100 ) -> PlaceRef < ' tcx , V > {
65101 assert ! ( layout. is_sized( ) ) ;
66- let val = PlaceValue :: new_sized ( llval, align) ;
67- PlaceRef { val, layout }
102+ PlaceValue :: new_sized ( llval, align) . with_type ( layout)
68103 }
69104
70105 // FIXME(eddyb) pass something else for the name so no work is done
71106 // unless LLVM IR names are turned on (e.g. for `--emit=llvm-ir`).
72107 pub fn alloca < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
73108 bx : & mut Bx ,
74109 layout : TyAndLayout < ' tcx > ,
75- ) -> Self {
76- Self :: alloca_aligned ( bx, layout, layout. align . abi )
77- }
78-
79- pub fn alloca_aligned < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
80- bx : & mut Bx ,
81- layout : TyAndLayout < ' tcx > ,
82- align : Align ,
83110 ) -> Self {
84111 assert ! ( layout. is_sized( ) , "tried to statically allocate unsized place" ) ;
85- let tmp = bx. alloca ( layout. size , align) ;
86- Self :: new_sized_aligned ( tmp, layout, align)
112+ PlaceValue :: alloca ( bx, layout. size , layout. align . abi ) . with_type ( layout)
87113 }
88114
89115 /// Returns a place for an indirect reference to an unsized place.
@@ -132,18 +158,12 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
132158 } else {
133159 bx. inbounds_ptradd ( self . val . llval , bx. const_usize ( offset. bytes ( ) ) )
134160 } ;
135- PlaceRef {
136- val : PlaceValue {
161+ let val = PlaceValue {
137162 llval,
138- llextra : if bx. cx ( ) . type_has_metadata ( field. ty ) {
139- self . val . llextra
140- } else {
141- None
142- } ,
163+ llextra : if bx. cx ( ) . type_has_metadata ( field. ty ) { self . val . llextra } else { None } ,
143164 align : effective_field_align,
144- } ,
145- layout : field,
146- }
165+ } ;
166+ val. with_type ( field)
147167 } ;
148168
149169 // Simple cases, which don't need DST adjustment:
@@ -198,7 +218,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
198218 let ptr = bx. inbounds_ptradd ( self . val . llval , offset) ;
199219 let val =
200220 PlaceValue { llval : ptr, llextra : self . val . llextra , align : effective_field_align } ;
201- PlaceRef { val, layout : field }
221+ val. with_type ( field)
202222 }
203223
204224 /// Obtain the actual discriminant of a value.
@@ -387,18 +407,13 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
387407 layout. size
388408 } ;
389409
390- PlaceRef {
391- val : PlaceValue {
392- llval : bx. inbounds_gep (
410+ let llval = bx. inbounds_gep (
393411 bx. cx ( ) . backend_type ( self . layout ) ,
394412 self . val . llval ,
395413 & [ bx. cx ( ) . const_usize ( 0 ) , llindex] ,
396- ) ,
397- llextra : None ,
398- align : self . val . align . restrict_for_offset ( offset) ,
399- } ,
400- layout,
401- }
414+ ) ;
415+ let align = self . val . align . restrict_for_offset ( offset) ;
416+ PlaceValue :: new_sized ( llval, align) . with_type ( layout)
402417 }
403418
404419 pub fn project_downcast < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
0 commit comments