kvarn::prelude::utils::prelude::compact_str::core::intrinsics

Module mir

source
🔬This is a nightly-only experimental API. (custom_mir)
Expand description

Rustc internal tooling for hand-writing MIR.

If for some reasons you are not writing rustc tests and have found yourself considering using this feature, turn back. This is exceptionally unstable. There is no attempt at all to make anything work besides those things which the rustc test suite happened to need. If you make a typo you’ll probably ICE. Really, this is not the solution to your problems. Consider instead supporting the stable MIR project group.

The documentation for this module describes how to use this feature. If you are interested in hacking on the implementation, most of that documentation lives at rustc_mir_build/src/build/custom/mod.rs.

Typical usage will look like this:

#![feature(core_intrinsics, custom_mir)]
#![allow(internal_features)]

use core::intrinsics::mir::*;

#[custom_mir(dialect = "built")]
pub fn simple(x: i32) -> i32 {
    mir! {
        let temp2: i32;

        {
            let temp1 = x;
            Goto(my_second_block)
        }

        my_second_block = {
            temp2 = Move(temp1);
            RET = temp2;
            Return()
        }
    }
}

The custom_mir attribute tells the compiler to treat the function as being custom MIR. This attribute only works on functions - there is no way to insert custom MIR into the middle of another function. The dialect and phase parameters indicate which version of MIR you are inserting here. Generally you’ll want to use #![custom_mir(dialect = "built")] if you want your MIR to be modified by the full MIR pipeline, or #![custom_mir(dialect = "runtime", phase = "optimized")] if you don’t.

The input to the mir! macro is:

  • An optional return type annotation in the form of type RET = ...;. This may be required if the compiler cannot infer the type of RET.
  • A possibly empty list of local declarations. Locals can also be declared inline on assignments via let. Type inference generally works. Shadowing does not.
  • A list of basic blocks. The first of these is the start block and is where execution begins. All blocks other than the start block need to be given a name, so that they can be referred to later.
    • Each block is a list of semicolon terminated statements, followed by a terminator. The syntax for the various statements and terminators is designed to be as similar as possible to the syntax for analogous concepts in native Rust. See below for a list.

§Examples

#![feature(core_intrinsics, custom_mir)]
#![allow(internal_features)]
#![allow(unused_assignments)]

use core::intrinsics::mir::*;

#[custom_mir(dialec