Skip to content

Commit c58787e

Browse files
Fix musttail returns for cast/indirect ABIs
1 parent 907705a commit c58787e

File tree

4 files changed

+49
-5
lines changed

4 files changed

+49
-5
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
1616
use rustc_codegen_ssa::traits::*;
1717
use rustc_data_structures::small_c_str::SmallCStr;
1818
use rustc_hir::def_id::DefId;
19-
use rustc_middle::bug;
2019
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
2120
use rustc_middle::ty::layout::{
2221
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers,
@@ -1458,10 +1457,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14581457

14591458
match &fn_abi.ret.mode {
14601459
PassMode::Ignore | PassMode::Indirect { .. } => self.ret_void(),
1461-
PassMode::Direct(_) | PassMode::Pair { .. } => self.ret(call),
1462-
mode @ PassMode::Cast { .. } => {
1463-
bug!("Encountered `PassMode::{mode:?}` during codegen")
1464-
}
1460+
PassMode::Direct(_) | PassMode::Pair { .. } | PassMode::Cast { .. } => self.ret(call),
14651461
}
14661462
}
14671463

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10551055

10561056
let mut llargs = Vec::with_capacity(arg_count);
10571057

1058+
if kind == CallKind::Tail && fn_abi.ret.is_indirect() {
1059+
match self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs) {
1060+
ReturnDest::Nothing => {}
1061+
_ => bug!(
1062+
"tail calls to functions with indirect returns cannot store into a destination"
1063+
),
1064+
}
1065+
}
1066+
10581067
// We still need to call `make_return_dest` even if there's no `target`, since
10591068
// `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited,
10601069
// and `make_return_dest` adds the return-place indirect pointer to `llargs`.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ check-pass
2+
#![allow(incomplete_features)]
3+
#![feature(explicit_tail_calls)]
4+
5+
#[inline(never)]
6+
fn leaf(_: &Box<u8>) -> [u8; 1] {
7+
[1]
8+
}
9+
10+
#[inline(never)]
11+
fn dispatch(param: &Box<u8>) -> [u8; 1] {
12+
become leaf(param)
13+
}
14+
15+
fn main() {
16+
let data = Box::new(0);
17+
let out = dispatch(&data);
18+
assert_eq!(out, [1]);
19+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//@ check-pass
2+
#![allow(incomplete_features)]
3+
#![feature(explicit_tail_calls)]
4+
5+
#[inline(never)]
6+
fn op_dummy(_param: &Box<u8>) -> [u8; 24] {
7+
[1; 24]
8+
}
9+
10+
#[inline(never)]
11+
fn dispatch(param: &Box<u8>) -> [u8; 24] {
12+
become op_dummy(param)
13+
}
14+
15+
fn main() {
16+
let param = Box::new(0);
17+
let result = dispatch(&param);
18+
eprintln!("dispatch returned: {result:?}");
19+
assert_eq!(result, [1; 24]);
20+
}

0 commit comments

Comments
 (0)