rucc_types/types.rs
1//! The type table: interning, canonicalisation, and the nominal declarations.
2//!
3//! Design: `spec/07-types-and-semantics.md` section 7.1.
4//!
5//! There is one [`Types`] per translation unit and every [`TypeId`] belongs to it. Interning
6//! is what makes type identity an integer comparison, which is the single most frequent
7//! question the compiler asks, and it is also what makes the canonical form free to look up:
8//! each entry stores the id of its own canonical type, so stripping a stack of typedefs is one
9//! array read rather than a walk.
10
11use std::num::NonZeroU32;
12
13use rucc_base::hash::Map;
14use rucc_base::{Idx, Symbol};
15
16use crate::kind::{
17 ArrayLen, EnumId, FloatKind, FunctionId, FunctionType, IntKind, Qualifiers, RecordId,
18 RecordKind, Type, TypeKind,
19};
20use crate::layout::Layout;
21use crate::record::{Field, RecordLayout, VariableLayout};
22
23/// The identity of a type.
24///
25/// Four bytes, `Copy`, and equal exactly when the two types are the same type. Ids from two
26/// different [`Types`] tables are not comparable, which is not a restriction in practice
27/// because there is one table per translation unit.
28#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
29pub struct TypeId(Idx<Entry>);
30
31impl std::fmt::Debug for TypeId {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 write!(f, "TypeId#{}", self.0.raw())
34 }
35}
36
37/// One row of the table.
38///
39/// The canonical id is stored rather than computed because almost every read of a type wants
40/// it, and computing it means walking a chain whose length is however many typedefs the header
41/// author felt like writing.
42#[derive(Debug, Clone, Copy)]
43struct Entry {
44 ty: Type,
45 canonical: TypeId,
46}
47
48/// What is known about one `struct` or `union` declaration.
49#[derive(Debug, Clone)]
50pub struct RecordInfo {
51 /// Whether it is a `struct` or a `union`.
52 pub kind: RecordKind,
53 /// The tag, absent for an anonymous one.
54 pub tag: Option<Symbol>,
55 /// The layout, absent until the members have been seen and laid out.
56 ///
57 /// This is also what says whether the type is complete. A record is incomplete from the
58 /// point its tag is first mentioned until its closing brace, and code in between may
59 /// declare pointers to it and nothing else.
60 ///
61 /// For a record with a member of no fixed size the alignment here is the right one and the
62 /// size is zero, since an alignment never depends on a length. [`RecordInfo::variable`] is
63 /// what holds the size in that case and what says the size here means nothing.
64 pub layout: Option<Layout>,
65 /// How long the record is and where its members sit, where those are not numbers.
66 ///
67 /// Present on exactly the records C calls variably modified, meaning a variable length array
68 /// is somewhere among the members, which may only be written inside a function.
69 pub variable: Option<VariableLayout>,
70 /// The members, placed, and empty until the record is complete.
71 ///
72 /// One entry per member the program wrote, in that order, so a caller that kept the
73 /// declarations can index the two together.
74 pub fields: Vec<Field>,
75 /// Whether `__attribute__((transparent_union))` was written on it and held up.
76 ///
77 /// Only ever true of a union, and only of one whose first member is the size and the
78 /// alignment of the whole of it, which is what makes passing the union and passing that
79 /// member the same thing at a call. What it buys is two rules: a parameter of this type is
80 /// compatible with a parameter of any member's type, and a value assigned to it is put into
81 /// whichever member it fits. Both are in `spec/13-gnu-compat.md`.
82 pub transparent: bool,
83 /// Whether the scalars in it are stored in the byte order the target does not have.
84 ///
85 /// What `__attribute__((scalar_storage_order("big-endian")))` on a little-endian target asks
86 /// for, and what the same attribute written with the target's own order does not. It changes
87 /// nothing about where the members sit: the record is the size and the alignment it would
88 /// otherwise be and every member is at the offset it would otherwise be at. What it changes
89 /// is the order of the bytes inside each scalar, which is a byte swap on every load and
90 /// store, and the end of a storage unit a bit-field is allocated from. Both are in
91 /// `spec/13-gnu-compat.md`.
92 pub reverse: bool,
93 /// Whether `__attribute__((may_alias))` was written on it.
94 ///
95 /// An access to a member of it may then touch an object of any type, the way an access
96 /// through a character type may, which is what a program that lays a structure over bytes it
97 /// did not write as that structure asks for. Nothing about the layout changes.
98 pub may_alias: bool,
99}
100
101/// What is known about one `enum` declaration.
102#[derive(Debug, Clone)]
103pub struct EnumInfo {
104 /// The tag, absent for an anonymous one.
105 pub tag: Option<Symbol>,
106 /// The type the enumerators are represented in, absent until it is decided.
107 ///
108 /// C23 lets the program write it, and before that it is chosen once every enumerator has
109 /// been seen. Either way it is a fact about the declaration rather than about the type
110 /// system, so it is recorded here and not derived twice.
111 pub underlying: Option<TypeId>,
112 /// Whether the underlying type was written by the program rather than chosen.
113 ///
114 /// It changes the answer to what an enumerator's own type is, and it decides whether an
115 /// enumerator that does not fit is an error or a reason to widen.
116 pub fixed: bool,
117 /// The enumerators in the order the program wrote them, empty until the enumeration is
118 /// complete.
119 ///
120 /// Nothing the type system itself asks about, since an enumerator is a name in a scope and
121 /// what has the type is the enumeration rather than the list. It is here because the
122 /// declaration is the only place the list ever exists, the scope it is declared into throws
123 /// away the order and the tie to the enumeration, and a reader that wants the list later has
124 /// nowhere else to ask. Debug information is that reader: without this a debugger prints the
125 /// number where the program wrote the name.
126 pub enumerators: Vec<Enumerator>,
127}
128
129/// One enumerator of an enumeration.
130#[derive(Debug, Clone)]
131pub struct Enumerator {
132 /// The name the program wrote.
133 pub name: Symbol,
134 /// Its value, in the enumeration's underlying type.
135 ///
136 /// Held as an [`i128`] because the value is worked out before the underlying type is chosen,
137 /// and because the widest enumeration a target has still has to fit in something wider than
138 /// itself while the list is being read.
139 pub value: i128,
140}
141
142/// A typedef name the program wrote, and what it stands for.
143#[derive(Debug, Clone, Copy)]
144pub struct Alias {
145 /// The name.
146 pub name: Symbol,
147 /// The type it was written for, which is the same type the name resolves to rather than a
148 /// type of its own.
149 pub of: TypeId,
150}
151
152/// A record member written with a typedef name, and the name it was written with.
153#[derive(Debug, Clone, Copy)]
154pub struct Spelled {
155 /// The record the member is in.
156 pub record: RecordId,
157 /// The member.
158 pub member: Symbol,
159 /// The typedef name its specifiers named.
160 pub name: Symbol,
161 /// The type the name stood for, which the member's type is built on top of.
162 pub of: TypeId,
163}
164
165/// Every type in one translation unit.
166#[derive(Debug)]
167pub struct Types {
168 entries: Vec<Entry>,
169 map: Map<Type, TypeId>,
170 functions: Vec<FunctionType>,
171 function_map: Map<FunctionType, FunctionId>,
172 records: Vec<RecordInfo>,
173 enums: Vec<EnumInfo>,
174 aliases: Vec<Alias>,
175 spelled: Vec<Spelled>,
176 void: TypeId,
177 boolean: TypeId,
178 ints: [TypeId; 13],
179 floats: [TypeId; FloatKind::ALL.len()],
180}
181
182impl Default for Types {
183 fn default() -> Types {
184 Types::new()
185 }
186}
187
188impl Types {
189 /// A table holding the basic types and nothing else.
190 ///
191 /// The basic types are interned here rather than on first use so that asking for `int` is
192 /// an array read. They are the ones asked for by far the most often, because every
193 /// integer promotion produces one.
194 #[must_use]
195 pub fn new() -> Types {
196 let mut types = Types {
197 entries: Vec::new(),
198 map: Map::default(),
199 functions: Vec::new(),
200 function_map: Map::default(),
201 records: Vec::new(),
202 enums: Vec::new(),
203 aliases: Vec::new(),
204 spelled: Vec::new(),
205 // Fixed up immediately below. There is no id to put here before the table exists,
206 // and an `Option` on each of them would be paid for on every read for the sake of
207 // four lines of construction.
208 void: TypeId(Idx::new(0)),
209 boolean: TypeId(Idx::new(0)),
210 ints: [TypeId(Idx::new(0)); 13],
211 floats: [TypeId(Idx::new(0)); FloatKind::ALL.len()],
212 };
213 types.void = types.intern(Type::new(TypeKind::Void));
214 types.boolean = types.intern(Type::new(TypeKind::Bool));
215 for kind in IntKind::ALL {
216 types.ints[kind.index()] = types.intern(Type::new(TypeKind::Int(kind)));
217 }
218 for kind in FloatKind::ALL {
219 types.floats[kind.index()] = types.intern(Type::new(TypeKind::Float(kind)));
220 }
221 types
222 }
223
224 /// How many distinct types there are.
225 #[must_use]
226 pub fn len(&self) -> usize {
227 self.entries.len()
228 }
229
230 /// Whether the table is empty, which it never is once [`Types::new`] has run.
231 #[must_use]
232 pub fn is_empty(&self) -> bool {
233 self.entries.is_empty()
234 }
235
236 /// The type `id` stands for, with its qualifiers.
237 ///
238 /// # Panics
239 ///
240 /// Panics if `id` came from a different table.
241 #[must_use]
242 pub fn get(&self, id: TypeId) -> Type {
243 self.entries[id.0.index()].ty
244 }
245
246 /// What `id` is, ignoring its qualifiers.
247 ///
248 /// # Panics
249 ///
250 /// Panics if `id` came from a different table.
251 #[must_use]
252 pub fn kind(&self, id: TypeId) -> TypeKind {
253 self.get(id).kind
254 }
255
256 /// What `id` is qualified with.
257 ///
258 /// # Panics
259 ///
260 /// Panics if `id` came from a different table.
261 #[must_use]
262 pub fn quals(&self, id: TypeId) -> Qualifiers {
263 self.get(id).quals
264 }
265
266 /// The canonical form of `id`, with every typedef resolved at every depth.
267 ///
268 /// This is what every semantic rule reads. `id` itself is what every diagnostic prints.
269 ///
270 /// # Panics
271 ///
272 /// Panics if `id` came from a different table.
273 #[must_use]
274 pub fn canonical(&self, id: TypeId) -> TypeId {
275 self.entries[id.0.index()].canonical
276 }
277
278 /// Whether `id` is written with a typedef name somewhere inside it.
279 ///
280 /// # Panics
281 ///
282 /// Panics if `id` came from a different table.
283 #[must_use]
284 pub fn is_sugar(&self, id: TypeId) -> bool {
285 self.canonical(id) != id
286 }
287
288 /// `void`.
289 #[must_use]
290 pub fn void(&self) -> TypeId {
291 self.void
292 }
293
294 /// `bool`, which is `_Bool` in the older spellings.
295 ///
296 /// Named this way because `bool` is a Rust keyword and `r#bool` at every call site would
297 /// be a worse trade than one unusual name here.
298 #[must_use]
299 pub fn boolean(&self) -> TypeId {
300 self.boolean
301 }
302
303 /// One of the standard integer types.
304 #[must_use]
305 pub fn int(&self, kind: IntKind) -> TypeId {
306 self.ints[kind.index()]
307 }
308
309 /// One of the real floating types.
310 #[must_use]
311 pub fn float(&self, kind: FloatKind) -> TypeId {
312 self.floats[kind.index()]
313 }
314
315 /// `_Complex T` for the real type `T`, which is one of the halves.
316 pub fn complex(&mut self, part: TypeId) -> TypeId {
317 self.intern(Type::new(TypeKind::Complex(part)))
318 }
319
320 /// `_Complex T` for a real floating `T`, which is the spelling C has.
321 pub fn complex_float(&mut self, kind: FloatKind) -> TypeId {
322 let part = self.float(kind);
323 self.complex(part)
324 }
325
326 /// `_BitInt(width)`, signed or not.
327 ///
328 /// The width is not checked against the target's maximum here. That check belongs where
329 /// there is a span to point at, and building the type anyway means the rest of the
330 /// declaration still gets checked instead of collapsing into a cascade.
331 pub fn bit_int(&mut self, signed: bool, width: u32) -> TypeId {
332 self.intern(Type::new(TypeKind::BitInt { signed, width }))
333 }
334
335 /// A pointer to `pointee`.
336 pub fn pointer(&mut self, pointee: TypeId) -> TypeId {
337 self.intern(Type::new(TypeKind::Pointer(pointee)))
338 }
339
340 /// `_Atomic(inner)`.
341 pub fn atomic(&mut self, inner: TypeId) -> TypeId {
342 self.intern(Type::new(TypeKind::Atomic(inner)))
343 }
344
345 /// An array of `elem`.
346 pub fn array(&mut self, elem: TypeId, len: ArrayLen) -> TypeId {
347 self.intern(Type::new(TypeKind::Array { elem, len }))
348 }
349
350 /// A GNU vector of `len` elements of `elem`.
351 pub fn vector(&mut self, elem: TypeId, len: u32) -> TypeId {
352 self.intern(Type::new(TypeKind::Vector { elem, len }))
353 }
354
355 /// A function type, deduplicated by content.
356 ///
357 /// # Panics
358 ///
359 /// Panics past four billion distinct function types in one translation unit. The
360 /// alternative to panicking is handing back an id that means a different type, so the
361 /// limit is stated rather than worked around.
362 pub fn function(&mut self, signature: FunctionType) -> TypeId {
363 let id = match self.function_map.get(&signature) {
364 Some(&id) => id,
365 None => {
366 let id = FunctionId(u32::try_from(self.functions.len()).expect("too many types"));
367 self.functions.push(signature.clone());
368 self.function_map.insert(signature, id);
369 id
370 }
371 };
372 self.intern(Type::new(TypeKind::Function(id)))
373 }
374
375 /// The signature behind a function type.
376 ///
377 /// # Panics
378 ///
379 /// Panics if `id` came from a different table.
380 #[must_use]
381 pub fn signature(&self, id: FunctionId) -> &FunctionType {
382 &self.functions[id.0 as usize]
383 }
384
385 /// Declares a `struct` or `union` that has been named but not yet laid out.
386 ///
387 /// Each call makes a new type even for the same tag, because a record type in C is its
388 /// declaration. Redeclaring a tag in an inner scope makes a different type, and the two
389 /// being distinct is what the scope rules mean.
390 ///
391 /// # Panics
392 ///
393 /// Panics past four billion record declarations in one translation unit.
394 pub fn declare_record(&mut self, kind: RecordKind, tag: Option<Symbol>) -> RecordId {
395 let id = RecordId(u32::try_from(self.records.len()).expect("too many types"));
396 self.records.push(RecordInfo {
397 kind,
398 tag,
399 layout: None,
400 variable: None,
401 fields: Vec::new(),
402 transparent: false,
403 reverse: false,
404 may_alias: false,
405 });
406 id
407 }
408
409 /// Records that a union was declared transparent, which is a decision made elsewhere.
410 ///
411 /// Whether the attribute holds up is a question about the members and their layout, so it is
412 /// answered where the members are read rather than here, and this only writes the answer down.
413 /// It is a fact about the declaration and not about one spelling of it, which is why the whole
414 /// record is marked rather than a variant of the type: every name for the union is the same
415 /// union and a parameter written with any of them takes the same values.
416 ///
417 /// # Panics
418 ///
419 /// Panics if `id` came from a different table.
420 pub fn make_transparent(&mut self, id: RecordId) {
421 self.records[id.0 as usize].transparent = true;
422 }
423
424 /// Records that a record holds its scalars in the byte order the target does not have.
425 ///
426 /// Which order the attribute asked for and which one the target has are both known where the
427 /// attribute is read, so what arrives here is the answer to the one question the rest of the
428 /// compiler asks. It is a fact about the declaration rather than about one spelling of it, for
429 /// the reason [`Types::make_transparent`] gives, and it is set after the members are laid out
430 /// because it changes nothing about the layout.
431 ///
432 /// # Panics
433 ///
434 /// Panics if `id` came from a different table.
435 pub fn make_reverse_order(&mut self, id: RecordId) {
436 self.records[id.0 as usize].reverse = true;
437 }
438
439 /// Records that a record said `may_alias`. See [`RecordInfo::may_alias`].
440 ///
441 /// # Panics
442 ///
443 /// Panics if `id` came from a different table.
444 pub fn make_may_alias(&mut self, id: RecordId) {
445 self.records[id.0 as usize].may_alias = true;
446 }
447
448 /// The type of a declared record.
449 pub fn record(&mut self, id: RecordId) -> TypeId {
450 self.intern(Type::new(TypeKind::Record(id)))
451 }
452
453 /// What is known about a declared record.
454 ///
455 /// # Panics
456 ///
457 /// Panics if `id` came from a different table.
458 #[must_use]
459 pub fn record_info(&self, id: RecordId) -> &RecordInfo {
460 &self.records[id.0 as usize]
461 }
462
463 /// Every record declared so far, in declaration order.
464 ///
465 /// For whoever wants to say something about all of them rather than about one, which so
466 /// far is [`measure_all`](crate::measure_all), measuring how their bytes fall into granules.
467 ///
468 /// # Panics
469 ///
470 /// Panics if more than `u32::MAX` records have been declared, which every other index into
471 /// this table would already have panicked on.
472 pub fn records(&self) -> impl Iterator<Item = (RecordId, &RecordInfo)> {
473 self.records
474 .iter()
475 .enumerate()
476 .map(|(index, info)| (RecordId(u32::try_from(index).expect("a declared record")), info))
477 }
478
479 /// Completes a record by recording what [`layout_record`](crate::layout_record) produced.
480 ///
481 /// # Panics
482 ///
483 /// Panics if `id` came from a different table.
484 pub fn complete_record(&mut self, id: RecordId, laid_out: RecordLayout) {
485 let info = &mut self.records[id.0 as usize];
486 info.layout = Some(laid_out.layout);
487 info.variable = laid_out.variable;
488 info.fields = laid_out.fields;
489 }
490
491 /// The member of a record with the given name.
492 ///
493 /// Direct members only. Reaching into an anonymous member is a name lookup with a path to
494 /// build rather than a search, so it belongs to whoever is resolving the expression.
495 ///
496 /// # Panics
497 ///
498 /// Panics if `id` came from a different table.
499 #[must_use]
500 pub fn field(&self, id: RecordId, name: Symbol) -> Option<&Field> {
501 self.records[id.0 as usize].fields.iter().find(|field| field.name == Some(name))
502 }
503
504 /// Declares an `enum` whose underlying type is not decided yet.
505 ///
506 /// # Panics
507 ///
508 /// Panics past four billion enumeration declarations in one translation unit.
509 pub fn declare_enum(&mut self, tag: Option<Symbol>) -> EnumId {
510 let id = EnumId(u32::try_from(self.enums.len()).expect("too many types"));
511 self.enums.push(EnumInfo { tag, underlying: None, fixed: false, enumerators: Vec::new() });
512 id
513 }
514
515 /// The type of a declared enumeration.
516 pub fn enumeration(&mut self, id: EnumId) -> TypeId {
517 self.intern(Type::new(TypeKind::Enum(id)))
518 }
519
520 /// What is known about a declared enumeration.
521 ///
522 /// # Panics
523 ///
524 /// Panics if `id` came from a different table.
525 #[must_use]
526 pub fn enum_info(&self, id: EnumId) -> &EnumInfo {
527 &self.enums[id.0 as usize]
528 }
529
530 /// Records what an enumeration is represented in, and whether the program said so.
531 ///
532 /// # Panics
533 ///
534 /// Panics if `id` came from a different table.
535 pub fn complete_enum(&mut self, id: EnumId, underlying: TypeId, fixed: bool) {
536 let info = &mut self.enums[id.0 as usize];
537 info.underlying = Some(underlying);
538 info.fixed = fixed;
539 }
540
541 /// Records what an enumeration's enumerators are.
542 ///
543 /// Apart from [`Types::complete_enum`] because it is a different fact with a different reader.
544 /// What an enumeration is represented in decides what its values do in arithmetic and is asked
545 /// by the rest of the compiler; the list of names is asked by nothing but the debug
546 /// information, and an enumeration that reaches completion without one, which is what a C23
547 /// declaration that writes an underlying type and no body does, is complete all the same.
548 ///
549 /// # Panics
550 ///
551 /// Panics if `id` came from a different table.
552 pub fn list_enumerators(&mut self, id: EnumId, enumerators: Vec<Enumerator>) {
553 self.enums[id.0 as usize].enumerators = enumerators;
554 }
555
556 /// Records that the program wrote `name` as a typedef name for `of`.
557 ///
558 /// Beside the table rather than in it, and that is the decision this is. A typedef name is a
559 /// second name for a type and not a type of its own, so an ordinary typedef interns nothing
560 /// and the name is written nowhere the types can be asked for it. Making it a type of its own
561 /// would mean two names for one type are two ids, and then the equality of two [`TypeId`]s
562 /// stops meaning the two are the same type, which is the question this table is built to
563 /// answer in one comparison. So the names go in a list that changes nothing about what a type
564 /// is.
565 ///
566 /// What the list cannot answer is which of two names a particular declaration was written
567 /// with, since that is a fact about the declaration and this is a fact about the type. A
568 /// reader gets the names the program wrote and what each one stands for, and no more.
569 pub fn alias(&mut self, name: Symbol, of: TypeId) {
570 if self.aliases.iter().any(|had| had.name == name && had.of == of) {
571 return;
572 }
573 self.aliases.push(Alias { name, of });
574 }
575
576 /// Every typedef name the program wrote, in the order it wrote them.
577 #[must_use]
578 pub fn aliases(&self) -> &[Alias] {
579 &self.aliases
580 }
581
582 /// Records that a member of a record was written with a typedef name.
583 ///
584 /// Here rather than on the member, for the reason the aliases above are beside the table
585 /// rather than in it: which name a member was written with says nothing about the record's
586 /// layout or about which records are compatible, and the member is compared for both. The
587 /// debug information is the one reader, and it wants `size_type n` where the program wrote it.
588 pub fn record_member_spelling(&mut self, spelled: Spelled) {
589 self.spelled.push(spelled);
590 }
591
592 /// Every record member written with a typedef name, in the order they were written.
593 #[must_use]
594 pub fn member_spellings(&self) -> &[Spelled] {
595 &self.spelled
596 }
597
598 /// A typedef name standing for `underlying`.
599 pub fn typedef(&mut self, name: Symbol, underlying: TypeId) -> TypeId {
600 self.intern(Type::new(TypeKind::Typedef {
601 name,
602 underlying,
603 align: None,
604 may_alias: false,
605 }))
606 }
607
608 /// The same, for a typedef that said what an object of it is aligned to.
609 ///
610 /// `align` is in bytes and is what the type is aligned to rather than a floor on it, which
611 /// is what `__attribute__((aligned(n)))` means in this one position. See
612 /// [`TypeKind::Typedef`].
613 pub fn aligned_typedef(
614 &mut self,
615 name: Symbol,
616 underlying: TypeId,
617 align: NonZeroU32,
618 ) -> TypeId {
619 self.intern(Type::new(TypeKind::Typedef {
620 name,
621 underlying,
622 align: Some(align),
623 may_alias: false,
624 }))
625 }
626
627 /// A typedef that said `may_alias`, and perhaps what an object of it is aligned to as well.
628 /// See [`TypeKind::Typedef`].
629 pub fn may_alias_typedef(
630 &mut self,
631 name: Symbol,
632 underlying: TypeId,
633 align: Option<NonZeroU32>,
634 ) -> TypeId {
635 self.intern(Type::new(TypeKind::Typedef { name, underlying, align, may_alias: true }))
636 }
637
638 /// Whether any typedef in `id`'s sugar said `may_alias`.
639 ///
640 /// Any of them rather than the nearest, unlike [`Self::align_override`], because a typedef
641 /// of a type that may alias anything cannot take that back: `typedef A B` over an `A` that
642 /// said it is still a type an access through which may touch anything.
643 ///
644 /// # Panics
645 ///
646 /// Panics if `id` came from a different table.
647 #[must_use]
648 pub fn may_alias(&self, id: TypeId) -> bool {
649 let mut id = id;
650 loop {
651 let TypeKind::Typedef { underlying, may_alias, .. } = self.kind(id) else {
652 return false;
653 };
654 if may_alias {
655 return true;
656 }
657 id = underlying;
658 }
659 }
660
661 /// What a typedef in `id`'s sugar asked an object of it to be aligned to, and [`None`] when
662 /// none of them asked for anything.
663 ///
664 /// The nearest one wins, because `typedef L M __attribute__((aligned(8)))` over an `L` that
665 /// asked for two is an eight and not a two: the outer typedef is the one the declaration was
666 /// written with. Below the sugar there is nothing to find, since only a typedef can carry one
667 /// of these, so the walk stops at the first node that is not one.
668 ///
669 /// # Panics
670 ///
671 /// Panics if `id` came from a different table.
672 #[must_use]
673 pub fn align_override(&self, id: TypeId) -> Option<NonZeroU32> {
674 let mut id = id;
675 loop {
676 let TypeKind::Typedef { underlying, align, .. } = self.kind(id) else { return None };
677 if align.is_some() {
678 return align;
679 }
680 id = underlying;
681 }
682 }
683
684 /// `id` with `quals` added to whatever it already carries.
685 ///
686 /// Qualifying an array qualifies its element type and leaves the array itself unqualified,
687 /// which is 6.7.3p10 and is not a shortcut. An array type has no qualifiers of its own,
688 /// and if it did then `const` on an array parameter would mean nothing at all.
689 pub fn qualified(&mut self, id: TypeId, quals: Qualifiers) -> TypeId {
690 if quals.is_none() {
691 return id;
692 }
693 let ty = self.get(id);
694 if let TypeKind::Array { elem, len } = ty.kind {
695 let elem = self.qualified(elem, quals);
696 return self.intern(Type { kind: TypeKind::Array { elem, len }, quals: ty.quals });
697 }
698 self.intern(Type { kind: ty.kind, quals: ty.quals.with(quals) })
699 }
700
701 /// `id` with every qualifier removed from its outermost node.
702 ///
703 /// Only the outermost, because that is what the standard means by the unqualified version
704 /// of a type. The pointee of a `const char *` stays `const`.
705 pub fn unqualified(&mut self, id: TypeId) -> TypeId {
706 let ty = self.get(id);
707 if ty.quals.is_none() {
708 return id;
709 }
710 self.intern(Type::new(ty.kind))
711 }
712
713 /// The qualifiers an object of `id` carries, which for an array are its element's.
714 ///
715 /// [`Self::quals`] answers what the node holds, and [`Self::qualified`] has just put an array's
716 /// qualifiers on its element rather than on the array, so the node holds nothing and an object
717 /// of the type is still `const`. That gap is only visible in one place, which is a pointer to an
718 /// array: `const int (*)[4]` points at something nobody may write to and asking the array node
719 /// says otherwise.
720 #[must_use]
721 pub fn object_quals(&self, id: TypeId) -> Qualifiers {
722 let ty = self.get(id);
723 match ty.kind {
724 TypeKind::Array { elem, .. } => ty.quals.with(self.object_quals(elem)),
725 _ => ty.quals,
726 }
727 }
728
729 /// `id` with the qualifiers of an object of it removed, which for an array are its element's.
730 ///
731 /// [`Self::unqualified`] taken through an array for the same reason [`Self::object_quals`] is,
732 /// so that the two agree about where an array keeps its qualifiers. What it is for is the
733 /// comparison in a pointer assignment: C's own compatibility says `const int [4]` and `int [4]`
734 /// are different types, because the element types are, so `const int (*)[4] = p` would be an
735 /// incompatible pointer rather than a qualifier being added. Every compiler takes it, C23 says
736 /// so outright, and taking the qualifiers off both sides before comparing is what makes the
737 /// assignment rule read the array the way it reads everything else.
738 pub fn unqualified_object(&mut self, id: TypeId) -> TypeId {
739 let ty = self.get(id);
740 if let TypeKind::Array { elem, len } = ty.kind {
741 let elem = self.unqualified_object(elem);
742 return self.intern(Type::new(TypeKind::Array { elem, len }));
743 }
744 self.unqualified(id)
745 }
746
747 /// The id for `ty`, making one if this is the first time it has been asked for.
748 fn intern(&mut self, ty: Type) -> TypeId {
749 if let Some(&id) = self.map.get(&ty) {
750 return id;
751 }
752 // Canonicalising can intern other types, which means `self.entries` may have grown by
753 // the time this returns and the id below has to be taken afterwards. It cannot have
754 // interned `ty` itself, because a canonical type differs from the sugar it came from,
755 // but the second lookup is one hash of a cold path against a duplicate entry that
756 // would quietly break the promise that equal ids mean equal types.
757 let canonical = self.canonicalise(&ty);
758 if let Some(&id) = self.map.get(&ty) {
759 return id;
760 }
761 let id = TypeId(Idx::from_usize(self.entries.len()));
762 self.entries.push(Entry { ty, canonical: canonical.unwrap_or(id) });
763 self.map.insert(ty, id);
764 id
765 }
766
767 /// The canonical form of `ty`, or `None` when `ty` is already canonical.
768 ///
769 /// A typedef is not the only place sugar hides. `T *` is sugar when `T` is, and so is an
770 /// array of one, and so is a function that returns one, so this rebuilds the type around
771 /// whatever its parts canonicalise to rather than only looking at the outermost node.
772 fn canonicalise(&mut self, ty: &Type) -> Option<TypeId> {
773 match ty.kind {
774 TypeKind::Typedef { underlying, .. } => {
775 let base = self.canonical(underlying);
776 Some(self.qualified(base, ty.quals))
777 }
778 TypeKind::Pointer(inner) => self.rebuild(ty, inner, TypeKind::Pointer),
779 TypeKind::Atomic(inner) => self.rebuild(ty, inner, TypeKind::Atomic),
780 TypeKind::Complex(part) => self.rebuild(ty, part, TypeKind::Complex),
781 TypeKind::Array { elem, len } => {
782 self.rebuild(ty, elem, |elem| TypeKind::Array { elem, len })
783 }
784 TypeKind::Vector { elem, len } => {
785 self.rebuild(ty, elem, |elem| TypeKind::Vector { elem, len })
786 }
787 TypeKind::Function(id) => self.canonicalise_function(ty, id),
788 TypeKind::Void
789 | TypeKind::Bool
790 | TypeKind::Int(_)
791 | TypeKind::Float(_)
792 | TypeKind::BitInt { .. }
793 | TypeKind::Record(_)
794 | TypeKind::Enum(_) => None,
795 }
796 }
797
798 /// The canonical form of a type built out of one other type.
799 fn rebuild(
800 &mut self,
801 ty: &Type,
802 inner: TypeId,
803 make: impl FnOnce(TypeId) -> TypeKind,
804 ) -> Option<TypeId> {
805 let canonical = self.canonical(inner);
806 if canonical == inner {
807 return None;
808 }
809 Some(self.intern(Type { kind: make(canonical), quals: ty.quals }))
810 }
811
812 /// The canonical form of a function type, which is sugar when any part of its signature is.
813 fn canonicalise_function(&mut self, ty: &Type, id: FunctionId) -> Option<TypeId> {
814 let signature = self.signature(id).clone();
815 let ret = self.canonical(signature.ret);
816 let params: Vec<TypeId> =
817 signature.params.iter().map(|¶m| self.canonical(param)).collect();
818 if ret == signature.ret && params == signature.params {
819 return None;
820 }
821 let canonical = FunctionType { ret, params, ..signature };
822 let id = self.function(canonical);
823 Some(self.qualified(id, ty.quals))
824 }
825}