1 //! Rustc internal tooling for hand-writing MIR.
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).
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_building/src/build/custom/mod.rs`.
13 //! Typical usage will look like this:
16 //! #![feature(core_intrinsics, custom_mir)]
18 //! extern crate core;
19 //! use core::intrinsics::mir::*;
21 //! #[custom_mir(dialect = "built")]
22 //! pub fn simple(x: i32) -> i32 {
33 //! temp2 = Move(temp1);
41 //! Hopefully most of this is fairly self-explanatory. Expanding on some notable details:
43 //! - The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This
44 //! attribute only works on functions - there is no way to insert custom MIR into the middle of
46 //! - The `dialect` and `phase` parameters indicate which version of MIR you are inserting here.
47 //! This will normally be the phase that corresponds to the thing you are trying to test. The
48 //! phase can be omitted for dialects that have just one.
49 //! - You should define your function signature like you normally would. Externally, this function
50 //! can be called like any other function.
51 //! - Type inference works - you don't have to spell out the type of all of your locals.
53 //! For now, all statements and terminators are parsed from nested invocations of the special
54 //! functions provided in this module. We additionally want to (but do not yet) support more
55 //! "normal" Rust syntax in places where it makes sense. Also, most kinds of instructions are not
60 feature = "custom_mir",
61 reason = "MIR is an implementation detail and extremely unstable",
64 #![allow(unused_variables, non_snake_case, missing_debug_implementations)]
66 /// Type representing basic blocks.
68 /// All terminators will have this type as a return type. It helps achieve some type safety.
69 pub struct BasicBlock;
72 ($name:literal, $($sig:tt)*) => {
73 #[rustc_diagnostic_item = $name]
74 pub $($sig)* { panic!() }
78 define!("mir_return", fn Return() -> BasicBlock);
79 define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
80 define!("mir_retag", fn Retag<T>(place: T));
81 define!("mir_retag_raw", fn RetagRaw<T>(place: T));
82 define!("mir_move", fn Move<T>(place: T) -> T);
83 define!("mir_static", fn Static<T>(s: T) -> &'static T);
84 define!("mir_static_mut", fn StaticMut<T>(s: T) -> *mut T);
86 /// Convenience macro for generating custom MIR.
88 /// See the module documentation for syntax details. This macro is not magic - it only transforms
89 /// your MIR into something that is easier to parse in the compiler.
90 #[rustc_macro_transparency = "transparent"]
93 $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)*
100 $block_name:ident = {
105 // First, we declare all basic blocks.
107 let $block_name: ::core::intrinsics::mir::BasicBlock;
112 #[allow(non_snake_case)]
115 let $local_decl $(: $local_decl_ty)? ;
118 ::core::intrinsics::mir::__internal_extract_let!($($entry)*);
120 ::core::intrinsics::mir::__internal_extract_let!($($block)*);
124 // Finally, the contents of the basic blocks
125 ::core::intrinsics::mir::__internal_remove_let!({
130 ::core::intrinsics::mir::__internal_remove_let!({
142 /// Helper macro that extracts the `let` declarations out of a bunch of statements.
144 /// This macro is written using the "statement muncher" strategy. Each invocation parses the first
145 /// statement out of the input, does the appropriate thing with it, and then recursively calls the
146 /// same macro on the remainder of the input.
148 pub macro __internal_extract_let {
149 // If it's a `let` like statement, keep the `let`
151 let $var:ident $(: $ty:ty)? = $expr:expr; $($rest:tt)*
154 ::core::intrinsics::mir::__internal_extract_let!($($rest)*);
156 // Due to #86730, we have to handle const blocks separately
158 let $var:ident $(: $ty:ty)? = const $block:block; $($rest:tt)*
161 ::core::intrinsics::mir::__internal_extract_let!($($rest)*);
163 // Otherwise, output nothing
165 $stmt:stmt; $($rest:tt)*
167 ::core::intrinsics::mir::__internal_extract_let!($($rest)*);
174 /// Helper macro that removes the `let` declarations from a bunch of statements.
176 /// Because expression position macros cannot expand to statements + expressions, we need to be
177 /// slightly creative here. The general strategy is also statement munching as above, but the output
178 /// of the macro is "stored" in the subsequent macro invocation. Easiest understood via example:
207 pub macro __internal_remove_let {
208 // If it's a `let` like statement, remove the `let`
212 $($already_parsed:tt)*
215 let $var:ident $(: $ty:ty)? = $expr:expr;
219 ) => { ::core::intrinsics::mir::__internal_remove_let!(
230 // Due to #86730 , we have to handle const blocks separately
234 $($already_parsed:tt)*
237 let $var:ident $(: $ty:ty)? = const $block:block;
241 ) => { ::core::intrinsics::mir::__internal_remove_let!(
252 // Otherwise, keep going
256 $($already_parsed:tt)*
263 ) => { ::core::intrinsics::mir::__internal_remove_let!(
277 $($already_parsed:tt)*