@@ -9,12 +9,15 @@ use rustc_middle::mir;
9
9
use rustc_middle:: mir:: tcx:: PlaceTy ;
10
10
use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , TyAndLayout } ;
11
11
use rustc_middle:: ty:: { self , Ty } ;
12
- use rustc_target:: abi:: { Align , FieldsShape , Int , Pointer , TagEncoding } ;
12
+ use rustc_target:: abi:: { Align , FieldsShape , Int , Pointer , Size , TagEncoding } ;
13
13
use rustc_target:: abi:: { VariantIdx , Variants } ;
14
14
15
15
/// The location and extra runtime properties of the place.
16
16
///
17
17
/// Typically found in a [`PlaceRef`] or an [`OperandValue::Ref`].
18
+ ///
19
+ /// As a location in memory, this has no specific type. If you want to
20
+ /// load or store it using a typed operation, use [`Self::with_type`].
18
21
#[ derive( Copy , Clone , Debug ) ]
19
22
pub struct PlaceValue < V > {
20
23
/// A pointer to the contents of the place.
@@ -34,6 +37,41 @@ impl<V: CodegenObject> PlaceValue<V> {
34
37
pub fn new_sized ( llval : V , align : Align ) -> PlaceValue < V > {
35
38
PlaceValue { llval, llextra : None , align }
36
39
}
40
+
41
+ /// Allocates a stack slot in the function for a value
42
+ /// of the specified size and alignment.
43
+ ///
44
+ /// The allocation itself is untyped.
45
+ pub fn alloca < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
46
+ bx : & mut Bx ,
47
+ size : Size ,
48
+ align : Align ,
49
+ ) -> PlaceValue < V > {
50
+ let llval = bx. alloca ( size, align) ;
51
+ PlaceValue :: new_sized ( llval, align)
52
+ }
53
+
54
+ /// Creates a `PlaceRef` to this location with the given type.
55
+ pub fn with_type < ' tcx > ( self , layout : TyAndLayout < ' tcx > ) -> PlaceRef < ' tcx , V > {
56
+ debug_assert ! (
57
+ layout. is_unsized( ) || layout. abi. is_uninhabited( ) || self . llextra. is_none( ) ,
58
+ "Had pointer metadata {:?} for sized type {layout:?}" ,
59
+ self . llextra,
60
+ ) ;
61
+ PlaceRef { val : self , layout }
62
+ }
63
+
64
+ /// Gets the pointer to this place as an [`OperandValue::Immediate`]
65
+ /// or, for those needing metadata, an [`OperandValue::Pair`].
66
+ ///
67
+ /// This is the inverse of [`OperandValue::deref`].
68
+ pub fn address ( self ) -> OperandValue < V > {
69
+ if let Some ( llextra) = self . llextra {
70
+ OperandValue :: Pair ( self . llval , llextra)
71
+ } else {
72
+ OperandValue :: Immediate ( self . llval )
73
+ }
74
+ }
37
75
}
38
76
39
77
#[ derive( Copy , Clone , Debug ) ]
@@ -51,9 +89,7 @@ pub struct PlaceRef<'tcx, V> {
51
89
52
90
impl < ' a , ' tcx , V : CodegenObject > PlaceRef < ' tcx , V > {
53
91
pub fn new_sized ( llval : V , layout : TyAndLayout < ' tcx > ) -> PlaceRef < ' tcx , V > {
54
- assert ! ( layout. is_sized( ) ) ;
55
- let val = PlaceValue :: new_sized ( llval, layout. align . abi ) ;
56
- PlaceRef { val, layout }
92
+ PlaceRef :: new_sized_aligned ( llval, layout, layout. align . abi )
57
93
}
58
94
59
95
pub fn new_sized_aligned (
@@ -62,27 +98,17 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
62
98
align : Align ,
63
99
) -> PlaceRef < ' tcx , V > {
64
100
assert ! ( layout. is_sized( ) ) ;
65
- let val = PlaceValue :: new_sized ( llval, align) ;
66
- PlaceRef { val, layout }
101
+ PlaceValue :: new_sized ( llval, align) . with_type ( layout)
67
102
}
68
103
69
104
// FIXME(eddyb) pass something else for the name so no work is done
70
105
// unless LLVM IR names are turned on (e.g. for `--emit=llvm-ir`).
71
106
pub fn alloca < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
72
107
bx : & mut Bx ,
73
108
layout : TyAndLayout < ' tcx > ,
74
- ) -> Self {
75
- Self :: alloca_aligned ( bx, layout, layout. align . abi )
76
- }
77
-
78
- pub fn alloca_aligned < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
79
- bx : & mut Bx ,
80
- layout : TyAndLayout < ' tcx > ,
81
- align : Align ,
82
109
) -> Self {
83
110
assert ! ( layout. is_sized( ) , "tried to statically allocate unsized place" ) ;
84
- let tmp = bx. alloca ( layout. size , align) ;
85
- Self :: new_sized_aligned ( tmp, layout, align)
111
+ PlaceValue :: alloca ( bx, layout. size , layout. align . abi ) . with_type ( layout)
86
112
}
87
113
88
114
/// Returns a place for an indirect reference to an unsized place.
@@ -131,18 +157,12 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
131
157
} else {
132
158
bx. inbounds_ptradd ( self . val . llval , bx. const_usize ( offset. bytes ( ) ) )
133
159
} ;
134
- PlaceRef {
135
- val : PlaceValue {
136
- llval,
137
- llextra : if bx. cx ( ) . type_has_metadata ( field. ty ) {
138
- self . val . llextra
139
- } else {
140
- None
141
- } ,
142
- align : effective_field_align,
143
- } ,
144
- layout : field,
145
- }
160
+ let val = PlaceValue {
161
+ llval,
162
+ llextra : if bx. cx ( ) . type_has_metadata ( field. ty ) { self . val . llextra } else { None } ,
163
+ align : effective_field_align,
164
+ } ;
165
+ val. with_type ( field)
146
166
} ;
147
167
148
168
// Simple cases, which don't need DST adjustment:
@@ -197,7 +217,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
197
217
let ptr = bx. inbounds_ptradd ( self . val . llval , offset) ;
198
218
let val =
199
219
PlaceValue { llval : ptr, llextra : self . val . llextra , align : effective_field_align } ;
200
- PlaceRef { val, layout : field }
220
+ val. with_type ( field)
201
221
}
202
222
203
223
/// Obtain the actual discriminant of a value.
@@ -386,18 +406,13 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
386
406
layout. size
387
407
} ;
388
408
389
- PlaceRef {
390
- val : PlaceValue {
391
- llval : bx. inbounds_gep (
392
- bx. cx ( ) . backend_type ( self . layout ) ,
393
- self . val . llval ,
394
- & [ bx. cx ( ) . const_usize ( 0 ) , llindex] ,
395
- ) ,
396
- llextra : None ,
397
- align : self . val . align . restrict_for_offset ( offset) ,
398
- } ,
399
- layout,
400
- }
409
+ let llval = bx. inbounds_gep (
410
+ bx. cx ( ) . backend_type ( self . layout ) ,
411
+ self . val . llval ,
412
+ & [ bx. cx ( ) . const_usize ( 0 ) , llindex] ,
413
+ ) ;
414
+ let align = self . val . align . restrict_for_offset ( offset) ;
415
+ PlaceValue :: new_sized ( llval, align) . with_type ( layout)
401
416
}
402
417
403
418
pub fn project_downcast < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
0 commit comments