core/intrinsics/
mir.rs

1//! Rustc internal tooling for hand-writing MIR.
2//!
3//! If for some reasons you are not writing rustc tests and have found yourself considering using
4//! this feature, turn back. This is *exceptionally* unstable. There is no attempt at all to make
5//! anything work besides those things which the rustc test suite happened to need. If you make a
6//! typo you'll probably ICE. Really, this is not the solution to your problems. Consider instead
7//! supporting the [stable MIR project group](https://github.com/rust-lang/project-stable-mir).
8//!
9//! The documentation for this module describes how to use this feature. If you are interested in
10//! hacking on the implementation, most of that documentation lives at
11//! `rustc_mir_build/src/build/custom/mod.rs`.
12//!
13//! Typical usage will look like this:
14//!
15//! ```rust
16//! #![feature(core_intrinsics, custom_mir)]
17//! #![allow(internal_features)]
18//!
19//! use core::intrinsics::mir::*;
20//!
21//! #[custom_mir(dialect = "built")]
22//! pub fn simple(x: i32) -> i32 {
23//!     mir! {
24//!         let temp2: i32;
25//!
26//!         {
27//!             let temp1 = x;
28//!             Goto(my_second_block)
29//!         }
30//!
31//!         my_second_block = {
32//!             temp2 = Move(temp1);
33//!             RET = temp2;
34//!             Return()
35//!         }
36//!     }
37//! }
38//! ```
39//!
40//! The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This
41//! attribute only works on functions - there is no way to insert custom MIR into the middle of
42//! another function. The `dialect` and `phase` parameters indicate which [version of MIR][dialect
43//! docs] you are inserting here. Generally you'll want to use `#![custom_mir(dialect = "built")]`
44//! if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
45//! "runtime", phase = "optimized")]` if you don't.
46//!
47//! [dialect docs]:
48//!     https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html
49//!
50//! The input to the [`mir!`] macro is:
51//!
52//!  - An optional return type annotation in the form of `type RET = ...;`. This may be required
53//!    if the compiler cannot infer the type of RET.
54//!  - A possibly empty list of local declarations. Locals can also be declared inline on
55//!    assignments via `let`. Type inference generally works. Shadowing does not.
56//!  - A list of basic blocks. The first of these is the start block and is where execution begins.
57//!    All blocks other than the start block need to be given a name, so that they can be referred
58//!    to later.
59//!     - Each block is a list of semicolon terminated statements, followed by a terminator. The
60//!       syntax for the various statements and terminators is designed to be as similar as possible
61//!       to the syntax for analogous concepts in native Rust. See below for a list.
62//!
63//! # Examples
64//!
65//! ```rust
66//! #![feature(core_intrinsics, custom_mir)]
67//! #![allow(internal_features)]
68//! #![allow(unused_assignments)]
69//!
70//! use core::intrinsics::mir::*;
71//!
72//! #[custom_mir(dialect = "built")]
73//! pub fn choose_load(a: &i32, b: &i32, c: bool) -> i32 {
74//!     mir! {
75//!         {
76//!             match c {
77//!                 true => t,
78//!                 _ => f,
79//!             }
80//!         }
81//!
82//!         t = {
83//!             let temp = a;
84//!             Goto(load_and_exit)
85//!         }
86//!
87//!         f = {
88//!             temp = b;
89//!             Goto(load_and_exit)
90//!         }
91//!
92//!         load_and_exit = {
93//!             RET = *temp;
94//!             Return()
95//!         }
96//!     }
97//! }
98//!
99//! #[custom_mir(dialect = "built")]
100//! fn unwrap_unchecked<T>(opt: Option<T>) -> T {
101//!     mir! {
102//!         {
103//!             RET = Move(Field(Variant(opt, 1), 0));
104//!             Return()
105//!         }
106//!     }
107//! }
108//!
109//! #[custom_mir(dialect = "runtime", phase = "optimized")]
110//! fn push_and_pop<T>(v: &mut Vec<T>, value: T) {
111//!     mir! {
112//!         let _unused;
113//!         let popped;
114//!
115//!         {
116//!             Call(_unused = Vec::push(v, value), ReturnTo(pop), UnwindContinue())
117//!         }
118//!
119//!         pop = {
120//!             Call(popped = Vec::pop(v), ReturnTo(drop), UnwindContinue())
121//!         }
122//!
123//!         drop = {
124//!             Drop(popped, ReturnTo(ret), UnwindContinue())
125//!         }
126//!
127//!         ret = {
128//!             Return()
129//!         }
130//!     }
131//! }
132//!
133//! #[custom_mir(dialect = "runtime", phase = "optimized")]
134//! fn annotated_return_type() -> (i32, bool) {
135//!     mir! {
136//!         type RET = (i32, bool);
137//!         {
138//!             RET.0 = 1;
139//!             RET.1 = true;
140//!             Return()
141//!         }
142//!     }
143//! }
144//! ```
145//!
146//! We can also set off compilation failures that happen in sufficiently late stages of the
147//! compiler:
148//!
149//! ```rust,compile_fail
150//! #![feature(core_intrinsics, custom_mir)]
151//!
152//! extern crate core;
153//! use core::intrinsics::mir::*;
154//!
155//! #[custom_mir(dialect = "built")]
156//! fn borrow_error(should_init: bool) -> i32 {
157//!     mir! {
158//!         let temp: i32;
159//!
160//!         {
161//!             match should_init {
162//!                 true => init,
163//!                 _ => use_temp,
164//!             }
165//!         }
166//!
167//!         init = {
168//!             temp = 0;
169//!             Goto(use_temp)
170//!         }
171//!
172//!         use_temp = {
173//!             RET = temp;
174//!             Return()
175//!         }
176//!     }
177//! }
178//! ```
179//!
180//! ```text
181//! error[E0381]: used binding is possibly-uninitialized
182//!   --> test.rs:24:13
183//!    |
184//! 8  | /     mir! {
185//! 9  | |         let temp: i32;
186//! 10 | |
187//! 11 | |         {
188//! ...  |
189//! 19 | |             temp = 0;
190//!    | |             -------- binding initialized here in some conditions
191//! ...  |
192//! 24 | |             RET = temp;
193//!    | |             ^^^^^^^^^^ value used here but it is possibly-uninitialized
194//! 25 | |             Return()
195//! 26 | |         }
196//! 27 | |     }
197//!    | |_____- binding declared here but left uninitialized
198//!
199//! error: aborting due to 1 previous error
200//!
201//! For more information about this error, try `rustc --explain E0381`.
202//! ```
203//!
204//! # Syntax
205//!
206//! The lists below are an exhaustive description of how various MIR constructs can be created.
207//! Anything missing from the list should be assumed to not be supported, PRs welcome.
208//!
209//! #### Locals
210//!
211//!  - The `_0` return local can always be accessed via `RET`.
212//!  - Arguments can be accessed via their regular name.
213//!  - All other locals need to be declared with `let` somewhere and then can be accessed by name.
214//!
215//! #### Places
216//!  - Locals implicitly convert to places.
217//!  - Field accesses, derefs, and indexing work normally.
218//!  - Fields in variants can be accessed via the [`Variant`] and [`Field`] associated functions,
219//!    see their documentation for details.
220//!
221//! #### Operands
222//!  - Places implicitly convert to `Copy` operands.
223//!  - `Move` operands can be created via [`Move`].
224//!  - Const blocks, literals, named constants, and const params all just work.
225//!  - [`Static`] and [`StaticMut`] can be used to create `&T` and `*mut T`s to statics. These are
226//!    constants in MIR and the only way to access statics.
227//!
228//! #### Statements
229//!  - Assign statements work via normal Rust assignment.
230//!  - [`Retag`], [`StorageLive`], [`StorageDead`] statements have an associated function.
231//!
232//! #### Rvalues
233//!
234//!  - Operands implicitly convert to `Use` rvalues.
235//!  - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue.
236//!  - [`CastTransmute`], [`CastPtrToPtr`], [`CastUnsize`], and [`Discriminant`]
237//!    have associated functions.
238//!  - Unary and binary operations use their normal Rust syntax - `a * b`, `!c`, etc.
239//!  - The binary operation `Offset` can be created via [`Offset`].
240//!  - Checked binary operations are represented by wrapping the associated binop in [`Checked`].
241//!  - Array repetition syntax (`[foo; 10]`) creates the associated rvalue.
242//!
243//! #### Terminators
244//!
245//!  - [`Goto`], [`Return`], [`Unreachable`] and [`Drop`](Drop()) have associated functions.
246//!  - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block`
247//!     - The exception is the last arm, which must be `_ => basic_block` and corresponds to the
248//!       otherwise branch.
249//!  - [`Call`] has an associated function as well, with special syntax:
250//!    `Call(ret_val = function(arg1, arg2, ...), ReturnTo(next_block), UnwindContinue())`.
251//!  - [`TailCall`] does not have a return destination or next block, so its syntax is just
252//!    `TailCall(function(arg1, arg2, ...))`.
253//!
254//! #### Debuginfo
255//!
256//! Debuginfo associates source code variable names (of variables that may not exist any more) with
257//! MIR expressions that indicate where the value of that variable is stored. The syntax to do so
258//! is:
259//! ```text
260//! debug source_var_name => expression;
261//! ```
262//! Both places and constants are supported in the `expression`.
263//!
264//! ```rust
265//! #![allow(internal_features)]
266//! #![feature(core_intrinsics, custom_mir)]
267//!
268//! use core::intrinsics::mir::*;
269//!
270//! #[custom_mir(dialect = "built")]
271//! fn debuginfo(arg: Option<&i32>) {
272//!     mir!(
273//!         // Debuginfo for a source variable `plain_local` that just duplicates `arg`.
274//!         debug plain_local => arg;
275//!         // Debuginfo for a source variable `projection` that can be computed by dereferencing
276//!         // a field of `arg`.
277//!         debug projection => *Field::<&i32>(Variant(arg, 1), 0);
278//!         // Debuginfo for a source variable `constant` that always holds the value `5`.
279//!         debug constant => 5_usize;
280//!         {
281//!             Return()
282//!         }
283//!     )
284//! }
285//! ```
286
287#![unstable(
288    feature = "custom_mir",
289    reason = "MIR is an implementation detail and extremely unstable",
290    issue = "none"
291)]
292#![allow(unused_variables, non_snake_case, missing_debug_implementations)]
293
294/// Type representing basic blocks.
295///
296/// All terminators will have this type as a return type. It helps achieve some type safety.
297#[rustc_diagnostic_item = "mir_basic_block"]
298pub enum BasicBlock {
299    /// A non-cleanup basic block.
300    Normal,
301    /// A basic block that lies on an unwind path.
302    Cleanup,
303}
304
305/// The reason we are terminating the process during unwinding.
306#[rustc_diagnostic_item = "mir_unwind_terminate_reason"]
307pub enum UnwindTerminateReason {
308    /// Unwinding is just not possible given the ABI of this function.
309    Abi,
310    /// We were already cleaning up for an ongoing unwind, and a *second*, *nested* unwind was
311    /// triggered by the drop glue.
312    InCleanup,
313}
314
315pub use UnwindTerminateReason::{Abi as ReasonAbi, InCleanup as ReasonInCleanup};
316
317macro_rules! define {
318    ($name:literal, $( #[ $meta:meta ] )* fn $($sig:tt)*) => {
319        #[rustc_diagnostic_item = $name]
320        #[inline]
321        $( #[ $meta ] )*
322        pub fn $($sig)* { panic!() }
323    }
324}
325
326// Unwind actions
327pub struct UnwindActionArg;
328define!(
329    "mir_unwind_continue",
330    /// An unwind action that continues unwinding.
331    fn UnwindContinue() -> UnwindActionArg
332);
333define!(
334    "mir_unwind_unreachable",
335    /// An unwind action that triggers undefined behavior.
336    fn UnwindUnreachable() -> UnwindActionArg
337);
338define!(
339    "mir_unwind_terminate",
340    /// An unwind action that terminates the execution.
341    ///
342    /// `UnwindTerminate` can also be used as a terminator.
343    fn UnwindTerminate(reason: UnwindTerminateReason) -> UnwindActionArg
344);
345define!(
346    "mir_unwind_cleanup",
347    /// An unwind action that continues execution in a given basic block.
348    fn UnwindCleanup(goto: BasicBlock) -> UnwindActionArg
349);
350
351// Return destination for `Call`
352pub struct ReturnToArg;
353define!("mir_return_to", fn ReturnTo(goto: BasicBlock) -> ReturnToArg);
354
355// Terminators
356define!("mir_return", fn Return() -> BasicBlock);
357define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
358define!("mir_unreachable", fn Unreachable() -> BasicBlock);
359define!("mir_drop",
360    /// Drop the contents of a place.
361    ///
362    /// The first argument must be a place.
363    ///
364    /// The second argument must be of the form `ReturnTo(bb)`, where `bb` is the basic block that
365    /// will be jumped to after the destructor returns.
366    ///
367    /// The third argument describes what happens on unwind. It can be one of:
368    /// - [`UnwindContinue`]
369    /// - [`UnwindUnreachable`]
370    /// - [`UnwindTerminate`]
371    /// - [`UnwindCleanup`]
372    fn Drop<T>(place: T, goto: ReturnToArg, unwind_action: UnwindActionArg)
373);
374define!("mir_call",
375    /// Call a function.
376    ///
377    /// The first argument must be of the form `ret_val = fun(arg1, arg2, ...)`.
378    ///
379    /// The second argument must be of the form `ReturnTo(bb)`, where `bb` is the basic block that
380    /// will be jumped to after the function returns.
381    ///
382    /// The third argument describes what happens on unwind. It can be one of:
383    /// - [`UnwindContinue`]
384    /// - [`UnwindUnreachable`]
385    /// - [`UnwindTerminate`]
386    /// - [`UnwindCleanup`]
387    fn Call(call: (), goto: ReturnToArg, unwind_action: UnwindActionArg)
388);
389define!("mir_tail_call",
390    /// Call a function.
391    ///
392    /// The argument must be of the form `fun(arg1, arg2, ...)`.
393    fn TailCall<T>(call: T)
394);
395define!("mir_unwind_resume",
396    /// A terminator that resumes the unwinding.
397    fn UnwindResume()
398);
399
400define!("mir_storage_live", fn StorageLive<T>(local: T));
401define!("mir_storage_dead", fn StorageDead<T>(local: T));
402define!("mir_assume", fn Assume(operand: bool));
403define!("mir_checked", fn Checked<T>(binop: T) -> (T, bool));
404define!(
405    "mir_ptr_metadata",
406    fn PtrMetadata<P: ?Sized>(place: *const P) -> <P as ::core::ptr::Pointee>::Metadata
407);
408define!("mir_retag", fn Retag<T>(place: T));
409define!("mir_move", fn Move<T>(place: T) -> T);
410define!("mir_static", fn Static<T>(s: T) -> &'static T);
411define!("mir_static_mut", fn StaticMut<T>(s: T) -> *mut T);
412define!(
413    "mir_discriminant",
414    /// Gets the discriminant of a place.
415    fn Discriminant<T>(place: T) -> <T as ::core::marker::DiscriminantKind>::Discriminant
416);
417define!("mir_set_discriminant", fn SetDiscriminant<T>(place: T, index: u32));
418define!("mir_offset", fn Offset<T, U>(ptr: T, count: U) -> T);
419define!(
420    "mir_field",
421    /// Access the field with the given index of some place.
422    ///
423    /// This only makes sense to use in conjunction with [`Variant`]. If the type you are looking to
424    /// access the field of does not have variants, you can use normal field projection syntax.
425    ///
426    /// There is no proper way to do a place projection to a variant in Rust, and so these two
427    /// functions are a workaround. You can access a field of a variant via `Field(Variant(place,
428    /// var_idx), field_idx)`, where `var_idx` and `field_idx` are appropriate literals. Some
429    /// caveats:
430    ///
431    ///  - The return type of `Variant` is always `()`. Don't worry about that, the correct MIR will
432    ///    still be generated.
433    ///  - In some situations, the return type of `Field` cannot be inferred. You may need to
434    ///    annotate it on the function in these cases.
435    ///  - Since `Field` is a function call which is not a place expression, using this on the left
436    ///    hand side of an expression is rejected by the compiler. [`place!`] is a macro provided to
437    ///    work around that issue. Wrap the left hand side of an assignment in the macro to convince
438    ///    the compiler that it's ok.
439    ///
440    /// # Examples
441    ///
442    /// ```rust
443    /// #![allow(internal_features)]
444    /// #![feature(custom_mir, core_intrinsics)]
445    ///
446    /// use core::intrinsics::mir::*;
447    ///
448    /// #[custom_mir(dialect = "built")]
449    /// fn unwrap_deref(opt: Option<&i32>) -> i32 {
450    ///     mir! {
451    ///         {
452    ///             RET = *Field::<&i32>(Variant(opt, 1), 0);
453    ///             Return()
454    ///         }
455    ///     }
456    /// }
457    ///
458    /// #[custom_mir(dialect = "built")]
459    /// fn set(opt: &mut Option<i32>) {
460    ///     mir! {
461    ///         {
462    ///             place!(Field(Variant(*opt, 1), 0)) = 5;
463    ///             Return()
464    ///         }
465    ///     }
466    /// }
467    /// ```
468    fn Field<F>(place: (), field: u32) -> F
469);
470define!(
471    "mir_variant",
472    /// Adds a variant projection with the given index to the place.
473    ///
474    /// See [`Field`] for documentation.
475    fn Variant<T>(place: T, index: u32) -> ()
476);
477define!(
478    "mir_cast_transmute",
479    /// Emits a `CastKind::Transmute` cast.
480    ///
481    /// Needed to test the UB when `sizeof(T) != sizeof(U)`, which can't be
482    /// generated via the normal `mem::transmute`.
483    fn CastTransmute<T, U>(operand: T) -> U
484);
485define!(
486    "mir_cast_ptr_to_ptr",
487    /// Emits a `CastKind::PtrToPtr` cast.
488    ///
489    /// This allows bypassing normal validation to generate strange casts.
490    fn CastPtrToPtr<T, U>(operand: T) -> U
491);
492define!(
493    "mir_cast_unsize",
494    /// Emits a `CastKind::PointerCoercion(Unsize)` cast.
495    ///
496    /// This allows bypassing normal validation to generate strange casts.
497    fn CastUnsize<T, U>(operand: T) -> U
498);
499define!(
500    "mir_make_place",
501    #[doc(hidden)]
502    fn __internal_make_place<T>(place: T) -> *mut T
503);
504define!(
505    "mir_debuginfo",
506    #[doc(hidden)]
507    fn __debuginfo<T>(name: &'static str, s: T)
508);
509
510/// Macro for generating custom MIR.
511///
512/// See the module documentation for syntax details. This macro is not magic - it only transforms
513/// your MIR into something that is easier to parse in the compiler.
514#[rustc_macro_transparency = "transparent"]
515pub macro mir {
516    {
517        $(type RET = $ret_ty:ty ;)?
518        $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)*
519        $(debug $dbg_name:ident => $dbg_data:expr ;)*
520
521        {
522            $($entry:tt)*
523        }
524
525        $(
526            $block_name:ident $(($block_cleanup:ident))? = {
527                $($block:tt)*
528            }
529        )*
530    } => {{
531        // First, we declare all basic blocks.
532        __internal_declare_basic_blocks!($(
533            $block_name $(($block_cleanup))?
534        )*);
535        {
536            // Now all locals
537            #[allow(non_snake_case)]
538            let RET $(: $ret_ty)?;
539            $(
540                let $local_decl $(: $local_decl_ty)? ;
541            )*
542            ::core::intrinsics::mir::__internal_extract_let!($($entry)*);
543            $(
544                ::core::intrinsics::mir::__internal_extract_let!($($block)*);
545            )*
546
547            {
548                // Now debuginfo
549                $(
550                    __debuginfo(stringify!($dbg_name), $dbg_data);
551                )*
552
553                {
554                    // Finally, the contents of the basic blocks
555                    ::core::intrinsics::mir::__internal_remove_let!({
556                        {}
557                        { $($entry)* }
558                    });
559                    $(
560                        ::core::intrinsics::mir::__internal_remove_let!({
561                            {}
562                            { $($block)* }
563                        });
564                    )*
565
566                    RET
567                }
568            }
569        }
570    }}
571}
572
573/// Helper macro that allows you to treat a value expression like a place expression.
574///
575/// See the documentation on [`Variant`] for why this is necessary and how to use it.
576pub macro place($e:expr) {
577    (*::core::intrinsics::mir::__internal_make_place($e))
578}
579
580/// Helper macro that extracts the `let` declarations out of a bunch of statements.
581///
582/// This macro is written using the "statement muncher" strategy. Each invocation parses the first
583/// statement out of the input, does the appropriate thing with it, and then recursively calls the
584/// same macro on the remainder of the input.
585#[doc(hidden)]
586pub macro __internal_extract_let {
587    // If it's a `let` like statement, keep the `let`
588    (
589        let $var:ident $(: $ty:ty)? = $expr:expr; $($rest:tt)*
590    ) => {
591        let $var $(: $ty)?;
592        ::core::intrinsics::mir::__internal_extract_let!($($rest)*);
593    },
594    // Due to #86730, we have to handle const blocks separately
595    (
596        let $var:ident $(: $ty:ty)? = const $block:block; $($rest:tt)*
597    ) => {
598        let $var $(: $ty)?;
599        ::core::intrinsics::mir::__internal_extract_let!($($rest)*);
600    },
601    // Otherwise, output nothing
602    (
603        $stmt:stmt; $($rest:tt)*
604    ) => {
605        ::core::intrinsics::mir::__internal_extract_let!($($rest)*);
606    },
607    (
608        $expr:expr
609    ) => {}
610}
611
612/// Helper macro that removes the `let` declarations from a bunch of statements.
613///
614/// Because expression position macros cannot expand to statements + expressions, we need to be
615/// slightly creative here. The general strategy is also statement munching as above, but the output
616/// of the macro is "stored" in the subsequent macro invocation. Easiest understood via example:
617/// ```text
618/// invoke!(
619///     {
620///         {
621///             x = 5;
622///         }
623///         {
624///             let d = e;
625///             Call()
626///         }
627///     }
628/// )
629/// ```
630/// becomes
631/// ```text
632/// invoke!(
633///     {
634///         {
635///             x = 5;
636///             d = e;
637///         }
638///         {
639///             Call()
640///         }
641///     }
642/// )
643/// ```
644#[doc(hidden)]
645pub macro __internal_remove_let {
646    // If it's a `let` like statement, remove the `let`
647    (
648        {
649            {
650                $($already_parsed:tt)*
651            }
652            {
653                let $var:ident $(: $ty:ty)? = $expr:expr;
654                $($rest:tt)*
655            }
656        }
657    ) => { ::core::intrinsics::mir::__internal_remove_let!(
658        {
659            {
660                $($already_parsed)*
661                $var = $expr;
662            }
663            {
664                $($rest)*
665            }
666        }
667    )},
668    // Due to #86730 , we have to handle const blocks separately
669    (
670        {
671            {
672                $($already_parsed:tt)*
673            }
674            {
675                let $var:ident $(: $ty:ty)? = const $block:block;
676                $($rest:tt)*
677            }
678        }
679    ) => { ::core::intrinsics::mir::__internal_remove_let!(
680        {
681            {
682                $($already_parsed)*
683                $var = const $block;
684            }
685            {
686                $($rest)*
687            }
688        }
689    )},
690    // Otherwise, keep going
691    (
692        {
693            {
694                $($already_parsed:tt)*
695            }
696            {
697                $stmt:stmt;
698                $($rest:tt)*
699            }
700        }
701    ) => { ::core::intrinsics::mir::__internal_remove_let!(
702        {
703            {
704                $($already_parsed)*
705                $stmt;
706            }
707            {
708                $($rest)*
709            }
710        }
711    )},
712    (
713        {
714            {
715                $($already_parsed:tt)*
716            }
717            {
718                $expr:expr
719            }
720        }
721    ) => {
722        {
723            $($already_parsed)*
724            $expr
725        }
726    },
727}
728
729/// Helper macro that declares the basic blocks.
730#[doc(hidden)]
731pub macro __internal_declare_basic_blocks {
732    () => {},
733    ($name:ident (cleanup) $($rest:tt)*) => {
734        let $name = ::core::intrinsics::mir::BasicBlock::Cleanup;
735        __internal_declare_basic_blocks!($($rest)*)
736    },
737    ($name:ident $($rest:tt)*) => {
738        let $name = ::core::intrinsics::mir::BasicBlock::Normal;
739        __internal_declare_basic_blocks!($($rest)*)
740    },
741}