]> git.proxmox.com Git - rustc.git/blob - compiler/stable_mir/src/mir/body.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / compiler / stable_mir / src / mir / body.rs
1 use crate::ty::{AdtDef, ClosureDef, Const, GeneratorDef, GenericArgs, Movability, Region};
2 use crate::Opaque;
3 use crate::{ty::Ty, Span};
4
5 #[derive(Clone, Debug)]
6 pub struct Body {
7 pub blocks: Vec<BasicBlock>,
8 pub locals: Vec<Ty>,
9 }
10
11 #[derive(Clone, Debug)]
12 pub struct BasicBlock {
13 pub statements: Vec<Statement>,
14 pub terminator: Terminator,
15 }
16
17 #[derive(Clone, Debug)]
18 pub enum Terminator {
19 Goto {
20 target: usize,
21 },
22 SwitchInt {
23 discr: Operand,
24 targets: Vec<SwitchTarget>,
25 otherwise: usize,
26 },
27 Resume,
28 Abort,
29 Return,
30 Unreachable,
31 Drop {
32 place: Place,
33 target: usize,
34 unwind: UnwindAction,
35 },
36 Call {
37 func: Operand,
38 args: Vec<Operand>,
39 destination: Place,
40 target: Option<usize>,
41 unwind: UnwindAction,
42 },
43 Assert {
44 cond: Operand,
45 expected: bool,
46 msg: AssertMessage,
47 target: usize,
48 unwind: UnwindAction,
49 },
50 GeneratorDrop,
51 InlineAsm {
52 template: String,
53 operands: Vec<InlineAsmOperand>,
54 options: String,
55 line_spans: String,
56 destination: Option<usize>,
57 unwind: UnwindAction,
58 },
59 }
60
61 #[derive(Clone, Debug)]
62 pub struct InlineAsmOperand {
63 pub in_value: Option<Operand>,
64 pub out_place: Option<Place>,
65 // This field has a raw debug representation of MIR's InlineAsmOperand.
66 // For now we care about place/operand + the rest in a debug format.
67 pub raw_rpr: String,
68 }
69
70 #[derive(Clone, Debug)]
71 pub enum UnwindAction {
72 Continue,
73 Unreachable,
74 Terminate,
75 Cleanup(usize),
76 }
77
78 #[derive(Clone, Debug)]
79 pub enum AssertMessage {
80 BoundsCheck { len: Operand, index: Operand },
81 Overflow(BinOp, Operand, Operand),
82 OverflowNeg(Operand),
83 DivisionByZero(Operand),
84 RemainderByZero(Operand),
85 ResumedAfterReturn(GeneratorKind),
86 ResumedAfterPanic(GeneratorKind),
87 MisalignedPointerDereference { required: Operand, found: Operand },
88 }
89
90 #[derive(Clone, Debug)]
91 pub enum BinOp {
92 Add,
93 AddUnchecked,
94 Sub,
95 SubUnchecked,
96 Mul,
97 MulUnchecked,
98 Div,
99 Rem,
100 BitXor,
101 BitAnd,
102 BitOr,
103 Shl,
104 ShlUnchecked,
105 Shr,
106 ShrUnchecked,
107 Eq,
108 Lt,
109 Le,
110 Ne,
111 Ge,
112 Gt,
113 Offset,
114 }
115
116 #[derive(Clone, Debug)]
117 pub enum UnOp {
118 Not,
119 Neg,
120 }
121
122 #[derive(Clone, Debug)]
123 pub enum GeneratorKind {
124 Async(AsyncGeneratorKind),
125 Gen,
126 }
127
128 #[derive(Clone, Debug)]
129 pub enum AsyncGeneratorKind {
130 Block,
131 Closure,
132 Fn,
133 }
134
135 pub(crate) type LocalDefId = Opaque;
136 /// The rustc coverage data structures are heavily tied to internal details of the
137 /// coverage implementation that are likely to change, and are unlikely to be
138 /// useful to third-party tools for the foreseeable future.
139 pub(crate) type Coverage = Opaque;
140
141 /// The FakeReadCause describes the type of pattern why a FakeRead statement exists.
142 #[derive(Clone, Debug)]
143 pub enum FakeReadCause {
144 ForMatchGuard,
145 ForMatchedPlace(LocalDefId),
146 ForGuardBinding,
147 ForLet(LocalDefId),
148 ForIndex,
149 }
150
151 /// Describes what kind of retag is to be performed
152 #[derive(Clone, Debug)]
153 pub enum RetagKind {
154 FnEntry,
155 TwoPhase,
156 Raw,
157 Default,
158 }
159
160 #[derive(Clone, Debug)]
161 pub enum Variance {
162 Covariant,
163 Invariant,
164 Contravariant,
165 Bivariant,
166 }
167
168 #[derive(Clone, Debug)]
169 pub struct CopyNonOverlapping {
170 pub src: Operand,
171 pub dst: Operand,
172 pub count: Operand,
173 }
174
175 #[derive(Clone, Debug)]
176 pub enum NonDivergingIntrinsic {
177 Assume(Operand),
178 CopyNonOverlapping(CopyNonOverlapping),
179 }
180
181 #[derive(Clone, Debug)]
182 pub enum Statement {
183 Assign(Place, Rvalue),
184 FakeRead(FakeReadCause, Place),
185 SetDiscriminant { place: Place, variant_index: VariantIdx },
186 Deinit(Place),
187 StorageLive(Local),
188 StorageDead(Local),
189 Retag(RetagKind, Place),
190 PlaceMention(Place),
191 AscribeUserType { place: Place, projections: UserTypeProjection, variance: Variance },
192 Coverage(Coverage),
193 Intrinsic(NonDivergingIntrinsic),
194 ConstEvalCounter,
195 Nop,
196 }
197
198 #[derive(Clone, Debug)]
199 pub enum Rvalue {
200 /// Creates a pointer with the indicated mutability to the place.
201 ///
202 /// This is generated by pointer casts like `&v as *const _` or raw address of expressions like
203 /// `&raw v` or `addr_of!(v)`.
204 AddressOf(Mutability, Place),
205
206 /// Creates an aggregate value, like a tuple or struct.
207 ///
208 /// This is needed because dataflow analysis needs to distinguish
209 /// `dest = Foo { x: ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case that `Foo`
210 /// has a destructor.
211 ///
212 /// Disallowed after deaggregation for all aggregate kinds except `Array` and `Generator`. After
213 /// generator lowering, `Generator` aggregate kinds are disallowed too.
214 Aggregate(AggregateKind, Vec<Operand>),
215
216 /// * `Offset` has the same semantics as `<*const T>::offset`, except that the second
217 /// parameter may be a `usize` as well.
218 /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats,
219 /// raw pointers, or function pointers and return a `bool`. The types of the operands must be
220 /// matching, up to the usual caveat of the lifetimes in function pointers.
221 /// * Left and right shift operations accept signed or unsigned integers not necessarily of the
222 /// same type and return a value of the same type as their LHS. Like in Rust, the RHS is
223 /// truncated as needed.
224 /// * The `Bit*` operations accept signed integers, unsigned integers, or bools with matching
225 /// types and return a value of that type.
226 /// * The remaining operations accept signed integers, unsigned integers, or floats with
227 /// matching types and return a value of that type.
228 BinaryOp(BinOp, Operand, Operand),
229
230 /// Performs essentially all of the casts that can be performed via `as`.
231 ///
232 /// This allows for casts from/to a variety of types.
233 Cast(CastKind, Operand, Ty),
234
235 /// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition.
236 ///
237 /// For addition, subtraction, and multiplication on integers the error condition is set when
238 /// the infinite precision result would not be equal to the actual result.
239 CheckedBinaryOp(BinOp, Operand, Operand),
240
241 /// A CopyForDeref is equivalent to a read from a place.
242 /// When such a read happens, it is guaranteed that the only use of the returned value is a
243 /// deref operation, immediately followed by one or more projections.
244 CopyForDeref(Place),
245
246 /// Computes the discriminant of the place, returning it as an integer.
247 /// Returns zero for types without discriminant.
248 ///
249 /// The validity requirements for the underlying value are undecided for this rvalue, see
250 /// [#91095]. Note too that the value of the discriminant is not the same thing as the
251 /// variant index;
252 ///
253 /// [#91095]: https://github.com/rust-lang/rust/issues/91095
254 Discriminant(Place),
255
256 /// Yields the length of the place, as a `usize`.
257 ///
258 /// If the type of the place is an array, this is the array length. For slices (`[T]`, not
259 /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is
260 /// ill-formed for places of other types.
261 Len(Place),
262
263 /// Creates a reference to the place.
264 Ref(Region, BorrowKind, Place),
265
266 /// Creates an array where each element is the value of the operand.
267 ///
268 /// This is the cause of a bug in the case where the repetition count is zero because the value
269 /// is not dropped, see [#74836].
270 ///
271 /// Corresponds to source code like `[x; 32]`.
272 ///
273 /// [#74836]: https://github.com/rust-lang/rust/issues/74836
274 Repeat(Operand, Const),
275
276 /// Transmutes a `*mut u8` into shallow-initialized `Box<T>`.
277 ///
278 /// This is different from a normal transmute because dataflow analysis will treat the box as
279 /// initialized but its content as uninitialized. Like other pointer casts, this in general
280 /// affects alias analysis.
281 ShallowInitBox(Operand, Ty),
282
283 /// Creates a pointer/reference to the given thread local.
284 ///
285 /// The yielded type is a `*mut T` if the static is mutable, otherwise if the static is extern a
286 /// `*const T`, and if neither of those apply a `&T`.
287 ///
288 /// **Note:** This is a runtime operation that actually executes code and is in this sense more
289 /// like a function call. Also, eliminating dead stores of this rvalue causes `fn main() {}` to
290 /// SIGILL for some reason that I (JakobDegen) never got a chance to look into.
291 ///
292 /// **Needs clarification**: Are there weird additional semantics here related to the runtime
293 /// nature of this operation?
294 ThreadLocalRef(crate::CrateItem),
295
296 /// Computes a value as described by the operation.
297 NullaryOp(NullOp, Ty),
298
299 /// Exactly like `BinaryOp`, but less operands.
300 ///
301 /// Also does two's-complement arithmetic. Negation requires a signed integer or a float;
302 /// bitwise not requires a signed integer, unsigned integer, or bool. Both operation kinds
303 /// return a value with the same type as their operand.
304 UnaryOp(UnOp, Operand),
305
306 /// Yields the operand unchanged
307 Use(Operand),
308 }
309
310 #[derive(Clone, Debug)]
311 pub enum AggregateKind {
312 Array(Ty),
313 Tuple,
314 Adt(AdtDef, VariantIdx, GenericArgs, Option<UserTypeAnnotationIndex>, Option<FieldIdx>),
315 Closure(ClosureDef, GenericArgs),
316 Generator(GeneratorDef, GenericArgs, Movability),
317 }
318
319 #[derive(Clone, Debug)]
320 pub enum Operand {
321 Copy(Place),
322 Move(Place),
323 Constant(Constant),
324 }
325
326 #[derive(Clone, Debug)]
327 pub struct Place {
328 pub local: Local,
329 pub projection: String,
330 }
331
332 #[derive(Clone, Debug)]
333 pub struct UserTypeProjection {
334 pub base: UserTypeAnnotationIndex,
335 pub projection: String,
336 }
337
338 pub type Local = usize;
339
340 type FieldIdx = usize;
341
342 /// The source-order index of a variant in a type.
343 pub type VariantIdx = usize;
344
345 type UserTypeAnnotationIndex = usize;
346
347 #[derive(Clone, Debug)]
348 pub struct Constant {
349 pub span: Span,
350 pub user_ty: Option<UserTypeAnnotationIndex>,
351 pub literal: Const,
352 }
353
354 #[derive(Clone, Debug)]
355 pub struct SwitchTarget {
356 pub value: u128,
357 pub target: usize,
358 }
359
360 #[derive(Clone, Debug)]
361 pub enum BorrowKind {
362 /// Data must be immutable and is aliasable.
363 Shared,
364
365 /// The immediately borrowed place must be immutable, but projections from
366 /// it don't need to be. This is used to prevent match guards from replacing
367 /// the scrutinee. For example, a fake borrow of `a.b` doesn't
368 /// conflict with a mutable borrow of `a.b.c`.
369 Fake,
370
371 /// Data is mutable and not aliasable.
372 Mut {
373 /// `true` if this borrow arose from method-call auto-ref
374 kind: MutBorrowKind,
375 },
376 }
377
378 #[derive(Clone, Debug)]
379 pub enum MutBorrowKind {
380 Default,
381 TwoPhaseBorrow,
382 ClosureCapture,
383 }
384
385 #[derive(Clone, Debug)]
386 pub enum Mutability {
387 Not,
388 Mut,
389 }
390
391 #[derive(Copy, Clone, Debug)]
392 pub enum Safety {
393 Unsafe,
394 Normal,
395 }
396
397 #[derive(Clone, Debug)]
398 pub enum PointerCoercion {
399 /// Go from a fn-item type to a fn-pointer type.
400 ReifyFnPointer,
401
402 /// Go from a safe fn pointer to an unsafe fn pointer.
403 UnsafeFnPointer,
404
405 /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
406 /// It cannot convert a closure that requires unsafe.
407 ClosureFnPointer(Safety),
408
409 /// Go from a mut raw pointer to a const raw pointer.
410 MutToConstPointer,
411
412 /// Go from `*const [T; N]` to `*const T`
413 ArrayToPointer,
414
415 /// Unsize a pointer/reference value, e.g., `&[T; n]` to
416 /// `&[T]`. Note that the source could be a thin or fat pointer.
417 /// This will do things like convert thin pointers to fat
418 /// pointers, or convert structs containing thin pointers to
419 /// structs containing fat pointers, or convert between fat
420 /// pointers.
421 Unsize,
422 }
423
424 #[derive(Clone, Debug)]
425 pub enum CastKind {
426 PointerExposeAddress,
427 PointerFromExposedAddress,
428 PointerCoercion(PointerCoercion),
429 DynStar,
430 IntToInt,
431 FloatToInt,
432 FloatToFloat,
433 IntToFloat,
434 PtrToPtr,
435 FnPtrToPtr,
436 Transmute,
437 }
438
439 #[derive(Clone, Debug)]
440 pub enum NullOp {
441 /// Returns the size of a value of that type.
442 SizeOf,
443 /// Returns the minimum alignment of a type.
444 AlignOf,
445 /// Returns the offset of a field.
446 OffsetOf(Vec<FieldIdx>),
447 }