about summary refs log tree commit diff
path: root/compiler/rustc_middle/src/mir/terminator.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-07-08 04:35:04 +0000
committerbors <bors@rust-lang.org>2024-07-08 04:35:04 +0000
commit9af6fee87de71729efca7dbb61c0931180895424 (patch)
tree90b357fccf2a1112c764084a90cc1900ddbbea4a /compiler/rustc_middle/src/mir/terminator.rs
parentb1de36ff34a4fe4ba820f195481a13aee74e1358 (diff)
parent14e5d5fbee637af09759f924e14f97685e5c24ea (diff)
downloadrust-9af6fee87de71729efca7dbb61c0931180895424.tar.gz
rust-9af6fee87de71729efca7dbb61c0931180895424.zip
Auto merge of #113128 - WaffleLapkin:become_trully_unuwuable, r=oli-obk,RalfJung
Support tail calls in mir via `TerminatorKind::TailCall`

This is one of the interesting bits in tail call implementation — MIR support.

This adds a new `TerminatorKind` which represents a tail call:
```rust
    TailCall {
        func: Operand<'tcx>,
        args: Vec<Operand<'tcx>>,
        fn_span: Span,
    },
```

*Structurally* this is very similar to a normal `Call` but is missing a few fields:
- `destination` — tail calls don't write to destination, instead they pass caller's destination to the callee (such that eventual `return` will write to the caller of the function that used tail call)
- `target` — similarly to `destination` tail calls pass the caller's return address to the callee, so there is nothing to do
- `unwind` — I _think_ this is applicable too, although it's a bit confusing
- `call_source` — `become` forbids operators and is not created as a lowering of something else; tail calls always come from HIR (at least for now)

It might be helpful to read the interpreter implementation to understand what `TailCall` means exactly, although I've tried documenting it too.

-----

There are a few `FIXME`-questions still left, ideally we'd be able to answer them during review ':)

-----

r? `@oli-obk`
cc `@scottmcm` `@DrMeepster` `@JakobDegen`
Diffstat (limited to 'compiler/rustc_middle/src/mir/terminator.rs')
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs13
1 files changed, 10 insertions, 3 deletions
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index ed592612358..5b035d9579d 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -439,6 +439,7 @@ mod helper {
                 | CoroutineDrop
                 | Return
                 | Unreachable
+                | TailCall { .. }
                 | Call { target: None, unwind: _, .. } => (&[]).into_iter().copied().chain(None),
                 InlineAsm { ref targets, unwind: UnwindAction::Cleanup(u), .. } => {
                     targets.iter().copied().chain(Some(u))
@@ -479,6 +480,7 @@ mod helper {
                 | CoroutineDrop
                 | Return
                 | Unreachable
+                | TailCall { .. }
                 | Call { target: None, unwind: _, .. } => (&mut []).into_iter().chain(None),
                 InlineAsm { ref mut targets, unwind: UnwindAction::Cleanup(ref mut u), .. } => {
                     targets.iter_mut().chain(Some(u))
@@ -501,6 +503,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             | TerminatorKind::UnwindResume
             | TerminatorKind::UnwindTerminate(_)
             | TerminatorKind::Return
+            | TerminatorKind::TailCall { .. }
             | TerminatorKind::Unreachable
             | TerminatorKind::CoroutineDrop
             | TerminatorKind::Yield { .. }
@@ -521,6 +524,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             | TerminatorKind::UnwindResume
             | TerminatorKind::UnwindTerminate(_)
             | TerminatorKind::Return
+            | TerminatorKind::TailCall { .. }
             | TerminatorKind::Unreachable
             | TerminatorKind::CoroutineDrop
             | TerminatorKind::Yield { .. }
@@ -606,9 +610,12 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> {
         use TerminatorKind::*;
         match *self {
-            Return | UnwindResume | UnwindTerminate(_) | CoroutineDrop | Unreachable => {
-                TerminatorEdges::None
-            }
+            Return
+            | TailCall { .. }
+            | UnwindResume
+            | UnwindTerminate(_)
+            | CoroutineDrop
+            | Unreachable => TerminatorEdges::None,
 
             Goto { target } => TerminatorEdges::Single(target),