Repository: rust-lang/rust
File: compiler/rustc_codegen_ssa/src/mir/block.rs (Rust)

Code before:
                        }
                        _ => (),
                    }
                }
                CallKind::Normal => {
                    // The callee needs to own the argument memory if we pass it
                    // by-ref, so make a local copy of non-immediate constants.
                    match (&arg.node, op.val) {
                        (&mir::Operand::Copy(_), Ref(PlaceValue { llextra: None, .. }))
                        | (&mir::Operand::Constant(_), Ref(PlaceValue { llextra: None, .. })) => {
                            let tmp = PlaceRef::alloca(bx, op.layout);
                            bx.lifetime_start(tmp.val.llval, tmp.layout.size);
                            op.store_with_annotation(bx, tmp);
                            op.val = Ref(tmp.val);
                            lifetime_ends_after_call.push((tmp.val.llval, tmp.layout.size));
                        }
                        _ => {}
                    }
                }
            }

            self.codegen_argument(
                bx,
                op,
                &mut llargs,
                &fn_abi.args[i],
                &mut lifetime_ends_after_call,
            );
        }
        let num_untupled = untuple.map(|tup| {
            self.codegen_arguments_untupled(
                bx,
                &tup.node,
                &mut llargs,
                &fn_abi.args[first_args.len()..],
                &mut lifetime_ends_after_call,
            )
        });

        let needs_location =
            instance.is_some_and(|i| i.def.requires_caller_location(self.cx.tcx()));
        if needs_location {
            let mir_args = if let Some(num_untupled) = num_untupled {
                first_args.len() + num_untupled
            } else {
                args.len()
            };
            assert_eq!(
                fn_abi.args.len(),
                mir_args + 1,
                "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR: {instance:?} {fn_span:?} {fn_abi:?}",

Review comment (bug):
I've kept the `span_bug!` for now. 

It looks like a fix for x86 might get cherry-picked into LLVM 22. If so, I think that is enough support to allow this variant too. At that point riscv would be the next most commonly used target that would miscompile.

Code after:
                                        place_value,
                                        tmp.val,
                                        fn_abi.args[i].layout,
                                    );
                                    op.val = arg.val;
                                }
                                LocalRef::UnsizedPlace(_) => {
                                    span_bug!(fn_span, "unsized types are not supported")
                                }
                                LocalRef::PendingOperand => {
                                    span_bug!(fn_span, "argument local should not be pending")
                                }
                            };

                            bx.lifetime_end(tmp.val.llval, tmp.layout.size);
                        }
                        PassMode::Indirect { on_stack: true, .. } => {
                            // FIXME: some LLVM backends (notably x86) do not correctly pass byval
                            // arguments to tail calls (as of LLVM 21). See also:
                            //
                            // - https://github.com/rust-lang/rust/pull/144232#discussion_r2218543841
                            // - https://github.com/rust-lang/rust/issues/144855
                            span_bug!(
                                fn_span,
                                "arguments using PassMode::Indirect {{ on_stack: true, .. }} are currently not supported for tail calls"
                            )
                        }
                        _ => (),
                    }
                }
            }

            self.codegen_argument(
                bx,
                op,
                &mut llargs,
                &fn_abi.args[i],
                &mut lifetime_ends_after_call,
            );
        }
        let num_untupled = untuple.map(|tup| {
            self.codegen_arguments_untupled(
                bx,
                &tup.node,
                &mut llargs,
                &fn_abi.args[first_args.len()..],
                &mut lifetime_ends_after_call,
            )
        });

        let needs_location =