Repository: rust-lang/rust
File: compiler/rustc_target/src/callconv/mod.rs (Rust)

Code before:
                    // across this boundary would cause corrupt data to show up.
                    //
                    // This problem is fixed by unconditionally passing SIMD
                    // arguments through memory between callers and callees
                    // which should get them all to agree on ABI regardless of
                    // target feature sets. Some more information about this
                    // issue can be found in #44367.
                    //
                    // We *could* do better in some cases, e.g. on x86_64 targets where SSE2 is
                    // required. However, it turns out that that makes LLVM worse at optimizing this
                    // code, so we pass things indirectly even there. See #139029 for more on that.
                    if spec.simd_types_indirect {
                        arg.make_indirect();
                    }
                }

                _ => {}
            }
        }

        // `cast_to()` creates a `CastTarget` with empty `attrs`, losing type validity
        // information. Restore `noundef` from the original layout where provable.
        for arg in self.args.iter_mut().chain(iter::once(&mut self.ret)) {
            if let PassMode::Cast { ref mut cast, .. } = arg.mode {
                if layout_is_noundef(arg.layout, cx) {
                    cast.attrs.set(ArgAttribute::NoUndef);
                }
            }
        }
    }
}

/// Determines whether `layout` contains no uninit bytes (no padding, no unions),
/// using only the computed layout.
///
/// Conservative: returns `false` for anything it cannot prove fully initialized,
/// including multi-variant enums and SIMD vectors.
// FIXME: extend to multi-variant enums (per-variant padding analysis needed).
fn layout_is_noundef<'a, Ty, C>(layout: TyAndLayout<'a, Ty>, cx: &C) -> bool
where
    Ty: TyAbiInterface<'a, C> + Copy,
    C: HasDataLayout,
{
    match layout.backend_repr {
        BackendRepr::Scalar(scalar) => !scalar.is_uninit_valid(),
        BackendRepr::ScalarPair(..) => fields_cover_layout(layout, cx),
        BackendRepr::Memory { .. } => match layout.fields {
            FieldsShape::Primitive | FieldsShape::Union(_) => false,
            // Array elements are at stride offsets with no inter-element gaps.
            FieldsShape::Array { stride: _, count } => {
                count == 0 || layout_is_noundef(layout.field(cx, 0), cx)

Review comment (suggestion):
Seems better to do this when invoking `cast_to`, rather than yet another layer of fixups. ABI adjustments are already an imperative mess, no need to make it even worse. :)

Code after:

                BackendRepr::SimdVector { .. } => {
                    // This is a fun case! The gist of what this is doing is
                    // that we want callers and callees to always agree on the
                    // ABI of how they pass SIMD arguments. If we were to *not*
                    // make these arguments indirect then they'd be immediates
                    // in LLVM, which means that they'd used whatever the
                    // appropriate ABI is for the callee and the caller. That
                    // means, for example, if the caller doesn't have AVX
                    // enabled but the callee does, then passing an AVX argument
                    // across this boundary would cause corrupt data to show up.
                    //
                    // This problem is fixed by unconditionally passing SIMD
                    // arguments through memory between callers and callees
                    // which should get them all to agree on ABI regardless of
                    // target feature sets. Some more information about this
                    // issue can be found in #44367.
                    //
                    // We *could* do better in some cases, e.g. on x86_64 targets where SSE2 is
                    // required. However, it turns out that that makes LLVM worse at optimizing this
                    // code, so we pass things indirectly even there. See #139029 for more on that.
                    if spec.simd_types_indirect {
                        arg.make_indirect();
                    }
                }

                _ => {}
            }
        }
    }
}

/// Determines whether `layout` contains no uninit bytes (no padding, no unions),
/// using only the computed layout.
///
/// Conservative: returns `false` for anything it cannot prove fully initialized,
/// including multi-variant enums and SIMD vectors.
// FIXME: extend to multi-variant enums (per-variant padding analysis needed).
fn layout_is_noundef<'a, Ty, C>(layout: TyAndLayout<'a, Ty>, cx: &C) -> bool
where
    Ty: TyAbiInterface<'a, C> + Copy,
    C: HasDataLayout,
{
    match layout.backend_repr {
        BackendRepr::Scalar(scalar) => !scalar.is_uninit_valid(),
        BackendRepr::ScalarPair(s1, s2) => {
            !s1.is_uninit_valid()
                && !s2.is_uninit_valid()
                // Ensure there is no padding.
                && s1.size(cx) + s2.size(cx) == layout.size
        }