diff options
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/mir/operand.rs')
-rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/operand.rs | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 34a5b638d..b37797fef 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -23,10 +23,26 @@ pub enum OperandValue<V> { /// to be valid for the operand's lifetime. /// The second value, if any, is the extra data (vtable or length) /// which indicates that it refers to an unsized rvalue. + /// + /// An `OperandValue` has this variant for types which are neither + /// `Immediate` nor `Pair`s. The backend value in this variant must be a + /// pointer to the *non*-immediate backend type. That pointee type is the + /// one returned by [`LayoutTypeMethods::backend_type`]. Ref(V, Option<V>, Align), - /// A single LLVM value. + /// A single LLVM immediate value. + /// + /// An `OperandValue` *must* be this variant for any type for which + /// [`LayoutTypeMethods::is_backend_immediate`] returns `true`. + /// The backend value in this variant must be the *immediate* backend type, + /// as returned by [`LayoutTypeMethods::immediate_backend_type`]. Immediate(V), /// A pair of immediate LLVM values. Used by fat pointers too. + /// + /// An `OperandValue` *must* be this variant for any type for which + /// [`LayoutTypeMethods::is_backend_scalar_pair`] returns `true`. + /// The backend values in this variant must be the *immediate* backend types, + /// as returned by [`LayoutTypeMethods::scalar_pair_element_backend_type`] + /// with `immediate: true`. Pair(V, V), } @@ -60,7 +76,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { ) -> OperandRef<'tcx, V> { assert!(layout.is_zst()); OperandRef { - val: OperandValue::Immediate(bx.const_undef(bx.immediate_backend_type(layout))), + val: OperandValue::Immediate(bx.const_poison(bx.immediate_backend_type(layout))), layout, } } @@ -145,7 +161,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let llty = bx.cx().backend_type(self.layout); debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}", self, llty); // Reconstruct the immediate aggregate. - let mut llpair = bx.cx().const_undef(llty); + let mut llpair = bx.cx().const_poison(llty); let imm_a = bx.from_immediate(a); let imm_b = bx.from_immediate(b); llpair = bx.insert_value(llpair, imm_a, 0); @@ -243,6 +259,31 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { } impl<'a, 'tcx, V: CodegenObject> OperandValue<V> { + /// Returns an `OperandValue` that's generally UB to use in any way. + /// + /// Depending on the `layout`, returns an `Immediate` or `Pair` containing + /// poison value(s), or a `Ref` containing a poison pointer. + /// + /// Supports sized types only. + pub fn poison<Bx: BuilderMethods<'a, 'tcx, Value = V>>( + bx: &mut Bx, + layout: TyAndLayout<'tcx>, + ) -> OperandValue<V> { + assert!(layout.is_sized()); + if bx.cx().is_backend_immediate(layout) { + let ibty = bx.cx().immediate_backend_type(layout); + OperandValue::Immediate(bx.const_poison(ibty)) + } else if bx.cx().is_backend_scalar_pair(layout) { + let ibty0 = bx.cx().scalar_pair_element_backend_type(layout, 0, true); + let ibty1 = bx.cx().scalar_pair_element_backend_type(layout, 1, true); + OperandValue::Pair(bx.const_poison(ibty0), bx.const_poison(ibty1)) + } else { + let bty = bx.cx().backend_type(layout); + let ptr_bty = bx.cx().type_ptr_to(bty); + OperandValue::Ref(bx.const_poison(ptr_bty), None, layout.align.abi) + } + } + pub fn store<Bx: BuilderMethods<'a, 'tcx, Value = V>>( self, bx: &mut Bx, @@ -370,7 +411,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref); match self.locals[place_ref.local] { - LocalRef::Operand(Some(mut o)) => { + LocalRef::Operand(mut o) => { // Moves out of scalar and scalar pair fields are trivial. for elem in place_ref.projection.iter() { match elem { @@ -395,7 +436,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Some(o) } - LocalRef::Operand(None) => { + LocalRef::PendingOperand => { bug!("use of {:?} before def", place_ref); } LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => { |