Skip to main content

cinrs_core/
ir.rs

1//! The typed intermediate representation.
2//!
3//! [`sema`](crate::sema) turns the untyped [`ast`](crate::ast) into this tree
4//! and [`codegen`](crate::codegen) turns this tree into Rust tokens. The two
5//! halves are deliberately separated by a data structure rather than by a
6//! traversal, for three reasons:
7//!
8//! * **Types never leak into the AST.** The AST records what the user wrote;
9//!   the IR records what it *means*. Every implicit conversion C performs —
10//!   integer promotions, the usual arithmetic conversions, array-to-pointer
11//!   decay, the conversion on assignment, initialisation, argument passing and
12//!   `return` — is an explicit node here, so codegen never has to re-derive a
13//!   type or guess where an `as` belongs.
14//!
15//! * **Sema is pure.** Nothing in this module refers to `proc_macro2`; every
16//!   node carries a [`SourceRange`] into the captured C text, which codegen
17//!   resolves to a span. That is what lets sema run on a thread with a large
18//!   stack while codegen — which needs the (non-`Send`) source map — runs on
19//!   the caller's.
20//!
21//! * **Control flow is already resolved.** `break` and `continue` name the
22//!   loop or switch they leave ([`BreakTarget`], [`LoopId`]), a `goto` names
23//!   the label it jumps to ([`LabelId`]), and a `switch` arrives as an ordered
24//!   list of groups rather than as a statement tree with labels buried in it.
25//!   Codegen can therefore be a straight transliteration.
26//!
27//!   A function that jumps is the exception: `goto`, and a `case` label the
28//!   groups cannot express, send the whole body through [`crate::cfg`] instead,
29//!   and its [`Body`] is a graph of basic blocks rather than a statement list.
30//!
31//! # Interned types
32//!
33//! [`Ty`] stays a small `Copy` value even though C's types are trees: the
34//! scalar types are variants of their own, and every derived type (pointer,
35//! array, function) is an index into the [`Types`] arena that hash-conses them.
36//! Two `int *` written in different places therefore compare equal with a
37//! single integer comparison, which is what the assignment rules and the switch
38//! over "what kind of thing is this" in codegen are written against.
39//!
40//! `struct`, `union` and `enum` are *nominal*, exactly as C says: each tag
41//! definition allocates a [`RecordId`] or [`EnumId`] of its own, and two
42//! structurally identical tags are different types. The tables also hold the
43//! computed [`Layout`], so `sizeof` folds to a constant everywhere.
44//!
45//! # Places
46//!
47//! Anything assignable is a [`Place`]: a named object, `*p`, `a[i]`, `s.f`, a
48//! string literal, or the temporary that holds a `struct` returned by value.
49//! The abstraction is what compound assignment and `++`/`--` are written
50//! against, so the "evaluate the operand exactly once" rule is expressed
51//! structurally: `p[i()] += 1` is one [`ExprKind::CompoundAssign`] holding one
52//! place, not a re-evaluated expression. Codegen lowers a place into a *setup*
53//! (statements that must run first, where the pointer arithmetic lands) plus an
54//! *access* that can be evaluated as often as needed.
55
56use std::collections::HashMap;
57
58use crate::capture::SourceRange;
59use crate::target::TargetModel;
60
61// ---------------------------------------------------------------------------
62// types
63// ---------------------------------------------------------------------------
64
65/// The spelling of the `va_list` type the compiler owns, which means
66/// [`Ty::VaList`].
67///
68/// It is the only one: the bundled `<stdarg.h>` writes
69/// `typedef __builtin_va_list va_list;`, the way GCC's own header does, so a
70/// translation unit that does not include it may use `va_list`, `va_end` and
71/// the rest as ordinary identifiers of its own. The name is seeded into the
72/// parser's and sema's outermost scopes, where a program may repeat the
73/// `typedef` but not give the name a different meaning.
74pub const VA_LIST_NAMES: &[&str] = &["__builtin_va_list"];
75
76/// The `typedef` names the compiler owns for the two 128-bit integer types,
77/// with the [`Ty`] each one means.
78///
79/// GCC predefines `__int128_t` and `__uint128_t` in every mode alongside the
80/// `__int128` keyword, and a great deal of code spells them that way. Like
81/// [`VA_LIST_NAMES`] they are seeded into the parser's and sema's outermost
82/// scopes, so `__int128_t *p;` is a declaration rather than a multiplication.
83pub const INT128_TYPEDEF_NAMES: &[(&str, Ty)] =
84    &[("__int128_t", Ty::Int128), ("__uint128_t", Ty::UInt128)];
85
86/// The `typedef` names the compiler owns for the x86 vector types, with the
87/// [`Ty`] each one means.
88///
89/// `__m128` and its five relatives are the compiler's types, not the library's:
90/// GCC writes them in `<xmmintrin.h>` as `__attribute__((vector_size(16)))`,
91/// which cinrs has no equivalent of, so the bundled header writes
92/// `typedef __cinrs_m128 __m128;` over a name seeded into the parser's and
93/// sema's outermost scopes — exactly the arrangement [`VA_LIST_NAMES`] uses
94/// for `va_list`. A translation unit that does not include the header may
95/// therefore still use `__m128` as an identifier of its own.
96pub const X86_VECTOR_TYPEDEF_NAMES: &[(&str, Ty)] = &[
97    ("__cinrs_m128", Ty::Vector(VecTy::M128)),
98    ("__cinrs_m128d", Ty::Vector(VecTy::M128d)),
99    ("__cinrs_m128i", Ty::Vector(VecTy::M128i)),
100    ("__cinrs_m256", Ty::Vector(VecTy::M256)),
101    ("__cinrs_m256d", Ty::Vector(VecTy::M256d)),
102    ("__cinrs_m256i", Ty::Vector(VecTy::M256i)),
103    ("__cinrs_m512", Ty::Vector(VecTy::M512)),
104    ("__cinrs_m512d", Ty::Vector(VecTy::M512d)),
105    ("__cinrs_m512i", Ty::Vector(VecTy::M512i)),
106    ("__cinrs_m128bh", Ty::Vector(VecTy::M128bh)),
107    ("__cinrs_m256bh", Ty::Vector(VecTy::M256bh)),
108    ("__cinrs_m512bh", Ty::Vector(VecTy::M512bh)),
109    ("__cinrs_m128h", Ty::Vector(VecTy::M128h)),
110    ("__cinrs_m256h", Ty::Vector(VecTy::M256h)),
111    ("__cinrs_m512h", Ty::Vector(VecTy::M512h)),
112];
113
114/// The builtin C23's `unreachable()` stands for.
115///
116/// The bundled `<stddef.h>` writes `#define unreachable() __builtin_unreachable()`,
117/// the way GCC's does, so a unit that does not include it may use the name
118/// `unreachable` for whatever it likes.
119pub const UNREACHABLE_BUILTIN: &str = "__builtin_unreachable";
120
121/// The names Rust cannot spell even as raw identifiers.
122///
123/// A C identifier that is one of them is generated with an underscore
124/// appended, which both code generation and the naming of the bit-field
125/// accessors have to agree on.
126pub const NEVER_RAW: &[&str] = &["self", "Self", "super", "crate", "_"];
127
128/// The Rust identifier a C name is generated as, spelled out.
129///
130/// Only the names [`NEVER_RAW`] lists change; a name that collides with an
131/// ordinary keyword becomes a raw identifier, which is the same identifier.
132///
133/// This is the rule as it stands before the translation unit is taken into
134/// account — enough to tell two accessor names of one record apart, which is
135/// all [`crate::sema`] needs it for. The spelling the generated code actually
136/// carries is [`crate::codegen`]'s, which also keeps a changed spelling clear
137/// of every other name the unit uses.
138pub fn rust_name_of(name: &str) -> String {
139    if NEVER_RAW.contains(&name) {
140        return format!("{name}_");
141    }
142    name.to_owned()
143}
144
145/// A pointer type in the [`Types`] arena.
146#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
147pub struct PointerId(pub u32);
148
149/// An array type in the [`Types`] arena.
150#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
151pub struct ArrayId(pub u32);
152
153/// A function type in the [`Types`] arena.
154#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
155pub struct FuncTyId(pub u32);
156
157/// A `struct` or `union` definition in the [`Types`] arena.
158#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
159pub struct RecordId(pub u32);
160
161/// An `enum` definition in the [`Types`] arena.
162#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
163pub struct EnumId(pub u32);
164
165/// An `_Atomic` type in the [`Types`] arena.
166#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
167pub struct AtomicId(pub u32);
168
169/// A resolved C type.
170///
171/// `long double` is mapped onto [`Ty::Double`] when the type is resolved,
172/// because there is no portable Rust type with the layout of an x87 extended
173/// double; the mapping is documented rather than diagnosed, since a procedural
174/// macro has no stable way to raise a warning.
175#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
176pub enum Ty {
177    /// `void`
178    Void,
179    /// `_Bool`
180    Bool,
181    /// Plain `char`, whose signedness is the target's business and which is a
182    /// distinct type from both `signed char` and `unsigned char`.
183    Char,
184    /// `signed char`
185    SChar,
186    /// `unsigned char`
187    UChar,
188    /// `short`
189    Short,
190    /// `unsigned short`
191    UShort,
192    /// `int`
193    Int,
194    /// `unsigned int`
195    UInt,
196    /// `long`
197    Long,
198    /// `unsigned long`
199    ULong,
200    /// `long long`
201    LongLong,
202    /// `unsigned long long`
203    ULongLong,
204    /// GNU's `__int128` (also spelled `__int128_t`), which ranks above
205    /// `long long` and is generated as Rust's `i128`.
206    Int128,
207    /// `unsigned __int128` (also spelled `__uint128_t`), generated as `u128`.
208    UInt128,
209    /// `float`
210    Float,
211    /// `double` (and `long double`)
212    Double,
213    /// `float _Complex`, generated as `cinrs_rt::Complex<f32>`.
214    ///
215    /// C calls the complex types *floating* types and therefore arithmetic
216    /// ones, but almost nothing in this crate wants them where a `float` or a
217    /// `double` goes: [`Ty::is_floating`] is deliberately the *real* floating
218    /// types only, and [`Ty::is_complex`] is the question to ask about these.
219    ComplexFloat,
220    /// `double _Complex` (and `long double _Complex`), generated as
221    /// `cinrs_rt::Complex<f64>`.
222    ComplexDouble,
223    /// A pointer, including a pointer to a function.
224    Pointer(PointerId),
225    /// An array of a known length.
226    Array(ArrayId),
227    /// A function type. Only ever reached through a pointer or as the type of
228    /// a function designator.
229    Func(FuncTyId),
230    /// A `struct` or `union`, complete or not.
231    Record(RecordId),
232    /// A file-scope `enum` with a tag, which becomes a named `c_int` alias.
233    /// Every other `enum` is simply [`Ty::Int`].
234    Enum(EnumId),
235    /// `va_list` (and its `__builtin_va_list` / `__gnuc_va_list` spellings),
236    /// which becomes [`core::ffi::VaList`].
237    ///
238    /// The type is opaque: it has no size, nothing may point at it, and it may
239    /// only be a local variable or a parameter — see [`crate::sema`] for why.
240    VaList,
241    /// One of x86's vector types: `__m128`, `__m128i`, `__m128d`, `__m256`,
242    /// `__m256i` or `__m256d`.
243    ///
244    /// Opaque, exactly as C sees it: there is no arithmetic on one, no
245    /// conversion to or from one, and no way to reach a lane except through an
246    /// intrinsic or through a union. What it *is* is an object of a known size
247    /// and alignment — sixteen or thirty-two bytes, aligned to itself — which
248    /// is what makes it a member, an element, a parameter, a return value and
249    /// the thing a `union { __m128i v; int i[4]; }` punnes. Code generation
250    /// writes `::core::arch::x86_64::__m128i`, whose layout is the same.
251    Vector(VecTy),
252    /// `_Atomic T`, for a scalar `T` (C11 6.7.2.4).
253    ///
254    /// It is the type of an *object*, never of a value: reading an atomic
255    /// lvalue is an atomic load whose result has the underlying type, so
256    /// [`ExprKind::Load`] of an atomic place is typed [`Types::unatomic`] of
257    /// it and nothing downstream of the load ever meets this variant. Where it
258    /// does appear is a declared object, a member, a pointee and `sizeof` —
259    /// which is why it is a type rather than a flag on the declaration:
260    /// `_Atomic int *` and `int *` are different types, and a store through
261    /// the first one is atomic.
262    ///
263    /// The alignment is the size (see [`Types::size_align`]), which is what
264    /// makes `_Atomic long long` eight-byte aligned on a target whose plain
265    /// `long long` is not.
266    Atomic(AtomicId),
267    /// The type of something whose declaration was already reported as wrong.
268    ///
269    /// It exists so that one bad declaration produces one diagnostic: an object
270    /// declared `int a[n]` still enters the symbol table, and every later use of
271    /// it is checked against a type that silences further complaints instead of
272    /// "use of undeclared identifier".
273    Error,
274}
275
276/// Which x86 vector type a [`Ty::Vector`] is.
277///
278/// The name is the same in C and in `core::arch`, which is the whole point:
279/// the generated Rust says `::core::arch::x86_64::__m128i` and Rust's type has
280/// the size, the alignment and the calling convention C's has.
281#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
282pub enum VecTy {
283    /// `__m128`: four `float` lanes.
284    M128,
285    /// `__m128i`: sixteen bytes of integer lanes, whatever width.
286    M128i,
287    /// `__m128d`: two `double` lanes.
288    M128d,
289    /// `__m256`: eight `float` lanes.
290    M256,
291    /// `__m256i`: thirty-two bytes of integer lanes.
292    M256i,
293    /// `__m256d`: four `double` lanes.
294    M256d,
295    /// `__m512`: sixteen `float` lanes (AVX-512).
296    M512,
297    /// `__m512i`: sixty-four bytes of integer lanes.
298    M512i,
299    /// `__m512d`: eight `double` lanes.
300    M512d,
301    /// `__m128bh`, `__m256bh`, `__m512bh`: bfloat16 lanes (AVX512-BF16). C
302    /// only moves them between intrinsics; no scalar `__bf16` is needed.
303    M128bh,
304    /// See [`VecTy::M128bh`].
305    M256bh,
306    /// See [`VecTy::M128bh`].
307    M512bh,
308    /// `__m128h`, `__m256h`, `__m512h`: half-precision lanes (AVX512-FP16),
309    /// opaque in the same way: no `_Float16` scalar is needed.
310    M128h,
311    /// See [`VecTy::M128h`].
312    M256h,
313    /// See [`VecTy::M128h`].
314    M512h,
315}
316
317impl VecTy {
318    /// The name, which C and `core::arch` spell the same way.
319    pub fn name(self) -> &'static str {
320        match self {
321            VecTy::M128 => "__m128",
322            VecTy::M128i => "__m128i",
323            VecTy::M128d => "__m128d",
324            VecTy::M256 => "__m256",
325            VecTy::M256i => "__m256i",
326            VecTy::M256d => "__m256d",
327            VecTy::M512 => "__m512",
328            VecTy::M512i => "__m512i",
329            VecTy::M512d => "__m512d",
330            VecTy::M128bh => "__m128bh",
331            VecTy::M256bh => "__m256bh",
332            VecTy::M512bh => "__m512bh",
333            VecTy::M128h => "__m128h",
334            VecTy::M256h => "__m256h",
335            VecTy::M512h => "__m512h",
336        }
337    }
338
339    /// `sizeof`, which is also `_Alignof`: a vector type is aligned to its own
340    /// width on every x86 ABI, and so is Rust's.
341    pub fn bytes(self) -> u64 {
342        match self {
343            VecTy::M128 | VecTy::M128i | VecTy::M128d | VecTy::M128bh | VecTy::M128h => 16,
344            VecTy::M256 | VecTy::M256i | VecTy::M256d | VecTy::M256bh | VecTy::M256h => 32,
345            VecTy::M512 | VecTy::M512i | VecTy::M512d | VecTy::M512bh | VecTy::M512h => 64,
346        }
347    }
348}
349
350/// A pointer type: what it points at, and whether that is `const`.
351#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
352pub struct PointerType {
353    /// The pointee type.
354    pub pointee: Ty,
355    /// Whether the pointee is `const`-qualified, which decides between
356    /// `*const T` and `*mut T`.
357    pub konst: bool,
358    /// The alignment the pointee has *in C*, when a `typedef` gave it one
359    /// that is not its type's own: `typedef uint64_t
360    /// __attribute__((aligned(1))) u64_unaligned;` makes `u64_unaligned *` a
361    /// pointer to a `u64` that may sit at any address. The Rust type is the
362    /// same `*const u64`; what changes is that every access through it is a
363    /// `read_unaligned`/`write_unaligned` (see `Codegen::place_underaligned`).
364    /// `None` is the pointee type's own alignment, which is almost always.
365    /// Two pointer types differing only here are compatible (GCC treats the
366    /// `typedef` as a variant of the same type).
367    pub align: Option<u64>,
368}
369
370/// One dimension of a [variably modified](Types::is_vm) array type.
371#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
372pub enum VmDim {
373    /// A constant bound, outside a variable one: the `3` of `int a[3][n]`.
374    Fixed(u64),
375    /// A run-time bound, held by a hidden `size_t` object.
376    Len(ObjectId),
377    /// A run-time bound the type does not carry — `int a[*]`, or a
378    /// prototype's, which is never evaluated (C99 6.7.5.3p7).
379    Unknown,
380}
381
382/// An array type.
383#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
384pub struct ArrayType {
385    /// The element type.
386    pub elem: Ty,
387    /// The number of elements, zero for a [variable length
388    /// array](ArrayType::vla), whose length is only known at run time.
389    pub len: u64,
390    /// Whether the element type is `const`-qualified, which is what decides
391    /// the constness of the pointer the array decays to.
392    pub elem_const: bool,
393    /// Whether this is a variable length array (C99 6.7.5.2), whose bound was
394    /// not an integer constant expression.
395    ///
396    /// The bound itself is not a number here but a *run-time object*, named by
397    /// [`ArrayType::vla_len`], which is why `sizeof` of one is an expression
398    /// rather than a constant. See [`Stmt::Vla`].
399    pub vla: bool,
400    /// The hidden `size_t` object holding this dimension's length, for a
401    /// [variable length array](ArrayType::vla) whose declaration evaluated its
402    /// bound.
403    ///
404    /// `None` says the length is not available: `int a[*]`, and the parameter
405    /// types of a prototype, whose bounds are never evaluated because C99
406    /// 6.7.5.3p7 leaves them out of the type. Two variably modified types are
407    /// compatible whatever their bounds (6.7.5.2p6), so this is deliberately
408    /// *not* part of what [`crate::sema`] compares — only of what the
409    /// generated code computes with.
410    pub vla_len: Option<ObjectId>,
411    /// Whether the bound was left out — `int j[]`, C99 6.2.5p22's *incomplete*
412    /// array type.
413    ///
414    /// It is what `extern int j[];` declares, and what a file-scope `int j[];`
415    /// with no initialiser is until the end of the translation unit completes
416    /// it to one element (6.9.2p5). `sizeof` of one is an error, but it may be
417    /// pointed at, subscripted and decayed like any other array, and it is
418    /// *compatible* with every completed array of the same element type
419    /// (6.2.7p1), which is what lets `extern int j[]; int j[3];` declare one
420    /// object.
421    pub incomplete: bool,
422}
423
424/// A function type.
425#[derive(Clone, PartialEq, Eq, Hash, Debug)]
426pub struct FuncType {
427    /// The return type.
428    pub ret: Ty,
429    /// The parameter types, after the adjustments C applies to them.
430    pub params: Vec<Ty>,
431    /// Whether the prototype ended with `, ...`.
432    pub variadic: bool,
433    /// Whether a parameter type list was given at all.
434    ///
435    /// `int f(void)` and `int f(int)` have a prototype; `int f()` — before C23,
436    /// which removed the form — does not, and says nothing about the number or
437    /// the types of the parameters. An unprototyped type has no parameters and
438    /// is never variadic, so `ret` is all that distinguishes two of them; the
439    /// difference from `int (void)` is what a call site has to know, since an
440    /// argument passed to one gets the default argument promotions and is then
441    /// passed as if the prototype had been written that way (C99 6.5.2.2p6).
442    pub prototyped: bool,
443}
444
445/// `struct` or `union`.
446#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
447pub enum RecordKind {
448    /// `struct`
449    Struct,
450    /// `union`
451    Union,
452}
453
454impl RecordKind {
455    /// The keyword that introduces this kind of record.
456    pub fn as_str(self) -> &'static str {
457        match self {
458            RecordKind::Struct => "struct",
459            RecordKind::Union => "union",
460        }
461    }
462}
463
464/// The size and alignment of a complete type, in bytes.
465#[derive(Clone, Copy, PartialEq, Eq, Debug)]
466pub struct Layout {
467    /// `sizeof` the type.
468    pub size: u64,
469    /// `_Alignof` the type.
470    pub align: u64,
471}
472
473/// What makes a member a bit-field (C99 6.7.2.1).
474///
475/// A bit-field has no address of its own, so it is not a Rust field: a maximal
476/// run of them shares one `[u8; K]` storage field, and reading or writing one
477/// goes through a pair of generated accessors. Everything code generation needs
478/// to emit those — where the bits are and how wide they are — lives here.
479#[derive(Clone, Debug)]
480pub struct BitField {
481    /// The declared width, in bits.
482    pub width: u32,
483    /// The bit offset from the start of the record, counting from the least
484    /// significant bit of byte 0 (the little-endian bit order every ABI this
485    /// crate targets uses).
486    pub bit_offset: u64,
487    /// Whether reading the field sign-extends.
488    ///
489    /// Usually the signedness of the declared type; an `enum` bit-field follows
490    /// the enumeration's underlying type instead, which GCC and Clang make
491    /// unsigned when no enumerator is negative.
492    pub signed: bool,
493    /// The name of the `[u8; K]` field the bits live in.
494    pub storage: String,
495    /// The byte offset of that field within the record.
496    pub storage_offset: u64,
497    /// The name of the generated getter.
498    pub getter: String,
499    /// The name of the generated setter.
500    pub setter: String,
501}
502
503impl BitField {
504    /// The bit offset of the field within its storage array.
505    pub fn offset_in_storage(&self) -> u64 {
506        self.bit_offset - self.storage_offset * 8
507    }
508}
509
510/// One member of a `struct` or `union`.
511#[derive(Clone, Debug)]
512pub struct Field {
513    /// The member name as written in C, or the synthetic `__cinrs_anonN` an
514    /// anonymous member is generated under.
515    pub name: String,
516    /// Whether this is an anonymous `struct`/`union` member (C11 6.7.2.1p13),
517    /// whose own members are reached through it as if they were the enclosing
518    /// record's.
519    pub anonymous: bool,
520    /// The member type.
521    pub ty: Ty,
522    /// Whether the member's type is `const`-qualified.
523    pub is_const: bool,
524    /// The byte offset from the start of the record (always 0 in a union).
525    ///
526    /// For a bit-field this is the byte the field's first bit falls in; the
527    /// exact position is in [`Field::bits`].
528    pub offset: u64,
529    /// Set when the member was declared with a width.
530    pub bits: Option<BitField>,
531    /// Whether this is the flexible array member `int data[];` — an array of
532    /// no elements that the object is expected to be over-allocated for.
533    pub flexible: bool,
534    /// Where the member was declared.
535    pub range: SourceRange,
536}
537
538/// One field of the generated Rust item.
539///
540/// A record without bit-fields maps one C member onto one Rust field, and this
541/// is simply its member list. Bit-fields break that correspondence: they share
542/// storage, they may be unnamed, and the bytes they occupy do not always start
543/// where `#[repr(C)]` would put the next field on its own.
544#[derive(Clone, Debug)]
545pub enum RustField {
546    /// A C member, by its index in [`RecordDef::fields`].
547    Member(usize),
548    /// The bytes one maximal run of bit-fields lives in.
549    Bits {
550        /// The field name, `__cinrs_bitsN`.
551        name: String,
552        /// The byte offset of the run within the record.
553        offset: u64,
554        /// How many bytes it covers.
555        bytes: u64,
556    },
557    /// Filler that puts the field after it where C puts it.
558    Pad {
559        /// The field name, `__cinrs_padN`.
560        name: String,
561        /// How many bytes it covers.
562        bytes: u64,
563    },
564    /// A zero-sized field whose only job is to raise the item's alignment.
565    ///
566    /// `#[repr(C, align(N))]` says the same thing and reads better, so it is
567    /// what a record normally carries. A record that is a member of a *packed*
568    /// one cannot use it: Rust refuses a packed type that transitively holds a
569    /// `#[repr(align)]` one (`E0588`), while C is perfectly happy to pack such
570    /// a member. A `[uN; 0]` field costs no bytes, raises the alignment the
571    /// same way, and is not a `repr(align)` type.
572    Align {
573        /// The field name, `__cinrs_alignN`.
574        name: String,
575        /// The alignment it carries, in bytes.
576        align: u64,
577    },
578}
579
580/// A `struct` or `union` tag.
581#[derive(Clone, Debug)]
582pub struct RecordDef {
583    /// Whether this is a `struct` or a `union`.
584    pub kind: RecordKind,
585    /// The C tag, absent for an anonymous `struct { … }`.
586    pub tag: Option<String>,
587    /// The name of the generated Rust item, already made unique.
588    pub rust_name: String,
589    /// Whether `rust_name` is still the synthetic name given to an anonymous
590    /// tag, and may therefore be replaced by the name of a `typedef` of it.
591    pub anonymous: bool,
592    /// The members, in declaration order. Empty while the tag is incomplete.
593    ///
594    /// An unnamed bit-field is *not* here: it declares no member, so nothing
595    /// can name it and no initialiser reaches it. It still occupies bits, and
596    /// [`RecordDef::rust_fields`] accounts for them.
597    pub fields: Vec<Field>,
598    /// The fields of the generated Rust item, in order.
599    pub rust_fields: Vec<RustField>,
600    /// Whether a member list has been seen.
601    pub complete: bool,
602    /// The layout, computed once the tag is complete.
603    pub layout: Option<Layout>,
604    /// The alignment `_Alignas` on a member raised the record to, which
605    /// becomes `#[repr(C, align(N))]` on the generated item.
606    pub align: Option<u64>,
607    /// The maximum member alignment `__attribute__((packed))` or
608    /// `#pragma pack(N)` asked for, which becomes `#[repr(C, packed(N))]`.
609    pub packed: Option<u64>,
610    /// The alignment the *generated Rust item* has, which is [`Layout::align`]
611    /// except for a packed record — Rust refuses `packed` and `align(N)`
612    /// together, so such an item is one byte aligned however strict C says the
613    /// record is. Laying out a record that has one as a member reads this
614    /// rather than the C alignment, so that the padding it inserts puts the
615    /// member where both sides agree it goes.
616    pub rust_align: u64,
617    /// Whether the record ends in a flexible array member.
618    pub flexible: bool,
619    /// Whether an item should be generated for this tag.
620    pub emit: bool,
621    /// The C type this record stands in for, when it is not a record in C at
622    /// all: `_Float128`, which may be named but never computed with, is a
623    /// struct of sixteen bytes here. Diagnostics name the C type.
624    pub stands_for: Option<&'static str>,
625    /// Where the tag was defined (or first mentioned).
626    pub range: SourceRange,
627}
628
629/// One `enum` constant.
630#[derive(Clone, Debug)]
631pub struct Enumerator {
632    /// The name as written in C.
633    pub name: String,
634    /// The name of the generated Rust `const`, already made unique.
635    pub rust_name: String,
636    /// The constant's type: `int`, or the fixed underlying type a C23 `enum`
637    /// was given.
638    pub ty: Ty,
639    /// The value.
640    pub value: i128,
641    /// Where it was written.
642    pub range: SourceRange,
643}
644
645/// A file-scope `enum` tag, which becomes a named `c_int` alias.
646#[derive(Clone, Debug)]
647pub struct EnumDef {
648    /// Whether the enumeration's underlying type is unsigned, which is what GCC
649    /// and Clang pick when no enumerator is negative.
650    ///
651    /// The choice is implementation defined and only observable through a
652    /// bit-field of the type, which is where this is used; everywhere else an
653    /// enumeration is `int`, as [`Ty::Enum`] says.
654    pub unsigned: bool,
655    /// The C tag, if one was written.
656    pub tag: Option<String>,
657    /// The name of the generated Rust type alias.
658    pub rust_name: String,
659    /// Whether `rust_name` is still synthetic and may be replaced by a
660    /// `typedef` name.
661    pub anonymous: bool,
662    /// Whether an alias item should be generated.
663    pub emit: bool,
664    /// Where the tag was defined.
665    pub range: SourceRange,
666}
667
668/// The arena of derived and tagged types.
669///
670/// Pointers, arrays and function types are hash-consed, so [`Ty`] equality is
671/// C's type compatibility for them; `struct`, `union` and `enum` are nominal
672/// and are simply appended.
673#[derive(Clone, Debug, Default)]
674pub struct Types {
675    pointers: Vec<PointerType>,
676    arrays: Vec<ArrayType>,
677    funcs: Vec<FuncType>,
678    records: Vec<RecordDef>,
679    enums: Vec<EnumDef>,
680    atomics: Vec<Ty>,
681    pointer_index: HashMap<PointerType, PointerId>,
682    array_index: HashMap<ArrayType, ArrayId>,
683    func_index: HashMap<FuncType, FuncTyId>,
684    atomic_index: HashMap<Ty, AtomicId>,
685}
686
687impl Types {
688    /// An empty arena.
689    pub fn new() -> Self {
690        Self::default()
691    }
692
693    /// The type `pointee *`, with `konst` set when the pointee is `const`.
694    pub fn pointer(&mut self, pointee: Ty, konst: bool) -> Ty {
695        self.pointer_aligned(pointee, konst, None)
696    }
697
698    /// The type `pointee *` where the pointee's C alignment is `align` rather
699    /// than its type's own; see [`PointerType::align`].
700    pub fn pointer_aligned(&mut self, pointee: Ty, konst: bool, align: Option<u64>) -> Ty {
701        let key = PointerType {
702            pointee,
703            konst,
704            align,
705        };
706        if let Some(id) = self.pointer_index.get(&key) {
707            return Ty::Pointer(*id);
708        }
709        let id = PointerId(self.pointers.len() as u32);
710        self.pointers.push(key);
711        self.pointer_index.insert(key, id);
712        Ty::Pointer(id)
713    }
714
715    /// The type `_Atomic inner`, for a scalar `inner`.
716    ///
717    /// Wrapping an atomic type again gives the same type back: C11 6.7.3p5
718    /// makes `_Atomic _Atomic int` the same as `_Atomic int`, exactly as a
719    /// repeated `const` is.
720    pub fn atomic(&mut self, inner: Ty) -> Ty {
721        if matches!(inner, Ty::Atomic(_)) {
722            return inner;
723        }
724        if let Some(id) = self.atomic_index.get(&inner) {
725            return Ty::Atomic(*id);
726        }
727        let id = AtomicId(self.atomics.len() as u32);
728        self.atomics.push(inner);
729        self.atomic_index.insert(inner, id);
730        Ty::Atomic(id)
731    }
732
733    /// The type inside a [`Ty::Atomic`].
734    ///
735    /// # Panics
736    ///
737    /// Panics if `id` did not come from this arena.
738    pub fn atomic_inner(&self, id: AtomicId) -> Ty {
739        self.atomics[id.0 as usize]
740    }
741
742    /// `ty` with an `_Atomic` taken off it, which is what reading an atomic
743    /// lvalue produces (C11 6.3.2.1p2: lvalue conversion drops the
744    /// qualifiers).
745    pub fn unatomic(&self, ty: Ty) -> Ty {
746        match ty {
747            Ty::Atomic(id) => self.atomic_inner(id),
748            other => other,
749        }
750    }
751
752    /// Whether `ty` is an `_Atomic` type.
753    pub fn is_atomic(&self, ty: Ty) -> bool {
754        matches!(ty, Ty::Atomic(_))
755    }
756
757    /// The type `elem[len]`.
758    pub fn array(&mut self, elem: Ty, len: u64, elem_const: bool) -> Ty {
759        self.array_type_of(ArrayType {
760            elem,
761            len,
762            elem_const,
763            vla: false,
764            vla_len: None,
765            incomplete: false,
766        })
767    }
768
769    /// The type `elem[n]` for a bound that is not a constant: a variable
770    /// length array, whose length lives in the object `vla_len` names.
771    pub fn vla_array(&mut self, elem: Ty, elem_const: bool, vla_len: Option<ObjectId>) -> Ty {
772        self.array_type_of(ArrayType {
773            elem,
774            len: 0,
775            elem_const,
776            vla: true,
777            vla_len,
778            incomplete: false,
779        })
780    }
781
782    /// The type `elem[]` — an array whose bound was left out (6.2.5p22).
783    pub fn incomplete_array(&mut self, elem: Ty, elem_const: bool) -> Ty {
784        self.array_type_of(ArrayType {
785            elem,
786            len: 0,
787            elem_const,
788            vla: false,
789            vla_len: None,
790            incomplete: true,
791        })
792    }
793
794    /// The same type with the elements of every array in it `const`.
795    ///
796    /// C99 6.7.3p9: "If the specification of an array type includes any type
797    /// qualifiers, the element type is so-qualified, not the array type."
798    /// Writing the declarator says so by itself — the qualifier in
799    /// `const int a[1]` is on `int` — but the `typedef` spelling does not:
800    ///
801    /// ```c
802    /// typedef int A[1];
803    /// const A a;      /* `const int[1]`, so `&a` is `const int (*)[1]` */
804    /// ```
805    ///
806    /// and neither does `typeof`. Anything that is not an array is returned
807    /// as it stands, because every other type carries `const` on the object
808    /// rather than in [`Ty`].
809    ///
810    /// A multidimensional array is an array *of arrays*, and the element type
811    /// the qualifier lands on is the one that is not an array — exactly where
812    /// the declarator spelling puts it, so that `const int a[2][3]` and
813    /// `typedef int A[2][3]; const A a;` are one type.
814    pub fn const_elements(&mut self, ty: Ty) -> Ty {
815        let Ty::Array(id) = ty else {
816            return ty;
817        };
818        let array = self.array_type(id);
819        if array.elem.is_array() {
820            let elem = self.const_elements(array.elem);
821            if elem == array.elem {
822                return ty;
823            }
824            return self.array_type_of(ArrayType { elem, ..array });
825        }
826        if array.elem_const {
827            return ty;
828        }
829        self.array_type_of(ArrayType {
830            elem_const: true,
831            ..array
832        })
833    }
834
835    fn array_type_of(&mut self, key: ArrayType) -> Ty {
836        if let Some(id) = self.array_index.get(&key) {
837            return Ty::Array(*id);
838        }
839        let id = ArrayId(self.arrays.len() as u32);
840        self.arrays.push(key);
841        self.array_index.insert(key, id);
842        Ty::Array(id)
843    }
844
845    /// The type of a function with a prototype.
846    pub fn func(&mut self, ret: Ty, params: Vec<Ty>, variadic: bool) -> Ty {
847        self.func_type_of(FuncType {
848            ret,
849            params,
850            variadic,
851            prototyped: true,
852        })
853    }
854
855    /// The type `ret ()`: a function whose parameters are unspecified.
856    ///
857    /// See [`FuncType::prototyped`]. Only the return type varies, so this needs
858    /// nothing else.
859    pub fn unprototyped_func(&mut self, ret: Ty) -> Ty {
860        self.func_type_of(FuncType {
861            ret,
862            params: Vec::new(),
863            variadic: false,
864            prototyped: false,
865        })
866    }
867
868    /// The interned type for a function type description.
869    pub fn func_type_of(&mut self, key: FuncType) -> Ty {
870        if let Some(id) = self.func_index.get(&key) {
871            return Ty::Func(*id);
872        }
873        let id = FuncTyId(self.funcs.len() as u32);
874        self.funcs.push(key.clone());
875        self.func_index.insert(key, id);
876        Ty::Func(id)
877    }
878
879    /// Adds a `struct` or `union` tag.
880    pub fn add_record(&mut self, def: RecordDef) -> RecordId {
881        let id = RecordId(self.records.len() as u32);
882        self.records.push(def);
883        id
884    }
885
886    /// Adds an `enum` tag.
887    pub fn add_enum(&mut self, def: EnumDef) -> EnumId {
888        let id = EnumId(self.enums.len() as u32);
889        self.enums.push(def);
890        id
891    }
892
893    /// The pointer type behind a [`Ty::Pointer`].
894    ///
895    /// # Panics
896    ///
897    /// Panics if `id` did not come from this arena.
898    pub fn pointer_type(&self, id: PointerId) -> PointerType {
899        self.pointers[id.0 as usize]
900    }
901
902    /// The array type behind a [`Ty::Array`].
903    ///
904    /// # Panics
905    ///
906    /// Panics if `id` did not come from this arena.
907    pub fn array_type(&self, id: ArrayId) -> ArrayType {
908        self.arrays[id.0 as usize]
909    }
910
911    /// The function type behind a [`Ty::Func`].
912    ///
913    /// # Panics
914    ///
915    /// Panics if `id` did not come from this arena.
916    pub fn func_type(&self, id: FuncTyId) -> &FuncType {
917        &self.funcs[id.0 as usize]
918    }
919
920    /// A tag definition.
921    ///
922    /// # Panics
923    ///
924    /// Panics if `id` did not come from this arena.
925    pub fn record(&self, id: RecordId) -> &RecordDef {
926        &self.records[id.0 as usize]
927    }
928
929    /// A tag definition, mutably.
930    ///
931    /// # Panics
932    ///
933    /// Panics if `id` did not come from this arena.
934    pub fn record_mut(&mut self, id: RecordId) -> &mut RecordDef {
935        &mut self.records[id.0 as usize]
936    }
937
938    /// Every tag, in definition order.
939    pub fn records(&self) -> &[RecordDef] {
940        &self.records
941    }
942
943    /// Generates no item for any tag added since there were `mark` of them.
944    ///
945    /// What this is for is C23's repeated definition of one tag (N3037): the
946    /// second member list has to be *resolved* to be compared with the first,
947    /// and everything that resolving it created — the tag itself, and any
948    /// anonymous member of it — is then a duplicate of something the first
949    /// definition already generated. The type the program sees is the first
950    /// one; these are left in the arena, unreferenced and unemitted, because
951    /// removing them would move every [`RecordId`] after them.
952    pub fn suppress_records_from(&mut self, mark: usize) {
953        for def in &mut self.records[mark..] {
954            def.emit = false;
955        }
956    }
957
958    /// An `enum` definition.
959    ///
960    /// # Panics
961    ///
962    /// Panics if `id` did not come from this arena.
963    pub fn enum_def(&self, id: EnumId) -> &EnumDef {
964        &self.enums[id.0 as usize]
965    }
966
967    /// An `enum` definition, mutably.
968    ///
969    /// # Panics
970    ///
971    /// Panics if `id` did not come from this arena.
972    pub fn enum_mut(&mut self, id: EnumId) -> &mut EnumDef {
973        &mut self.enums[id.0 as usize]
974    }
975
976    /// Every `enum` definition, in definition order.
977    pub fn enums(&self) -> &[EnumDef] {
978        &self.enums
979    }
980
981    /// What a pointer points at, if `ty` is a pointer.
982    pub fn pointee(&self, ty: Ty) -> Option<Ty> {
983        match ty {
984            Ty::Pointer(id) => Some(self.pointer_type(id).pointee),
985            _ => None,
986        }
987    }
988
989    /// Whether `ty` is a pointer whose pointee is `const`.
990    pub fn points_to_const(&self, ty: Ty) -> bool {
991        match ty {
992            Ty::Pointer(id) => self.pointer_type(id).konst,
993            _ => false,
994        }
995    }
996
997    /// The element type of an array.
998    pub fn elem(&self, ty: Ty) -> Option<Ty> {
999        match ty {
1000            Ty::Array(id) => Some(self.array_type(id).elem),
1001            _ => None,
1002        }
1003    }
1004
1005    /// Whether `ty` is an array whose own bound is a run-time value.
1006    ///
1007    /// `int a[n]` is one and `int a[3][n]` is not — that one is an array *of*
1008    /// variable length arrays, which C calls variably modified all the same.
1009    /// [`Types::is_vm`] is the question to ask about the type as a whole.
1010    pub fn is_vla(&self, ty: Ty) -> bool {
1011        matches!(ty, Ty::Array(id) if self.array_type(id).vla)
1012    }
1013
1014    /// Whether `ty` is *variably modified* (C99 6.7.5.2p4): an array with a
1015    /// run-time bound anywhere in it.
1016    ///
1017    /// A pointer to one is variably modified too by C's definition, but what
1018    /// the question is asked for here is "does this type have a size only the
1019    /// running program knows", and a pointer's size is a constant.
1020    pub fn is_vm(&self, ty: Ty) -> bool {
1021        match ty {
1022            Ty::Array(id) => {
1023                let array = self.array_type(id);
1024                array.vla || self.is_vm(array.elem)
1025            }
1026            _ => false,
1027        }
1028    }
1029
1030    /// The type a pointer into a [variably modified](Types::is_vm) array
1031    /// addresses: what is left after every dimension with a run-time size is
1032    /// taken off.
1033    ///
1034    /// It is the element type a [`Stmt::Vla`] allocates off the function's
1035    /// arena and the pointee of the generated Rust pointer — `double a[n][m]` is a
1036    /// `*mut c_double` over `n * m` of them, and `double a[n][3]` a
1037    /// `*mut [c_double; 3]` over `n`. Everything else about a variably
1038    /// modified type is arithmetic on top of that: see [`Types::vm_dims`].
1039    pub fn vm_step_ty(&self, ty: Ty) -> Ty {
1040        match ty {
1041            Ty::Array(id) if self.is_vm(ty) => self.vm_step_ty(self.array_type(id).elem),
1042            other => other,
1043        }
1044    }
1045
1046    /// The dimensions between `ty` and its [step type](Types::vm_step_ty),
1047    /// outermost first.
1048    ///
1049    /// Their product is how many step-type elements the type holds, which is
1050    /// what `sizeof` multiplies by the element size and what pointer
1051    /// arithmetic on a pointer to `ty` scales by.
1052    pub fn vm_dims(&self, ty: Ty) -> Vec<VmDim> {
1053        let mut out = Vec::new();
1054        let mut ty = ty;
1055        while self.is_vm(ty) {
1056            let Ty::Array(id) = ty else { break };
1057            let array = self.array_type(id);
1058            out.push(match (array.vla, array.vla_len) {
1059                (true, Some(len)) => VmDim::Len(len),
1060                (true, None) => VmDim::Unknown,
1061                // A fixed dimension outside a variable one counts too: the
1062                // rows of `int a[3][n]` are `n` ints apart, and there are
1063                // three of them.
1064                (false, _) => VmDim::Fixed(array.len),
1065            });
1066            ty = array.elem;
1067        }
1068        out
1069    }
1070
1071    /// Whether `ty` is an array whose bound was left out — `int j[]`.
1072    pub fn is_incomplete_array(&self, ty: Ty) -> bool {
1073        matches!(ty, Ty::Array(id) if self.array_type(id).incomplete)
1074    }
1075
1076    /// `elem[1]`, for an incomplete array type: what C99 6.9.2p5 completes a
1077    /// tentative definition with one to at the end of the translation unit.
1078    pub fn complete_tentative_array(&mut self, ty: Ty) -> Option<Ty> {
1079        let Ty::Array(id) = ty else { return None };
1080        let array = self.array_type(id);
1081        if !array.incomplete {
1082            return None;
1083        }
1084        Some(self.array(array.elem, 1, array.elem_const))
1085    }
1086
1087    /// Whether `ty` is a pointer to a function.
1088    pub fn is_func_pointer(&self, ty: Ty) -> bool {
1089        matches!(self.pointee(ty), Some(Ty::Func(_)))
1090    }
1091
1092    /// Whether `ty` is `void *` (however qualified).
1093    pub fn is_void_pointer(&self, ty: Ty) -> bool {
1094        self.pointee(ty) == Some(Ty::Void)
1095    }
1096
1097    /// Whether the two pointer types point at the same thing, ignoring `const`.
1098    pub fn same_pointee(&self, a: Ty, b: Ty) -> bool {
1099        match (a, b) {
1100            (Ty::Pointer(a), Ty::Pointer(b)) => {
1101                self.pointer_type(a).pointee == self.pointer_type(b).pointee
1102            }
1103            _ => false,
1104        }
1105    }
1106
1107    /// The type an array or function decays to in a value context.
1108    pub fn decayed(&mut self, ty: Ty, konst: bool) -> Ty {
1109        match ty {
1110            Ty::Array(id) => {
1111                let array = self.array_type(id);
1112                self.pointer(array.elem, array.elem_const || konst)
1113            }
1114            Ty::Func(_) => self.pointer(ty, false),
1115            other => other,
1116        }
1117    }
1118
1119    /// Whether the type is complete, i.e. whether `sizeof` applies to it.
1120    pub fn is_complete(&self, ty: Ty) -> bool {
1121        match ty {
1122            Ty::Void | Ty::Func(_) | Ty::Error => false,
1123            Ty::Record(id) => self.record(id).complete,
1124            Ty::Array(id) => {
1125                let array = self.array_type(id);
1126                !array.incomplete && self.is_complete(array.elem)
1127            }
1128            _ => true,
1129        }
1130    }
1131
1132    /// The name of a `const`-qualified member of `ty`, if it has one.
1133    ///
1134    /// C11 6.3.2.1p1 makes a structure or union with such a member — "any
1135    /// member (including, recursively, any member or element of all contained
1136    /// aggregates or unions)" — something other than a modifiable lvalue, so
1137    /// the whole object cannot be assigned to even though nothing about the
1138    /// object itself was declared `const`. WG14 DR131 is that rule, and
1139    /// `drs/dr1xx.c` is where it is checked.
1140    ///
1141    /// The walk terminates: a record cannot contain itself by value.
1142    pub fn const_member(&self, ty: Ty) -> Option<&str> {
1143        match ty {
1144            Ty::Record(id) => self.record(id).fields.iter().find_map(|field| {
1145                if field.is_const || self.has_const_elements(field.ty) {
1146                    Some(field.name.as_str())
1147                } else {
1148                    self.const_member(field.ty)
1149                }
1150            }),
1151            Ty::Array(id) => self.const_member(self.array_type(id).elem),
1152            _ => None,
1153        }
1154    }
1155
1156    /// Whether `ty` is an array whose elements are `const`-qualified.
1157    ///
1158    /// An array type is never itself qualified — 6.7.3p9 puts the qualifiers
1159    /// on the elements — so `const int a[3];` as a member is a `const` member
1160    /// with `is_const` clear.
1161    fn has_const_elements(&self, ty: Ty) -> bool {
1162        match ty {
1163            Ty::Array(id) => {
1164                let array = self.array_type(id);
1165                array.elem_const || self.has_const_elements(array.elem)
1166            }
1167            _ => false,
1168        }
1169    }
1170
1171    /// The size and alignment of `ty`, or `None` when it is incomplete.
1172    pub fn size_align(&self, ty: Ty, target: &TargetModel) -> Option<Layout> {
1173        Some(match ty {
1174            // `va_list` has a layout, but not one this crate can know: it is
1175            // whatever the target's ABI made of it.
1176            Ty::Void | Ty::Func(_) | Ty::Error | Ty::VaList => return None,
1177            Ty::Pointer(_) => {
1178                let size = u64::from(target.ptr_bits).div_ceil(8);
1179                Layout { size, align: size }
1180            }
1181            Ty::Array(id) => {
1182                let array = self.array_type(id);
1183                let elem = self.size_align(array.elem, target)?;
1184                // A variable length array has no size the front end can know:
1185                // `sizeof` of one is a run-time value, computed from the
1186                // object's own hidden length. Answering `None` here is what
1187                // keeps a path that forgot about that loud rather than silently
1188                // wrong.
1189                // An incomplete array has no size either, and `sizeof` of one
1190                // is a constraint violation until a later declaration in the
1191                // same unit completes it.
1192                if array.vla || array.incomplete {
1193                    return None;
1194                }
1195                Layout {
1196                    size: elem.size.saturating_mul(array.len),
1197                    align: elem.align,
1198                }
1199            }
1200            Ty::Record(id) => self.record(id).layout?,
1201            // C11 6.2.5p27 lets an atomic type have a different size and
1202            // alignment from its underlying one, and every implementation
1203            // makes the alignment at least the size: `_Atomic long long` is
1204            // eight-byte aligned on i386, where a plain `long long` is
1205            // four-byte aligned, because that is what a lock-free 64-bit
1206            // instruction needs. Rust's `AtomicU64` says the same thing.
1207            Ty::Atomic(id) => {
1208                let inner = self.size_align(self.atomic_inner(id), target)?;
1209                Layout {
1210                    size: inner.size,
1211                    align: inner.size.max(inner.align).max(1),
1212                }
1213            }
1214            Ty::Enum(_) => {
1215                let size = u64::from(target.int_bits).div_ceil(8);
1216                Layout { size, align: size }
1217            }
1218            // A complex type is two of its component type laid out side by
1219            // side (C99 6.2.5p13), so it is twice as big and no more strictly
1220            // aligned — which is what `#[repr(C)] struct Complex<T>` gives
1221            // and what every ABI this crate targets says.
1222            Ty::ComplexFloat | Ty::ComplexDouble => {
1223                let component = ty.complex_component().size_bytes(target);
1224                Layout {
1225                    size: component * 2,
1226                    align: component.min(target.max_scalar_align).max(1),
1227                }
1228            }
1229            // The one scalar whose alignment is not its size on every target;
1230            // see [`TargetModel::int128_align`].
1231            Ty::Int128 | Ty::UInt128 => Layout {
1232                size: 16,
1233                align: target.int128_align,
1234            },
1235            // A vector type is aligned to its own width — sixteen bytes for a
1236            // `__m128i`, thirty-two for a `__m256i` — which is both what the
1237            // x86 ABIs say and what `core::arch`'s types have. The scalar rule
1238            // below would clamp it to [`TargetModel::max_scalar_align`], which
1239            // is eight, and a `_mm_load_si128` from an object aligned to eight
1240            // faults.
1241            Ty::Vector(vec) => Layout {
1242                size: vec.bytes(),
1243                align: vec.bytes(),
1244            },
1245            scalar => {
1246                let size = scalar.size_bytes(target);
1247                // A scalar is aligned to its own width, up to whatever the ABI
1248                // stops at: the i386 System V ABI aligns `long long` and
1249                // `double` to four bytes rather than eight, and `rustc` gives
1250                // `u64` and `f64` the same alignment there. See
1251                // [`TargetModel::max_scalar_align`].
1252                Layout {
1253                    size,
1254                    align: size.min(target.max_scalar_align).max(1),
1255                }
1256            }
1257        })
1258    }
1259
1260    /// `sizeof ty`, or `None` when it is incomplete.
1261    pub fn size_of(&self, ty: Ty, target: &TargetModel) -> Option<u64> {
1262        self.size_align(ty, target).map(|l| l.size)
1263    }
1264
1265    /// The C spelling of a type, as it should appear in a diagnostic.
1266    pub fn name(&self, ty: Ty) -> String {
1267        match ty {
1268            Ty::Pointer(id) => {
1269                let p = self.pointer_type(id);
1270                if let Ty::Func(f) = p.pointee {
1271                    return self.func_name(f, "(*)");
1272                }
1273                let prefix = if p.konst { "const " } else { "" };
1274                format!("{prefix}{} *", self.name(p.pointee))
1275            }
1276            Ty::Array(id) => {
1277                let a = self.array_type(id);
1278                let prefix = if a.elem_const { "const " } else { "" };
1279                if a.vla {
1280                    // C's own spelling for an array whose bound is not a
1281                    // constant expression; the bound belongs to the object, so
1282                    // there is nothing else honest to print.
1283                    return format!("{prefix}{}[*]", self.name(a.elem));
1284                }
1285                if a.incomplete {
1286                    return format!("{prefix}{}[]", self.name(a.elem));
1287                }
1288                format!("{prefix}{}[{}]", self.name(a.elem), a.len)
1289            }
1290            Ty::Func(id) => self.func_name(id, ""),
1291            Ty::Record(id) => {
1292                let record = self.record(id);
1293                if let Some(c_type) = record.stands_for {
1294                    return c_type.to_owned();
1295                }
1296                match &record.tag {
1297                    Some(tag) => format!("{} {tag}", record.kind.as_str()),
1298                    None => format!("{} {}", record.kind.as_str(), record.rust_name),
1299                }
1300            }
1301            Ty::Enum(id) => {
1302                let def = self.enum_def(id);
1303                match &def.tag {
1304                    Some(tag) => format!("enum {tag}"),
1305                    None => format!("enum {}", def.rust_name),
1306                }
1307            }
1308            Ty::Atomic(id) => format!("_Atomic({})", self.name(self.atomic_inner(id))),
1309            Ty::Error => "<error>".to_owned(),
1310            scalar => scalar.scalar_name().to_owned(),
1311        }
1312    }
1313
1314    fn func_name(&self, id: FuncTyId, middle: &str) -> String {
1315        let f = self.func_type(id);
1316        let mut params: Vec<String> = f.params.iter().map(|p| self.name(*p)).collect();
1317        if f.variadic {
1318            params.push("...".to_owned());
1319        }
1320        // `int ()` and `int (void)` are two types, and a diagnostic that says
1321        // which one it means is the whole point of the distinction.
1322        if params.is_empty() && f.prototyped {
1323            params.push("void".to_owned());
1324        }
1325        format!("{} {middle}({})", self.name(f.ret), params.join(", "))
1326    }
1327}
1328
1329impl Ty {
1330    /// The C spelling of a scalar type.
1331    ///
1332    /// Derived and tagged types need the arena; use [`Types::name`] for a type
1333    /// that may be one of those.
1334    pub fn scalar_name(self) -> &'static str {
1335        match self {
1336            Ty::Void => "void",
1337            Ty::Bool => "_Bool",
1338            Ty::Char => "char",
1339            Ty::SChar => "signed char",
1340            Ty::UChar => "unsigned char",
1341            Ty::Short => "short",
1342            Ty::UShort => "unsigned short",
1343            Ty::Int => "int",
1344            Ty::UInt => "unsigned int",
1345            Ty::Long => "long",
1346            Ty::ULong => "unsigned long",
1347            Ty::LongLong => "long long",
1348            Ty::ULongLong => "unsigned long long",
1349            Ty::Int128 => "__int128",
1350            Ty::UInt128 => "unsigned __int128",
1351            Ty::Float => "float",
1352            Ty::Double => "double",
1353            Ty::ComplexFloat => "float _Complex",
1354            Ty::ComplexDouble => "double _Complex",
1355            Ty::Pointer(_) => "pointer",
1356            Ty::Array(_) => "array",
1357            Ty::Func(_) => "function",
1358            Ty::Record(_) => "struct",
1359            Ty::Enum(_) => "enum",
1360            Ty::VaList => "va_list",
1361            Ty::Vector(vec) => vec.name(),
1362            Ty::Atomic(_) => "_Atomic",
1363            Ty::Error => "<error>",
1364        }
1365    }
1366
1367    /// Whether this is `void`.
1368    pub fn is_void(self) -> bool {
1369        self == Ty::Void
1370    }
1371
1372    /// Whether this is `_Bool`.
1373    pub fn is_bool(self) -> bool {
1374        self == Ty::Bool
1375    }
1376
1377    /// Whether this is a pointer.
1378    pub fn is_pointer(self) -> bool {
1379        matches!(self, Ty::Pointer(_))
1380    }
1381
1382    /// Whether this is an array.
1383    pub fn is_array(self) -> bool {
1384        matches!(self, Ty::Array(_))
1385    }
1386
1387    /// Whether this is a `struct` or `union`.
1388    pub fn is_record(self) -> bool {
1389        matches!(self, Ty::Record(_))
1390    }
1391
1392    /// Whether this is a function type.
1393    pub fn is_func(self) -> bool {
1394        matches!(self, Ty::Func(_))
1395    }
1396
1397    /// Whether this is a named `enum` type.
1398    pub fn is_enum(self) -> bool {
1399        matches!(self, Ty::Enum(_))
1400    }
1401
1402    /// Whether this is `va_list`.
1403    pub fn is_va_list(self) -> bool {
1404        self == Ty::VaList
1405    }
1406
1407    /// Whether this is one of x86's vector types.
1408    ///
1409    /// They are neither arithmetic nor scalar — nothing C does to a number can
1410    /// be done to one — so every operator asks this before complaining, and
1411    /// says "use an intrinsic" rather than the generic "invalid operands".
1412    pub fn is_vector(self) -> bool {
1413        matches!(self, Ty::Vector(_))
1414    }
1415
1416    /// Whether this stands for something already reported as ill formed.
1417    pub fn is_error(self) -> bool {
1418        self == Ty::Error
1419    }
1420
1421    /// Whether this is an integer type (`_Bool` and `enum` included, as C
1422    /// requires).
1423    pub fn is_integer(self) -> bool {
1424        matches!(
1425            self,
1426            Ty::Bool
1427                | Ty::Char
1428                | Ty::SChar
1429                | Ty::UChar
1430                | Ty::Short
1431                | Ty::UShort
1432                | Ty::Int
1433                | Ty::UInt
1434                | Ty::Long
1435                | Ty::ULong
1436                | Ty::LongLong
1437                | Ty::ULongLong
1438                | Ty::Int128
1439                | Ty::UInt128
1440                | Ty::Enum(_)
1441        )
1442    }
1443
1444    /// Whether this is one of the two 128-bit integer types.
1445    ///
1446    /// They are the only integers whose values do not all fit in the `i128` a
1447    /// constant is carried in, so the places that fold, print or emit one have
1448    /// to know; see [`Ty::wrap`].
1449    pub fn is_int128(self) -> bool {
1450        matches!(self, Ty::Int128 | Ty::UInt128)
1451    }
1452
1453    /// Whether this is `float` or `double` — one of C's *real* floating types.
1454    ///
1455    /// The complex types are floating types too as far as the standard's
1456    /// wording goes; [`Ty::is_complex`] is the question about those, and
1457    /// keeping them out of this one is what stops every existing floating-point
1458    /// path from silently treating a `Complex<f64>` as an `f64`.
1459    pub fn is_floating(self) -> bool {
1460        matches!(self, Ty::Float | Ty::Double)
1461    }
1462
1463    /// Whether this is one of the complex types.
1464    pub fn is_complex(self) -> bool {
1465        matches!(self, Ty::ComplexFloat | Ty::ComplexDouble)
1466    }
1467
1468    /// The *corresponding real type* (C99 6.2.5p14) — the type of each part of
1469    /// a complex value, and the type itself for everything else.
1470    pub fn complex_component(self) -> Ty {
1471        match self {
1472            Ty::ComplexFloat => Ty::Float,
1473            Ty::ComplexDouble => Ty::Double,
1474            other => other,
1475        }
1476    }
1477
1478    /// The complex type whose parts have this real type (C99 6.2.5p13).
1479    ///
1480    /// Anything that is not a real floating type gets `double _Complex`, which
1481    /// is what the usual arithmetic conversions give an integer operand.
1482    pub fn complex_of(self) -> Ty {
1483        match self {
1484            Ty::Float => Ty::ComplexFloat,
1485            Ty::ComplexFloat => Ty::ComplexFloat,
1486            _ => Ty::ComplexDouble,
1487        }
1488    }
1489
1490    /// Whether this is an arithmetic type: an integer, a real floating type, or
1491    /// a complex one (C99 6.2.5p18).
1492    pub fn is_arithmetic(self) -> bool {
1493        self.is_integer() || self.is_floating() || self.is_complex()
1494    }
1495
1496    /// Whether this is a scalar, i.e. something C can compare against zero.
1497    ///
1498    /// An [`Ty::Atomic`] is *not* one: it is the type of an object, and a
1499    /// value read out of one has the underlying type. Everything that asks
1500    /// this question about a declared type therefore has to take the
1501    /// `_Atomic` off first, with [`Types::unatomic`].
1502    pub fn is_scalar(self) -> bool {
1503        self.is_arithmetic() || self.is_pointer()
1504    }
1505
1506    /// Whether this is `_Atomic T`.
1507    pub fn is_atomic(self) -> bool {
1508        matches!(self, Ty::Atomic(_))
1509    }
1510
1511    /// Whether values of this type are signed.
1512    pub fn is_signed(self, target: &TargetModel) -> bool {
1513        match self {
1514            Ty::Char => target.char_signed,
1515            Ty::SChar | Ty::Short | Ty::Int | Ty::Long | Ty::LongLong | Ty::Enum(_) => true,
1516            Ty::Int128 => true,
1517            Ty::Float | Ty::Double | Ty::ComplexFloat | Ty::ComplexDouble => true,
1518            _ => false,
1519        }
1520    }
1521
1522    /// The width of this type in bits.
1523    pub fn bits(self, target: &TargetModel) -> u32 {
1524        match self {
1525            Ty::Void => 0,
1526            Ty::Bool => 1,
1527            Ty::Char | Ty::SChar | Ty::UChar => 8,
1528            Ty::Short | Ty::UShort => target.short_bits,
1529            Ty::Int | Ty::UInt | Ty::Enum(_) => target.int_bits,
1530            Ty::Long | Ty::ULong => target.long_bits,
1531            Ty::LongLong | Ty::ULongLong => target.long_long_bits,
1532            // Not a knob: GCC's `__int128` is 128 bits wherever it exists.
1533            Ty::Int128 | Ty::UInt128 => 128,
1534            Ty::Float => 32,
1535            Ty::Double => 64,
1536            Ty::ComplexFloat => 64,
1537            Ty::ComplexDouble => 128,
1538            Ty::Pointer(_) => target.ptr_bits,
1539            // Not a number of *value* bits — a vector type has no value this
1540            // crate reasons about — but the width the object occupies, which
1541            // is what `sizeof` asks for through [`Ty::size_bytes`].
1542            Ty::Vector(vec) => (vec.bytes() * 8) as u32,
1543            // An atomic type's width is its underlying one's, which needs the
1544            // arena; nothing asks this about one, because every value has
1545            // already had the `_Atomic` taken off it.
1546            Ty::Array(_) | Ty::Func(_) | Ty::Record(_) | Ty::VaList | Ty::Atomic(_) | Ty::Error => {
1547                0
1548            }
1549        }
1550    }
1551
1552    /// `sizeof` this scalar type, in bytes.
1553    ///
1554    /// Aggregates need the arena; use [`Types::size_of`] for a type that may be
1555    /// one.
1556    pub fn size_bytes(self, target: &TargetModel) -> u64 {
1557        match self {
1558            Ty::Void => 1, // GCC's extension; C says this is an error.
1559            Ty::Bool => 1,
1560            _ => u64::from(self.bits(target)).div_ceil(8),
1561        }
1562    }
1563
1564    /// The conversion rank of an integer type (C99 6.3.1.1).
1565    ///
1566    /// Only the ordering matters; the absolute values are arbitrary.
1567    pub fn rank(self) -> u32 {
1568        match self {
1569            Ty::Bool => 1,
1570            Ty::Char | Ty::SChar | Ty::UChar => 2,
1571            Ty::Short | Ty::UShort => 3,
1572            Ty::Int | Ty::UInt | Ty::Enum(_) => 4,
1573            Ty::Long | Ty::ULong => 5,
1574            Ty::LongLong | Ty::ULongLong => 6,
1575            // GCC ranks `__int128` above every standard integer type, which is
1576            // what makes `(__int128)x * y` compute in 128 bits.
1577            Ty::Int128 | Ty::UInt128 => 7,
1578            Ty::Float => 8,
1579            Ty::Double => 9,
1580            // The complex types have no *conversion* rank of their own: C
1581            // ranks their corresponding real types and makes the result
1582            // complex, which is what `usual_arithmetic` does before this is
1583            // ever consulted.
1584            _ => 0,
1585        }
1586    }
1587
1588    /// The unsigned type of the same rank.
1589    pub fn to_unsigned(self) -> Ty {
1590        match self {
1591            Ty::Char | Ty::SChar => Ty::UChar,
1592            Ty::Short => Ty::UShort,
1593            Ty::Int | Ty::Enum(_) => Ty::UInt,
1594            Ty::Long => Ty::ULong,
1595            Ty::LongLong => Ty::ULongLong,
1596            Ty::Int128 => Ty::UInt128,
1597            other => other,
1598        }
1599    }
1600
1601    /// The smallest value this integer type can hold.
1602    pub fn min_value(self, target: &TargetModel) -> i128 {
1603        if !self.is_signed(target) {
1604            return 0;
1605        }
1606        let bits = self.bits(target);
1607        if bits >= 128 {
1608            return i128::MIN;
1609        }
1610        -(1i128 << (bits - 1))
1611    }
1612
1613    /// The largest value this integer type can hold.
1614    ///
1615    /// `unsigned __int128` is the one type whose largest value does not fit in
1616    /// the `i128` this returns, and it is clamped to [`i128::MAX`]. Nothing
1617    /// reads it: the only comparison of two maxima is the last step of the
1618    /// [usual arithmetic conversions](Ty::usual_arithmetic), which is reached
1619    /// only when the *unsigned* operand has the lower rank — and no integer
1620    /// type ranks above `unsigned __int128`.
1621    pub fn max_value(self, target: &TargetModel) -> i128 {
1622        if self == Ty::Bool {
1623            return 1;
1624        }
1625        let bits = self.bits(target);
1626        if bits >= 128 {
1627            return i128::MAX;
1628        }
1629        if self.is_signed(target) {
1630            (1i128 << (bits - 1)) - 1
1631        } else {
1632            (1i128 << bits) - 1
1633        }
1634    }
1635
1636    /// Whether `value` fits in this integer type without conversion.
1637    pub fn can_represent(self, value: i128, target: &TargetModel) -> bool {
1638        value >= self.min_value(target) && value <= self.max_value(target)
1639    }
1640
1641    /// Converts an integer value to this type the way C's conversions do:
1642    /// modulo 2^N for unsigned types, and the same (implementation-defined)
1643    /// wrap-around for signed ones.
1644    ///
1645    /// # How a 128-bit constant is carried
1646    ///
1647    /// A folded constant is an `i128`, which holds every value of every type
1648    /// this models except those of `unsigned __int128` above `i128::MAX`. Such
1649    /// a value is carried as its **two's-complement bit pattern**, which is
1650    /// what this returns unchanged for a 128-bit type: for every narrower type
1651    /// the bit pattern and the mathematical value coincide, so the invariant is
1652    /// "the value, except that an `unsigned __int128` is reinterpreted". The
1653    /// places where the difference shows — division, remainder, a right shift,
1654    /// a comparison and the literal that is finally emitted — dispatch on
1655    /// [`Ty::is_signed`] instead of on the sign of the `i128`.
1656    pub fn wrap(self, value: i128, target: &TargetModel) -> i128 {
1657        if self == Ty::Bool {
1658            return i128::from(value != 0);
1659        }
1660        let bits = self.bits(target);
1661        if bits == 0 || bits >= 128 {
1662            return value;
1663        }
1664        let masked = (value as u128) & (u128::MAX >> (128 - bits));
1665        if self.is_signed(target) && masked >> (bits - 1) != 0 {
1666            (masked | (u128::MAX << bits)) as i128
1667        } else {
1668            masked as i128
1669        }
1670    }
1671
1672    /// The integer promotions (C99 6.3.1.1p2).
1673    ///
1674    /// Anything of lower rank than `int` becomes `int` when `int` can hold
1675    /// every one of its values and `unsigned int` otherwise; an `enum` becomes
1676    /// `int`; everything else is unchanged.
1677    pub fn promote(self, target: &TargetModel) -> Ty {
1678        if self.is_enum() {
1679            return Ty::Int;
1680        }
1681        if !self.is_integer() || self.rank() >= Ty::Int.rank() {
1682            return self;
1683        }
1684        if Ty::Int.can_represent(self.min_value(target), target)
1685            && Ty::Int.can_represent(self.max_value(target), target)
1686        {
1687            Ty::Int
1688        } else {
1689            Ty::UInt
1690        }
1691    }
1692
1693    /// The integer promotions applied to a bit-field (C99 6.3.1.1p2, "as
1694    /// restricted by the width").
1695    ///
1696    /// The value of a bit-field of width `width` ranges over `width` bits
1697    /// rather than over the whole declared type, so `unsigned x : 31` promotes
1698    /// to `int` — every value fits — while `unsigned x : 32` promotes to
1699    /// `unsigned int`. The standard only defines the promotions for a type
1700    /// whose rank is at most `int`'s, which is the only case standard C allows
1701    /// a bit-field to have; GCC and Clang apply the same width-restricted rule
1702    /// to the wider types they accept as an extension, so `unsigned long x : 31`
1703    /// is an `int` too and `unsigned long x : 33` keeps its declared type. This
1704    /// follows them.
1705    ///
1706    /// `signed` is the signedness of the *field*, which is the declared type's
1707    /// except for an `enum` whose underlying type the implementation made
1708    /// unsigned.
1709    pub fn promote_bit_field(self, width: u32, signed: bool, target: &TargetModel) -> Ty {
1710        if !self.is_integer() || width == 0 || width > 127 {
1711            return self.promote(target);
1712        }
1713        let (min, max) = if signed {
1714            (-(1i128 << (width - 1)), (1i128 << (width - 1)) - 1)
1715        } else {
1716            (0, (1i128 << width) - 1)
1717        };
1718        for candidate in [Ty::Int, Ty::UInt] {
1719            if candidate.can_represent(min, target) && candidate.can_represent(max, target) {
1720                return candidate;
1721            }
1722        }
1723        self
1724    }
1725
1726    /// The default argument promotions, applied to the variable part of a
1727    /// variadic call: `float` becomes `double`, and the integer promotions do
1728    /// the rest.
1729    pub fn promote_argument(self, target: &TargetModel) -> Ty {
1730        if self == Ty::Float {
1731            return Ty::Double;
1732        }
1733        self.promote(target)
1734    }
1735
1736    /// The usual arithmetic conversions (C99 6.3.1.8): the common type two
1737    /// arithmetic operands are converted to.
1738    ///
1739    /// With a complex operand the standard's rule is in two steps: the *common
1740    /// real type* is worked out from the two operands' corresponding real
1741    /// types, and the result is the complex type belonging to it if either
1742    /// operand was complex. `float _Complex + long` is therefore
1743    /// `float _Complex`, not `double _Complex`.
1744    pub fn usual_arithmetic(lhs: Ty, rhs: Ty, target: &TargetModel) -> Ty {
1745        if lhs.is_complex() || rhs.is_complex() {
1746            let real =
1747                Ty::usual_arithmetic(lhs.complex_component(), rhs.complex_component(), target);
1748            return real.complex_of();
1749        }
1750        if lhs == Ty::Double || rhs == Ty::Double {
1751            return Ty::Double;
1752        }
1753        if lhs == Ty::Float || rhs == Ty::Float {
1754            return Ty::Float;
1755        }
1756        let lhs = lhs.promote(target);
1757        let rhs = rhs.promote(target);
1758        if lhs == rhs {
1759            return lhs;
1760        }
1761        let lhs_signed = lhs.is_signed(target);
1762        if lhs_signed == rhs.is_signed(target) {
1763            return if lhs.rank() >= rhs.rank() { lhs } else { rhs };
1764        }
1765        let (unsigned, signed) = if lhs_signed { (rhs, lhs) } else { (lhs, rhs) };
1766        if unsigned.rank() >= signed.rank() {
1767            unsigned
1768        } else if signed.max_value(target) >= unsigned.max_value(target) {
1769            signed
1770        } else {
1771            signed.to_unsigned()
1772        }
1773    }
1774
1775    /// `size_t` for `target`.
1776    ///
1777    /// The *narrowest* unsigned type as wide as a pointer, which is how GCC
1778    /// picks it and therefore what `__SIZE_TYPE__` says: `unsigned int` on
1779    /// i686, `unsigned long` on LP64, `unsigned long long` on 64-bit Windows,
1780    /// where `long` is only 32 bits.
1781    pub fn size_ty(target: &TargetModel) -> Ty {
1782        if target.int_bits >= target.ptr_bits {
1783            Ty::UInt
1784        } else if target.long_bits >= target.ptr_bits {
1785            Ty::ULong
1786        } else {
1787            Ty::ULongLong
1788        }
1789    }
1790
1791    /// `ptrdiff_t` for `target`, chosen the same way as [`Ty::size_ty`].
1792    pub fn ptrdiff_ty(target: &TargetModel) -> Ty {
1793        if target.int_bits >= target.ptr_bits {
1794            Ty::Int
1795        } else if target.long_bits >= target.ptr_bits {
1796            Ty::Long
1797        } else {
1798            Ty::LongLong
1799        }
1800    }
1801
1802    /// `wchar_t` for `target`: `unsigned short` on Windows, `unsigned int` on
1803    /// Arm outside Apple's platforms, and `int` everywhere else.
1804    ///
1805    /// This is the type `L'x'` and `L"…"` get, and what the bundled
1806    /// `<stddef.h>` typedefs from `__WCHAR_TYPE__`; the two have to agree, or
1807    /// a call passing `L"…"` to a `const wchar_t *` would be a type error.
1808    pub fn wchar_ty(target: &TargetModel) -> Ty {
1809        match (target.wchar_bits, target.wchar_signed) {
1810            (16, true) => Ty::Short,
1811            (16, false) => Ty::UShort,
1812            (_, true) => Ty::Int,
1813            (_, false) => Ty::UInt,
1814        }
1815    }
1816
1817    /// `char16_t` (C11 7.28), which is `uint_least16_t` — `unsigned short` on
1818    /// every target this models, and what the bundled `<uchar.h>` typedefs it
1819    /// to.
1820    pub fn char16_ty() -> Ty {
1821        Ty::UShort
1822    }
1823
1824    /// `char32_t` (C11 7.28), which is `uint_least32_t` — `unsigned int`.
1825    pub fn char32_ty() -> Ty {
1826        Ty::UInt
1827    }
1828}
1829
1830// ---------------------------------------------------------------------------
1831// identifiers
1832// ---------------------------------------------------------------------------
1833
1834/// Identifies a named object (a local, a parameter, a `static` local or a
1835/// file-scope variable) inside a [`Program`].
1836#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1837pub struct ObjectId(pub u32);
1838
1839/// Identifies a function inside a [`Program`].
1840#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1841pub struct FuncId(pub u32);
1842
1843/// Identifies one loop inside a function; used to build its Rust label.
1844#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1845pub struct LoopId(pub u32);
1846
1847/// Identifies one `switch` inside a function; used to build its Rust label.
1848#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1849pub struct SwitchId(pub u32);
1850
1851/// Identifies one `goto` label inside a function.
1852///
1853/// C gives labels function scope and their own namespace, so every label of a
1854/// function is collected before its body is checked — that is what lets a
1855/// `goto` jump forwards.
1856#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
1857pub struct LabelId(pub u32);
1858
1859/// Identifies a string literal inside a [`Program`].
1860#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1861pub struct StrId(pub u32);
1862
1863// ---------------------------------------------------------------------------
1864// objects and functions
1865// ---------------------------------------------------------------------------
1866
1867/// Where an object lives, and how it is generated.
1868#[derive(Clone, Debug, PartialEq, Eq)]
1869pub enum Storage {
1870    /// A `let` binding: a local variable or a parameter.
1871    Automatic,
1872    /// A `static mut` item: a file-scope variable or a function-local `static`.
1873    Static {
1874        /// The name of the generated Rust item, already made unique.
1875        item_name: String,
1876        /// Whether the item is `pub` — true for a file-scope object without
1877        /// `static`, which C gives external linkage and which Rust code should
1878        /// therefore be able to reach.
1879        exported: bool,
1880    },
1881    /// A `thread_local!` item: an object declared `_Thread_local`,
1882    /// `thread_local` or `__thread`.
1883    ///
1884    /// C gives it static storage duration and one instance per thread, which
1885    /// is exactly what `std::thread_local!` provides. The item holds an
1886    /// `UnsafeCell<T>`, and every access goes through the `*mut T` its `with`
1887    /// hands out — valid for as long as the current thread's copy is, which is
1888    /// the lifetime C promises. It is the third construct whose expansion
1889    /// needs more than `core`, after variable length arrays and `alloca`.
1890    ThreadLocal {
1891        /// The name of the generated Rust item, already made unique.
1892        item_name: String,
1893        /// Whether the item is `pub`; see [`Storage::Static`].
1894        exported: bool,
1895    },
1896    /// An object defined outside the translation unit, declared in the
1897    /// expansion's `extern` block.
1898    Extern {
1899        /// The name the symbol has.
1900        item_name: String,
1901    },
1902}
1903
1904impl Storage {
1905    /// The name of the generated item, for the two storage classes that have
1906    /// one of their own.
1907    pub fn item_name(&self) -> Option<&str> {
1908        match self {
1909            Storage::Static { item_name, .. } | Storage::ThreadLocal { item_name, .. } => {
1910                Some(item_name)
1911            }
1912            Storage::Automatic | Storage::Extern { .. } => None,
1913        }
1914    }
1915
1916    /// Whether this is a thread-local object.
1917    pub fn is_thread_local(&self) -> bool {
1918        matches!(self, Storage::ThreadLocal { .. })
1919    }
1920}
1921
1922/// A named object.
1923#[derive(Clone, Debug)]
1924pub struct Object {
1925    /// The name as written in C.
1926    pub name: String,
1927    /// The object's type.
1928    pub ty: Ty,
1929    /// How the object is stored.
1930    pub storage: Storage,
1931    /// Whether the object's type is `const`-qualified.
1932    pub is_const: bool,
1933    /// Whether the declaration said `register`.
1934    ///
1935    /// The specifier is a hint about speed that this crate has nothing to do
1936    /// with — Rust decides where a local lives — but it has one rule with
1937    /// teeth: C11 6.7.1p6 says the address of such an object "cannot be
1938    /// computed, either explicitly (by use of the unary `&` operator as
1939    /// discussed in 6.5.3.2) or implicitly (by converting an array name to a
1940    /// pointer as discussed in 6.3.2.1)", so `sizeof` is the only operator an
1941    /// array declared `register` can be the operand of. WG14 DR116 is that
1942    /// rule; `drs/dr1xx.c` is where it is checked.
1943    pub is_register: bool,
1944    /// Set when this is the hidden frame of a
1945    /// [variable length array](Stmt::Vla): the mark of the function's bump
1946    /// arena taken just before the elements were allocated, in which case
1947    /// [`Object::ty`] is the *element* type and the generated binding is the
1948    /// arena's frame guard (a slot of the function's array of marks in
1949    /// [CFG mode](crate::cfg)).
1950    ///
1951    /// It is not an object of the C program at all; it exists so that the
1952    /// arena moves back down to the mark when the block ends, which is the
1953    /// lifetime C gives the array.
1954    pub vla_storage: bool,
1955    /// The alignment `_Alignas(N)` or `__attribute__((aligned(N)))` asked for,
1956    /// when it is stricter than the one the type already has.
1957    ///
1958    /// Rust has no way to over-align a binding, so the object is generated
1959    /// inside a one-field wrapper that carries the alignment —
1960    /// `#[repr(C, align(N))] struct __cinrs_align_N<T>(pub T);` — and every
1961    /// access to it goes through the field. The C object's *type* is unchanged:
1962    /// `sizeof` is the type's size and the wrapper is invisible to everything
1963    /// but the generated binding. See [`codegen`](crate::codegen).
1964    ///
1965    /// `None` is the ordinary case, and also what a request no stricter than
1966    /// the natural alignment leaves behind — there is nothing for a wrapper to
1967    /// say.
1968    pub align: Option<u64>,
1969    /// How many elements the object's storage gives the record's [flexible
1970    /// array member](Field::flexible), when an initialiser filled it in.
1971    ///
1972    /// GNU C lets an object with *static* storage duration initialise the
1973    /// member (`static struct W w = { 3, { 1, 2, 3 } };`), which makes the
1974    /// object larger than its own type — something Rust has no way to say
1975    /// about a value of type `W`. The item is therefore given a *companion*
1976    /// type with the same leading layout and a tail of this length,
1977    /// `__cinrs_W_3`, and every use of the object is a place reached through
1978    /// `(*(&raw mut w).cast::<W>())`. `sizeof w` is still `sizeof(struct W)`,
1979    /// which is what GCC says too. See [`codegen`](crate::codegen).
1980    pub flexible_len: Option<u64>,
1981    /// The symbol `__asm__("name")` renamed the object to.
1982    pub asm_label: Option<String>,
1983    /// The section `__attribute__((section("…")))` asked for.
1984    pub section: Option<String>,
1985    /// Where the declarator was written.
1986    pub range: SourceRange,
1987}
1988
1989/// A `static mut` item and its constant initialiser.
1990#[derive(Clone, Debug)]
1991pub struct StaticVar {
1992    /// The object the item defines.
1993    pub object: ObjectId,
1994    /// The initial value; C zero-initialises objects with static storage
1995    /// duration, so this is present even when the source wrote no initialiser.
1996    pub init: Expr,
1997}
1998
1999/// A function's signature.
2000#[derive(Clone, Debug, PartialEq, Eq)]
2001pub struct Signature {
2002    /// The return type.
2003    pub ret: Ty,
2004    /// The parameter types.
2005    pub params: Vec<Ty>,
2006    /// Whether the prototype ended with `, ...`.
2007    pub variadic: bool,
2008    /// Whether a parameter type list was given at all; see
2009    /// [`FuncType::prototyped`].
2010    ///
2011    /// `int f();` before C23 declares a function whose parameters are
2012    /// unspecified: `params` is empty because nothing was said, not because
2013    /// there are none. A *definition* written that way does take no parameters
2014    /// — that is what the generated item has — but its type still has no
2015    /// prototype, so a call with arguments is legal C and reaches the callee
2016    /// with the default argument promotions applied.
2017    pub prototyped: bool,
2018}
2019
2020/// How a function's body is lowered.
2021///
2022/// Nearly every C function maps onto Rust's own control flow, which is what
2023/// makes the expansion readable. A function that jumps around — a `goto`, or a
2024/// `case` label the enclosing `switch` cannot reach without one — cannot, and
2025/// is lowered into a [control-flow graph](crate::cfg) instead.
2026#[derive(Clone, Debug)]
2027pub enum Body {
2028    /// Rust control flow mirrors C's.
2029    Structured(Vec<Stmt>),
2030    /// A graph of basic blocks; see [`crate::cfg`].
2031    Cfg(crate::cfg::Cfg),
2032}
2033
2034/// A function declared or defined in the translation unit.
2035#[derive(Clone, Debug)]
2036pub struct Function {
2037    /// The name as written in C.
2038    pub name: String,
2039    /// The signature every declaration of it must agree on.
2040    pub sig: Signature,
2041    /// The parameter objects. Empty until the definition is seen.
2042    pub params: Vec<ObjectId>,
2043    /// The parameter names as first declared, for the generated `extern` block.
2044    pub param_names: Vec<Option<String>>,
2045    /// Whether the function was declared `static`, i.e. is private to the unit.
2046    pub is_static: bool,
2047    /// Whether the function was declared `inline`.
2048    pub is_inline: bool,
2049    /// Whether the function was declared `_Noreturn` (or `[[noreturn]]`), so
2050    /// that a call to it ends the statement it is in.
2051    pub noreturn: bool,
2052    /// What `always_inline` / `noinline` asked for.
2053    pub inline_hint: Option<InlineHint>,
2054    /// Whether `__attribute__((cold))` marked it unlikely.
2055    pub cold: bool,
2056    /// The message `__attribute__((deprecated))` gave, if it was there at all.
2057    pub deprecated: Option<Option<String>>,
2058    /// The section `__attribute__((section("…")))` asked for.
2059    pub section: Option<String>,
2060    /// The symbol `__asm__("name")` renamed the function to.
2061    pub asm_label: Option<String>,
2062    /// Whether `__attribute__((constructor))` asked for it to run before
2063    /// `main`, or `destructor` for after it.
2064    pub init_kind: Option<InitKind>,
2065    /// The instruction sets `__attribute__((target("…")))` or
2066    /// `#pragma GCC target("…")` asked for, in Rust's spelling, which the
2067    /// generated item carries as `#[target_feature(enable = "…")]`.
2068    ///
2069    /// Only a *definition* can carry them: an `extern` declaration has no item
2070    /// for the attribute to go on, and the function it names was compiled
2071    /// somewhere else.
2072    pub target_features: Vec<String>,
2073    /// Whether anything in the unit uses the function other than by calling
2074    /// it by name: its address taken as a value (`&f`, or `f` where a pointer
2075    /// is wanted), or it named by `__attribute__((cleanup))`, whose guard
2076    /// holds a pointer to it. Such a function has to be an `extern "C" fn`,
2077    /// since that is what a C function pointer is; one that is only ever called
2078    /// can be a Rust function, which is what an
2079    /// [always-inline helper with target features](Function::inline_helper)
2080    /// needs.
2081    pub address_taken: bool,
2082    /// Set when this name is an [x86 intrinsic](crate::x86) rather than a
2083    /// symbol: a call to it is generated as `::core::arch::x86_64::<name>`,
2084    /// and it is left out of the unit's `extern` block because there is
2085    /// nothing to link.
2086    pub intrinsic: Option<&'static crate::x86::Intrinsic>,
2087    /// Where the function was asked to be [safe](crate::sema::check_safe), if
2088    /// it was: `[[cinrs::safe]]`, `__attribute__((cinrs_safe))` or
2089    /// `#pragma cinrs safe`.
2090    ///
2091    /// A safe function is generated as `extern "C" fn` rather than
2092    /// `unsafe extern "C" fn`, and its body is *not* wrapped in an `unsafe`
2093    /// block, so `rustc` checks it. The range is where the request was
2094    /// written, which is what the diagnostics about it point at.
2095    pub safe: Option<SourceRange>,
2096    /// Whether the body declares a variable length array or calls `alloca`,
2097    /// in which case the generated item opens with the bump arena both
2098    /// emulations allocate out of.
2099    ///
2100    /// The arena is per function and is dropped by the `return`, which frees
2101    /// everything in it: that is `alloca`'s lifetime, and a variable length
2102    /// array gives its space back earlier, at the end of its block, by moving
2103    /// the arena's position back down. See [`codegen`](crate::codegen).
2104    pub uses_arena: bool,
2105    /// Every automatic object the body declared, in declaration order.
2106    ///
2107    /// Code generation needs the whole list — not only the ones a `let`
2108    /// statement is visible for — because a local declared inside a statement
2109    /// expression is a binding too and may need renaming apart.
2110    pub locals: Vec<ObjectId>,
2111    /// The body, present once a definition has been type checked.
2112    pub body: Option<Body>,
2113    /// The Rust item name, when it is not the C name.
2114    ///
2115    /// Only a lifted [GNU nested function](EnvParam) has one: it becomes a
2116    /// file-scope item, so it needs a name that cannot collide with the C
2117    /// function of the same name at file scope, while [`Function::name`] stays
2118    /// what the program called it — which is what diagnostics and `__func__`
2119    /// say.
2120    pub item_name: Option<String>,
2121    /// The hidden environment parameters a lifted GNU nested function takes in
2122    /// front of its declared ones, in the order they are passed.
2123    ///
2124    /// Empty for every ordinary function, and for a nested one that captures
2125    /// nothing — which is why such a nested function's address may still be
2126    /// taken: the generated item has exactly the signature C gave it.
2127    pub env: Vec<EnvParam>,
2128    /// Where the function's name was written, at its definition if there is one
2129    /// and at its first declaration otherwise.
2130    pub range: SourceRange,
2131}
2132
2133/// One hidden parameter of a lifted [GNU nested
2134/// function](crate::sema#nested-functions).
2135///
2136/// GCC gives a nested function a *static chain* — a pointer to the enclosing
2137/// frame — and writes a trampoline when its address is taken. This crate
2138/// lambda-lifts instead: each enclosing object the body uses becomes a
2139/// pointer parameter of its own, the body reads and writes it through that
2140/// pointer, and every call site passes the address of the object it has. The
2141/// sharing C promises is therefore kept — a store in the nested function is
2142/// visible in the enclosing one — without a trampoline, at the price of not
2143/// being able to hand the function's address out.
2144#[derive(Clone, Copy, Debug)]
2145pub struct EnvParam {
2146    /// The enclosing function's object the pointer carries.
2147    pub owner: ObjectId,
2148    /// The `*mut T` (or `*const T`) parameter of *this* function that holds
2149    /// its address.
2150    pub param: ObjectId,
2151}
2152
2153/// What `always_inline` and `noinline` ask for.
2154#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2155pub enum InlineHint {
2156    /// `#[inline(always)]`
2157    Always,
2158    /// `#[inline(never)]`
2159    Never,
2160}
2161
2162/// Whether a function runs before `main` or after it.
2163#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2164pub enum InitKind {
2165    /// `__attribute__((constructor))`
2166    Constructor,
2167    /// `__attribute__((destructor))`
2168    Destructor,
2169}
2170
2171impl Function {
2172    /// Whether this function is only declared here and linked from elsewhere.
2173    pub fn is_extern(&self) -> bool {
2174        self.body.is_none()
2175    }
2176
2177    /// The name the generated Rust item has.
2178    pub fn item_name(&self) -> &str {
2179        self.item_name.as_deref().unwrap_or(&self.name)
2180    }
2181
2182    /// Whether this is a lifted GNU nested function.
2183    pub fn is_nested(&self) -> bool {
2184        self.item_name.is_some()
2185    }
2186
2187    /// Whether the function is generated without `unsafe`; see
2188    /// [`Function::safe`].
2189    pub fn is_safe(&self) -> bool {
2190        self.safe.is_some()
2191    }
2192
2193    /// Whether the function is an `always_inline` helper under a target
2194    /// feature that is generated as a Rust `#[inline(always)] unsafe fn`
2195    /// *without* `#[target_feature]`.
2196    ///
2197    /// rustc refuses `#[inline(always)]` together with `#[target_feature]`
2198    /// (rust-lang/rust#145574), and `#[inline]` alone is a hint LLVM may
2199    /// decline: BLAKE3's `round_fn16`, called seven times from one kernel, was
2200    /// left out of line, its state spilled to the stack around every call.
2201    /// GCC's contract makes the attribute unnecessary: it refuses to inline an
2202    /// `always_inline` function into a caller without its target options, so
2203    /// every caller of one that compiles has the features, and once the helper
2204    /// is inlined into such a caller the intrinsics in its body are inlined
2205    /// there too. Without the attribute the helper must not be a C-ABI
2206    /// function — the C ABI passes a 256- or 512-bit vector in registers the
2207    /// feature provides — so it is a Rust function, and that is only possible
2208    /// when nothing needs it as a C function pointer: it is `static`, never
2209    /// has its address taken, is not variadic, nested, safe (whose body would
2210    /// then call intrinsics without `unsafe`), a constructor or an intrinsic.
2211    pub fn inline_helper(&self) -> bool {
2212        self.inline_hint == Some(InlineHint::Always)
2213            && !self.target_features.is_empty()
2214            && self.is_static
2215            && !self.address_taken
2216            && !self.sig.variadic
2217            && !self.is_nested()
2218            && !self.is_safe()
2219            && self.init_kind.is_none()
2220            && self.intrinsic.is_none()
2221    }
2222}
2223
2224/// One direct call, from the function whose body holds it to the function it
2225/// names.
2226///
2227/// Sema records these as it checks the calls, and
2228/// [`check_safe`](crate::sema::check_safe) is the one thing that reads them: a
2229/// [safe](Function::safe) function calling one that is not gets a diagnostic
2230/// worded in C rather than `rustc`'s "call to unsafe function". A call through
2231/// a *pointer* has no edge — there is no callee to name — and is left to
2232/// `rustc`, which refuses it in a safe function like any other unsafe
2233/// operation.
2234#[derive(Clone, Copy, Debug)]
2235pub struct CallEdge {
2236    /// The function the call was written in.
2237    pub caller: FuncId,
2238    /// The function it calls.
2239    pub callee: FuncId,
2240    /// Where the callee was named, which is where a diagnostic points.
2241    pub range: SourceRange,
2242}
2243
2244/// A file-scope `typedef`, which becomes a Rust type alias.
2245#[derive(Clone, Debug)]
2246pub struct TypedefItem {
2247    /// The name of the generated alias.
2248    pub rust_name: String,
2249    /// What it stands for.
2250    pub ty: Ty,
2251    /// Where it was written.
2252    pub range: SourceRange,
2253}
2254
2255/// A string literal's decoded contents.
2256#[derive(Clone, Debug)]
2257pub struct StrData {
2258    /// The elements, without the terminating NUL: bytes for a narrow or
2259    /// `u8"…"` literal, UTF-16 code units for `u"…"`, and character values for
2260    /// `U"…"` and `L"…"`.
2261    pub values: Vec<u32>,
2262    /// The type of one element: `char`, `char8_t`, `char16_t`, `char32_t` or
2263    /// `wchar_t`, whichever prefix the literal was written with.
2264    pub elem: Ty,
2265}
2266
2267impl StrData {
2268    /// The number of elements including the terminating NUL.
2269    pub fn len_with_nul(&self) -> u64 {
2270        self.values.len() as u64 + 1
2271    }
2272}
2273
2274/// Everything one translation unit generates.
2275#[derive(Clone, Debug, Default)]
2276pub struct Program {
2277    /// A hash of the invocation site, used to build the synthetic item names
2278    /// that must not collide between two `c99!` blocks in one module.
2279    pub unit_id: u64,
2280    /// Every derived and tagged type.
2281    pub types: Types,
2282    /// Every named object, indexed by [`ObjectId`].
2283    pub objects: Vec<Object>,
2284    /// The objects that become `static mut` items, in declaration order.
2285    pub statics: Vec<StaticVar>,
2286    /// The objects declared `extern`, in declaration order.
2287    pub externs: Vec<ObjectId>,
2288    /// Every function, indexed by [`FuncId`], in declaration order.
2289    pub functions: Vec<Function>,
2290    /// Every direct call the unit's bodies make; see [`CallEdge`].
2291    pub calls: Vec<CallEdge>,
2292    /// The file-scope `typedef`s, in declaration order.
2293    pub typedefs: Vec<TypedefItem>,
2294    /// The `enum` constants that become Rust `const` items, in order.
2295    pub enum_constants: Vec<Enumerator>,
2296    /// Every string literal, indexed by [`StrId`].
2297    pub strings: Vec<StrData>,
2298    /// The libraries the unit must be linked against, named by
2299    /// `#pragma cinrs link "…"`.
2300    ///
2301    /// Filled in after semantic analysis: it is the preprocessor that reads
2302    /// the pragma, and nothing about the program itself depends on it.
2303    pub link_libraries: Vec<String>,
2304    /// Whether `#pragma cinrs export` asked for every function and object with
2305    /// external linkage to become a real C symbol.
2306    ///
2307    /// Filled in after semantic analysis, for the same reason as
2308    /// [`Program::link_libraries`].
2309    pub export: bool,
2310    /// Every `__builtin_cpu_supports` the unit wrote, by where it was written.
2311    ///
2312    /// It becomes `::std::is_x86_feature_detected!`, and `core` has no CPU
2313    /// detection at all — so a unit that said `#pragma cinrs no_std` cannot
2314    /// have one. The pragma is only known after semantic analysis, which is
2315    /// why the sites are collected rather than checked where they are met; see
2316    /// [`crate::sema::check_pragmas`].
2317    pub cpu_supports: Vec<SourceRange>,
2318    /// Whether `#pragma cinrs no_std` said the expansion goes into a
2319    /// `#![no_std]` crate.
2320    ///
2321    /// Everything generated is `core`-only except the storage a [variable
2322    /// length array](Stmt::Vla) and `alloca` need, which is a bump arena made
2323    /// of `Vec`s; this decides whether they are spelled `::std::vec::Vec` or
2324    /// `::alloc::vec::Vec`. Filled in after semantic analysis, for the same
2325    /// reason as [`Program::link_libraries`].
2326    pub no_std: bool,
2327    /// The Rust path of the `cinrs` facade crate, which the generated code
2328    /// names when it needs the runtime: `::cinrs` unless
2329    /// `#pragma cinrs crate "…"` said otherwise.
2330    ///
2331    /// Only a unit that uses a complex type spells it at all. Filled in after
2332    /// semantic analysis, for the same reason as [`Program::link_libraries`].
2333    pub crate_path: String,
2334}
2335
2336/// The Rust path of the facade crate the generated code names, when the unit
2337/// does not say.
2338///
2339/// A crate renamed in `Cargo.toml` — `cinrs = { package = "cinrs", … }` under
2340/// another name — is reached with `#pragma cinrs crate "<path>"` instead.
2341pub const DEFAULT_CRATE_PATH: &str = "::cinrs";
2342
2343impl Program {
2344    /// Looks an object up.
2345    ///
2346    /// # Panics
2347    ///
2348    /// Panics if `id` did not come from this program.
2349    pub fn object(&self, id: ObjectId) -> &Object {
2350        &self.objects[id.0 as usize]
2351    }
2352
2353    /// Looks a function up.
2354    ///
2355    /// # Panics
2356    ///
2357    /// Panics if `id` did not come from this program.
2358    pub fn function(&self, id: FuncId) -> &Function {
2359        &self.functions[id.0 as usize]
2360    }
2361
2362    /// Looks a string literal up.
2363    ///
2364    /// # Panics
2365    ///
2366    /// Panics if `id` did not come from this program.
2367    pub fn string(&self, id: StrId) -> &StrData {
2368        &self.strings[id.0 as usize]
2369    }
2370
2371    /// The hidden Rust name an externally linked **object** is declared under.
2372    ///
2373    /// Only an object. A function the unit merely declares is generated under
2374    /// its own C name, like everything else the unit spells, so that
2375    /// `#include <zlib.h>` is enough for Rust to call `crc32`; an object is
2376    /// not, and the difference is Rust's rule for patterns rather than a
2377    /// matter of taste.
2378    ///
2379    /// A glob-imported **function** cannot change the meaning of Rust code
2380    /// that does not mention it: a function is not a pattern, so `let read =
2381    /// 1;` beside a unit that declares `read` is still a new binding. A glob
2382    /// imported **static** can. Rust resolves a binding pattern against the
2383    /// value namespace first, and a `static` there is not a name a `let` may
2384    /// shadow:
2385    ///
2386    /// ```text
2387    /// error[E0530]: let bindings cannot shadow statics
2388    /// ```
2389    ///
2390    /// — which is what `let stdout = std::io::stdout();` would become next to a
2391    /// block that includes `<stdio.h>`, and `let timezone = …` next to one that
2392    /// includes glibc's `<time.h>`. `optarg`, `optind` and `environ` are the
2393    /// same story. So a declared-only object keeps a name of its own,
2394    /// `__cinrs_<unit>_<symbol>`, and Rust reaches it the way C code does in
2395    /// the same situation: through an accessor written in the block,
2396    /// `FILE *get_stdout(void) { return stdout; }`.
2397    ///
2398    /// The C code in the unit is unaffected either way — it refers to the
2399    /// object by its C name, and this is only the Rust side of that.
2400    ///
2401    /// A module of its own for the `extern` block would have avoided the
2402    /// question altogether, but a module cannot see the `struct` items of the
2403    /// block it is written in, which an `extern` declaration taking a `struct`
2404    /// needs.
2405    ///
2406    /// A `$` in the C name — an identifier character here, and one Rust has no
2407    /// spelling for — is written [`crate::codegen::DOLLAR`]; the symbol the
2408    /// declaration links by is a `#[link_name]` string and keeps the `$`.
2409    pub fn extern_object_name(&self, symbol: &str) -> String {
2410        format!(
2411            "__cinrs_{:08x}_{}",
2412            self.unit_id as u32,
2413            symbol.replace('$', crate::codegen::DOLLAR)
2414        )
2415    }
2416
2417    /// Whether anything at all has to go into the `extern` block.
2418    ///
2419    /// An [x86 intrinsic](crate::x86) does not count: it is declared like any
2420    /// other function and generated as a call to `core::arch`, so a unit whose
2421    /// only declarations came from `<immintrin.h>` needs no block at all.
2422    pub fn has_externs(&self) -> bool {
2423        !self.externs.is_empty()
2424            || self
2425                .functions
2426                .iter()
2427                .any(|func| func.is_extern() && func.intrinsic.is_none())
2428    }
2429}
2430
2431// ---------------------------------------------------------------------------
2432// constants
2433// ---------------------------------------------------------------------------
2434
2435/// The value of an arithmetic constant expression.
2436#[derive(Clone, Copy, PartialEq, Debug)]
2437pub enum ConstValue {
2438    /// An integer value, already reduced to the range of its type.
2439    Int(i128),
2440    /// A floating value.
2441    Float(f64),
2442    /// A complex value: the real part and the imaginary one, each already
2443    /// rounded to the component type.
2444    ///
2445    /// Both parts are carried as `f64` whatever the type is, exactly as a
2446    /// `float` constant is; the rounding to `f32` happens where the value is
2447    /// stored, so that `(float _Complex) 0.1` is the same number here and in
2448    /// the generated code.
2449    Complex(f64, f64),
2450}
2451
2452// ---------------------------------------------------------------------------
2453// expressions
2454// ---------------------------------------------------------------------------
2455
2456/// A binary arithmetic, bitwise or shift operator.
2457#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2458#[allow(missing_docs)]
2459pub enum BinOp {
2460    Add,
2461    Sub,
2462    Mul,
2463    Div,
2464    Rem,
2465    BitAnd,
2466    BitXor,
2467    BitOr,
2468    Shl,
2469    Shr,
2470}
2471
2472impl BinOp {
2473    /// The C spelling.
2474    pub fn as_str(self) -> &'static str {
2475        match self {
2476            BinOp::Add => "+",
2477            BinOp::Sub => "-",
2478            BinOp::Mul => "*",
2479            BinOp::Div => "/",
2480            BinOp::Rem => "%",
2481            BinOp::BitAnd => "&",
2482            BinOp::BitXor => "^",
2483            BinOp::BitOr => "|",
2484            BinOp::Shl => "<<",
2485            BinOp::Shr => ">>",
2486        }
2487    }
2488
2489    /// Whether this operator shifts, in which case its operands are promoted
2490    /// separately rather than converted to a common type.
2491    pub fn is_shift(self) -> bool {
2492        matches!(self, BinOp::Shl | BinOp::Shr)
2493    }
2494}
2495
2496/// A relational or equality operator.
2497#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2498#[allow(missing_docs)]
2499pub enum CmpOp {
2500    Lt,
2501    Gt,
2502    Le,
2503    Ge,
2504    Eq,
2505    Ne,
2506}
2507
2508/// `&&` or `||`.
2509#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2510pub enum LogicalOp {
2511    /// `&&`
2512    And,
2513    /// `||`
2514    Or,
2515}
2516
2517/// The `(rw, locality)` of a [`BuiltinOp::Prefetch`]: whether it is a
2518/// prefetch for writing, and how long the line should stay, 0 to 3.
2519pub fn prefetch_hint(packed: u8) -> (bool, u8) {
2520    (packed & 4 != 0, packed & 3)
2521}
2522
2523/// A GNU builtin that becomes a fixed piece of Rust rather than a call.
2524///
2525/// The bit-manipulation ones map onto the integer methods of the same name;
2526/// the overflow ones do the arithmetic in `i128` and check the result against
2527/// the range of the type it is stored in, which is exactly the "compute in
2528/// infinite precision, then convert" the builtins are defined by.
2529#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2530pub enum BuiltinOp {
2531    /// `__builtin_popcount…`
2532    Popcount,
2533    /// `__builtin_clz…`; undefined for zero in C, and this follows Rust.
2534    Clz,
2535    /// `__builtin_ctz…`
2536    Ctz,
2537    /// `__builtin_ffs…`: one more than the index of the lowest set bit, or 0.
2538    Ffs,
2539    /// `__builtin_parity…`
2540    Parity,
2541    /// `__builtin_clrsb…`: leading redundant sign bits.
2542    Clrsb,
2543    /// `__builtin_bswap16/32/64`
2544    Bswap,
2545    /// `__builtin_{add,sub,mul}_overflow(a, b, &r)`, whose value is the flag.
2546    Overflow(BinOp),
2547    /// The `_p` forms, which only ask whether it *would* overflow.
2548    OverflowP(BinOp),
2549    /// Evaluate the operands and produce nothing: `__builtin_assume` and
2550    /// `__builtin_speculation_safe_value`, which promise something the
2551    /// generated code cannot pass on.
2552    Discard,
2553    /// `__builtin_prefetch(p, rw, locality)`, whose one operand is `p`
2554    /// converted to `const void *`. The payload is the two constants packed
2555    /// into one byte, `locality | rw << 2`, so that [`BuiltinOp`] stays two
2556    /// bytes wide (see [`BuiltinOp::CpuSupports`]); [`prefetch_hint`] takes
2557    /// it apart.
2558    ///
2559    /// On x86 it is `_mm_prefetch` with the locality's hint, on AArch64 a
2560    /// `prfm`, and anywhere else — or in a [safe](Function::is_safe) function,
2561    /// where the call would need `unsafe` — the operand is evaluated and the
2562    /// hint dropped, which is always a correct translation of a hint.
2563    Prefetch(u8),
2564    /// `__builtin_alloca(size)`, whose one operand is the size in bytes,
2565    /// converted to `size_t`.
2566    ///
2567    /// The memory comes out of the arena [`Function::uses_arena`] puts at the
2568    /// top of the function, and no variable length array's end of scope gives
2569    /// it back, so it is freed by the `return` — which is `alloca`'s own
2570    /// lifetime.
2571    Alloca,
2572    /// `__builtin_fabs…`: the sign bit cleared, which is what C's `fabs` is
2573    /// defined as and what makes it exact for a NaN and for a zero.
2574    Fabs,
2575    /// `__builtin_copysign…`: the first operand's magnitude with the second
2576    /// operand's sign bit.
2577    Copysign,
2578    /// One of the quiet comparison macros' builtins, whose value is an `int`.
2579    FloatOrder(FloatOrder),
2580    /// One of the classification builtins, whose value is an `int`.
2581    FloatClass(FloatClass),
2582    /// `__builtin_fpclassify(nan, inf, normal, subnormal, zero, x)`: the one
2583    /// of the first five operands the sixth one's class selects.
2584    Fpclassify,
2585    /// `__builtin_cpu_supports("avx2")`: whether the processor running the
2586    /// program has that instruction set, as an `int`.
2587    ///
2588    /// It becomes `::std::is_x86_feature_detected!("avx2")`, which is the same
2589    /// question asked of the same `cpuid` leaves. The payload is the row of
2590    /// [`crate::x86::TARGET_FEATURES`] the instruction set is in, so that
2591    /// [`BuiltinOp`] stays two bytes wide — it is a field of [`ExprKind`], and
2592    /// every expression in the program pays for whatever the largest variant
2593    /// is. Several Rust features for one GCC name (`abm` is LZCNT and POPCNT)
2594    /// are `&&`ed together; [`crate::x86::detect_features`] is the lookup.
2595    CpuSupports(u8),
2596    /// `__builtin_cproj(z)`: C99 7.3.9.5's projection onto the Riemann sphere.
2597    ///
2598    /// Everything is itself except a value with an infinite part, which becomes
2599    /// `+∞` with the imaginary part's sign kept on a zero — so every infinity
2600    /// is the *one* point at infinity.
2601    ComplexProj,
2602}
2603
2604/// The `float` bit pattern of a NaN that travels through the IR as a `double`.
2605///
2606/// A NaN's payload and its sign are part of its value — `__builtin_nanf
2607/// ("0x123")` asks for one in particular — and [`ExprKind::Float`] carries
2608/// every floating constant as an `f64`, so a `float` NaN is carried as the
2609/// `double` whose sign, quiet bit and payload are the same. Widening with `as`
2610/// would not do: it may quiet a signalling NaN and is free to choose the
2611/// payload. This and [`widen_nan_bits`] are exact inverses.
2612pub fn narrow_nan_bits(bits: u64) -> u32 {
2613    let sign = ((bits >> 63) as u32) << 31;
2614    let payload = ((bits >> 29) & 0x7f_ffff) as u32;
2615    sign | 0x7f80_0000 | payload
2616}
2617
2618/// The `double` bit pattern a `float` NaN is carried as; see
2619/// [`narrow_nan_bits`].
2620pub fn widen_nan_bits(bits: u32) -> u64 {
2621    let sign = u64::from(bits >> 31) << 63;
2622    let payload = u64::from(bits & 0x7f_ffff) << 29;
2623    sign | 0x7ff0_0000_0000_0000 | payload
2624}
2625
2626/// A quiet floating-point comparison: `__builtin_isgreater` and its relatives.
2627///
2628/// "Quiet" is the whole point of them — C99 7.12.14 defines each as the
2629/// comparison it names *without* raising the invalid exception on a NaN, which
2630/// `<` and friends would. Rust's floating comparison operators are the quiet
2631/// ones, so each is written out as the operator it stands for.
2632#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2633pub enum FloatOrder {
2634    /// `__builtin_isgreater`
2635    Greater,
2636    /// `__builtin_isgreaterequal`
2637    GreaterEqual,
2638    /// `__builtin_isless`
2639    Less,
2640    /// `__builtin_islessequal`
2641    LessEqual,
2642    /// `__builtin_islessgreater`: `x < y || x > y`, which is `x != y` without
2643    /// the NaN case.
2644    LessGreater,
2645    /// `__builtin_isunordered`: either operand is a NaN.
2646    Unordered,
2647}
2648
2649/// A floating-point classification: `__builtin_isnan` and its relatives.
2650#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2651pub enum FloatClass {
2652    /// `__builtin_isnan…`
2653    IsNan,
2654    /// `__builtin_isinf…`
2655    IsInf,
2656    /// `__builtin_isinf_sign`, whose value is -1, 0 or 1.
2657    IsInfSign,
2658    /// `__builtin_isfinite`
2659    IsFinite,
2660    /// `__builtin_isnormal`
2661    IsNormal,
2662    /// `__builtin_issignaling`: a NaN whose quiet bit is clear.
2663    IsSignaling,
2664    /// `__builtin_signbit…`, which is 1 for a negative zero too.
2665    SignBit,
2666}
2667
2668// ---------------------------------------------------------------------------
2669// atomics
2670// ---------------------------------------------------------------------------
2671
2672/// A memory order, C11 7.17.3's `memory_order` and Rust's `Ordering`.
2673///
2674/// `memory_order_consume` is not here: no compiler implements dependency
2675/// ordering and Rust has no `Consume`, so it arrives as [`MemOrder::Acquire`]
2676/// — which is what GCC and Clang also emit for it, and what C11 7.17.3p1
2677/// allows an implementation to do.
2678#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2679pub enum MemOrder {
2680    /// `memory_order_relaxed`
2681    Relaxed,
2682    /// `memory_order_acquire` (and `memory_order_consume`).
2683    Acquire,
2684    /// `memory_order_release`
2685    Release,
2686    /// `memory_order_acq_rel`
2687    AcqRel,
2688    /// `memory_order_seq_cst`
2689    SeqCst,
2690}
2691
2692impl MemOrder {
2693    /// The name of the `core::sync::atomic::Ordering` variant.
2694    pub fn rust_name(self) -> &'static str {
2695        match self {
2696            MemOrder::Relaxed => "Relaxed",
2697            MemOrder::Acquire => "Acquire",
2698            MemOrder::Release => "Release",
2699            MemOrder::AcqRel => "AcqRel",
2700            MemOrder::SeqCst => "SeqCst",
2701        }
2702    }
2703
2704    /// The C spelling, for a diagnostic.
2705    pub fn c_name(self) -> &'static str {
2706        match self {
2707            MemOrder::Relaxed => "memory_order_relaxed",
2708            MemOrder::Acquire => "memory_order_acquire",
2709            MemOrder::Release => "memory_order_release",
2710            MemOrder::AcqRel => "memory_order_acq_rel",
2711            MemOrder::SeqCst => "memory_order_seq_cst",
2712        }
2713    }
2714
2715    /// Whether a load may be performed with this order (C11 7.17.7.2p3).
2716    pub fn valid_for_load(self) -> bool {
2717        !matches!(self, MemOrder::Release | MemOrder::AcqRel)
2718    }
2719
2720    /// Whether a store may be performed with this order (C11 7.17.7.1p2).
2721    pub fn valid_for_store(self) -> bool {
2722        !matches!(self, MemOrder::Acquire | MemOrder::AcqRel)
2723    }
2724
2725    /// How strong the order is, for the rule that a compare-exchange's failure
2726    /// order may not be stronger than its success order.
2727    pub fn strength(self) -> u8 {
2728        match self {
2729            MemOrder::Relaxed => 0,
2730            MemOrder::Acquire | MemOrder::Release => 1,
2731            MemOrder::AcqRel => 2,
2732            MemOrder::SeqCst => 3,
2733        }
2734    }
2735
2736    /// The strongest order a failed compare-exchange may use beside this one,
2737    /// which is what `fetch_update` and a nand loop are given.
2738    pub fn failure_order(self) -> MemOrder {
2739        match self {
2740            MemOrder::Release => MemOrder::Relaxed,
2741            MemOrder::AcqRel => MemOrder::Acquire,
2742            other => other,
2743        }
2744    }
2745}
2746
2747/// What kind of Rust atomic an object is reached through.
2748///
2749/// The width comes from the C type's size, so `long` is an `AtomicI64` on an
2750/// LP64 target and an `AtomicI32` on an ILP32 one; the
2751/// [data-model check](crate::codegen) is what makes that assumption safe.
2752#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2753pub enum AtomicClass {
2754    /// `_Bool`, which is `AtomicBool` — a Rust `bool` may only ever hold 0 or
2755    /// 1, so it may not be reached through an integer atomic.
2756    Bool,
2757    /// An integer (or `enum`) of `bytes` bytes: `AtomicI8` … `AtomicU64`.
2758    Int {
2759        /// The width in bytes: 1, 2, 4 or 8.
2760        bytes: u64,
2761        /// Whether the C type is signed.
2762        signed: bool,
2763    },
2764    /// `float` or `double`, reached through the integer atomic of the same
2765    /// width and `to_bits`/`from_bits`.
2766    Float {
2767        /// The width in bytes: 4 or 8.
2768        bytes: u64,
2769    },
2770    /// An object pointer, which is `AtomicPtr`.
2771    Ptr,
2772    /// A *function* pointer, which is also an `AtomicPtr` — but whose C value
2773    /// is an `Option<unsafe extern "C" fn(…)>` in Rust rather than a raw
2774    /// pointer, so the two ends of every operation are a `transmute` instead
2775    /// of a cast.
2776    ///
2777    /// That transmute is sound because an `Option<fn>` is pointer-sized with
2778    /// the null pointer as its `None` niche, which is exactly the
2779    /// representation C gives a function pointer that may be null. Arithmetic
2780    /// is not: C has none on a function pointer, and neither has this.
2781    FnPtr,
2782}
2783
2784impl AtomicClass {
2785    /// The name of the `core::sync::atomic` type.
2786    pub fn rust_name(self) -> &'static str {
2787        match self {
2788            AtomicClass::Bool => "AtomicBool",
2789            AtomicClass::Ptr | AtomicClass::FnPtr => "AtomicPtr",
2790            AtomicClass::Float { bytes } => match bytes {
2791                4 => "AtomicU32",
2792                _ => "AtomicU64",
2793            },
2794            AtomicClass::Int { bytes, signed } => match (bytes, signed) {
2795                (1, true) => "AtomicI8",
2796                (1, false) => "AtomicU8",
2797                (2, true) => "AtomicI16",
2798                (2, false) => "AtomicU16",
2799                (4, true) => "AtomicI32",
2800                (4, false) => "AtomicU32",
2801                (_, true) => "AtomicI64",
2802                (_, false) => "AtomicU64",
2803            },
2804        }
2805    }
2806
2807    /// The Rust primitive the atomic holds, which is what the pointer handed
2808    /// to `from_ptr` points at.
2809    pub fn repr_name(self) -> &'static str {
2810        match self {
2811            AtomicClass::Bool => "bool",
2812            AtomicClass::Ptr | AtomicClass::FnPtr => "",
2813            AtomicClass::Float { bytes } => match bytes {
2814                4 => "u32",
2815                _ => "u64",
2816            },
2817            AtomicClass::Int { bytes, signed } => match (bytes, signed) {
2818                (1, true) => "i8",
2819                (1, false) => "u8",
2820                (2, true) => "i16",
2821                (2, false) => "u16",
2822                (4, true) => "i32",
2823                (4, false) => "u32",
2824                (_, true) => "i64",
2825                (_, false) => "u64",
2826            },
2827        }
2828    }
2829}
2830
2831/// The operation an [`ExprKind::Atomic`] performs.
2832#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2833pub enum AtomicOp {
2834    /// An atomic load, whose value has the object's type.
2835    Load,
2836    /// An atomic store, whose value is `void`.
2837    Store,
2838    /// An atomic exchange, whose value is the old one.
2839    Exchange,
2840    /// A compare-and-exchange whose value is `_Bool`, writing the value it
2841    /// observed back through the `expected` pointer when it fails — C11's
2842    /// `atomic_compare_exchange_strong` and GCC's
2843    /// `__atomic_compare_exchange_n`.
2844    CompareExchange {
2845        /// Whether a spurious failure is allowed (`compare_exchange_weak`).
2846        weak: bool,
2847    },
2848    /// The older `__sync_bool_compare_and_swap` and
2849    /// `__sync_val_compare_and_swap`, whose expected value is a *value* rather
2850    /// than a pointer and which write nothing back.
2851    SyncCompareSwap {
2852        /// Whether the value of the expression is the old one rather than
2853        /// whether the swap happened.
2854        value_is_old: bool,
2855    },
2856    /// A read-modify-write, whose value is the old one for `fetch_op` and the
2857    /// new one for `op_fetch`.
2858    Rmw {
2859        /// The operation.
2860        op: AtomicRmw,
2861        /// Whether the value of the expression is the *new* one.
2862        returns_new: bool,
2863    },
2864    /// `__atomic_test_and_set`: an atomic exchange of "set" into a byte, whose
2865    /// value is what was there before, as a `_Bool`.
2866    TestAndSet,
2867    /// `__atomic_clear`: an atomic store of zero into a byte.
2868    Clear,
2869    /// A fence, which has no operand at all.
2870    Fence {
2871        /// Whether this is a `signal_fence`, which is a compiler fence only.
2872        signal: bool,
2873    },
2874}
2875
2876/// The arithmetic a [`AtomicOp::Rmw`] performs.
2877#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2878pub enum AtomicRmw {
2879    /// `+`
2880    Add,
2881    /// `-`
2882    Sub,
2883    /// `&`
2884    And,
2885    /// `|`
2886    Or,
2887    /// `^`
2888    Xor,
2889    /// `~(a & b)`, which Rust has no `fetch_nand` for on the integers and
2890    /// which is therefore a `fetch_update`.
2891    Nand,
2892}
2893
2894impl AtomicRmw {
2895    /// The `core::sync::atomic` method that performs it, where there is one.
2896    pub fn rust_method(self) -> Option<&'static str> {
2897        Some(match self {
2898            AtomicRmw::Add => "fetch_add",
2899            AtomicRmw::Sub => "fetch_sub",
2900            AtomicRmw::And => "fetch_and",
2901            AtomicRmw::Or => "fetch_or",
2902            AtomicRmw::Xor => "fetch_xor",
2903            AtomicRmw::Nand => return None,
2904        })
2905    }
2906
2907    /// The C operator, for a diagnostic.
2908    pub fn c_op(self) -> &'static str {
2909        match self {
2910            AtomicRmw::Add => "+",
2911            AtomicRmw::Sub => "-",
2912            AtomicRmw::And => "&",
2913            AtomicRmw::Or => "|",
2914            AtomicRmw::Xor => "^",
2915            AtomicRmw::Nand => "~&",
2916        }
2917    }
2918}
2919
2920/// One of the `__atomic_*`, `__sync_*` or `__c11_atomic_*` builtins, resolved.
2921///
2922/// The pointer is the object the operation is performed on; sema has already
2923/// checked that what it points at is one of the types
2924/// [`AtomicClass`] covers, and has resolved the memory orders — which C
2925/// requires to be integer constant expressions here, exactly as `<stdatomic.h>`
2926/// writes them.
2927#[derive(Clone, Debug)]
2928pub struct AtomicExpr {
2929    /// What to do.
2930    pub op: AtomicOp,
2931    /// What kind of atomic to do it through.
2932    pub class: AtomicClass,
2933    /// The C type of the object, with any `_Atomic` already taken off: the
2934    /// type of the value the operation produces or stores.
2935    pub value_ty: Ty,
2936    /// The object's address, absent only for a fence.
2937    pub ptr: Option<Expr>,
2938    /// The value operand — what is stored, exchanged or added.
2939    pub value: Option<Expr>,
2940    /// The expected value of a compare-and-exchange: a *pointer* to it for
2941    /// [`AtomicOp::CompareExchange`], which writes the observed value back
2942    /// through it, and the value itself for [`AtomicOp::SyncCompareSwap`].
2943    pub expected: Option<Expr>,
2944    /// The order of the operation, and of a successful compare-and-exchange.
2945    pub success: MemOrder,
2946    /// The order of a *failed* compare-and-exchange.
2947    pub failure: MemOrder,
2948}
2949
2950impl AtomicExpr {
2951    /// Every expression the node holds, in evaluation order.
2952    pub fn operands(&self) -> impl Iterator<Item = &Expr> {
2953        self.ptr
2954            .iter()
2955            .chain(self.expected.iter())
2956            .chain(self.value.iter())
2957    }
2958}
2959
2960/// Which Rust atomic a C object type is reached through, if any is.
2961///
2962/// The width comes from the target model, which the [data-model
2963/// check](crate::codegen) makes safe to rely on. `None` means there is no
2964/// atomic of that width or shape: a 128-bit integer, an aggregate.
2965pub fn atomic_class(types: &Types, ty: Ty, target: &TargetModel) -> Option<AtomicClass> {
2966    let ty = types.unatomic(ty);
2967    if ty == Ty::Bool {
2968        return Some(AtomicClass::Bool);
2969    }
2970    if ty.is_integer() {
2971        let bytes = ty.size_bytes(target);
2972        return matches!(bytes, 1 | 2 | 4 | 8).then_some(AtomicClass::Int {
2973            bytes,
2974            signed: ty.is_signed(target),
2975        });
2976    }
2977    if ty.is_floating() {
2978        let bytes = ty.size_bytes(target);
2979        return matches!(bytes, 4 | 8).then_some(AtomicClass::Float { bytes });
2980    }
2981    if ty.is_pointer() {
2982        return Some(if types.is_func_pointer(ty) {
2983            AtomicClass::FnPtr
2984        } else {
2985            AtomicClass::Ptr
2986        });
2987    }
2988    None
2989}
2990
2991/// An assignable location.
2992#[derive(Clone, Debug)]
2993pub struct Place {
2994    /// What is being addressed.
2995    pub kind: PlaceKind,
2996    /// The type of the object addressed.
2997    pub ty: Ty,
2998    /// Whether the object is `const`-qualified, and therefore not assignable.
2999    pub is_const: bool,
3000    /// Where it was written.
3001    pub range: SourceRange,
3002}
3003
3004/// The shape of a [`Place`].
3005#[derive(Clone, Debug)]
3006pub enum PlaceKind {
3007    /// A named object.
3008    Object(ObjectId),
3009    /// `*ptr`, where `ptr` has pointer type.
3010    Deref(Box<Expr>),
3011    /// `base[index]`, where `base` has pointer type: the same thing as
3012    /// `*(base + index)`, which is what C says it is.
3013    Index {
3014        /// The pointer the subscript is relative to.
3015        base: Box<Expr>,
3016        /// The subscript, of integer type.
3017        index: Box<Expr>,
3018    },
3019    /// `base.field`, where `field` indexes the record's member list. `p->f`
3020    /// arrives as a `Field` over a `Deref`.
3021    Field {
3022        /// The record the member belongs to.
3023        base: Box<Place>,
3024        /// The record's identity.
3025        record: RecordId,
3026        /// The index of the member in the record's field list.
3027        index: usize,
3028    },
3029    /// `__real__ z` or `__imag__ z`: one part of a complex object, which GNU C
3030    /// makes an lvalue whenever `z` is one, so `__imag__ z = 1.0;` assigns.
3031    ///
3032    /// The type of the place is the [corresponding real
3033    /// type](Ty::complex_component); `base` is the complex object, which may be
3034    /// a [`PlaceKind::Temporary`] when the operand was an rvalue.
3035    ComplexPart {
3036        /// The complex object the part belongs to.
3037        base: Box<Place>,
3038        /// Whether this is `__imag__` rather than `__real__`.
3039        imag: bool,
3040    },
3041    /// A string literal, whose type is an array of `char` (or of `wchar_t`).
3042    Str(StrId),
3043    /// A temporary holding the value of an expression, which is what makes
3044    /// `f().field` work for a `struct` returned by value.
3045    Temporary(Box<Expr>),
3046    /// The object a block-scope compound literal (`(T){ … }`, C99 6.5.2.5)
3047    /// denotes.
3048    ///
3049    /// Unlike a [`PlaceKind::Temporary`] it is a real object with automatic
3050    /// storage duration and the lifetime of the *enclosing block*, so its
3051    /// address may be taken and used for the rest of that block. `object` is a
3052    /// hidden local sema declares at the top of that block, zero-initialised;
3053    /// `init` is the value the literal was written with, and is evaluated
3054    /// *here* — where the literal stands — so that C's evaluation order
3055    /// survives and a literal inside a loop is built afresh on every
3056    /// iteration. A compound literal at *file* scope is an ordinary
3057    /// [`Storage::Static`] object instead and arrives as a
3058    /// [`PlaceKind::Object`].
3059    CompoundLiteral {
3060        /// The hidden local the object lives in.
3061        object: ObjectId,
3062        /// The value stored into it where the literal was written.
3063        init: Box<Expr>,
3064    },
3065}
3066
3067/// A typed expression.
3068#[derive(Clone, Debug)]
3069pub struct Expr {
3070    /// What the expression computes.
3071    pub kind: ExprKind,
3072    /// The type of its value.
3073    pub ty: Ty,
3074    /// The number of bits the value is reduced to, when that is narrower than
3075    /// [`Expr::ty`].
3076    ///
3077    /// A bit-field wider than `int` keeps its declared type through the
3078    /// integer promotions (6.3.1.1p2 has nothing to say about it), but its
3079    /// *value* still ranges over the declared width only, and C99 6.7.2.1p10
3080    /// makes that width the type the arithmetic happens in: `unsigned long
3081    /// long b : 40` multiplies, adds and shifts in forty bits, exactly as an
3082    /// `unsigned int` does in thirty-two. Nothing else in the type model can
3083    /// say that, so the width rides along on the expression and code
3084    /// generation reduces the result to it.
3085    pub bits: Option<u32>,
3086    /// Where it was written.
3087    pub range: SourceRange,
3088}
3089
3090impl Expr {
3091    /// Builds an expression.
3092    pub fn new(kind: ExprKind, ty: Ty, range: SourceRange) -> Self {
3093        Self {
3094            kind,
3095            ty,
3096            bits: None,
3097            range,
3098        }
3099    }
3100
3101    /// The same expression, computed in `bits` bits; see [`Expr::bits`].
3102    pub fn narrowed(mut self, bits: Option<u32>) -> Self {
3103        self.bits = bits;
3104        self
3105    }
3106
3107    /// An integer constant of type `ty`.
3108    pub fn int(value: i128, ty: Ty, range: SourceRange) -> Self {
3109        Self::new(ExprKind::Int(value), ty, range)
3110    }
3111}
3112
3113/// The class of one *eightbyte* of a `struct` or `union` read out of an
3114/// argument list, under the x86-64 System V classification (AMD64 psABI
3115/// 3.2.3).
3116///
3117/// [`crate::sema`] computes it and code generation turns each entry into one
3118/// `next_arg` call. There is deliberately no `SseUp`: the reference
3119/// implementation this mirrors — `rustc_target`'s
3120/// `compiler/rustc_target/src/callconv/x86_64.rs` — needs that class for SIMD
3121/// vectors and for the floating types wider than eight bytes, and a C program
3122/// this crate translates has neither, `long double` being mapped to `double`.
3123#[derive(Clone, Copy, PartialEq, Eq, Debug)]
3124pub enum Eightbyte {
3125    /// An integer register: read as a `u64`.
3126    Int,
3127    /// An SSE register: read as an `f64`, whose bits are the eightbyte.
3128    Sse,
3129    /// Nothing of the object reaches this eightbyte — it is padding, which the
3130    /// ABI passes in no register at all, so nothing is read for it.
3131    None,
3132}
3133
3134/// Who is being called.
3135#[derive(Clone, Debug)]
3136pub enum Callee {
3137    /// A named function.
3138    Direct(FuncId),
3139    /// An expression of function-pointer type.
3140    Indirect(Box<Expr>),
3141}
3142
3143/// The shape of an [`Expr`].
3144#[derive(Clone, Debug)]
3145pub enum ExprKind {
3146    /// An integer constant, already reduced to the range of its type.
3147    Int(i128),
3148    /// A floating constant.
3149    Float(f64),
3150    /// A complex value built from its two parts, which have the
3151    /// [corresponding real type](Ty::complex_component).
3152    ///
3153    /// It is what `__builtin_complex(x, y)` — and therefore `CMPLX` — makes,
3154    /// what an imaginary constant such as `2.0i` is, and what a folded complex
3155    /// constant comes back as.
3156    ComplexOf {
3157        /// The real part.
3158        re: Box<Expr>,
3159        /// The imaginary part.
3160        im: Box<Expr>,
3161    },
3162    /// The all-bits-zero value of the expression's type: `0`, `0.0`, `false`,
3163    /// a null pointer, or a zeroed aggregate.
3164    Zeroed,
3165    /// Reading a place.
3166    Load(Place),
3167    /// The address of a place. The expression's type says what pointer type is
3168    /// wanted, which is what turns an array place into a pointer to its first
3169    /// element.
3170    AddrOf(Place),
3171    /// The address of a function, whose type is a pointer to it.
3172    FuncAddr(FuncId),
3173    /// GNU's `&&label`: the address of a label of the enclosing function, of
3174    /// type `void *`.
3175    ///
3176    /// A function that takes one is lowered through a [control-flow
3177    /// graph](crate::cfg), and the value is the label's *number* among the
3178    /// function's labels whose address is taken, from 1, cast to a pointer —
3179    /// which is what `goto *e`'s `switch` matches on. It is an *address constant*,
3180    /// so a `static void *table[] = { &&a, &&b };` holds a table of them.
3181    LabelAddr(LabelId),
3182    /// `place = value`, whose value is the value stored.
3183    Assign {
3184        /// The assigned-to location.
3185        place: Place,
3186        /// The value, already converted to the place's type.
3187        value: Box<Expr>,
3188    },
3189    /// `place op= value`, whose value is the value stored.
3190    ///
3191    /// For a pointer place `compute` is the pointer type and `value` keeps its
3192    /// integer type: `p += n` is pointer arithmetic, not an addition.
3193    CompoundAssign {
3194        /// The assigned-to location, evaluated exactly once.
3195        place: Place,
3196        /// The operator.
3197        op: BinOp,
3198        /// The right operand, already converted for `compute`.
3199        value: Box<Expr>,
3200        /// The type the operation is carried out in, before the result is
3201        /// converted back to the place's type.
3202        compute: Ty,
3203    },
3204    /// `++place`, `place++`, `--place` or `place--`.
3205    IncDec {
3206        /// The affected location.
3207        place: Place,
3208        /// Whether this decrements.
3209        dec: bool,
3210        /// Whether the value is the one from before the update.
3211        postfix: bool,
3212    },
3213    /// Arithmetic negation, on an already promoted operand.
3214    Neg(Box<Expr>),
3215    /// `~x`, on an already promoted operand.
3216    BitNot(Box<Expr>),
3217    /// A binary operation. Both operands already have the result type, except
3218    /// for shifts, whose operands are promoted separately.
3219    Binary {
3220        /// The operator.
3221        op: BinOp,
3222        /// Left operand.
3223        lhs: Box<Expr>,
3224        /// Right operand.
3225        rhs: Box<Expr>,
3226    },
3227    /// `ptr + index` or `ptr - index`: pointer arithmetic in units of the
3228    /// pointee, which is what `<*mut T>::offset` does.
3229    PtrOffset {
3230        /// The pointer, which is also the type of the result.
3231        ptr: Box<Expr>,
3232        /// The offset, of integer type.
3233        index: Box<Expr>,
3234        /// Whether the offset is subtracted.
3235        sub: bool,
3236    },
3237    /// `lhs - rhs` between two pointers, whose value has type `ptrdiff_t`.
3238    PtrDiff {
3239        /// Left operand.
3240        lhs: Box<Expr>,
3241        /// Right operand.
3242        rhs: Box<Expr>,
3243    },
3244    /// A comparison. Both operands already have a common type; the result has
3245    /// type `int` and is 0 or 1.
3246    Compare {
3247        /// The operator.
3248        op: CmpOp,
3249        /// Left operand.
3250        lhs: Box<Expr>,
3251        /// Right operand.
3252        rhs: Box<Expr>,
3253    },
3254    /// `&&` or `||`: each operand is tested against zero, the right one only if
3255    /// the left does not already decide the result. The result has type `int`
3256    /// and is 0 or 1.
3257    Logical {
3258        /// The operator.
3259        op: LogicalOp,
3260        /// Left operand.
3261        lhs: Box<Expr>,
3262        /// Right operand.
3263        rhs: Box<Expr>,
3264    },
3265    /// A conversion to the expression's own type.
3266    Cast(Box<Expr>),
3267    /// `cond ? then_expr : else_expr`, with both arms already converted to the
3268    /// expression's type.
3269    Cond {
3270        /// The controlling expression.
3271        cond: Box<Expr>,
3272        /// The value when the condition is true.
3273        then_expr: Box<Expr>,
3274        /// The value otherwise.
3275        else_expr: Box<Expr>,
3276    },
3277    /// GNU's `a ?: b`: `a` if it is non-zero and `b` otherwise, with `a`
3278    /// evaluated exactly once. Both operands already have the result type.
3279    CondDefault {
3280        /// The value that is both the condition and the first result.
3281        value: Box<Expr>,
3282        /// The value when it is zero.
3283        else_expr: Box<Expr>,
3284    },
3285    /// GNU's statement expression, `({ …; e; })`.
3286    StmtExpr {
3287        /// The statements, in order.
3288        stmts: Vec<Stmt>,
3289        /// The value of the last expression statement, if there was one.
3290        value: Option<Box<Expr>>,
3291    },
3292    /// A builtin lowered to a fixed piece of Rust; see [`BuiltinOp`].
3293    Builtin {
3294        /// Which builtin.
3295        op: BuiltinOp,
3296        /// Its operands, already converted.
3297        args: Vec<Expr>,
3298    },
3299    /// One of the atomic builtins; see [`AtomicExpr`].
3300    ///
3301    /// Boxed because it is much the largest thing an expression can hold and
3302    /// every other node would grow to its size.
3303    Atomic(Box<AtomicExpr>),
3304    /// `lhs, rhs`: `lhs` is evaluated for its side effects only.
3305    Comma {
3306        /// Evaluated and discarded.
3307        lhs: Box<Expr>,
3308        /// The result.
3309        rhs: Box<Expr>,
3310    },
3311    /// A call, with every argument already converted to its parameter's type
3312    /// (or promoted, for the variable part of a variadic call).
3313    Call {
3314        /// What is called.
3315        callee: Callee,
3316        /// The arguments.
3317        args: Vec<Expr>,
3318    },
3319    /// A `struct` value: one expression per member, in declaration order.
3320    RecordLit {
3321        /// The record's identity.
3322        record: RecordId,
3323        /// The member values.
3324        fields: Vec<Expr>,
3325    },
3326    /// A `union` value, which initialises exactly one member.
3327    UnionLit {
3328        /// The record's identity.
3329        record: RecordId,
3330        /// The index of the initialised member.
3331        index: usize,
3332        /// Its value.
3333        value: Box<Expr>,
3334    },
3335    /// An array value: one expression per element.
3336    ArrayLit(Vec<Expr>),
3337    /// An array value whose elements are all the same: `[value; len]`.
3338    ArrayRepeat {
3339        /// The repeated element.
3340        value: Box<Expr>,
3341        /// How many times it is repeated.
3342        len: u64,
3343    },
3344    /// A fresh copy of the argument list the function was called with.
3345    ///
3346    /// It is what `va_start` stores and what a `va_list` local starts out as;
3347    /// the list it copies is the `...` parameter of a variadic definition, or
3348    /// the function's own `va_list` parameter. Its type is [`Ty::VaList`].
3349    VaListPristine,
3350    /// `va_arg(ap, T)`: reads the next argument and advances `ap`. The
3351    /// expression's own type is `T`.
3352    VaArg {
3353        /// The list to read from and advance.
3354        ap: Place,
3355        /// How a `struct` or `union` is taken apart to be read: one entry per
3356        /// [eightbyte](Eightbyte) of it, in order. `None` for every other
3357        /// type, which is read in one `next_arg` at the type itself.
3358        record: Option<Vec<Eightbyte>>,
3359    },
3360    /// C23's `unreachable()`, which promises control never gets here.
3361    Unreachable,
3362    /// `va_end(ap)`, whose type is `void`.
3363    ///
3364    /// Rust ends a list when it goes out of scope, so this does nothing; it is
3365    /// a node of its own so that the expansion does not have to pretend the
3366    /// call happened.
3367    VaEnd,
3368}
3369
3370// ---------------------------------------------------------------------------
3371// statements
3372// ---------------------------------------------------------------------------
3373
3374/// What a `break` leaves.
3375#[derive(Clone, Copy, PartialEq, Eq, Debug)]
3376pub enum BreakTarget {
3377    /// The innermost enclosing loop.
3378    Loop(LoopId),
3379    /// The innermost enclosing `switch`.
3380    Switch(SwitchId),
3381}
3382
3383/// A typed statement.
3384#[derive(Clone, Debug)]
3385pub enum Stmt {
3386    /// The null statement.
3387    Nop,
3388    /// An expression evaluated for its side effects.
3389    Expr(Expr),
3390    /// A local variable definition. C leaves an uninitialised local
3391    /// indeterminate; the initialiser here is a zero of the right type in that
3392    /// case, so that the generated Rust never reads uninitialised memory.
3393    Let {
3394        /// The object being defined.
3395        object: ObjectId,
3396        /// Its initial value, already converted to the object's type.
3397        init: Expr,
3398        /// Whether the source wrote an initialiser at all.
3399        ///
3400        /// It decides what happens when the definition has to be hoisted out
3401        /// of the block it was written in — out of a `switch` body, or to the
3402        /// top of a function lowered into a [control-flow graph](crate::cfg).
3403        /// The hoisted definition zero-initialises; only an initialiser the
3404        /// program actually wrote has to run again where it was written.
3405        explicit: bool,
3406    },
3407    /// The definition of a variable length array (C99 6.7.5.2).
3408    ///
3409    /// It is a [`Stmt::Let`] with two bindings instead of one, because the
3410    /// object needs storage whose size is only known here; see [`VlaDef`].
3411    Vla(Box<VlaDef>),
3412    /// `T x __attribute__((cleanup(f)));` — the registration of the call that
3413    /// runs when `x` goes out of scope. See [`CleanupDef`].
3414    Cleanup(Box<CleanupDef>),
3415    /// A compound statement.
3416    Block(Vec<Stmt>),
3417    /// `if (cond) then_branch else else_branch`
3418    If {
3419        /// The controlling expression.
3420        cond: Expr,
3421        /// Taken when `cond` is non-zero.
3422        then_branch: Box<Stmt>,
3423        /// Taken otherwise.
3424        else_branch: Option<Box<Stmt>>,
3425    },
3426    /// `while (cond) body`
3427    While {
3428        /// This loop's identity.
3429        id: LoopId,
3430        /// The controlling expression.
3431        cond: Expr,
3432        /// The loop body.
3433        body: Box<Stmt>,
3434        /// Where the statement was written.
3435        range: SourceRange,
3436    },
3437    /// `do body while (cond);`
3438    DoWhile {
3439        /// This loop's identity.
3440        id: LoopId,
3441        /// The loop body.
3442        body: Box<Stmt>,
3443        /// The controlling expression.
3444        cond: Expr,
3445        /// Where the statement was written.
3446        range: SourceRange,
3447    },
3448    /// `for (init; cond; step) body`
3449    For {
3450        /// This loop's identity.
3451        id: LoopId,
3452        /// The init clause, which may declare variables scoped to the loop.
3453        init: Vec<Stmt>,
3454        /// The controlling expression; absent means "always true".
3455        cond: Option<Expr>,
3456        /// The iteration expression.
3457        step: Option<Expr>,
3458        /// The loop body.
3459        body: Box<Stmt>,
3460        /// Where the statement was written.
3461        range: SourceRange,
3462    },
3463    /// `switch (scrutinee) { … }`
3464    Switch(Box<Switch>),
3465    /// `switch (scrutinee) body`, with the body left as a statement tree.
3466    ///
3467    /// Only produced in [CFG mode](crate::cfg), where the labels stay where
3468    /// they were written — a `case` inside a nested statement (Duff's device)
3469    /// is simply another edge into the loop the CFG builds.
3470    SwitchTree(Box<SwitchTree>),
3471    /// `case value:` or `default:` inside a [`Stmt::SwitchTree`].
3472    Case {
3473        /// The `switch` the label belongs to.
3474        switch: SwitchId,
3475        /// The values that enter here, or `None` for `default:`.
3476        value: Option<CaseRange>,
3477        /// The labelled statement.
3478        body: Box<Stmt>,
3479        /// Where the label was written.
3480        range: SourceRange,
3481    },
3482    /// `label: body` — a `goto` target.
3483    Label {
3484        /// The label's identity.
3485        id: LabelId,
3486        /// The labelled statement.
3487        body: Box<Stmt>,
3488        /// Where the label was written.
3489        range: SourceRange,
3490    },
3491    /// A labelled region a `goto` leaves, in the structured lowering.
3492    ///
3493    /// Only produced by [`regions`](crate::regions), which is where the shape
3494    /// and the two kinds are described. A [`Stmt::Goto`] inside one names its
3495    /// label and becomes `break` or `continue` accordingly.
3496    Region(Box<Region>),
3497    /// `goto label;`
3498    Goto {
3499        /// The label jumped to.
3500        id: LabelId,
3501        /// Where the statement was written.
3502        range: SourceRange,
3503    },
3504    /// GNU's computed `goto *e;`, whose operand is a [label
3505    /// address](ExprKind::LabelAddr).
3506    ///
3507    /// Only produced in [CFG mode](crate::cfg), which is the only mode a
3508    /// function containing one is lowered in.
3509    GotoPtr {
3510        /// The pointer jumped through.
3511        target: Expr,
3512        /// Where the statement was written.
3513        range: SourceRange,
3514    },
3515    /// `break;`
3516    Break {
3517        /// What the `break` leaves.
3518        target: BreakTarget,
3519        /// Where the statement was written.
3520        range: SourceRange,
3521    },
3522    /// `continue;`
3523    Continue {
3524        /// The loop the `continue` restarts.
3525        id: LoopId,
3526        /// Where the statement was written.
3527        range: SourceRange,
3528    },
3529    /// `return;` or `return expr;`
3530    Return {
3531        /// The returned value.
3532        value: Option<Expr>,
3533        /// Where the statement was written.
3534        range: SourceRange,
3535    },
3536    /// GNU inline assembly, mapped onto `core::arch::asm!`; see [`AsmStmt`].
3537    ///
3538    /// It has no control flow of its own (`asm goto` is refused), so the
3539    /// [control-flow graph](crate::cfg) carries it as a simple statement.
3540    Asm(Box<AsmStmt>),
3541}
3542
3543/// An inline assembly statement, already in `asm!`'s terms.
3544///
3545/// Sema has done all the mapping (see `sema/asm.rs`): the template is Rust's
3546/// — `%0` is `{o0}`, `%%` is `%`, braces are doubled — and each operand says
3547/// which register and which direction. What is left for code generation is
3548/// evaluating the operands and storing the outputs back.
3549#[derive(Clone, Debug)]
3550pub struct AsmStmt {
3551    /// The template in `asm!`'s syntax, still AT&T assembly: code generation
3552    /// always adds `options(att_syntax)`.
3553    pub template: String,
3554    /// The operands, in GCC's order (outputs, then inputs), with each tied
3555    /// input folded into the output it is tied to.
3556    pub operands: Vec<AsmOperand>,
3557    /// The registers the statement clobbers, in `asm!`'s spelling (`rax`,
3558    /// `xmm0`), each of which becomes `out("rax") _`. `"memory"` and `"cc"`
3559    /// are not here: they are what `asm!` assumes without being told.
3560    pub clobbers: Vec<&'static str>,
3561    /// Where the statement was written.
3562    pub range: SourceRange,
3563}
3564
3565/// One operand of an [`AsmStmt`].
3566#[derive(Clone, Debug)]
3567pub struct AsmOperand {
3568    /// The `asm!` name the template refers to it by — `o` and the GCC
3569    /// operand number — or `None` for an explicit register, which `asm!`
3570    /// does not let a template name (sema writes the register itself).
3571    pub name: Option<String>,
3572    /// Where the value lives.
3573    pub reg: AsmReg,
3574    /// The direction, and the C side of it.
3575    pub kind: AsmOperandKind,
3576    /// The C type of the value, which is what the `asm!` operand has.
3577    pub ty: Ty,
3578    /// Where the operand was written.
3579    pub range: SourceRange,
3580}
3581
3582impl AsmOperand {
3583    /// The head of the `asm!` operand, up to the expression: `o0 =
3584    /// lateout(reg)`, `inout("eax")`, `o2 = const`.
3585    pub fn head(&self) -> String {
3586        let dir = match &self.kind {
3587            AsmOperandKind::In(_) => "in",
3588            AsmOperandKind::Out { late: true, .. } => "lateout",
3589            AsmOperandKind::Out { late: false, .. } => "out",
3590            AsmOperandKind::InOut { .. } | AsmOperandKind::Scratch(_) => "inout",
3591            AsmOperandKind::Const(_) => "const",
3592        };
3593        let reg = match (&self.kind, self.reg) {
3594            (AsmOperandKind::Const(_), _) => String::new(),
3595            (_, AsmReg::Class(class)) => format!("({class})"),
3596            (_, AsmReg::Explicit(name)) => format!("(\"{name}\")"),
3597        };
3598        match &self.name {
3599            Some(name) => format!("{name} = {dir}{reg}"),
3600            None => format!("{dir}{reg}"),
3601        }
3602    }
3603}
3604
3605/// Where an [`AsmOperand`] lives.
3606#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3607pub enum AsmReg {
3608    /// A register `asm!` allocates from a class: `reg`, `reg_byte`,
3609    /// `reg_abcd`, `xmm_reg`, `ymm_reg`, `zmm_reg`.
3610    Class(&'static str),
3611    /// One register, spelled at the operand's width: `al`, `ecx`, `rdx`.
3612    Explicit(&'static str),
3613}
3614
3615/// The direction of an [`AsmOperand`].
3616#[derive(Clone, Debug)]
3617pub enum AsmOperandKind {
3618    /// An input: the value is computed before the statement.
3619    In(Expr),
3620    /// An output, stored into `place` afterwards. `late` is `lateout` — GCC's
3621    /// plain `=`, written only after every input has been read — and its
3622    /// absence is `out`, GCC's early clobber `=&`.
3623    Out {
3624        /// Where the value goes.
3625        place: Place,
3626        /// Whether the register may share one with an input.
3627        late: bool,
3628    },
3629    /// An operand that is read and written: GCC's `+`, or an output with an
3630    /// input tied to it by a digit constraint (`"=r"(x) : "0"(y)`).
3631    InOut {
3632        /// The tied input's value, already converted to the output's type;
3633        /// `None` for `+`, where the input is whatever `output` holds.
3634        input: Option<Expr>,
3635        /// Where the value goes.
3636        output: Place,
3637    },
3638    /// An input whose register the statement overwrites, so the value it
3639    /// leaves there is thrown away: `inout(reg) value => _`. This is an
3640    /// input with the constraint `"b"`, carried through a scratch register
3641    /// that the `xchg` around the template swaps with rbx (see `sema/asm.rs`).
3642    Scratch(Expr),
3643    /// An immediate, folded: `"i"(3)` is `const 3`.
3644    Const(i128),
3645}
3646
3647impl Stmt {
3648    /// Whether this is a [`cleanup`](CleanupDef) registration.
3649    pub fn is_cleanup(&self) -> bool {
3650        matches!(self, Stmt::Cleanup(_))
3651    }
3652}
3653
3654/// A variably modified object's definition: `T a[n];`, `T a[n][m];`.
3655///
3656/// C99 6.7.5.2 gives the object automatic storage duration, a size fixed when
3657/// the declaration is reached, and the lifetime of the block it is written in;
3658/// each bound is evaluated exactly once, where the declaration stands, and
3659/// lives in a hidden `size_t` object the [type](ArrayType::vla_len) points at.
3660/// This crate emulates the storage with a per-function bump arena on the heap
3661/// — the elements are bumped off it, and a hidden frame guard whose `Drop`
3662/// moves the arena back down is that lifetime — so the one definition becomes
3663/// a [`Stmt::Let`] per bound followed by two more bindings:
3664///
3665/// ```text
3666/// let __cinrs_vla_len_a: size_t = <n>;                     // one per bound
3667/// let __cinrs_vla_frame_a = __cinrs_vla.frame();          // frame
3668/// let mut a: *mut T = __cinrs_vla.alloc::<T>(count);       // object
3669/// ```
3670///
3671/// From there the object *is* a pointer to the first element: decay is the
3672/// identity, `a[i]` is pointer indexing scaled by the run-time size of a row,
3673/// and `sizeof a` is the product of the bounds times the element size — see
3674/// [`Types::vm_step_ty`] for what "element" means once more than one dimension
3675/// is variable.
3676#[derive(Clone, Debug)]
3677pub struct VlaDef {
3678    /// The object the C program declared, whose type is the array type and
3679    /// whose generated binding is a pointer to the first element.
3680    pub object: ObjectId,
3681    /// The hidden frame that gives the elements back; see
3682    /// [`Object::vla_storage`].
3683    pub storage: ObjectId,
3684    /// The number of elements to allocate: the product of every dimension,
3685    /// read out of the hidden bound objects, in units of the storage's
3686    /// element type.
3687    pub count: Expr,
3688    /// The alignment `_Alignas(N)` or `__attribute__((aligned(N)))` asked
3689    /// for, when it is stricter than the element type's: the arena then pads
3690    /// its position to the first address that is a multiple of it.
3691    pub align: Option<u64>,
3692    /// Where the declarator was written.
3693    pub range: SourceRange,
3694}
3695
3696/// A `cleanup` attribute's registration: `T x __attribute__((cleanup(f)));`.
3697///
3698/// GCC calls `f(&x)` on *every* exit from the scope `x` was declared in, in
3699/// reverse declaration order. The two lowerings say that in different ways:
3700///
3701/// * the structured one binds a drop guard right after the object, so that
3702///   Rust's own drop order — reverse declaration order, on every path out of
3703///   the block, `return` from inside a statement expression included — is C's;
3704/// * the [CFG](crate::cfg) one has no scopes left to drop in, so it emits
3705///   [`CleanupDef::call`] on each edge that leaves the scope.
3706#[derive(Clone, Debug)]
3707pub struct CleanupDef {
3708    /// The variable whose address the function is given.
3709    pub object: ObjectId,
3710    /// The function called with it.
3711    pub func: FuncId,
3712    /// The type of that function's one parameter, which is the pointer type
3713    /// the address is converted to.
3714    pub param: Ty,
3715    /// `f(&x)`, ready to be emitted where a scope is left.
3716    pub call: Expr,
3717    /// Where the declarator was written.
3718    pub range: SourceRange,
3719}
3720
3721/// A `switch` statement, flattened into the groups its labels delimit.
3722///
3723/// The body of a `switch` is a single statement that execution *jumps into*,
3724/// which is why it cannot be a tree here: the labels split it into a sequence
3725/// of groups that fall through into one another. See [`codegen`](crate::codegen)
3726/// for how the sequence becomes Rust.
3727#[derive(Clone, Debug)]
3728pub struct Switch {
3729    /// This switch's identity.
3730    pub id: SwitchId,
3731    /// The controlling expression, after the integer promotions.
3732    pub scrutinee: Expr,
3733    /// Objects declared directly in the switch body.
3734    ///
3735    /// C keeps them alive for the whole body even though execution may jump
3736    /// past their declaration, so they are defined ahead of the dispatch and
3737    /// zero-initialised; whatever initialiser the source wrote stays where it
3738    /// was written, as an assignment.
3739    pub hoisted: Vec<ObjectId>,
3740    /// Statements between the `{` and the first label. C can never reach them.
3741    pub prelude: Vec<Stmt>,
3742    /// The groups, in source order.
3743    pub groups: Vec<SwitchGroup>,
3744    /// The index in `groups` that `default:` labels, if any.
3745    pub default_group: Option<usize>,
3746    /// Where the statement was written.
3747    pub range: SourceRange,
3748}
3749
3750/// A labelled region a `goto` leaves or restarts.
3751///
3752/// The statements a C label divides are wrapped in one of these when every
3753/// `goto` to that label is a jump Rust can make on its own; see
3754/// [`regions`](crate::regions) for which jumps those are and how the
3755/// boundaries are chosen. Code generation emits a labelled block or a labelled
3756/// loop, named after the C label:
3757///
3758/// ```text
3759/// 'done: { … break 'done; … }        'retry: loop { … continue 'retry; … break 'retry; }
3760/// ```
3761#[derive(Clone, Debug)]
3762pub struct Region {
3763    /// The label the region belongs to, which the `goto`s inside it name.
3764    pub label: LabelId,
3765    /// The label's name in C, which the generated Rust label is built from.
3766    pub name: String,
3767    /// Whether a `goto` to it leaves the region or restarts it.
3768    pub kind: RegionKind,
3769    /// The statements inside.
3770    pub body: Vec<Stmt>,
3771    /// Whether control can reach the end of `body`, so that a
3772    /// [loop](RegionKind::Loop) needs a `break` there to leave it. A loop
3773    /// without one is a Rust `loop` that never finishes, which is what makes a
3774    /// function ending in it need no `return`.
3775    pub falls_out: bool,
3776    /// Where the label was written.
3777    pub range: SourceRange,
3778}
3779
3780/// Which way a [`Region`]'s label is entered.
3781#[derive(Clone, Copy, PartialEq, Eq, Debug)]
3782pub enum RegionKind {
3783    /// The label stands *after* the region: a `goto` to it is `break 'l`, and
3784    /// the statements the label introduces follow the block.
3785    Block,
3786    /// The label stands at the *start* of the region: a `goto` to it is
3787    /// `continue 'l`, and control leaves by falling off the end.
3788    Loop,
3789}
3790
3791/// A `switch` whose body has been left as a statement tree.
3792///
3793/// The [CFG lowering](crate::cfg) walks the tree and turns every [`Stmt::Case`]
3794/// it finds into an edge from this statement's dispatch, wherever in the tree
3795/// it sits. That is what makes Duff's device work, and it is why sema does not
3796/// need to flatten the body into groups in that mode.
3797#[derive(Clone, Debug)]
3798pub struct SwitchTree {
3799    /// This switch's identity, which `break` and the labels refer to.
3800    pub id: SwitchId,
3801    /// The controlling expression, after the integer promotions.
3802    pub scrutinee: Expr,
3803    /// The body, with its labels still in place.
3804    pub body: Box<Stmt>,
3805    /// Where the statement was written.
3806    pub range: SourceRange,
3807}
3808
3809/// The values one `case` label matches.
3810///
3811/// A plain `case k:` is the range `k..=k`; GNU's `case low ... high:` is the
3812/// whole interval, which code generation emits as one Rust range pattern
3813/// rather than as one arm per value — `case 0 ... 1000000:` is a perfectly
3814/// ordinary thing to write.
3815#[derive(Clone, Copy, PartialEq, Eq, Debug)]
3816pub struct CaseRange {
3817    /// The lowest value, already converted to the controlling type.
3818    pub low: i128,
3819    /// The highest, which equals `low` for a plain label.
3820    pub high: i128,
3821}
3822
3823impl CaseRange {
3824    /// The range one value makes.
3825    pub fn single(value: i128) -> Self {
3826        Self {
3827            low: value,
3828            high: value,
3829        }
3830    }
3831
3832    /// Whether this is a plain `case k:`.
3833    pub fn is_single(self) -> bool {
3834        self.low == self.high
3835    }
3836
3837    /// Whether two labels would both match some value.
3838    pub fn overlaps(self, other: CaseRange) -> bool {
3839        self.low <= other.high && other.low <= self.high
3840    }
3841}
3842
3843/// One run of statements in a `switch`, together with the values that enter it.
3844#[derive(Clone, Debug)]
3845pub struct SwitchGroup {
3846    /// The `case` values that jump here, already converted to the type of the
3847    /// controlling expression.
3848    pub values: Vec<CaseRange>,
3849    /// The statements, which fall through into the next group.
3850    pub body: Vec<Stmt>,
3851}
3852
3853// ---------------------------------------------------------------------------
3854// reachability
3855// ---------------------------------------------------------------------------
3856
3857/// Whether control can never fall off the end of `stmts`.
3858///
3859/// Used to decide whether a non-`void` function needs a synthesised
3860/// `return`. Deliberately conservative: saying "no" only ever costs a
3861/// `return` statement the program does not reach, while saying "yes" wrongly
3862/// would produce Rust that does not compile.
3863///
3864/// `functions` is the program's function table, which is what a call to a
3865/// `_Noreturn` function is recognised through; code generation makes that
3866/// divergence visible to Rust by following such a call with
3867/// `::core::unreachable!()`.
3868pub fn always_terminates(stmts: &[Stmt], functions: &[Function]) -> bool {
3869    stmts
3870        .last()
3871        .is_some_and(|stmt| stmt_always_terminates(stmt, functions))
3872}
3873
3874/// Whether evaluating `expr` never returns.
3875///
3876/// Only a direct call to a `_Noreturn` function counts: a call through a
3877/// pointer has no declaration to read the specifier from.
3878pub fn expr_never_returns(expr: &Expr, functions: &[Function]) -> bool {
3879    match &expr.kind {
3880        ExprKind::Call {
3881            callee: Callee::Direct(id),
3882            ..
3883        } => functions
3884            .get(id.0 as usize)
3885            .is_some_and(|func| func.noreturn),
3886        ExprKind::Unreachable => true,
3887        // `(void)abort();` and `f(), abort();` end just as surely.
3888        ExprKind::Cast(inner) => expr_never_returns(inner, functions),
3889        ExprKind::Comma { rhs, .. } => expr_never_returns(rhs, functions),
3890        _ => false,
3891    }
3892}
3893
3894/// Whether evaluating `expr` can call a function.
3895///
3896/// C11 6.5.16.2p3 is why this is worth asking: a compound assignment is, "with
3897/// respect to an indeterminately-sequenced function call, a single evaluation",
3898/// so the read-modify-write of `x |= f()` may not be split around the call to
3899/// `f` the way `x = x | f()` would be. Code generation evaluates such a right
3900/// operand into a temporary first, and asks this to know when it has to.
3901pub fn calls_a_function(expr: &Expr) -> bool {
3902    let any = |list: &[Expr]| list.iter().any(calls_a_function);
3903    match &expr.kind {
3904        // A statement expression is a block, which can hold anything.
3905        ExprKind::Call { .. } | ExprKind::StmtExpr { .. } => true,
3906        ExprKind::Int(_)
3907        | ExprKind::Float(_)
3908        | ExprKind::Zeroed
3909        | ExprKind::FuncAddr(_)
3910        | ExprKind::LabelAddr(_)
3911        | ExprKind::VaListPristine
3912        | ExprKind::Unreachable
3913        | ExprKind::VaEnd => false,
3914        ExprKind::Load(place) | ExprKind::AddrOf(place) => place_calls_a_function(place),
3915        ExprKind::VaArg { ap, .. } => place_calls_a_function(ap),
3916        ExprKind::Assign { place, value } | ExprKind::CompoundAssign { place, value, .. } => {
3917            place_calls_a_function(place) || calls_a_function(value)
3918        }
3919        ExprKind::IncDec { place, .. } => place_calls_a_function(place),
3920        ExprKind::Neg(inner) | ExprKind::BitNot(inner) | ExprKind::Cast(inner) => {
3921            calls_a_function(inner)
3922        }
3923        ExprKind::Binary { lhs, rhs, .. }
3924        | ExprKind::Compare { lhs, rhs, .. }
3925        | ExprKind::Logical { lhs, rhs, .. }
3926        | ExprKind::PtrDiff { lhs, rhs }
3927        | ExprKind::Comma { lhs, rhs } => calls_a_function(lhs) || calls_a_function(rhs),
3928        ExprKind::ComplexOf { re, im } => calls_a_function(re) || calls_a_function(im),
3929        ExprKind::PtrOffset { ptr, index, .. } => calls_a_function(ptr) || calls_a_function(index),
3930        ExprKind::Cond {
3931            cond,
3932            then_expr,
3933            else_expr,
3934        } => calls_a_function(cond) || calls_a_function(then_expr) || calls_a_function(else_expr),
3935        ExprKind::CondDefault { value, else_expr } => {
3936            calls_a_function(value) || calls_a_function(else_expr)
3937        }
3938        ExprKind::Builtin { args, .. } => any(args),
3939        ExprKind::Atomic(atomic) => atomic.operands().any(calls_a_function),
3940        ExprKind::RecordLit { fields, .. } => any(fields),
3941        ExprKind::UnionLit { value, .. } => calls_a_function(value),
3942        ExprKind::ArrayLit(items) => any(items),
3943        ExprKind::ArrayRepeat { value, .. } => calls_a_function(value),
3944    }
3945}
3946
3947/// [`calls_a_function`], for the expressions inside a place.
3948fn place_calls_a_function(place: &Place) -> bool {
3949    match &place.kind {
3950        PlaceKind::Object(_) | PlaceKind::Str(_) => false,
3951        PlaceKind::Deref(ptr) => calls_a_function(ptr),
3952        PlaceKind::Index { base, index } => calls_a_function(base) || calls_a_function(index),
3953        PlaceKind::Field { base, .. } | PlaceKind::ComplexPart { base, .. } => {
3954            place_calls_a_function(base)
3955        }
3956        PlaceKind::Temporary(expr) => calls_a_function(expr),
3957        PlaceKind::CompoundLiteral { init, .. } => calls_a_function(init),
3958    }
3959}
3960
3961/// Whether `expr` reads or takes the address of `object`.
3962///
3963/// C99 6.2.1p7 puts an identifier in scope from the end of its declarator, so
3964/// an initialiser may name the object it initialises: `struct list head = {
3965/// &head, &head }` is the idiom, and `T *p = malloc(sizeof *p)` is the one
3966/// everybody writes. A Rust binding cannot be named in its own initialiser, so
3967/// an *automatic* object whose initialiser does this is defined with a zero
3968/// and assigned afterwards; this is what tells the two apart. An object with
3969/// static storage duration needs nothing: the generated item takes its own
3970/// address with `&raw mut`, which reads nothing and is a constant.
3971pub fn mentions_object(expr: &Expr, object: ObjectId) -> bool {
3972    mentions_object_in(expr, object, false)
3973}
3974
3975/// The index of `table[index]` read as a value — the whole of `expr` being
3976/// that read, the array decayed to a pointer to its first element and only
3977/// conversions around the decay.
3978///
3979/// This is the one use of a dispatch table of label addresses that leaves the
3980/// table's contents known; see [`crate::cfg`]'s table fold.
3981pub fn table_read(expr: &Expr, table: ObjectId) -> Option<&Expr> {
3982    let ExprKind::Load(place) = &expr.kind else {
3983        return None;
3984    };
3985    let PlaceKind::Index { base, index } = &place.kind else {
3986        return None;
3987    };
3988    let mut base: &Expr = base;
3989    while let ExprKind::Cast(inner) = &base.kind {
3990        base = inner;
3991    }
3992    match &base.kind {
3993        ExprKind::AddrOf(Place {
3994            kind: PlaceKind::Object(id),
3995            ..
3996        }) if *id == table => Some(index),
3997        _ => None,
3998    }
3999}
4000
4001/// Whether any of `stmts` names `object` other than in a [`table_read`] of
4002/// it — which is what says a table is never written, never has its address
4003/// taken and never goes anywhere, so its contents are its initialiser's.
4004///
4005/// Conservative: a statement expression, a variable length array's size and
4006/// an inline assembly statement all count as naming it.
4007pub fn stmts_use_object_beyond_reads(stmts: &[Stmt], object: ObjectId) -> bool {
4008    stmts.iter().any(|stmt| stmt_uses_object(stmt, object))
4009}
4010
4011/// The initialisers of every [`Stmt::Let`] that defines `object` in `stmts`,
4012/// however deeply nested.
4013pub fn lets_of(stmts: &[Stmt], object: ObjectId) -> Vec<&Expr> {
4014    fn walk<'a>(stmt: &'a Stmt, object: ObjectId, out: &mut Vec<&'a Expr>) {
4015        match stmt {
4016            Stmt::Let {
4017                object: id, init, ..
4018            } if *id == object => out.push(init),
4019            Stmt::Block(items) => items.iter().for_each(|s| walk(s, object, out)),
4020            Stmt::If {
4021                then_branch,
4022                else_branch,
4023                ..
4024            } => {
4025                walk(then_branch, object, out);
4026                if let Some(branch) = else_branch {
4027                    walk(branch, object, out);
4028                }
4029            }
4030            Stmt::For { init, body, .. } => {
4031                init.iter().for_each(|s| walk(s, object, out));
4032                walk(body, object, out);
4033            }
4034            Stmt::While { body, .. }
4035            | Stmt::DoWhile { body, .. }
4036            | Stmt::Case { body, .. }
4037            | Stmt::Label { body, .. } => walk(body, object, out),
4038            Stmt::SwitchTree(switch) => walk(&switch.body, object, out),
4039            _ => {}
4040        }
4041    }
4042    let mut out = Vec::new();
4043    stmts.iter().for_each(|s| walk(s, object, &mut out));
4044    out
4045}
4046
4047fn stmt_uses_object(stmt: &Stmt, object: ObjectId) -> bool {
4048    let expr = |e: &Expr| mentions_object_in(e, object, true);
4049    let sub = |s: &Stmt| stmt_uses_object(s, object);
4050    match stmt {
4051        Stmt::Nop
4052        | Stmt::Goto { .. }
4053        | Stmt::Break { .. }
4054        | Stmt::Continue { .. }
4055        | Stmt::Return { value: None, .. } => false,
4056        Stmt::Expr(e) | Stmt::GotoPtr { target: e, .. } => expr(e),
4057        Stmt::Return { value: Some(e), .. } => expr(e),
4058        Stmt::Let { init, .. } => expr(init),
4059        Stmt::Cleanup(def) => expr(&def.call),
4060        Stmt::Block(items) => items.iter().any(sub),
4061        Stmt::If {
4062            cond,
4063            then_branch,
4064            else_branch,
4065        } => expr(cond) || sub(then_branch) || else_branch.as_deref().is_some_and(sub),
4066        Stmt::While { cond, body, .. } | Stmt::DoWhile { cond, body, .. } => {
4067            expr(cond) || sub(body)
4068        }
4069        Stmt::For {
4070            init,
4071            cond,
4072            step,
4073            body,
4074            ..
4075        } => {
4076            init.iter().any(sub)
4077                || cond.as_ref().is_some_and(expr)
4078                || step.as_ref().is_some_and(expr)
4079                || sub(body)
4080        }
4081        Stmt::SwitchTree(switch) => expr(&switch.scrutinee) || sub(&switch.body),
4082        Stmt::Case { body, .. } | Stmt::Label { body, .. } => sub(body),
4083        Stmt::Vla(_) | Stmt::Asm(_) | Stmt::Switch(_) | Stmt::Region(_) => true,
4084    }
4085}
4086
4087/// [`mentions_object`], or — with `reads_ok` — the same with every
4088/// [`table_read`] of the object counted as not naming it.
4089fn mentions_object_in(expr: &Expr, object: ObjectId, reads_ok: bool) -> bool {
4090    if reads_ok && let Some(index) = table_read(expr, object) {
4091        return mentions_object_in(index, object, reads_ok);
4092    }
4093    let mentions_object = |e: &Expr, object: ObjectId| mentions_object_in(e, object, reads_ok);
4094    let place_mentions_object =
4095        |p: &Place, object: ObjectId| place_mentions_in(p, object, reads_ok);
4096    let any = |list: &[Expr]| list.iter().any(|e| mentions_object(e, object));
4097    match &expr.kind {
4098        ExprKind::Int(_)
4099        | ExprKind::Float(_)
4100        | ExprKind::Zeroed
4101        | ExprKind::FuncAddr(_)
4102        | ExprKind::LabelAddr(_)
4103        | ExprKind::VaListPristine
4104        | ExprKind::Unreachable
4105        | ExprKind::VaEnd => false,
4106        ExprKind::Load(place) | ExprKind::AddrOf(place) => place_mentions_object(place, object),
4107        ExprKind::VaArg { ap, .. } => place_mentions_object(ap, object),
4108        ExprKind::Assign { place, value } | ExprKind::CompoundAssign { place, value, .. } => {
4109            place_mentions_object(place, object) || mentions_object(value, object)
4110        }
4111        ExprKind::IncDec { place, .. } => place_mentions_object(place, object),
4112        ExprKind::Neg(inner) | ExprKind::BitNot(inner) | ExprKind::Cast(inner) => {
4113            mentions_object(inner, object)
4114        }
4115        ExprKind::Binary { lhs, rhs, .. }
4116        | ExprKind::Compare { lhs, rhs, .. }
4117        | ExprKind::Logical { lhs, rhs, .. }
4118        | ExprKind::PtrDiff { lhs, rhs }
4119        | ExprKind::Comma { lhs, rhs } => {
4120            mentions_object(lhs, object) || mentions_object(rhs, object)
4121        }
4122        ExprKind::ComplexOf { re, im } => {
4123            mentions_object(re, object) || mentions_object(im, object)
4124        }
4125        ExprKind::PtrOffset { ptr, index, .. } => {
4126            mentions_object(ptr, object) || mentions_object(index, object)
4127        }
4128        ExprKind::Cond {
4129            cond,
4130            then_expr,
4131            else_expr,
4132        } => {
4133            mentions_object(cond, object)
4134                || mentions_object(then_expr, object)
4135                || mentions_object(else_expr, object)
4136        }
4137        ExprKind::CondDefault { value, else_expr } => {
4138            mentions_object(value, object) || mentions_object(else_expr, object)
4139        }
4140        ExprKind::Call { callee, args } => {
4141            let callee = match callee {
4142                Callee::Direct(_) => false,
4143                Callee::Indirect(target) => mentions_object(target, object),
4144            };
4145            callee || any(args)
4146        }
4147        ExprKind::Builtin { args, .. } => any(args),
4148        ExprKind::Atomic(atomic) => atomic.operands().any(|e| mentions_object(e, object)),
4149        ExprKind::RecordLit { fields, .. } => any(fields),
4150        ExprKind::UnionLit { value, .. } => mentions_object(value, object),
4151        ExprKind::ArrayLit(items) => any(items),
4152        ExprKind::ArrayRepeat { value, .. } => mentions_object(value, object),
4153        // A statement expression is a block of its own; whatever it names, it
4154        // names through a scope this cannot walk, so it is taken to reach the
4155        // object rather than risk a binding read before it exists.
4156        ExprKind::StmtExpr { .. } => true,
4157    }
4158}
4159
4160/// [`mentions_object_in`], for the expressions inside a place.
4161fn place_mentions_in(place: &Place, object: ObjectId, reads_ok: bool) -> bool {
4162    let mentions_object = |e: &Expr, object: ObjectId| mentions_object_in(e, object, reads_ok);
4163    let place_mentions_object =
4164        |p: &Place, object: ObjectId| place_mentions_in(p, object, reads_ok);
4165    match &place.kind {
4166        PlaceKind::Object(id) => *id == object,
4167        PlaceKind::Str(_) => false,
4168        PlaceKind::Deref(ptr) => mentions_object(ptr, object),
4169        PlaceKind::Index { base, index } => {
4170            mentions_object(base, object) || mentions_object(index, object)
4171        }
4172        PlaceKind::Field { base, .. } | PlaceKind::ComplexPart { base, .. } => {
4173            place_mentions_object(base, object)
4174        }
4175        PlaceKind::Temporary(expr) => mentions_object(expr, object),
4176        PlaceKind::CompoundLiteral { init, .. } => mentions_object(init, object),
4177    }
4178}
4179
4180fn stmt_always_terminates(stmt: &Stmt, functions: &[Function]) -> bool {
4181    let terminates = |stmt: &Stmt| stmt_always_terminates(stmt, functions);
4182    match stmt {
4183        Stmt::Return { .. } => true,
4184        Stmt::Expr(expr) => expr_never_returns(expr, functions),
4185        Stmt::Block(items) => always_terminates(items, functions),
4186        Stmt::Label { body, .. } => terminates(body),
4187        // Control does not continue into the next statement: the jump is a
4188        // `break` or a `continue` of a region that encloses it.
4189        Stmt::Goto { .. } => true,
4190        // A block is left by falling off its end or by a `break` to its label,
4191        // and both continue at the label the region ends before; a loop is
4192        // left only by the `break` that stands at the end of its body, so one
4193        // that needs none never finishes.
4194        Stmt::Region(region) => match region.kind {
4195            RegionKind::Block => {
4196                always_terminates(&region.body, functions) && !jumps_to(&region.body, region.label)
4197            }
4198            RegionKind::Loop => !region.falls_out,
4199        },
4200        Stmt::If {
4201            then_branch,
4202            else_branch: Some(else_branch),
4203            ..
4204        } => terminates(then_branch) && terminates(else_branch),
4205        Stmt::While { id, cond, body, .. } => {
4206            is_always_true(cond) && !breaks_to(body, BreakTarget::Loop(*id))
4207        }
4208        Stmt::DoWhile { id, body, cond, .. } => {
4209            is_always_true(cond) && !breaks_to(body, BreakTarget::Loop(*id))
4210        }
4211        Stmt::For { id, cond, body, .. } => {
4212            cond.as_ref().is_none_or(is_always_true) && !breaks_to(body, BreakTarget::Loop(*id))
4213        }
4214        // Control enters a `switch` at one label and then runs through every
4215        // group after it, so the statement terminates exactly when it can
4216        // neither be skipped (there is a `default:`) nor left early (nothing
4217        // `break`s out of it) and the last group terminates.
4218        Stmt::Switch(switch) => {
4219            switch.default_group.is_some()
4220                && switch
4221                    .groups
4222                    .last()
4223                    .is_some_and(|group| always_terminates(&group.body, functions))
4224                && !switch
4225                    .groups
4226                    .iter()
4227                    .flat_map(|group| group.body.iter())
4228                    .chain(switch.prelude.iter())
4229                    .any(|s| breaks_to(s, BreakTarget::Switch(switch.id)))
4230        }
4231        _ => false,
4232    }
4233}
4234
4235/// Whether `expr` is a constant that C treats as true.
4236///
4237/// Code generation asks the same question, so that a loop it turns into a Rust
4238/// `loop` — which has no exit for the type checker to see — is exactly the loop
4239/// [`always_terminates`] promised would not fall through.
4240pub fn is_always_true(expr: &Expr) -> bool {
4241    match &expr.kind {
4242        ExprKind::Int(v) => *v != 0,
4243        ExprKind::Float(v) => *v != 0.0,
4244        ExprKind::Cast(inner) => is_always_true(inner),
4245        _ => false,
4246    }
4247}
4248
4249/// Whether any `goto` inside `stmts` names `label`.
4250///
4251/// Every `goto` left in a structured body is a jump to a [`Region`] enclosing
4252/// it, so this is what says whether control can leave a [block](
4253/// RegionKind::Block) other than by falling off its end.
4254fn jumps_to(stmts: &[Stmt], label: LabelId) -> bool {
4255    stmts.iter().any(|stmt| stmt_jumps_to(stmt, label))
4256}
4257
4258fn stmt_jumps_to(stmt: &Stmt, label: LabelId) -> bool {
4259    let jumps = |stmt: &Stmt| stmt_jumps_to(stmt, label);
4260    match stmt {
4261        Stmt::Goto { id, .. } => *id == label,
4262        Stmt::Block(items) => items.iter().any(jumps),
4263        Stmt::Region(region) => region.body.iter().any(jumps),
4264        Stmt::If {
4265            then_branch,
4266            else_branch,
4267            ..
4268        } => jumps(then_branch) || else_branch.as_ref().is_some_and(|s| jumps(s)),
4269        Stmt::While { body, .. }
4270        | Stmt::DoWhile { body, .. }
4271        | Stmt::For { body, .. }
4272        | Stmt::Label { body, .. }
4273        | Stmt::Case { body, .. } => jumps(body),
4274        Stmt::Switch(switch) => {
4275            switch.prelude.iter().any(jumps)
4276                || switch
4277                    .groups
4278                    .iter()
4279                    .any(|group| group.body.iter().any(jumps))
4280        }
4281        Stmt::SwitchTree(switch) => jumps(&switch.body),
4282        _ => false,
4283    }
4284}
4285
4286/// Whether any `break` inside `stmt` leaves `target`.
4287///
4288/// Every `break` names what it leaves, so this never has to reason about
4289/// nesting: a `break` belonging to an inner loop simply names that loop.
4290fn breaks_to(stmt: &Stmt, target: BreakTarget) -> bool {
4291    let breaks = |stmt: &Stmt| breaks_to(stmt, target);
4292    match stmt {
4293        Stmt::Break { target: found, .. } => *found == target,
4294        Stmt::Block(items) => items.iter().any(breaks),
4295        Stmt::Region(region) => region.body.iter().any(breaks),
4296        Stmt::If {
4297            then_branch,
4298            else_branch,
4299            ..
4300        } => breaks(then_branch) || else_branch.as_ref().is_some_and(|s| breaks(s)),
4301        Stmt::While { body, .. }
4302        | Stmt::DoWhile { body, .. }
4303        | Stmt::For { body, .. }
4304        | Stmt::Label { body, .. }
4305        | Stmt::Case { body, .. } => breaks(body),
4306        Stmt::Switch(switch) => {
4307            switch.prelude.iter().any(breaks)
4308                || switch
4309                    .groups
4310                    .iter()
4311                    .any(|g| g.body.iter().any(|s| breaks_to(s, target)))
4312        }
4313        Stmt::SwitchTree(switch) => breaks(&switch.body),
4314        _ => false,
4315    }
4316}
4317
4318#[cfg(test)]
4319mod tests {
4320    use super::*;
4321
4322    const T: TargetModel = TargetModel::LP64;
4323
4324    #[test]
4325    fn small_types_promote_to_int() {
4326        for ty in [
4327            Ty::Bool,
4328            Ty::Char,
4329            Ty::SChar,
4330            Ty::UChar,
4331            Ty::Short,
4332            Ty::UShort,
4333        ] {
4334            assert_eq!(ty.promote(&T), Ty::Int, "{}", ty.scalar_name());
4335        }
4336        assert_eq!(Ty::Int.promote(&T), Ty::Int);
4337        assert_eq!(Ty::UInt.promote(&T), Ty::UInt);
4338        assert_eq!(Ty::Double.promote(&T), Ty::Double);
4339    }
4340
4341    #[test]
4342    fn bit_fields_promote_by_their_width() {
4343        // 6.3.1.1p2's "as restricted by the width": `int` first, then
4344        // `unsigned int`, and only then the declared type. The expectations
4345        // were read off gcc 15 and clang 21 on x86-64.
4346        let p = |ty: Ty, width: u32| ty.promote_bit_field(width, ty.is_signed(&T), &T);
4347        assert_eq!(p(Ty::UInt, 31), Ty::Int);
4348        assert_eq!(p(Ty::UInt, 32), Ty::UInt);
4349        assert_eq!(p(Ty::Int, 32), Ty::Int);
4350        assert_eq!(p(Ty::Int, 3), Ty::Int);
4351        assert_eq!(p(Ty::Bool, 1), Ty::Int);
4352        assert_eq!(p(Ty::Char, 8), Ty::Int);
4353        assert_eq!(p(Ty::UChar, 8), Ty::Int);
4354        assert_eq!(p(Ty::UShort, 16), Ty::Int);
4355        // The types GCC accepts as an extension follow the same rule, so a
4356        // narrow field of a wide type is still an `int`.
4357        assert_eq!(p(Ty::ULong, 31), Ty::Int);
4358        assert_eq!(p(Ty::ULong, 32), Ty::UInt);
4359        assert_eq!(p(Ty::ULong, 33), Ty::ULong);
4360        assert_eq!(p(Ty::Long, 33), Ty::Long);
4361        assert_eq!(p(Ty::LongLong, 32), Ty::Int);
4362        assert_eq!(p(Ty::ULongLong, 40), Ty::ULongLong);
4363        assert_eq!(p(Ty::ULongLong, 64), Ty::ULongLong);
4364        // An `enum` whose underlying type the implementation made unsigned.
4365        assert_eq!(Ty::Int.promote_bit_field(8, false, &T), Ty::Int);
4366        assert_eq!(Ty::Int.promote_bit_field(32, false, &T), Ty::UInt);
4367    }
4368
4369    #[test]
4370    fn unsigned_short_promotes_to_unsigned_int_on_a_16_bit_target() {
4371        let t = TargetModel {
4372            int_bits: 16,
4373            ..TargetModel::ILP32
4374        };
4375        assert_eq!(Ty::UShort.promote(&t), Ty::UInt);
4376        assert_eq!(Ty::Short.promote(&t), Ty::Int);
4377    }
4378
4379    #[test]
4380    fn the_usual_arithmetic_conversions_follow_6_3_1_8() {
4381        let u = |a, b| Ty::usual_arithmetic(a, b, &T);
4382        assert_eq!(u(Ty::Int, Ty::UInt), Ty::UInt);
4383        assert_eq!(u(Ty::Char, Ty::Char), Ty::Int);
4384        assert_eq!(u(Ty::Int, Ty::Long), Ty::Long);
4385        // `long` is wider than `unsigned int` on LP64, so it wins.
4386        assert_eq!(u(Ty::UInt, Ty::Long), Ty::Long);
4387        // ... but not on ILP32, where the result is `unsigned long`.
4388        assert_eq!(
4389            Ty::usual_arithmetic(Ty::UInt, Ty::Long, &TargetModel::ILP32),
4390            Ty::ULong
4391        );
4392        // `long long` cannot hold every `unsigned long`, so both become
4393        // `unsigned long long` — the last clause of 6.3.1.8.
4394        assert_eq!(u(Ty::ULong, Ty::LongLong), Ty::ULongLong);
4395        assert_eq!(u(Ty::UChar, Ty::Long), Ty::Long);
4396        assert_eq!(u(Ty::Float, Ty::LongLong), Ty::Float);
4397        assert_eq!(u(Ty::Double, Ty::Float), Ty::Double);
4398    }
4399
4400    /// GNU's `__int128` ranks above every standard integer type, which is what
4401    /// makes `(__int128) a * b` a 128-bit multiplication.
4402    #[test]
4403    fn int128_outranks_every_standard_integer_type() {
4404        let u = |a, b| Ty::usual_arithmetic(a, b, &T);
4405        assert_eq!(u(Ty::Int128, Ty::LongLong), Ty::Int128);
4406        assert_eq!(u(Ty::Int128, Ty::ULongLong), Ty::Int128);
4407        assert_eq!(u(Ty::UInt128, Ty::LongLong), Ty::UInt128);
4408        assert_eq!(u(Ty::UInt128, Ty::Int128), Ty::UInt128);
4409        assert_eq!(u(Ty::Int128, Ty::Int), Ty::Int128);
4410        // …and a floating type still outranks it.
4411        assert_eq!(u(Ty::Float, Ty::UInt128), Ty::Float);
4412        assert_eq!(u(Ty::Double, Ty::Int128), Ty::Double);
4413        // The promotions leave it alone, as they do every type of `int`'s rank
4414        // or above.
4415        assert_eq!(Ty::Int128.promote(&T), Ty::Int128);
4416        assert_eq!(Ty::UInt128.promote(&T), Ty::UInt128);
4417        assert_eq!(Ty::Int128.promote_argument(&T), Ty::Int128);
4418        assert_eq!(Ty::Int128.to_unsigned(), Ty::UInt128);
4419        assert!(Ty::Int128.is_signed(&T));
4420        assert!(!Ty::UInt128.is_signed(&T));
4421        assert_eq!(Ty::Int128.size_bytes(&T), 16);
4422        assert_eq!(Ty::UInt128.bits(&T), 128);
4423    }
4424
4425    /// A 128-bit constant is carried as its two's-complement bit pattern, so
4426    /// `wrap` leaves it alone and the ends of the range come out exactly.
4427    #[test]
4428    fn int128_constants_are_carried_as_bit_patterns() {
4429        assert_eq!(Ty::UInt128.wrap(-1, &T), -1);
4430        assert_eq!(Ty::Int128.wrap(-1, &T), -1);
4431        assert_eq!(Ty::Int128.wrap(i128::MIN, &T), i128::MIN);
4432        assert_eq!(Ty::Int128.min_value(&T), i128::MIN);
4433        assert_eq!(Ty::Int128.max_value(&T), i128::MAX);
4434        assert_eq!(Ty::UInt128.min_value(&T), 0);
4435        // Clamped, and documented as such: the real maximum is 2^128 - 1.
4436        assert_eq!(Ty::UInt128.max_value(&T), i128::MAX);
4437        // Converting a 128-bit pattern down to a narrower type is the ordinary
4438        // truncation.
4439        assert_eq!(Ty::UInt.wrap(-1, &T), 4_294_967_295);
4440    }
4441
4442    /// `__int128` is sixteen bytes; its *alignment* is the one thing the model
4443    /// decides, because it is the one scalar whose alignment is not its size
4444    /// on every target.
4445    #[test]
4446    fn int128_takes_its_alignment_from_the_model() {
4447        let types = Types::new();
4448        let layout = types
4449            .size_align(Ty::UInt128, &T)
4450            .expect("a scalar has a layout");
4451        assert_eq!(layout.size, 16);
4452        assert_eq!(layout.align, 16);
4453        let eight = TargetModel {
4454            int128_align: 8,
4455            ..TargetModel::LP64
4456        };
4457        let layout = types
4458            .size_align(Ty::Int128, &eight)
4459            .expect("a scalar has a layout");
4460        assert_eq!(layout.size, 16);
4461        assert_eq!(layout.align, 8);
4462    }
4463
4464    #[test]
4465    fn conversions_wrap() {
4466        assert_eq!(Ty::UChar.wrap(300, &T), 44);
4467        assert_eq!(Ty::SChar.wrap(200, &T), -56);
4468        assert_eq!(Ty::UInt.wrap(-1, &T), 4_294_967_295);
4469        assert_eq!(Ty::Int.wrap(4_294_967_295, &T), -1);
4470        assert_eq!(Ty::Bool.wrap(5, &T), 1);
4471        assert_eq!(Ty::Bool.wrap(0, &T), 0);
4472        assert_eq!(Ty::ULongLong.wrap(-1, &T), u64::MAX as i128);
4473    }
4474
4475    #[test]
4476    fn derived_types_are_interned() {
4477        let mut types = Types::new();
4478        let a = types.pointer(Ty::Int, false);
4479        let b = types.pointer(Ty::Int, false);
4480        let c = types.pointer(Ty::Int, true);
4481        assert_eq!(a, b);
4482        assert_ne!(a, c);
4483        assert!(types.same_pointee(a, c));
4484        assert_eq!(types.pointee(a), Some(Ty::Int));
4485        let arr = types.array(Ty::Char, 4, false);
4486        assert_eq!(arr, types.array(Ty::Char, 4, false));
4487        assert_ne!(arr, types.array(Ty::Char, 5, false));
4488        let f = types.func(Ty::Int, vec![a], false);
4489        assert_eq!(f, types.func(Ty::Int, vec![b], false));
4490        assert_ne!(f, types.func(Ty::Int, vec![a], true));
4491    }
4492
4493    #[test]
4494    fn layouts_follow_natural_alignment() {
4495        let mut types = Types::new();
4496        let arr = types.array(Ty::Char, 5, false);
4497        assert_eq!(
4498            types.size_align(arr, &T),
4499            Some(Layout { size: 5, align: 1 })
4500        );
4501        let ptr = types.pointer(Ty::Void, false);
4502        assert_eq!(
4503            types.size_align(ptr, &T),
4504            Some(Layout { size: 8, align: 8 })
4505        );
4506        // A function type has no size at all.
4507        let f = types.func(Ty::Void, Vec::new(), false);
4508        assert_eq!(types.size_align(f, &T), None);
4509    }
4510
4511    #[test]
4512    fn names_read_like_c() {
4513        let mut types = Types::new();
4514        let cchar = types.pointer(Ty::Char, true);
4515        assert_eq!(types.name(cchar), "const char *");
4516        let arr = types.array(Ty::Int, 3, false);
4517        assert_eq!(types.name(arr), "int[3]");
4518        let f = types.func(Ty::Int, vec![cchar], true);
4519        let fp = types.pointer(f, false);
4520        assert_eq!(types.name(fp), "int (*)(const char *, ...)");
4521    }
4522}