Skip to content

Commit 80b656f

Browse files
oli-obkmark-i-m
authored andcommitted
Document MIR building somewhat
1 parent bed7044 commit 80b656f

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed

src/mir/construction.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,111 @@
11
# MIR construction
2+
3+
The lowering of [HIR] to [MIR] occurs for the following (probably incomplete)
4+
list of items:
5+
6+
* Function and Closure bodies
7+
* Initializers of `static` and `const` items
8+
* Initializers of enum discriminants
9+
* Glue and Shims of any kind
10+
* Tuple struct initializer functions
11+
* Drop code (the `Drop::drop` function is not called directly)
12+
* Drop implementations of types without an explicit `Drop` implementation
13+
14+
The lowering is triggered by calling the `mir_built` query. The entire lowering
15+
code lives in `src/librustc_mir/build`. There is an intermediate representation
16+
between [HIR] and [MIR] called the `HAIR` that is only used during the lowering.
17+
The `HAIR` has datatypes that mirror the [HIR] datatypes, but instead of e.g. `-x`
18+
being a `hair::ExprKind::Neg(hair::Expr)` it is a `hair::ExprKind::Neg(hir::Expr)`.
19+
20+
This shallowness enables the `HAIR` to represent all datatypes that [HIR] has, but
21+
without having to create an in-memory copy of the entire [HIR]. The `HAIR` also
22+
does a few simplifications, e.g. method calls and function calls have been merged
23+
into a single variant.
24+
25+
The lowering creates local variables for every argument as specified in the signature.
26+
Next it creates local variables for every binding specified (e.g. `(a, b): (i32, String)`)
27+
produces 3 bindings, one for the argument, and two for the bindings. Next it generates
28+
field accesses that read the fields from the argument and writes the value to the binding
29+
variable.
30+
31+
With this initialization out of the way, the lowering triggers a recursive call
32+
to a function that generates the MIR for the body (a `Block` expression) and
33+
writes the result into the `RETURN_PLACE`.
34+
35+
## `unpack!` all the things
36+
37+
One important thing of note is the `unpack!` macro, which accompanies all recursive
38+
calls. The macro ensures, that you get the result of the recursive call while updating
39+
the basic block that you are now in. As an example: lowering `a + b` will need to do
40+
three somewhat independent things:
41+
42+
* give you an `Rvalue` referring to the result of the operation
43+
* insert an assertion ensuring that the operation does not overflow
44+
* tell you in which basic block you should write further operations into, because
45+
the basic block has changed due to the inserted assertion (assertions terminate
46+
blocks and jump either to a panic block or a newly created block, the latter being
47+
the one you get back).
48+
49+
The `unpack!` macro will call the recursive function you pass it, return the `Rvalue`
50+
and update the basic block by mutating the basic block variable you pass to it.
51+
52+
## Lowering expressions into the desired MIR
53+
54+
There are essentially four kinds of representations one might want of a value:
55+
56+
* `Place` refers to a (or a part of) preexisting memory ___location (local, static, promoted)
57+
* `Rvalue` is something that can be assigned to a `Place`
58+
* `Operand` is an argument to e.g. a `+` operation or a function call
59+
* a temporary variable containing a copy of the value
60+
61+
Since we start out with lowering the function body to an `Rvalue` so we can create an
62+
assignment to `RETURN_PLACE`, that `Rvalue` lowering will in turn trigger lowering to
63+
`Operand` for its arguments (if any). `Operand` lowering either produces a `const`
64+
operand, or moves/copies out of a `Place`, thus triggering a `Place` lowering. An
65+
expression being lowered to a `Place` can in turn trigger a temporary to be created
66+
if the expression being lowered contains operations. This is where the snake bites its
67+
own tail and we need to trigger an `Rvalue` lowering for the expression to be written
68+
into the local.
69+
70+
## Operator lowering
71+
72+
Operators on builtin types are not lowered to function calls (which would end up being
73+
infinite recursion calls, because the trait impls just contain the operation itself
74+
again). Instead there are `Rvalue`s for binary and unary operators and index operations.
75+
These `Rvalue`s later get codegened to llvm primitive operations or llvm intrinsics.
76+
77+
Operators on all other types get lowered to a function call to their `impl` of the
78+
Operator's corresponding trait.
79+
80+
Irrelevant of the lowering kind, the arguments to the operator are lowered to `Operand`s.
81+
This means all arguments are either constants, or refer to an already existing value
82+
somewhere in a local or static.
83+
84+
## Method call lowering
85+
86+
Method calls are lowered to the same `TerminatorKind` that function calls are.
87+
In [MIR] there is no difference between method calls and function calls anymore.
88+
89+
## Conditions
90+
91+
`if` conditions and `match` statements for `enum`s without variants with fields are
92+
lowered to `TerminatorKind::SwitchInt`. Each possible value (so `0` and `1` for `if`
93+
conditions) has a corresponding `BasicBlock` to which the code continues.
94+
The argument being branched on is again an `Operand`.
95+
96+
### Pattern matching
97+
98+
`match` statements for `enum`s with variants that have fields are lowered to
99+
`TerminatorKind::SwitchInt`, too, but the `Operand` refers to a `Place` where the
100+
discriminant of the value can be found. This often involves reading the discriminant
101+
to a new temporary variable.
102+
103+
## Aggregate construction
104+
105+
Aggregate values of any kind are built via `Rvalue::Aggregate`. All fields are
106+
lowered to `Operator`s. This is essentially equivalent to one assignment
107+
statement per aggregate field plus an assignment to the discriminant in the
108+
case of `enum`s.
109+
110+
[MIR]: ./index.html
111+
[HIR]: ../hir.html

0 commit comments

Comments
 (0)