Skip to content

Commit

Permalink
Rollup merge of #128688 - RalfJung:custom-mir-tail-calls, r=compiler-…
Browse files Browse the repository at this point in the history
…errors

custom MIR: add support for tail calls

Cc ``@WaffleLapkin``
  • Loading branch information
matthiaskrgr committed Aug 5, 2024
2 parents 9cb3688 + 212417b commit 83155b3
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 0 deletions.
22 changes: 22 additions & 0 deletions compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
@call(mir_call, args) => {
self.parse_call(args)
},
@call(mir_tail_call, args) => {
self.parse_tail_call(args)
},
ExprKind::Match { scrutinee, arms, .. } => {
let discr = self.parse_operand(*scrutinee)?;
self.parse_match(arms, expr.span).map(|t| TerminatorKind::SwitchInt { discr, targets: t })
Expand Down Expand Up @@ -187,6 +190,25 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
)
}

fn parse_tail_call(&self, args: &[ExprId]) -> PResult<TerminatorKind<'tcx>> {
parse_by_kind!(self, args[0], _, "tail call",
ExprKind::Call { fun, args, fn_span, .. } => {
let fun = self.parse_operand(*fun)?;
let args = args
.iter()
.map(|arg|
Ok(Spanned { node: self.parse_operand(*arg)?, span: self.thir.exprs[*arg].span } )
)
.collect::<PResult<Box<[_]>>>()?;
Ok(TerminatorKind::TailCall {
func: fun,
args,
fn_span: *fn_span,
})
},
)
}

fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
parse_by_kind!(self, expr_id, expr, "rvalue",
@call(mir_discriminant, args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,7 @@ symbols! {
mir_static_mut,
mir_storage_dead,
mir_storage_live,
mir_tail_call,
mir_unreachable,
mir_unwind_cleanup,
mir_unwind_continue,
Expand Down
8 changes: 8 additions & 0 deletions library/core/src/intrinsics/mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@
//! otherwise branch.
//! - [`Call`] has an associated function as well, with special syntax:
//! `Call(ret_val = function(arg1, arg2, ...), ReturnTo(next_block), UnwindContinue())`.
//! - [`TailCall`] does not have a return destination or next block, so its syntax is just
//! `TailCall(function(arg1, arg2, ...))`.

#![unstable(
feature = "custom_mir",
Expand Down Expand Up @@ -350,6 +352,12 @@ define!("mir_call",
/// - [`UnwindCleanup`]
fn Call(call: (), goto: ReturnToArg, unwind_action: UnwindActionArg)
);
define!("mir_tail_call",
/// Call a function.
///
/// The argument must be of the form `fun(arg1, arg2, ...)`.
fn TailCall<T>(call: T)
);
define!("mir_unwind_resume",
/// A terminator that resumes the unwinding.
fn UnwindResume()
Expand Down
12 changes: 12 additions & 0 deletions tests/mir-opt/building/custom/terminators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ fn direct_call(x: i32) -> i32 {
}
}

// EMIT_MIR terminators.tail_call.built.after.mir
#[custom_mir(dialect = "built")]
fn tail_call(x: i32) -> i32 {
mir! {
let y;
{
y = x + 42;
TailCall(ident(y))
}
}
}

// EMIT_MIR terminators.indirect_call.built.after.mir
#[custom_mir(dialect = "built")]
fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// MIR for `tail_call` after built

fn tail_call(_1: i32) -> i32 {
let mut _0: i32;
let mut _2: i32;

bb0: {
_2 = Add(_1, const 42_i32);
tailcall ident::<i32>(Spanned { node: _2, span: $DIR/terminators.rs:32:28: 32:29 (#0) });
}
}

0 comments on commit 83155b3

Please sign in to comment.