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(|¶m| 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}