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;
12
13use rucc_base::{Idx, Symbol};
14
15use crate::kind::{
16    ArrayLen, EnumId, FloatKind, FunctionId, FunctionType, IntKind, Qualifiers, RecordId,
17    RecordKind, Type, TypeKind,
18};
19use crate::layout::Layout;
20use crate::record::{Field, RecordLayout};
21
22/// The identity of a type.
23///
24/// Four bytes, `Copy`, and equal exactly when the two types are the same type. Ids from two
25/// different [`Types`] tables are not comparable, which is not a restriction in practice
26/// because there is one table per translation unit.
27#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
28pub struct TypeId(Idx<Entry>);
29
30impl std::fmt::Debug for TypeId {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        write!(f, "TypeId#{}", self.0.raw())
33    }
34}
35
36/// One row of the table.
37///
38/// The canonical id is stored rather than computed because almost every read of a type wants
39/// it, and computing it means walking a chain whose length is however many typedefs the header
40/// author felt like writing.
41#[derive(Debug, Clone, Copy)]
42struct Entry {
43    ty: Type,
44    canonical: TypeId,
45}
46
47/// What is known about one `struct` or `union` declaration.
48#[derive(Debug, Clone)]
49pub struct RecordInfo {
50    /// Whether it is a `struct` or a `union`.
51    pub kind: RecordKind,
52    /// The tag, absent for an anonymous one.
53    pub tag: Option<Symbol>,
54    /// The layout, absent until the members have been seen and laid out.
55    ///
56    /// This is also what says whether the type is complete. A record is incomplete from the
57    /// point its tag is first mentioned until its closing brace, and code in between may
58    /// declare pointers to it and nothing else.
59    pub layout: Option<Layout>,
60    /// The members, placed, and empty until the record is complete.
61    ///
62    /// One entry per member the program wrote, in that order, so a caller that kept the
63    /// declarations can index the two together.
64    pub fields: Vec<Field>,
65}
66
67/// What is known about one `enum` declaration.
68#[derive(Debug, Clone)]
69pub struct EnumInfo {
70    /// The tag, absent for an anonymous one.
71    pub tag: Option<Symbol>,
72    /// The type the enumerators are represented in, absent until it is decided.
73    ///
74    /// C23 lets the program write it, and before that it is chosen once every enumerator has
75    /// been seen. Either way it is a fact about the declaration rather than about the type
76    /// system, so it is recorded here and not derived twice.
77    pub underlying: Option<TypeId>,
78    /// Whether the underlying type was written by the program rather than chosen.
79    ///
80    /// It changes the answer to what an enumerator's own type is, and it decides whether an
81    /// enumerator that does not fit is an error or a reason to widen.
82    pub fixed: bool,
83}
84
85/// Every type in one translation unit.
86#[derive(Debug)]
87pub struct Types {
88    entries: Vec<Entry>,
89    map: HashMap<Type, TypeId>,
90    functions: Vec<FunctionType>,
91    function_map: HashMap<FunctionType, FunctionId>,
92    records: Vec<RecordInfo>,
93    enums: Vec<EnumInfo>,
94    void: TypeId,
95    boolean: TypeId,
96    ints: [TypeId; 13],
97    floats: [TypeId; 3],
98}
99
100impl Default for Types {
101    fn default() -> Types {
102        Types::new()
103    }
104}
105
106impl Types {
107    /// A table holding the basic types and nothing else.
108    ///
109    /// The basic types are interned here rather than on first use so that asking for `int` is
110    /// an array read. They are the ones asked for by far the most often, because every
111    /// integer promotion produces one.
112    #[must_use]
113    pub fn new() -> Types {
114        let mut types = Types {
115            entries: Vec::new(),
116            map: HashMap::new(),
117            functions: Vec::new(),
118            function_map: HashMap::new(),
119            records: Vec::new(),
120            enums: Vec::new(),
121            // Fixed up immediately below. There is no id to put here before the table exists,
122            // and an `Option` on each of them would be paid for on every read for the sake of
123            // four lines of construction.
124            void: TypeId(Idx::new(0)),
125            boolean: TypeId(Idx::new(0)),
126            ints: [TypeId(Idx::new(0)); 13],
127            floats: [TypeId(Idx::new(0)); 3],
128        };
129        types.void = types.intern(Type::new(TypeKind::Void));
130        types.boolean = types.intern(Type::new(TypeKind::Bool));
131        for kind in IntKind::ALL {
132            types.ints[kind.index()] = types.intern(Type::new(TypeKind::Int(kind)));
133        }
134        for kind in FloatKind::ALL {
135            types.floats[kind.index()] = types.intern(Type::new(TypeKind::Float(kind)));
136        }
137        types
138    }
139
140    /// How many distinct types there are.
141    #[must_use]
142    pub fn len(&self) -> usize {
143        self.entries.len()
144    }
145
146    /// Whether the table is empty, which it never is once [`Types::new`] has run.
147    #[must_use]
148    pub fn is_empty(&self) -> bool {
149        self.entries.is_empty()
150    }
151
152    /// The type `id` stands for, with its qualifiers.
153    ///
154    /// # Panics
155    ///
156    /// Panics if `id` came from a different table.
157    #[must_use]
158    pub fn get(&self, id: TypeId) -> Type {
159        self.entries[id.0.index()].ty
160    }
161
162    /// What `id` is, ignoring its qualifiers.
163    ///
164    /// # Panics
165    ///
166    /// Panics if `id` came from a different table.
167    #[must_use]
168    pub fn kind(&self, id: TypeId) -> TypeKind {
169        self.get(id).kind
170    }
171
172    /// What `id` is qualified with.
173    ///
174    /// # Panics
175    ///
176    /// Panics if `id` came from a different table.
177    #[must_use]
178    pub fn quals(&self, id: TypeId) -> Qualifiers {
179        self.get(id).quals
180    }
181
182    /// The canonical form of `id`, with every typedef resolved at every depth.
183    ///
184    /// This is what every semantic rule reads. `id` itself is what every diagnostic prints.
185    ///
186    /// # Panics
187    ///
188    /// Panics if `id` came from a different table.
189    #[must_use]
190    pub fn canonical(&self, id: TypeId) -> TypeId {
191        self.entries[id.0.index()].canonical
192    }
193
194    /// Whether `id` is written with a typedef name somewhere inside it.
195    ///
196    /// # Panics
197    ///
198    /// Panics if `id` came from a different table.
199    #[must_use]
200    pub fn is_sugar(&self, id: TypeId) -> bool {
201        self.canonical(id) != id
202    }
203
204    /// `void`.
205    #[must_use]
206    pub fn void(&self) -> TypeId {
207        self.void
208    }
209
210    /// `bool`, which is `_Bool` in the older spellings.
211    ///
212    /// Named this way because `bool` is a Rust keyword and `r#bool` at every call site would
213    /// be a worse trade than one unusual name here.
214    #[must_use]
215    pub fn boolean(&self) -> TypeId {
216        self.boolean
217    }
218
219    /// One of the standard integer types.
220    #[must_use]
221    pub fn int(&self, kind: IntKind) -> TypeId {
222        self.ints[kind.index()]
223    }
224
225    /// One of the real floating types.
226    #[must_use]
227    pub fn float(&self, kind: FloatKind) -> TypeId {
228        self.floats[kind.index()]
229    }
230
231    /// `_Complex T`.
232    pub fn complex(&mut self, kind: FloatKind) -> TypeId {
233        self.intern(Type::new(TypeKind::Complex(kind)))
234    }
235
236    /// `_BitInt(width)`, signed or not.
237    ///
238    /// The width is not checked against the target's maximum here. That check belongs where
239    /// there is a span to point at, and building the type anyway means the rest of the
240    /// declaration still gets checked instead of collapsing into a cascade.
241    pub fn bit_int(&mut self, signed: bool, width: u32) -> TypeId {
242        self.intern(Type::new(TypeKind::BitInt { signed, width }))
243    }
244
245    /// A pointer to `pointee`.
246    pub fn pointer(&mut self, pointee: TypeId) -> TypeId {
247        self.intern(Type::new(TypeKind::Pointer(pointee)))
248    }
249
250    /// `_Atomic(inner)`.
251    pub fn atomic(&mut self, inner: TypeId) -> TypeId {
252        self.intern(Type::new(TypeKind::Atomic(inner)))
253    }
254
255    /// An array of `elem`.
256    pub fn array(&mut self, elem: TypeId, len: ArrayLen) -> TypeId {
257        self.intern(Type::new(TypeKind::Array { elem, len }))
258    }
259
260    /// A GNU vector of `len` elements of `elem`.
261    pub fn vector(&mut self, elem: TypeId, len: u32) -> TypeId {
262        self.intern(Type::new(TypeKind::Vector { elem, len }))
263    }
264
265    /// A function type, deduplicated by content.
266    ///
267    /// # Panics
268    ///
269    /// Panics past four billion distinct function types in one translation unit. The
270    /// alternative to panicking is handing back an id that means a different type, so the
271    /// limit is stated rather than worked around.
272    pub fn function(&mut self, signature: FunctionType) -> TypeId {
273        let id = match self.function_map.get(&signature) {
274            Some(&id) => id,
275            None => {
276                let id = FunctionId(u32::try_from(self.functions.len()).expect("too many types"));
277                self.functions.push(signature.clone());
278                self.function_map.insert(signature, id);
279                id
280            }
281        };
282        self.intern(Type::new(TypeKind::Function(id)))
283    }
284
285    /// The signature behind a function type.
286    ///
287    /// # Panics
288    ///
289    /// Panics if `id` came from a different table.
290    #[must_use]
291    pub fn signature(&self, id: FunctionId) -> &FunctionType {
292        &self.functions[id.0 as usize]
293    }
294
295    /// Declares a `struct` or `union` that has been named but not yet laid out.
296    ///
297    /// Each call makes a new type even for the same tag, because a record type in C is its
298    /// declaration. Redeclaring a tag in an inner scope makes a different type, and the two
299    /// being distinct is what the scope rules mean.
300    ///
301    /// # Panics
302    ///
303    /// Panics past four billion record declarations in one translation unit.
304    pub fn declare_record(&mut self, kind: RecordKind, tag: Option<Symbol>) -> RecordId {
305        let id = RecordId(u32::try_from(self.records.len()).expect("too many types"));
306        self.records.push(RecordInfo { kind, tag, layout: None, fields: Vec::new() });
307        id
308    }
309
310    /// The type of a declared record.
311    pub fn record(&mut self, id: RecordId) -> TypeId {
312        self.intern(Type::new(TypeKind::Record(id)))
313    }
314
315    /// What is known about a declared record.
316    ///
317    /// # Panics
318    ///
319    /// Panics if `id` came from a different table.
320    #[must_use]
321    pub fn record_info(&self, id: RecordId) -> &RecordInfo {
322        &self.records[id.0 as usize]
323    }
324
325    /// Completes a record by recording what [`layout_record`](crate::layout_record) produced.
326    ///
327    /// # Panics
328    ///
329    /// Panics if `id` came from a different table.
330    pub fn complete_record(&mut self, id: RecordId, laid_out: RecordLayout) {
331        let info = &mut self.records[id.0 as usize];
332        info.layout = Some(laid_out.layout);
333        info.fields = laid_out.fields;
334    }
335
336    /// The member of a record with the given name.
337    ///
338    /// Direct members only. Reaching into an anonymous member is a name lookup with a path to
339    /// build rather than a search, so it belongs to whoever is resolving the expression.
340    ///
341    /// # Panics
342    ///
343    /// Panics if `id` came from a different table.
344    #[must_use]
345    pub fn field(&self, id: RecordId, name: Symbol) -> Option<&Field> {
346        self.records[id.0 as usize].fields.iter().find(|field| field.name == Some(name))
347    }
348
349    /// Declares an `enum` whose underlying type is not decided yet.
350    ///
351    /// # Panics
352    ///
353    /// Panics past four billion enumeration declarations in one translation unit.
354    pub fn declare_enum(&mut self, tag: Option<Symbol>) -> EnumId {
355        let id = EnumId(u32::try_from(self.enums.len()).expect("too many types"));
356        self.enums.push(EnumInfo { tag, underlying: None, fixed: false });
357        id
358    }
359
360    /// The type of a declared enumeration.
361    pub fn enumeration(&mut self, id: EnumId) -> TypeId {
362        self.intern(Type::new(TypeKind::Enum(id)))
363    }
364
365    /// What is known about a declared enumeration.
366    ///
367    /// # Panics
368    ///
369    /// Panics if `id` came from a different table.
370    #[must_use]
371    pub fn enum_info(&self, id: EnumId) -> &EnumInfo {
372        &self.enums[id.0 as usize]
373    }
374
375    /// Records what an enumeration is represented in, and whether the program said so.
376    ///
377    /// # Panics
378    ///
379    /// Panics if `id` came from a different table.
380    pub fn complete_enum(&mut self, id: EnumId, underlying: TypeId, fixed: bool) {
381        let info = &mut self.enums[id.0 as usize];
382        info.underlying = Some(underlying);
383        info.fixed = fixed;
384    }
385
386    /// A typedef name standing for `underlying`.
387    pub fn typedef(&mut self, name: Symbol, underlying: TypeId) -> TypeId {
388        self.intern(Type::new(TypeKind::Typedef { name, underlying }))
389    }
390
391    /// `id` with `quals` added to whatever it already carries.
392    ///
393    /// Qualifying an array qualifies its element type and leaves the array itself unqualified,
394    /// which is 6.7.3p10 and is not a shortcut. An array type has no qualifiers of its own,
395    /// and if it did then `const` on an array parameter would mean nothing at all.
396    pub fn qualified(&mut self, id: TypeId, quals: Qualifiers) -> TypeId {
397        if quals.is_none() {
398            return id;
399        }
400        let ty = self.get(id);
401        if let TypeKind::Array { elem, len } = ty.kind {
402            let elem = self.qualified(elem, quals);
403            return self.intern(Type { kind: TypeKind::Array { elem, len }, quals: ty.quals });
404        }
405        self.intern(Type { kind: ty.kind, quals: ty.quals.with(quals) })
406    }
407
408    /// `id` with every qualifier removed from its outermost node.
409    ///
410    /// Only the outermost, because that is what the standard means by the unqualified version
411    /// of a type. The pointee of a `const char *` stays `const`.
412    pub fn unqualified(&mut self, id: TypeId) -> TypeId {
413        let ty = self.get(id);
414        if ty.quals.is_none() {
415            return id;
416        }
417        self.intern(Type::new(ty.kind))
418    }
419
420    /// The id for `ty`, making one if this is the first time it has been asked for.
421    fn intern(&mut self, ty: Type) -> TypeId {
422        if let Some(&id) = self.map.get(&ty) {
423            return id;
424        }
425        // Canonicalising can intern other types, which means `self.entries` may have grown by
426        // the time this returns and the id below has to be taken afterwards. It cannot have
427        // interned `ty` itself, because a canonical type differs from the sugar it came from,
428        // but the second lookup is one hash of a cold path against a duplicate entry that
429        // would quietly break the promise that equal ids mean equal types.
430        let canonical = self.canonicalise(&ty);
431        if let Some(&id) = self.map.get(&ty) {
432            return id;
433        }
434        let id = TypeId(Idx::from_usize(self.entries.len()));
435        self.entries.push(Entry { ty, canonical: canonical.unwrap_or(id) });
436        self.map.insert(ty, id);
437        id
438    }
439
440    /// The canonical form of `ty`, or `None` when `ty` is already canonical.
441    ///
442    /// A typedef is not the only place sugar hides. `T *` is sugar when `T` is, and so is an
443    /// array of one, and so is a function that returns one, so this rebuilds the type around
444    /// whatever its parts canonicalise to rather than only looking at the outermost node.
445    fn canonicalise(&mut self, ty: &Type) -> Option<TypeId> {
446        match ty.kind {
447            TypeKind::Typedef { underlying, .. } => {
448                let base = self.canonical(underlying);
449                Some(self.qualified(base, ty.quals))
450            }
451            TypeKind::Pointer(inner) => self.rebuild(ty, inner, TypeKind::Pointer),
452            TypeKind::Atomic(inner) => self.rebuild(ty, inner, TypeKind::Atomic),
453            TypeKind::Array { elem, len } => {
454                self.rebuild(ty, elem, |elem| TypeKind::Array { elem, len })
455            }
456            TypeKind::Vector { elem, len } => {
457                self.rebuild(ty, elem, |elem| TypeKind::Vector { elem, len })
458            }
459            TypeKind::Function(id) => self.canonicalise_function(ty, id),
460            TypeKind::Void
461            | TypeKind::Bool
462            | TypeKind::Int(_)
463            | TypeKind::Float(_)
464            | TypeKind::Complex(_)
465            | TypeKind::BitInt { .. }
466            | TypeKind::Record(_)
467            | TypeKind::Enum(_) => None,
468        }
469    }
470
471    /// The canonical form of a type built out of one other type.
472    fn rebuild(
473        &mut self,
474        ty: &Type,
475        inner: TypeId,
476        make: impl FnOnce(TypeId) -> TypeKind,
477    ) -> Option<TypeId> {
478        let canonical = self.canonical(inner);
479        if canonical == inner {
480            return None;
481        }
482        Some(self.intern(Type { kind: make(canonical), quals: ty.quals }))
483    }
484
485    /// The canonical form of a function type, which is sugar when any part of its signature is.
486    fn canonicalise_function(&mut self, ty: &Type, id: FunctionId) -> Option<TypeId> {
487        let signature = self.signature(id).clone();
488        let ret = self.canonical(signature.ret);
489        let params: Vec<TypeId> =
490            signature.params.iter().map(|&param| self.canonical(param)).collect();
491        if ret == signature.ret && params == signature.params {
492            return None;
493        }
494        let canonical = FunctionType { ret, params, ..signature };
495        let id = self.function(canonical);
496        Some(self.qualified(id, ty.quals))
497    }
498}