Skip to main content

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::collections::HashMap;
12use std::num::NonZeroU32;
13
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}
84
85/// What is known about one `enum` declaration.
86#[derive(Debug, Clone)]
87pub struct EnumInfo {
88    /// The tag, absent for an anonymous one.
89    pub tag: Option<Symbol>,
90    /// The type the enumerators are represented in, absent until it is decided.
91    ///
92    /// C23 lets the program write it, and before that it is chosen once every enumerator has
93    /// been seen. Either way it is a fact about the declaration rather than about the type
94    /// system, so it is recorded here and not derived twice.
95    pub underlying: Option<TypeId>,
96    /// Whether the underlying type was written by the program rather than chosen.
97    ///
98    /// It changes the answer to what an enumerator's own type is, and it decides whether an
99    /// enumerator that does not fit is an error or a reason to widen.
100    pub fixed: bool,
101}
102
103/// Every type in one translation unit.
104#[derive(Debug)]
105pub struct Types {
106    entries: Vec<Entry>,
107    map: HashMap<Type, TypeId>,
108    functions: Vec<FunctionType>,
109    function_map: HashMap<FunctionType, FunctionId>,
110    records: Vec<RecordInfo>,
111    enums: Vec<EnumInfo>,
112    void: TypeId,
113    boolean: TypeId,
114    ints: [TypeId; 13],
115    floats: [TypeId; 9],
116}
117
118impl Default for Types {
119    fn default() -> Types {
120        Types::new()
121    }
122}
123
124impl Types {
125    /// A table holding the basic types and nothing else.
126    ///
127    /// The basic types are interned here rather than on first use so that asking for `int` is
128    /// an array read. They are the ones asked for by far the most often, because every
129    /// integer promotion produces one.
130    #[must_use]
131    pub fn new() -> Types {
132        let mut types = Types {
133            entries: Vec::new(),
134            map: HashMap::new(),
135            functions: Vec::new(),
136            function_map: HashMap::new(),
137            records: Vec::new(),
138            enums: Vec::new(),
139            // Fixed up immediately below. There is no id to put here before the table exists,
140            // and an `Option` on each of them would be paid for on every read for the sake of
141            // four lines of construction.
142            void: TypeId(Idx::new(0)),
143            boolean: TypeId(Idx::new(0)),
144            ints: [TypeId(Idx::new(0)); 13],
145            floats: [TypeId(Idx::new(0)); 9],
146        };
147        types.void = types.intern(Type::new(TypeKind::Void));
148        types.boolean = types.intern(Type::new(TypeKind::Bool));
149        for kind in IntKind::ALL {
150            types.ints[kind.index()] = types.intern(Type::new(TypeKind::Int(kind)));
151        }
152        for kind in FloatKind::ALL {
153            types.floats[kind.index()] = types.intern(Type::new(TypeKind::Float(kind)));
154        }
155        types
156    }
157
158    /// How many distinct types there are.
159    #[must_use]
160    pub fn len(&self) -> usize {
161        self.entries.len()
162    }
163
164    /// Whether the table is empty, which it never is once [`Types::new`] has run.
165    #[must_use]
166    pub fn is_empty(&self) -> bool {
167        self.entries.is_empty()
168    }
169
170    /// The type `id` stands for, with its qualifiers.
171    ///
172    /// # Panics
173    ///
174    /// Panics if `id` came from a different table.
175    #[must_use]
176    pub fn get(&self, id: TypeId) -> Type {
177        self.entries[id.0.index()].ty
178    }
179
180    /// What `id` is, ignoring its qualifiers.
181    ///
182    /// # Panics
183    ///
184    /// Panics if `id` came from a different table.
185    #[must_use]
186    pub fn kind(&self, id: TypeId) -> TypeKind {
187        self.get(id).kind
188    }
189
190    /// What `id` is qualified with.
191    ///
192    /// # Panics
193    ///
194    /// Panics if `id` came from a different table.
195    #[must_use]
196    pub fn quals(&self, id: TypeId) -> Qualifiers {
197        self.get(id).quals
198    }
199
200    /// The canonical form of `id`, with every typedef resolved at every depth.
201    ///
202    /// This is what every semantic rule reads. `id` itself is what every diagnostic prints.
203    ///
204    /// # Panics
205    ///
206    /// Panics if `id` came from a different table.
207    #[must_use]
208    pub fn canonical(&self, id: TypeId) -> TypeId {
209        self.entries[id.0.index()].canonical
210    }
211
212    /// Whether `id` is written with a typedef name somewhere inside it.
213    ///
214    /// # Panics
215    ///
216    /// Panics if `id` came from a different table.
217    #[must_use]
218    pub fn is_sugar(&self, id: TypeId) -> bool {
219        self.canonical(id) != id
220    }
221
222    /// `void`.
223    #[must_use]
224    pub fn void(&self) -> TypeId {
225        self.void
226    }
227
228    /// `bool`, which is `_Bool` in the older spellings.
229    ///
230    /// Named this way because `bool` is a Rust keyword and `r#bool` at every call site would
231    /// be a worse trade than one unusual name here.
232    #[must_use]
233    pub fn boolean(&self) -> TypeId {
234        self.boolean
235    }
236
237    /// One of the standard integer types.
238    #[must_use]
239    pub fn int(&self, kind: IntKind) -> TypeId {
240        self.ints[kind.index()]
241    }
242
243    /// One of the real floating types.
244    #[must_use]
245    pub fn float(&self, kind: FloatKind) -> TypeId {
246        self.floats[kind.index()]
247    }
248
249    /// `_Complex T` for the real type `T`, which is one of the halves.
250    pub fn complex(&mut self, part: TypeId) -> TypeId {
251        self.intern(Type::new(TypeKind::Complex(part)))
252    }
253
254    /// `_Complex T` for a real floating `T`, which is the spelling C has.
255    pub fn complex_float(&mut self, kind: FloatKind) -> TypeId {
256        let part = self.float(kind);
257        self.complex(part)
258    }
259
260    /// `_BitInt(width)`, signed or not.
261    ///
262    /// The width is not checked against the target's maximum here. That check belongs where
263    /// there is a span to point at, and building the type anyway means the rest of the
264    /// declaration still gets checked instead of collapsing into a cascade.
265    pub fn bit_int(&mut self, signed: bool, width: u32) -> TypeId {
266        self.intern(Type::new(TypeKind::BitInt { signed, width }))
267    }
268
269    /// A pointer to `pointee`.
270    pub fn pointer(&mut self, pointee: TypeId) -> TypeId {
271        self.intern(Type::new(TypeKind::Pointer(pointee)))
272    }
273
274    /// `_Atomic(inner)`.
275    pub fn atomic(&mut self, inner: TypeId) -> TypeId {
276        self.intern(Type::new(TypeKind::Atomic(inner)))
277    }
278
279    /// An array of `elem`.
280    pub fn array(&mut self, elem: TypeId, len: ArrayLen) -> TypeId {
281        self.intern(Type::new(TypeKind::Array { elem, len }))
282    }
283
284    /// A GNU vector of `len` elements of `elem`.
285    pub fn vector(&mut self, elem: TypeId, len: u32) -> TypeId {
286        self.intern(Type::new(TypeKind::Vector { elem, len }))
287    }
288
289    /// A function type, deduplicated by content.
290    ///
291    /// # Panics
292    ///
293    /// Panics past four billion distinct function types in one translation unit. The
294    /// alternative to panicking is handing back an id that means a different type, so the
295    /// limit is stated rather than worked around.
296    pub fn function(&mut self, signature: FunctionType) -> TypeId {
297        let id = match self.function_map.get(&signature) {
298            Some(&id) => id,
299            None => {
300                let id = FunctionId(u32::try_from(self.functions.len()).expect("too many types"));
301                self.functions.push(signature.clone());
302                self.function_map.insert(signature, id);
303                id
304            }
305        };
306        self.intern(Type::new(TypeKind::Function(id)))
307    }
308
309    /// The signature behind a function type.
310    ///
311    /// # Panics
312    ///
313    /// Panics if `id` came from a different table.
314    #[must_use]
315    pub fn signature(&self, id: FunctionId) -> &FunctionType {
316        &self.functions[id.0 as usize]
317    }
318
319    /// Declares a `struct` or `union` that has been named but not yet laid out.
320    ///
321    /// Each call makes a new type even for the same tag, because a record type in C is its
322    /// declaration. Redeclaring a tag in an inner scope makes a different type, and the two
323    /// being distinct is what the scope rules mean.
324    ///
325    /// # Panics
326    ///
327    /// Panics past four billion record declarations in one translation unit.
328    pub fn declare_record(&mut self, kind: RecordKind, tag: Option<Symbol>) -> RecordId {
329        let id = RecordId(u32::try_from(self.records.len()).expect("too many types"));
330        self.records.push(RecordInfo {
331            kind,
332            tag,
333            layout: None,
334            variable: None,
335            fields: Vec::new(),
336            transparent: false,
337        });
338        id
339    }
340
341    /// Records that a union was declared transparent, which is a decision made elsewhere.
342    ///
343    /// Whether the attribute holds up is a question about the members and their layout, so it is
344    /// answered where the members are read rather than here, and this only writes the answer down.
345    /// It is a fact about the declaration and not about one spelling of it, which is why the whole
346    /// record is marked rather than a variant of the type: every name for the union is the same
347    /// union and a parameter written with any of them takes the same values.
348    ///
349    /// # Panics
350    ///
351    /// Panics if `id` came from a different table.
352    pub fn make_transparent(&mut self, id: RecordId) {
353        self.records[id.0 as usize].transparent = true;
354    }
355
356    /// The type of a declared record.
357    pub fn record(&mut self, id: RecordId) -> TypeId {
358        self.intern(Type::new(TypeKind::Record(id)))
359    }
360
361    /// What is known about a declared record.
362    ///
363    /// # Panics
364    ///
365    /// Panics if `id` came from a different table.
366    #[must_use]
367    pub fn record_info(&self, id: RecordId) -> &RecordInfo {
368        &self.records[id.0 as usize]
369    }
370
371    /// Every record declared so far, in declaration order.
372    ///
373    /// For whoever wants to say something about all of them rather than about one, which so
374    /// far is [`measure_all`](crate::measure_all), measuring how their bytes fall into granules.
375    ///
376    /// # Panics
377    ///
378    /// Panics if more than `u32::MAX` records have been declared, which every other index into
379    /// this table would already have panicked on.
380    pub fn records(&self) -> impl Iterator<Item = (RecordId, &RecordInfo)> {
381        self.records
382            .iter()
383            .enumerate()
384            .map(|(index, info)| (RecordId(u32::try_from(index).expect("a declared record")), info))
385    }
386
387    /// Completes a record by recording what [`layout_record`](crate::layout_record) produced.
388    ///
389    /// # Panics
390    ///
391    /// Panics if `id` came from a different table.
392    pub fn complete_record(&mut self, id: RecordId, laid_out: RecordLayout) {
393        let info = &mut self.records[id.0 as usize];
394        info.layout = Some(laid_out.layout);
395        info.variable = laid_out.variable;
396        info.fields = laid_out.fields;
397    }
398
399    /// The member of a record with the given name.
400    ///
401    /// Direct members only. Reaching into an anonymous member is a name lookup with a path to
402    /// build rather than a search, so it belongs to whoever is resolving the expression.
403    ///
404    /// # Panics
405    ///
406    /// Panics if `id` came from a different table.
407    #[must_use]
408    pub fn field(&self, id: RecordId, name: Symbol) -> Option<&Field> {
409        self.records[id.0 as usize].fields.iter().find(|field| field.name == Some(name))
410    }
411
412    /// Declares an `enum` whose underlying type is not decided yet.
413    ///
414    /// # Panics
415    ///
416    /// Panics past four billion enumeration declarations in one translation unit.
417    pub fn declare_enum(&mut self, tag: Option<Symbol>) -> EnumId {
418        let id = EnumId(u32::try_from(self.enums.len()).expect("too many types"));
419        self.enums.push(EnumInfo { tag, underlying: None, fixed: false });
420        id
421    }
422
423    /// The type of a declared enumeration.
424    pub fn enumeration(&mut self, id: EnumId) -> TypeId {
425        self.intern(Type::new(TypeKind::Enum(id)))
426    }
427
428    /// What is known about a declared enumeration.
429    ///
430    /// # Panics
431    ///
432    /// Panics if `id` came from a different table.
433    #[must_use]
434    pub fn enum_info(&self, id: EnumId) -> &EnumInfo {
435        &self.enums[id.0 as usize]
436    }
437
438    /// Records what an enumeration is represented in, and whether the program said so.
439    ///
440    /// # Panics
441    ///
442    /// Panics if `id` came from a different table.
443    pub fn complete_enum(&mut self, id: EnumId, underlying: TypeId, fixed: bool) {
444        let info = &mut self.enums[id.0 as usize];
445        info.underlying = Some(underlying);
446        info.fixed = fixed;
447    }
448
449    /// A typedef name standing for `underlying`.
450    pub fn typedef(&mut self, name: Symbol, underlying: TypeId) -> TypeId {
451        self.intern(Type::new(TypeKind::Typedef { name, underlying, align: None }))
452    }
453
454    /// The same, for a typedef that said what an object of it is aligned to.
455    ///
456    /// `align` is in bytes and is what the type is aligned to rather than a floor on it, which
457    /// is what `__attribute__((aligned(n)))` means in this one position. See
458    /// [`TypeKind::Typedef`].
459    pub fn aligned_typedef(
460        &mut self,
461        name: Symbol,
462        underlying: TypeId,
463        align: NonZeroU32,
464    ) -> TypeId {
465        self.intern(Type::new(TypeKind::Typedef { name, underlying, align: Some(align) }))
466    }
467
468    /// What a typedef in `id`'s sugar asked an object of it to be aligned to, and [`None`] when
469    /// none of them asked for anything.
470    ///
471    /// The nearest one wins, because `typedef L M __attribute__((aligned(8)))` over an `L` that
472    /// asked for two is an eight and not a two: the outer typedef is the one the declaration was
473    /// written with. Below the sugar there is nothing to find, since only a typedef can carry one
474    /// of these, so the walk stops at the first node that is not one.
475    ///
476    /// # Panics
477    ///
478    /// Panics if `id` came from a different table.
479    #[must_use]
480    pub fn align_override(&self, id: TypeId) -> Option<NonZeroU32> {
481        let mut id = id;
482        loop {
483            let TypeKind::Typedef { underlying, align, .. } = self.kind(id) else { return None };
484            if align.is_some() {
485                return align;
486            }
487            id = underlying;
488        }
489    }
490
491    /// `id` with `quals` added to whatever it already carries.
492    ///
493    /// Qualifying an array qualifies its element type and leaves the array itself unqualified,
494    /// which is 6.7.3p10 and is not a shortcut. An array type has no qualifiers of its own,
495    /// and if it did then `const` on an array parameter would mean nothing at all.
496    pub fn qualified(&mut self, id: TypeId, quals: Qualifiers) -> TypeId {
497        if quals.is_none() {
498            return id;
499        }
500        let ty = self.get(id);
501        if let TypeKind::Array { elem, len } = ty.kind {
502            let elem = self.qualified(elem, quals);
503            return self.intern(Type { kind: TypeKind::Array { elem, len }, quals: ty.quals });
504        }
505        self.intern(Type { kind: ty.kind, quals: ty.quals.with(quals) })
506    }
507
508    /// `id` with every qualifier removed from its outermost node.
509    ///
510    /// Only the outermost, because that is what the standard means by the unqualified version
511    /// of a type. The pointee of a `const char *` stays `const`.
512    pub fn unqualified(&mut self, id: TypeId) -> TypeId {
513        let ty = self.get(id);
514        if ty.quals.is_none() {
515            return id;
516        }
517        self.intern(Type::new(ty.kind))
518    }
519
520    /// The qualifiers an object of `id` carries, which for an array are its element's.
521    ///
522    /// [`Self::quals`] answers what the node holds, and [`Self::qualified`] has just put an array's
523    /// qualifiers on its element rather than on the array, so the node holds nothing and an object
524    /// of the type is still `const`. That gap is only visible in one place, which is a pointer to an
525    /// array: `const int (*)[4]` points at something nobody may write to and asking the array node
526    /// says otherwise.
527    #[must_use]
528    pub fn object_quals(&self, id: TypeId) -> Qualifiers {
529        let ty = self.get(id);
530        match ty.kind {
531            TypeKind::Array { elem, .. } => ty.quals.with(self.object_quals(elem)),
532            _ => ty.quals,
533        }
534    }
535
536    /// `id` with the qualifiers of an object of it removed, which for an array are its element's.
537    ///
538    /// [`Self::unqualified`] taken through an array for the same reason [`Self::object_quals`] is,
539    /// so that the two agree about where an array keeps its qualifiers. What it is for is the
540    /// comparison in a pointer assignment: C's own compatibility says `const int [4]` and `int [4]`
541    /// are different types, because the element types are, so `const int (*)[4] = p` would be an
542    /// incompatible pointer rather than a qualifier being added. Every compiler takes it, C23 says
543    /// so outright, and taking the qualifiers off both sides before comparing is what makes the
544    /// assignment rule read the array the way it reads everything else.
545    pub fn unqualified_object(&mut self, id: TypeId) -> TypeId {
546        let ty = self.get(id);
547        if let TypeKind::Array { elem, len } = ty.kind {
548            let elem = self.unqualified_object(elem);
549            return self.intern(Type::new(TypeKind::Array { elem, len }));
550        }
551        self.unqualified(id)
552    }
553
554    /// The id for `ty`, making one if this is the first time it has been asked for.
555    fn intern(&mut self, ty: Type) -> TypeId {
556        if let Some(&id) = self.map.get(&ty) {
557            return id;
558        }
559        // Canonicalising can intern other types, which means `self.entries` may have grown by
560        // the time this returns and the id below has to be taken afterwards. It cannot have
561        // interned `ty` itself, because a canonical type differs from the sugar it came from,
562        // but the second lookup is one hash of a cold path against a duplicate entry that
563        // would quietly break the promise that equal ids mean equal types.
564        let canonical = self.canonicalise(&ty);
565        if let Some(&id) = self.map.get(&ty) {
566            return id;
567        }
568        let id = TypeId(Idx::from_usize(self.entries.len()));
569        self.entries.push(Entry { ty, canonical: canonical.unwrap_or(id) });
570        self.map.insert(ty, id);
571        id
572    }
573
574    /// The canonical form of `ty`, or `None` when `ty` is already canonical.
575    ///
576    /// A typedef is not the only place sugar hides. `T *` is sugar when `T` is, and so is an
577    /// array of one, and so is a function that returns one, so this rebuilds the type around
578    /// whatever its parts canonicalise to rather than only looking at the outermost node.
579    fn canonicalise(&mut self, ty: &Type) -> Option<TypeId> {
580        match ty.kind {
581            TypeKind::Typedef { underlying, .. } => {
582                let base = self.canonical(underlying);
583                Some(self.qualified(base, ty.quals))
584            }
585            TypeKind::Pointer(inner) => self.rebuild(ty, inner, TypeKind::Pointer),
586            TypeKind::Atomic(inner) => self.rebuild(ty, inner, TypeKind::Atomic),
587            TypeKind::Complex(part) => self.rebuild(ty, part, TypeKind::Complex),
588            TypeKind::Array { elem, len } => {
589                self.rebuild(ty, elem, |elem| TypeKind::Array { elem, len })
590            }
591            TypeKind::Vector { elem, len } => {
592                self.rebuild(ty, elem, |elem| TypeKind::Vector { elem, len })
593            }
594            TypeKind::Function(id) => self.canonicalise_function(ty, id),
595            TypeKind::Void
596            | TypeKind::Bool
597            | TypeKind::Int(_)
598            | TypeKind::Float(_)
599            | TypeKind::BitInt { .. }
600            | TypeKind::Record(_)
601            | TypeKind::Enum(_) => None,
602        }
603    }
604
605    /// The canonical form of a type built out of one other type.
606    fn rebuild(
607        &mut self,
608        ty: &Type,
609        inner: TypeId,
610        make: impl FnOnce(TypeId) -> TypeKind,
611    ) -> Option<TypeId> {
612        let canonical = self.canonical(inner);
613        if canonical == inner {
614            return None;
615        }
616        Some(self.intern(Type { kind: make(canonical), quals: ty.quals }))
617    }
618
619    /// The canonical form of a function type, which is sugar when any part of its signature is.
620    fn canonicalise_function(&mut self, ty: &Type, id: FunctionId) -> Option<TypeId> {
621        let signature = self.signature(id).clone();
622        let ret = self.canonical(signature.ret);
623        let params: Vec<TypeId> =
624            signature.params.iter().map(|&param| self.canonical(param)).collect();
625        if ret == signature.ret && params == signature.params {
626            return None;
627        }
628        let canonical = FunctionType { ret, params, ..signature };
629        let id = self.function(canonical);
630        Some(self.qualified(id, ty.quals))
631    }
632}