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`.
233 pub fn complex(&mut self, kind: FloatKind) -> TypeId {
234 self.intern(Type::new(TypeKind::Complex(kind)))
235 }
236
237 /// `_BitInt(width)`, signed or not.
238 ///
239 /// The width is not checked against the target's maximum here. That check belongs where
240 /// there is a span to point at, and building the type anyway means the rest of the
241 /// declaration still gets checked instead of collapsing into a cascade.
242 pub fn bit_int(&mut self, signed: bool, width: u32) -> TypeId {
243 self.intern(Type::new(TypeKind::BitInt { signed, width }))
244 }
245
246 /// A pointer to `pointee`.
247 pub fn pointer(&mut self, pointee: TypeId) -> TypeId {
248 self.intern(Type::new(TypeKind::Pointer(pointee)))
249 }
250
251 /// `_Atomic(inner)`.
252 pub fn atomic(&mut self, inner: TypeId) -> TypeId {
253 self.intern(Type::new(TypeKind::Atomic(inner)))
254 }
255
256 /// An array of `elem`.
257 pub fn array(&mut self, elem: TypeId, len: ArrayLen) -> TypeId {
258 self.intern(Type::new(TypeKind::Array { elem, len }))
259 }
260
261 /// A GNU vector of `len` elements of `elem`.
262 pub fn vector(&mut self, elem: TypeId, len: u32) -> TypeId {
263 self.intern(Type::new(TypeKind::Vector { elem, len }))
264 }
265
266 /// A function type, deduplicated by content.
267 ///
268 /// # Panics
269 ///
270 /// Panics past four billion distinct function types in one translation unit. The
271 /// alternative to panicking is handing back an id that means a different type, so the
272 /// limit is stated rather than worked around.
273 pub fn function(&mut self, signature: FunctionType) -> TypeId {
274 let id = match self.function_map.get(&signature) {
275 Some(&id) => id,
276 None => {
277 let id = FunctionId(u32::try_from(self.functions.len()).expect("too many types"));
278 self.functions.push(signature.clone());
279 self.function_map.insert(signature, id);
280 id
281 }
282 };
283 self.intern(Type::new(TypeKind::Function(id)))
284 }
285
286 /// The signature behind a function type.
287 ///
288 /// # Panics
289 ///
290 /// Panics if `id` came from a different table.
291 #[must_use]
292 pub fn signature(&self, id: FunctionId) -> &FunctionType {
293 &self.functions[id.0 as usize]
294 }
295
296 /// Declares a `struct` or `union` that has been named but not yet laid out.
297 ///
298 /// Each call makes a new type even for the same tag, because a record type in C is its
299 /// declaration. Redeclaring a tag in an inner scope makes a different type, and the two
300 /// being distinct is what the scope rules mean.
301 ///
302 /// # Panics
303 ///
304 /// Panics past four billion record declarations in one translation unit.
305 pub fn declare_record(&mut self, kind: RecordKind, tag: Option<Symbol>) -> RecordId {
306 let id = RecordId(u32::try_from(self.records.len()).expect("too many types"));
307 self.records.push(RecordInfo { kind, tag, layout: None, fields: Vec::new() });
308 id
309 }
310
311 /// The type of a declared record.
312 pub fn record(&mut self, id: RecordId) -> TypeId {
313 self.intern(Type::new(TypeKind::Record(id)))
314 }
315
316 /// What is known about a declared record.
317 ///
318 /// # Panics
319 ///
320 /// Panics if `id` came from a different table.
321 #[must_use]
322 pub fn record_info(&self, id: RecordId) -> &RecordInfo {
323 &self.records[id.0 as usize]
324 }
325
326 /// Every record declared so far, in declaration order.
327 ///
328 /// For whoever wants to say something about all of them rather than about one, which so
329 /// far is [`measure_all`](crate::measure_all), measuring how their bytes fall into granules.
330 ///
331 /// # Panics
332 ///
333 /// Panics if more than `u32::MAX` records have been declared, which every other index into
334 /// this table would already have panicked on.
335 pub fn records(&self) -> impl Iterator<Item = (RecordId, &RecordInfo)> {
336 self.records
337 .iter()
338 .enumerate()
339 .map(|(index, info)| (RecordId(u32::try_from(index).expect("a declared record")), info))
340 }
341
342 /// Completes a record by recording what [`layout_record`](crate::layout_record) produced.
343 ///
344 /// # Panics
345 ///
346 /// Panics if `id` came from a different table.
347 pub fn complete_record(&mut self, id: RecordId, laid_out: RecordLayout) {
348 let info = &mut self.records[id.0 as usize];
349 info.layout = Some(laid_out.layout);
350 info.fields = laid_out.fields;
351 }
352
353 /// The member of a record with the given name.
354 ///
355 /// Direct members only. Reaching into an anonymous member is a name lookup with a path to
356 /// build rather than a search, so it belongs to whoever is resolving the expression.
357 ///
358 /// # Panics
359 ///
360 /// Panics if `id` came from a different table.
361 #[must_use]
362 pub fn field(&self, id: RecordId, name: Symbol) -> Option<&Field> {
363 self.records[id.0 as usize].fields.iter().find(|field| field.name == Some(name))
364 }
365
366 /// Declares an `enum` whose underlying type is not decided yet.
367 ///
368 /// # Panics
369 ///
370 /// Panics past four billion enumeration declarations in one translation unit.
371 pub fn declare_enum(&mut self, tag: Option<Symbol>) -> EnumId {
372 let id = EnumId(u32::try_from(self.enums.len()).expect("too many types"));
373 self.enums.push(EnumInfo { tag, underlying: None, fixed: false });
374 id
375 }
376
377 /// The type of a declared enumeration.
378 pub fn enumeration(&mut self, id: EnumId) -> TypeId {
379 self.intern(Type::new(TypeKind::Enum(id)))
380 }
381
382 /// What is known about a declared enumeration.
383 ///
384 /// # Panics
385 ///
386 /// Panics if `id` came from a different table.
387 #[must_use]
388 pub fn enum_info(&self, id: EnumId) -> &EnumInfo {
389 &self.enums[id.0 as usize]
390 }
391
392 /// Records what an enumeration is represented in, and whether the program said so.
393 ///
394 /// # Panics
395 ///
396 /// Panics if `id` came from a different table.
397 pub fn complete_enum(&mut self, id: EnumId, underlying: TypeId, fixed: bool) {
398 let info = &mut self.enums[id.0 as usize];
399 info.underlying = Some(underlying);
400 info.fixed = fixed;
401 }
402
403 /// A typedef name standing for `underlying`.
404 pub fn typedef(&mut self, name: Symbol, underlying: TypeId) -> TypeId {
405 self.intern(Type::new(TypeKind::Typedef { name, underlying, align: None }))
406 }
407
408 /// The same, for a typedef that said what an object of it is aligned to.
409 ///
410 /// `align` is in bytes and is what the type is aligned to rather than a floor on it, which
411 /// is what `__attribute__((aligned(n)))` means in this one position. See
412 /// [`TypeKind::Typedef`].
413 pub fn aligned_typedef(
414 &mut self,
415 name: Symbol,
416 underlying: TypeId,
417 align: NonZeroU32,
418 ) -> TypeId {
419 self.intern(Type::new(TypeKind::Typedef { name, underlying, align: Some(align) }))
420 }
421
422 /// What a typedef in `id`'s sugar asked an object of it to be aligned to, and [`None`] when
423 /// none of them asked for anything.
424 ///
425 /// The nearest one wins, because `typedef L M __attribute__((aligned(8)))` over an `L` that
426 /// asked for two is an eight and not a two: the outer typedef is the one the declaration was
427 /// written with. Below the sugar there is nothing to find, since only a typedef can carry one
428 /// of these, so the walk stops at the first node that is not one.
429 ///
430 /// # Panics
431 ///
432 /// Panics if `id` came from a different table.
433 #[must_use]
434 pub fn align_override(&self, id: TypeId) -> Option<NonZeroU32> {
435 let mut id = id;
436 loop {
437 let TypeKind::Typedef { underlying, align, .. } = self.kind(id) else { return None };
438 if align.is_some() {
439 return align;
440 }
441 id = underlying;
442 }
443 }
444
445 /// `id` with `quals` added to whatever it already carries.
446 ///
447 /// Qualifying an array qualifies its element type and leaves the array itself unqualified,
448 /// which is 6.7.3p10 and is not a shortcut. An array type has no qualifiers of its own,
449 /// and if it did then `const` on an array parameter would mean nothing at all.
450 pub fn qualified(&mut self, id: TypeId, quals: Qualifiers) -> TypeId {
451 if quals.is_none() {
452 return id;
453 }
454 let ty = self.get(id);
455 if let TypeKind::Array { elem, len } = ty.kind {
456 let elem = self.qualified(elem, quals);
457 return self.intern(Type { kind: TypeKind::Array { elem, len }, quals: ty.quals });
458 }
459 self.intern(Type { kind: ty.kind, quals: ty.quals.with(quals) })
460 }
461
462 /// `id` with every qualifier removed from its outermost node.
463 ///
464 /// Only the outermost, because that is what the standard means by the unqualified version
465 /// of a type. The pointee of a `const char *` stays `const`.
466 pub fn unqualified(&mut self, id: TypeId) -> TypeId {
467 let ty = self.get(id);
468 if ty.quals.is_none() {
469 return id;
470 }
471 self.intern(Type::new(ty.kind))
472 }
473
474 /// The id for `ty`, making one if this is the first time it has been asked for.
475 fn intern(&mut self, ty: Type) -> TypeId {
476 if let Some(&id) = self.map.get(&ty) {
477 return id;
478 }
479 // Canonicalising can intern other types, which means `self.entries` may have grown by
480 // the time this returns and the id below has to be taken afterwards. It cannot have
481 // interned `ty` itself, because a canonical type differs from the sugar it came from,
482 // but the second lookup is one hash of a cold path against a duplicate entry that
483 // would quietly break the promise that equal ids mean equal types.
484 let canonical = self.canonicalise(&ty);
485 if let Some(&id) = self.map.get(&ty) {
486 return id;
487 }
488 let id = TypeId(Idx::from_usize(self.entries.len()));
489 self.entries.push(Entry { ty, canonical: canonical.unwrap_or(id) });
490 self.map.insert(ty, id);
491 id
492 }
493
494 /// The canonical form of `ty`, or `None` when `ty` is already canonical.
495 ///
496 /// A typedef is not the only place sugar hides. `T *` is sugar when `T` is, and so is an
497 /// array of one, and so is a function that returns one, so this rebuilds the type around
498 /// whatever its parts canonicalise to rather than only looking at the outermost node.
499 fn canonicalise(&mut self, ty: &Type) -> Option<TypeId> {
500 match ty.kind {
501 TypeKind::Typedef { underlying, .. } => {
502 let base = self.canonical(underlying);
503 Some(self.qualified(base, ty.quals))
504 }
505 TypeKind::Pointer(inner) => self.rebuild(ty, inner, TypeKind::Pointer),
506 TypeKind::Atomic(inner) => self.rebuild(ty, inner, TypeKind::Atomic),
507 TypeKind::Array { elem, len } => {
508 self.rebuild(ty, elem, |elem| TypeKind::Array { elem, len })
509 }
510 TypeKind::Vector { elem, len } => {
511 self.rebuild(ty, elem, |elem| TypeKind::Vector { elem, len })
512 }
513 TypeKind::Function(id) => self.canonicalise_function(ty, id),
514 TypeKind::Void
515 | TypeKind::Bool
516 | TypeKind::Int(_)
517 | TypeKind::Float(_)
518 | TypeKind::Complex(_)
519 | TypeKind::BitInt { .. }
520 | TypeKind::Record(_)
521 | TypeKind::Enum(_) => None,
522 }
523 }
524
525 /// The canonical form of a type built out of one other type.
526 fn rebuild(
527 &mut self,
528 ty: &Type,
529 inner: TypeId,
530 make: impl FnOnce(TypeId) -> TypeKind,
531 ) -> Option<TypeId> {
532 let canonical = self.canonical(inner);
533 if canonical == inner {
534 return None;
535 }
536 Some(self.intern(Type { kind: make(canonical), quals: ty.quals }))
537 }
538
539 /// The canonical form of a function type, which is sugar when any part of its signature is.
540 fn canonicalise_function(&mut self, ty: &Type, id: FunctionId) -> Option<TypeId> {
541 let signature = self.signature(id).clone();
542 let ret = self.canonical(signature.ret);
543 let params: Vec<TypeId> =
544 signature.params.iter().map(|¶m| self.canonical(param)).collect();
545 if ret == signature.ret && params == signature.params {
546 return None;
547 }
548 let canonical = FunctionType { ret, params, ..signature };
549 let id = self.function(canonical);
550 Some(self.qualified(id, ty.quals))
551 }
552}