summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_codegen_ssa/src/mir/operand.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/mir/operand.rs')
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs51
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(..) => {