@@ -10,12 +10,15 @@ use rustc_middle::mir;
10
10
use rustc_middle:: mir:: tcx:: PlaceTy ;
11
11
use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , TyAndLayout } ;
12
12
use 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 } ;
14
14
use rustc_target:: abi:: { VariantIdx , Variants } ;
15
15
16
16
/// The location and extra runtime properties of the place.
17
17
///
18
18
/// 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`].
19
22
#[ derive( Copy , Clone , Debug ) ]
20
23
pub struct PlaceValue < V > {
21
24
/// A pointer to the contents of the place.
@@ -35,6 +38,41 @@ impl<V: CodegenObject> PlaceValue<V> {
35
38
pub fn new_sized ( llval : V , align : Align ) -> PlaceValue < V > {
36
39
PlaceValue { llval, llextra : None , align }
37
40
}
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
+ }
38
76
}
39
77
40
78
#[ derive( Copy , Clone , Debug ) ]
@@ -52,9 +90,7 @@ pub struct PlaceRef<'tcx, V> {
52
90
53
91
impl < ' a , ' tcx , V : CodegenObject > PlaceRef < ' tcx , V > {
54
92
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 )
58
94
}
59
95
60
96
pub fn new_sized_aligned (
@@ -63,27 +99,17 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
63
99
align : Align ,
64
100
) -> PlaceRef < ' tcx , V > {
65
101
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)
68
103
}
69
104
70
105
// FIXME(eddyb) pass something else for the name so no work is done
71
106
// unless LLVM IR names are turned on (e.g. for `--emit=llvm-ir`).
72
107
pub fn alloca < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
73
108
bx : & mut Bx ,
74
109
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 ,
83
110
) -> Self {
84
111
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)
87
113
}
88
114
89
115
/// Returns a place for an indirect reference to an unsized place.
@@ -132,18 +158,12 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
132
158
} else {
133
159
bx. inbounds_ptradd ( self . val . llval , bx. const_usize ( offset. bytes ( ) ) )
134
160
} ;
135
- PlaceRef {
136
- val : PlaceValue {
161
+ let val = PlaceValue {
137
162
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 } ,
143
164
align : effective_field_align,
144
- } ,
145
- layout : field,
146
- }
165
+ } ;
166
+ val. with_type ( field)
147
167
} ;
148
168
149
169
// Simple cases, which don't need DST adjustment:
@@ -198,7 +218,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
198
218
let ptr = bx. inbounds_ptradd ( self . val . llval , offset) ;
199
219
let val =
200
220
PlaceValue { llval : ptr, llextra : self . val . llextra , align : effective_field_align } ;
201
- PlaceRef { val, layout : field }
221
+ val. with_type ( field)
202
222
}
203
223
204
224
/// Obtain the actual discriminant of a value.
@@ -387,18 +407,13 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
387
407
layout. size
388
408
} ;
389
409
390
- PlaceRef {
391
- val : PlaceValue {
392
- llval : bx. inbounds_gep (
410
+ let llval = bx. inbounds_gep (
393
411
bx. cx ( ) . backend_type ( self . layout ) ,
394
412
self . val . llval ,
395
413
& [ 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)
402
417
}
403
418
404
419
pub fn project_downcast < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
0 commit comments