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