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(®ion.body, functions) && !jumps_to(®ion.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}