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