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