custom MIR: add support for tail calls
This commit is contained in:
parent
83e9b93c90
commit
212417b87f
@ -75,6 +75,9 @@ pub(crate) fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind
|
|||||||
@call(mir_call, args) => {
|
@call(mir_call, args) => {
|
||||||
self.parse_call(args)
|
self.parse_call(args)
|
||||||
},
|
},
|
||||||
|
@call(mir_tail_call, args) => {
|
||||||
|
self.parse_tail_call(args)
|
||||||
|
},
|
||||||
ExprKind::Match { scrutinee, arms, .. } => {
|
ExprKind::Match { scrutinee, arms, .. } => {
|
||||||
let discr = self.parse_operand(*scrutinee)?;
|
let discr = self.parse_operand(*scrutinee)?;
|
||||||
self.parse_match(arms, expr.span).map(|t| TerminatorKind::SwitchInt { discr, targets: t })
|
self.parse_match(arms, expr.span).map(|t| TerminatorKind::SwitchInt { discr, targets: t })
|
||||||
@ -187,6 +190,25 @@ fn parse_call(&self, args: &[ExprId]) -> PResult<TerminatorKind<'tcx>> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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>> {
|
fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
|
||||||
parse_by_kind!(self, expr_id, expr, "rvalue",
|
parse_by_kind!(self, expr_id, expr, "rvalue",
|
||||||
@call(mir_discriminant, args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
|
@call(mir_discriminant, args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
|
||||||
|
@ -1216,6 +1216,7 @@
|
|||||||
mir_static_mut,
|
mir_static_mut,
|
||||||
mir_storage_dead,
|
mir_storage_dead,
|
||||||
mir_storage_live,
|
mir_storage_live,
|
||||||
|
mir_tail_call,
|
||||||
mir_unreachable,
|
mir_unreachable,
|
||||||
mir_unwind_cleanup,
|
mir_unwind_cleanup,
|
||||||
mir_unwind_continue,
|
mir_unwind_continue,
|
||||||
|
@ -247,6 +247,8 @@
|
|||||||
//! otherwise branch.
|
//! otherwise branch.
|
||||||
//! - [`Call`] has an associated function as well, with special syntax:
|
//! - [`Call`] has an associated function as well, with special syntax:
|
||||||
//! `Call(ret_val = function(arg1, arg2, ...), ReturnTo(next_block), UnwindContinue())`.
|
//! `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(
|
#![unstable(
|
||||||
feature = "custom_mir",
|
feature = "custom_mir",
|
||||||
@ -350,6 +352,12 @@ fn Drop<T>(place: T, goto: ReturnToArg, unwind_action: UnwindActionArg)
|
|||||||
/// - [`UnwindCleanup`]
|
/// - [`UnwindCleanup`]
|
||||||
fn Call(call: (), goto: ReturnToArg, unwind_action: UnwindActionArg)
|
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",
|
define!("mir_unwind_resume",
|
||||||
/// A terminator that resumes the unwinding.
|
/// A terminator that resumes the unwinding.
|
||||||
fn UnwindResume()
|
fn UnwindResume()
|
||||||
|
@ -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
|
// EMIT_MIR terminators.indirect_call.built.after.mir
|
||||||
#[custom_mir(dialect = "built")]
|
#[custom_mir(dialect = "built")]
|
||||||
fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 {
|
fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 {
|
||||||
|
@ -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) });
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user