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