]>
Commit | Line | Data |
---|---|---|
60c5eb7d | 1 | use super::place::PlaceRef; |
dfeec247 | 2 | use super::{FunctionCx, LocalRef}; |
3157f602 | 3 | |
60c5eb7d | 4 | use crate::base; |
9fa01778 | 5 | use crate::glue; |
9fa01778 | 6 | use crate::traits::*; |
dfeec247 | 7 | use crate::MemFlags; |
a1dfa0c6 | 8 | |
ba9703b0 | 9 | use rustc_middle::mir; |
5869c6ff | 10 | use rustc_middle::mir::interpret::{ConstValue, Pointer, Scalar}; |
c295e0f8 | 11 | use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; |
ba9703b0 | 12 | use rustc_middle::ty::Ty; |
c295e0f8 | 13 | use rustc_target::abi::{Abi, Align, Size}; |
54a0048b | 14 | |
60c5eb7d | 15 | use std::fmt; |
92a42be0 SL |
16 | |
17 | /// The representation of a Rust value. The enum variant is in fact | |
18 | /// uniquely determined by the value's type, but is kept as a | |
19 | /// safety check. | |
b7449926 | 20 | #[derive(Copy, Clone, Debug)] |
a1dfa0c6 | 21 | pub enum OperandValue<V> { |
92a42be0 SL |
22 | /// A reference to the actual operand. The data is guaranteed |
23 | /// to be valid for the operand's lifetime. | |
b7449926 XL |
24 | /// The second value, if any, is the extra data (vtable or length) |
25 | /// which indicates that it refers to an unsized rvalue. | |
a1dfa0c6 | 26 | Ref(V, Option<V>, Align), |
92a42be0 | 27 | /// A single LLVM value. |
a1dfa0c6 | 28 | Immediate(V), |
3157f602 | 29 | /// A pair of immediate LLVM values. Used by fat pointers too. |
dfeec247 | 30 | Pair(V, V), |
ff7c6d11 XL |
31 | } |
32 | ||
92a42be0 SL |
33 | /// An `OperandRef` is an "SSA" reference to a Rust value, along with |
34 | /// its type. | |
35 | /// | |
36 | /// NOTE: unless you know a value's type exactly, you should not | |
37 | /// generate LLVM opcodes acting on it and instead act via methods, | |
ff7c6d11 XL |
38 | /// to avoid nasty edge cases. In particular, using `Builder::store` |
39 | /// directly is sure to cause problems -- use `OperandRef::store` | |
7453a54e | 40 | /// instead. |
92a42be0 | 41 | #[derive(Copy, Clone)] |
a1dfa0c6 | 42 | pub struct OperandRef<'tcx, V> { |
92a42be0 | 43 | // The value. |
a1dfa0c6 | 44 | pub val: OperandValue<V>, |
92a42be0 | 45 | |
ff7c6d11 | 46 | // The layout of value, based on its Rust type. |
ba9703b0 | 47 | pub layout: TyAndLayout<'tcx>, |
92a42be0 SL |
48 | } |
49 | ||
a2a8927a | 50 | impl<V: CodegenObject> fmt::Debug for OperandRef<'_, V> { |
9fa01778 | 51 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
ff7c6d11 | 52 | write!(f, "OperandRef({:?} @ {:?})", self.val, self.layout) |
92a42be0 | 53 | } |
54a0048b | 54 | } |
9cc50fc6 | 55 | |
dc9dc135 | 56 | impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { |
532ac7d7 XL |
57 | pub fn new_zst<Bx: BuilderMethods<'a, 'tcx, Value = V>>( |
58 | bx: &mut Bx, | |
ba9703b0 | 59 | layout: TyAndLayout<'tcx>, |
a1dfa0c6 | 60 | ) -> OperandRef<'tcx, V> { |
ff7c6d11 | 61 | assert!(layout.is_zst()); |
cc61c64b | 62 | OperandRef { |
532ac7d7 | 63 | val: OperandValue::Immediate(bx.const_undef(bx.immediate_backend_type(layout))), |
dfeec247 | 64 | layout, |
cc61c64b XL |
65 | } |
66 | } | |
67 | ||
a1dfa0c6 XL |
68 | pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>( |
69 | bx: &mut Bx, | |
74b04a01 XL |
70 | val: ConstValue<'tcx>, |
71 | ty: Ty<'tcx>, | |
dc9dc135 | 72 | ) -> Self { |
74b04a01 | 73 | let layout = bx.layout_of(ty); |
0531ce1d XL |
74 | |
75 | if layout.is_zst() { | |
dc9dc135 | 76 | return OperandRef::new_zst(bx, layout); |
0531ce1d XL |
77 | } |
78 | ||
74b04a01 | 79 | let val = match val { |
94b46f34 | 80 | ConstValue::Scalar(x) => { |
5e7ed085 FG |
81 | let Abi::Scalar(scalar) = layout.abi else { |
82 | bug!("from_const: invalid ByVal layout: {:#?}", layout); | |
0531ce1d | 83 | }; |
dfeec247 | 84 | let llval = bx.scalar_to_backend(x, scalar, bx.immediate_backend_type(layout)); |
0531ce1d | 85 | OperandValue::Immediate(llval) |
dfeec247 | 86 | } |
064997fb FG |
87 | ConstValue::ZeroSized => { |
88 | let llval = bx.zst_to_backend(bx.immediate_backend_type(layout)); | |
89 | OperandValue::Immediate(llval) | |
90 | } | |
dc9dc135 | 91 | ConstValue::Slice { data, start, end } => { |
5e7ed085 FG |
92 | let Abi::ScalarPair(a_scalar, _) = layout.abi else { |
93 | bug!("from_const: invalid ScalarPair layout: {:#?}", layout); | |
0531ce1d | 94 | }; |
136023e0 XL |
95 | let a = Scalar::from_pointer( |
96 | Pointer::new(bx.tcx().create_memory_alloc(data), Size::from_bytes(start)), | |
97 | &bx.tcx(), | |
98 | ); | |
532ac7d7 | 99 | let a_llval = bx.scalar_to_backend( |
0531ce1d XL |
100 | a, |
101 | a_scalar, | |
532ac7d7 | 102 | bx.scalar_pair_element_backend_type(layout, 0, true), |
0531ce1d | 103 | ); |
dc9dc135 | 104 | let b_llval = bx.const_usize((end - start) as u64); |
0531ce1d | 105 | OperandValue::Pair(a_llval, b_llval) |
dfeec247 | 106 | } |
416331ca XL |
107 | ConstValue::ByRef { alloc, offset } => { |
108 | return bx.load_operand(bx.from_const_alloc(layout, alloc, offset)); | |
dfeec247 | 109 | } |
0531ce1d XL |
110 | }; |
111 | ||
dfeec247 | 112 | OperandRef { val, layout } |
0531ce1d XL |
113 | } |
114 | ||
54a0048b SL |
115 | /// Asserts that this operand refers to a scalar and returns |
116 | /// a reference to its value. | |
a1dfa0c6 | 117 | pub fn immediate(self) -> V { |
54a0048b SL |
118 | match self.val { |
119 | OperandValue::Immediate(s) => s, | |
dfeec247 | 120 | _ => bug!("not immediate: {:?}", self), |
9cc50fc6 SL |
121 | } |
122 | } | |
3157f602 | 123 | |
dfeec247 | 124 | pub fn deref<Cx: LayoutTypeMethods<'tcx>>(self, cx: &Cx) -> PlaceRef<'tcx, V> { |
923072b8 FG |
125 | if self.layout.ty.is_box() { |
126 | bug!("dereferencing {:?} in codegen", self.layout.ty); | |
127 | } | |
128 | ||
dfeec247 XL |
129 | let projected_ty = self |
130 | .layout | |
131 | .ty | |
132 | .builtin_deref(true) | |
133 | .unwrap_or_else(|| bug!("deref of non-pointer {:?}", self)) | |
134 | .ty; | |
923072b8 | 135 | |
cc61c64b | 136 | let (llptr, llextra) = match self.val { |
b7449926 | 137 | OperandValue::Immediate(llptr) => (llptr, None), |
923072b8 | 138 | OperandValue::Pair(llptr, llextra) => (llptr, Some(llextra)), |
dfeec247 | 139 | OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self), |
cc61c64b | 140 | }; |
2c00a5a8 | 141 | let layout = cx.layout_of(projected_ty); |
dfeec247 | 142 | PlaceRef { llval: llptr, llextra, layout, align: layout.align.abi } |
cc61c64b XL |
143 | } |
144 | ||
ff7c6d11 XL |
145 | /// If this operand is a `Pair`, we return an aggregate with the two values. |
146 | /// For other cases, see `immediate`. | |
a1dfa0c6 XL |
147 | pub fn immediate_or_packed_pair<Bx: BuilderMethods<'a, 'tcx, Value = V>>( |
148 | self, | |
dfeec247 | 149 | bx: &mut Bx, |
a1dfa0c6 | 150 | ) -> V { |
3157f602 | 151 | if let OperandValue::Pair(a, b) = self.val { |
a1dfa0c6 | 152 | let llty = bx.cx().backend_type(self.layout); |
dfeec247 | 153 | debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}", self, llty); |
3157f602 | 154 | // Reconstruct the immediate aggregate. |
a1dfa0c6 | 155 | let mut llpair = bx.cx().const_undef(llty); |
1b1a35ee XL |
156 | let imm_a = bx.from_immediate(a); |
157 | let imm_b = bx.from_immediate(b); | |
a1dfa0c6 XL |
158 | llpair = bx.insert_value(llpair, imm_a, 0); |
159 | llpair = bx.insert_value(llpair, imm_b, 1); | |
ff7c6d11 XL |
160 | llpair |
161 | } else { | |
162 | self.immediate() | |
3157f602 | 163 | } |
3157f602 XL |
164 | } |
165 | ||
ff7c6d11 | 166 | /// If the type is a pair, we return a `Pair`, otherwise, an `Immediate`. |
a1dfa0c6 XL |
167 | pub fn from_immediate_or_packed_pair<Bx: BuilderMethods<'a, 'tcx, Value = V>>( |
168 | bx: &mut Bx, | |
169 | llval: V, | |
ba9703b0 | 170 | layout: TyAndLayout<'tcx>, |
a1dfa0c6 | 171 | ) -> Self { |
c295e0f8 | 172 | let val = if let Abi::ScalarPair(a, b) = layout.abi { |
dfeec247 | 173 | debug!("Operand::from_immediate_or_packed_pair: unpacking {:?} @ {:?}", llval, layout); |
ff7c6d11 | 174 | |
3157f602 | 175 | // Deconstruct the immediate aggregate. |
a1dfa0c6 | 176 | let a_llval = bx.extract_value(llval, 0); |
1b1a35ee | 177 | let a_llval = bx.to_immediate_scalar(a_llval, a); |
a1dfa0c6 | 178 | let b_llval = bx.extract_value(llval, 1); |
1b1a35ee | 179 | let b_llval = bx.to_immediate_scalar(b_llval, b); |
8faf50e0 | 180 | OperandValue::Pair(a_llval, b_llval) |
ff7c6d11 XL |
181 | } else { |
182 | OperandValue::Immediate(llval) | |
183 | }; | |
184 | OperandRef { val, layout } | |
185 | } | |
3157f602 | 186 | |
a1dfa0c6 XL |
187 | pub fn extract_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>( |
188 | &self, | |
189 | bx: &mut Bx, | |
dfeec247 | 190 | i: usize, |
a1dfa0c6 XL |
191 | ) -> Self { |
192 | let field = self.layout.field(bx.cx(), i); | |
ff7c6d11 XL |
193 | let offset = self.layout.fields.offset(i); |
194 | ||
c295e0f8 | 195 | let mut val = match (self.val, self.layout.abi) { |
83c7162d XL |
196 | // If the field is ZST, it has no data. |
197 | _ if field.is_zst() => { | |
532ac7d7 | 198 | return OperandRef::new_zst(bx, field); |
ff7c6d11 | 199 | } |
cc61c64b | 200 | |
ff7c6d11 | 201 | // Newtype of a scalar, scalar pair or vector. |
ba9703b0 | 202 | (OperandValue::Immediate(_) | OperandValue::Pair(..), _) |
dfeec247 XL |
203 | if field.size == self.layout.size => |
204 | { | |
ff7c6d11 XL |
205 | assert_eq!(offset.bytes(), 0); |
206 | self.val | |
207 | } | |
3157f602 | 208 | |
ff7c6d11 | 209 | // Extract a scalar component from a pair. |
c295e0f8 | 210 | (OperandValue::Pair(a_llval, b_llval), Abi::ScalarPair(a, b)) => { |
ff7c6d11 | 211 | if offset.bytes() == 0 { |
04454e1e | 212 | assert_eq!(field.size, a.size(bx.cx())); |
ff7c6d11 XL |
213 | OperandValue::Immediate(a_llval) |
214 | } else { | |
04454e1e FG |
215 | assert_eq!(offset, a.size(bx.cx()).align_to(b.align(bx.cx()).abi)); |
216 | assert_eq!(field.size, b.size(bx.cx())); | |
ff7c6d11 | 217 | OperandValue::Immediate(b_llval) |
3157f602 | 218 | } |
ff7c6d11 | 219 | } |
3157f602 | 220 | |
ff7c6d11 | 221 | // `#[repr(simd)]` types are also immediate. |
c295e0f8 | 222 | (OperandValue::Immediate(llval), Abi::Vector { .. }) => { |
dfeec247 | 223 | OperandValue::Immediate(bx.extract_element(llval, bx.cx().const_usize(i as u64))) |
3157f602 | 224 | } |
ff7c6d11 | 225 | |
dfeec247 | 226 | _ => bug!("OperandRef::extract_field({:?}): not applicable", self), |
ff7c6d11 XL |
227 | }; |
228 | ||
c295e0f8 | 229 | match (&mut val, field.abi) { |
1b1a35ee XL |
230 | (OperandValue::Immediate(llval), _) => { |
231 | // Bools in union fields needs to be truncated. | |
232 | *llval = bx.to_immediate(*llval, field); | |
233 | // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. | |
234 | *llval = bx.bitcast(*llval, bx.cx().immediate_backend_type(field)); | |
ff7c6d11 | 235 | } |
1b1a35ee XL |
236 | (OperandValue::Pair(a, b), Abi::ScalarPair(a_abi, b_abi)) => { |
237 | // Bools in union fields needs to be truncated. | |
238 | *a = bx.to_immediate_scalar(*a, a_abi); | |
239 | *b = bx.to_immediate_scalar(*b, b_abi); | |
240 | // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. | |
241 | *a = bx.bitcast(*a, bx.cx().scalar_pair_element_backend_type(field, 0, true)); | |
242 | *b = bx.bitcast(*b, bx.cx().scalar_pair_element_backend_type(field, 1, true)); | |
ff7c6d11 | 243 | } |
1b1a35ee XL |
244 | (OperandValue::Pair(..), _) => bug!(), |
245 | (OperandValue::Ref(..), _) => bug!(), | |
ff7c6d11 XL |
246 | } |
247 | ||
dfeec247 | 248 | OperandRef { val, layout: field } |
3157f602 | 249 | } |
92a42be0 SL |
250 | } |
251 | ||
dc9dc135 | 252 | impl<'a, 'tcx, V: CodegenObject> OperandValue<V> { |
a1dfa0c6 XL |
253 | pub fn store<Bx: BuilderMethods<'a, 'tcx, Value = V>>( |
254 | self, | |
255 | bx: &mut Bx, | |
dfeec247 | 256 | dest: PlaceRef<'tcx, V>, |
a1dfa0c6 | 257 | ) { |
83c7162d XL |
258 | self.store_with_flags(bx, dest, MemFlags::empty()); |
259 | } | |
260 | ||
a1dfa0c6 XL |
261 | pub fn volatile_store<Bx: BuilderMethods<'a, 'tcx, Value = V>>( |
262 | self, | |
263 | bx: &mut Bx, | |
dfeec247 | 264 | dest: PlaceRef<'tcx, V>, |
a1dfa0c6 | 265 | ) { |
83c7162d XL |
266 | self.store_with_flags(bx, dest, MemFlags::VOLATILE); |
267 | } | |
268 | ||
a1dfa0c6 XL |
269 | pub fn unaligned_volatile_store<Bx: BuilderMethods<'a, 'tcx, Value = V>>( |
270 | self, | |
271 | bx: &mut Bx, | |
272 | dest: PlaceRef<'tcx, V>, | |
273 | ) { | |
8faf50e0 XL |
274 | self.store_with_flags(bx, dest, MemFlags::VOLATILE | MemFlags::UNALIGNED); |
275 | } | |
276 | ||
a1dfa0c6 XL |
277 | pub fn nontemporal_store<Bx: BuilderMethods<'a, 'tcx, Value = V>>( |
278 | self, | |
279 | bx: &mut Bx, | |
dfeec247 | 280 | dest: PlaceRef<'tcx, V>, |
a1dfa0c6 | 281 | ) { |
83c7162d XL |
282 | self.store_with_flags(bx, dest, MemFlags::NONTEMPORAL); |
283 | } | |
284 | ||
a1dfa0c6 | 285 | fn store_with_flags<Bx: BuilderMethods<'a, 'tcx, Value = V>>( |
b7449926 | 286 | self, |
a1dfa0c6 XL |
287 | bx: &mut Bx, |
288 | dest: PlaceRef<'tcx, V>, | |
b7449926 XL |
289 | flags: MemFlags, |
290 | ) { | |
ff7c6d11 XL |
291 | debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest); |
292 | // Avoid generating stores of zero-sized values, because the only way to have a zero-sized | |
293 | // value is through `undef`, and store itself is useless. | |
294 | if dest.layout.is_zst() { | |
295 | return; | |
296 | } | |
297 | match self { | |
b7449926 | 298 | OperandValue::Ref(r, None, source_align) => { |
136023e0 XL |
299 | if flags.contains(MemFlags::NONTEMPORAL) { |
300 | // HACK(nox): This is inefficient but there is no nontemporal memcpy. | |
301 | let ty = bx.backend_type(dest.layout); | |
302 | let ptr = bx.pointercast(r, bx.type_ptr_to(ty)); | |
303 | let val = bx.load(ty, ptr, source_align); | |
304 | bx.store_with_flags(val, dest.llval, dest.align, flags); | |
305 | return; | |
306 | } | |
dfeec247 | 307 | base::memcpy_ty(bx, dest.llval, dest.align, r, source_align, dest.layout, flags) |
83c7162d | 308 | } |
b7449926 XL |
309 | OperandValue::Ref(_, Some(_), _) => { |
310 | bug!("cannot directly store unsized values"); | |
311 | } | |
ff7c6d11 | 312 | OperandValue::Immediate(s) => { |
1b1a35ee | 313 | let val = bx.from_immediate(s); |
83c7162d | 314 | bx.store_with_flags(val, dest.llval, dest.align, flags); |
ff7c6d11 XL |
315 | } |
316 | OperandValue::Pair(a, b) => { | |
5e7ed085 FG |
317 | let Abi::ScalarPair(a_scalar, b_scalar) = dest.layout.abi else { |
318 | bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout); | |
450edc1f | 319 | }; |
94222f64 | 320 | let ty = bx.backend_type(dest.layout); |
04454e1e | 321 | let b_offset = a_scalar.size(bx).align_to(b_scalar.align(bx).abi); |
450edc1f | 322 | |
94222f64 | 323 | let llptr = bx.struct_gep(ty, dest.llval, 0); |
1b1a35ee | 324 | let val = bx.from_immediate(a); |
450edc1f XL |
325 | let align = dest.align; |
326 | bx.store_with_flags(val, llptr, align, flags); | |
327 | ||
94222f64 | 328 | let llptr = bx.struct_gep(ty, dest.llval, 1); |
1b1a35ee | 329 | let val = bx.from_immediate(b); |
450edc1f XL |
330 | let align = dest.align.restrict_for_offset(b_offset); |
331 | bx.store_with_flags(val, llptr, align, flags); | |
ff7c6d11 XL |
332 | } |
333 | } | |
7453a54e | 334 | } |
60c5eb7d | 335 | |
a1dfa0c6 XL |
336 | pub fn store_unsized<Bx: BuilderMethods<'a, 'tcx, Value = V>>( |
337 | self, | |
338 | bx: &mut Bx, | |
dfeec247 | 339 | indirect_dest: PlaceRef<'tcx, V>, |
a1dfa0c6 | 340 | ) { |
b7449926 XL |
341 | debug!("OperandRef::store_unsized: operand={:?}, indirect_dest={:?}", self, indirect_dest); |
342 | let flags = MemFlags::empty(); | |
343 | ||
344 | // `indirect_dest` must have `*mut T` type. We extract `T` out of it. | |
dfeec247 XL |
345 | let unsized_ty = indirect_dest |
346 | .layout | |
347 | .ty | |
348 | .builtin_deref(true) | |
349 | .unwrap_or_else(|| bug!("indirect_dest has non-pointer type: {:?}", indirect_dest)) | |
350 | .ty; | |
351 | ||
3c0e092e | 352 | let OperandValue::Ref(llptr, Some(llextra), _) = self else { |
dfeec247 XL |
353 | bug!("store_unsized called with a sized value") |
354 | }; | |
b7449926 XL |
355 | |
356 | // FIXME: choose an appropriate alignment, or use dynamic align somehow | |
a1dfa0c6 XL |
357 | let max_align = Align::from_bits(128).unwrap(); |
358 | let min_align = Align::from_bits(8).unwrap(); | |
b7449926 XL |
359 | |
360 | // Allocate an appropriate region on the stack, and copy the value into it | |
a1dfa0c6 | 361 | let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); |
e1599b0c | 362 | let lldst = bx.array_alloca(bx.cx().type_i8(), llsize, max_align); |
a1dfa0c6 | 363 | bx.memcpy(lldst, max_align, llptr, min_align, llsize, flags); |
b7449926 XL |
364 | |
365 | // Store the allocated region and the extra to the indirect place. | |
366 | let indirect_operand = OperandValue::Pair(lldst, llextra); | |
a1dfa0c6 | 367 | indirect_operand.store(bx, indirect_dest); |
b7449926 | 368 | } |
ff7c6d11 | 369 | } |
7453a54e | 370 | |
dc9dc135 | 371 | impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { |
a1dfa0c6 XL |
372 | fn maybe_codegen_consume_direct( |
373 | &mut self, | |
374 | bx: &mut Bx, | |
74b04a01 | 375 | place_ref: mir::PlaceRef<'tcx>, |
a1dfa0c6 | 376 | ) -> Option<OperandRef<'tcx, Bx::Value>> { |
416331ca | 377 | debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref); |
3157f602 | 378 | |
74b04a01 | 379 | match self.locals[place_ref.local] { |
dfeec247 XL |
380 | LocalRef::Operand(Some(mut o)) => { |
381 | // Moves out of scalar and scalar pair fields are trivial. | |
382 | for elem in place_ref.projection.iter() { | |
383 | match elem { | |
384 | mir::ProjectionElem::Field(ref f, _) => { | |
385 | o = o.extract_field(bx, f.index()); | |
386 | } | |
387 | mir::ProjectionElem::Index(_) | |
388 | | mir::ProjectionElem::ConstantIndex { .. } => { | |
389 | // ZSTs don't require any actual memory access. | |
390 | // FIXME(eddyb) deduplicate this with the identical | |
391 | // checks in `codegen_consume` and `extract_field`. | |
392 | let elem = o.layout.field(bx.cx(), 0); | |
393 | if elem.is_zst() { | |
394 | o = OperandRef::new_zst(bx, elem); | |
395 | } else { | |
396 | return None; | |
dc9dc135 XL |
397 | } |
398 | } | |
dfeec247 | 399 | _ => return None, |
3157f602 XL |
400 | } |
401 | } | |
dfeec247 XL |
402 | |
403 | Some(o) | |
404 | } | |
405 | LocalRef::Operand(None) => { | |
406 | bug!("use of {:?} before def", place_ref); | |
407 | } | |
408 | LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => { | |
409 | // watch out for locals that do not have an | |
410 | // alloca; they are handled somewhat differently | |
411 | None | |
3157f602 | 412 | } |
e1599b0c | 413 | } |
ff7c6d11 XL |
414 | } |
415 | ||
a1dfa0c6 XL |
416 | pub fn codegen_consume( |
417 | &mut self, | |
418 | bx: &mut Bx, | |
74b04a01 | 419 | place_ref: mir::PlaceRef<'tcx>, |
a1dfa0c6 | 420 | ) -> OperandRef<'tcx, Bx::Value> { |
416331ca | 421 | debug!("codegen_consume(place_ref={:?})", place_ref); |
ff7c6d11 | 422 | |
416331ca | 423 | let ty = self.monomorphized_place_ty(place_ref); |
a1dfa0c6 | 424 | let layout = bx.cx().layout_of(ty); |
ff7c6d11 XL |
425 | |
426 | // ZSTs don't require any actual memory access. | |
427 | if layout.is_zst() { | |
532ac7d7 | 428 | return OperandRef::new_zst(bx, layout); |
ff7c6d11 XL |
429 | } |
430 | ||
416331ca | 431 | if let Some(o) = self.maybe_codegen_consume_direct(bx, place_ref) { |
ff7c6d11 XL |
432 | return o; |
433 | } | |
434 | ||
435 | // for most places, to consume them we just load them | |
3157f602 | 436 | // out from their home |
416331ca | 437 | let place = self.codegen_place(bx, place_ref); |
a1dfa0c6 | 438 | bx.load_operand(place) |
3157f602 XL |
439 | } |
440 | ||
a1dfa0c6 XL |
441 | pub fn codegen_operand( |
442 | &mut self, | |
443 | bx: &mut Bx, | |
dfeec247 | 444 | operand: &mir::Operand<'tcx>, |
a1dfa0c6 | 445 | ) -> OperandRef<'tcx, Bx::Value> { |
94b46f34 | 446 | debug!("codegen_operand(operand={:?})", operand); |
92a42be0 SL |
447 | |
448 | match *operand { | |
dfeec247 | 449 | mir::Operand::Copy(ref place) | mir::Operand::Move(ref place) => { |
74b04a01 | 450 | self.codegen_consume(bx, place.as_ref()) |
92a42be0 SL |
451 | } |
452 | ||
453 | mir::Operand::Constant(ref constant) => { | |
5869c6ff XL |
454 | // This cannot fail because we checked all required_consts in advance. |
455 | self.eval_mir_constant_to_operand(bx, constant).unwrap_or_else(|_err| { | |
456 | span_bug!(constant.span, "erroneous constant not captured by required_consts") | |
dfeec247 | 457 | }) |
92a42be0 SL |
458 | } |
459 | } | |
460 | } | |
92a42be0 | 461 | } |