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