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