Skip to main content

rucc_sema/
tast.rs

1//! The arenas of the typed tree, and everything that hangs off them.
2//!
3//! Design: `spec/03-architecture.md` section 3.3 and `spec/07-types-and-semantics.md` section
4//! 7.12.
5//!
6//! The same shape as the untyped tree and for the same reasons: flat vectors, four-byte
7//! indices, spans out of line, one owner per translation unit and one drop at the end of it.
8//! What is different is that a type is in the node rather than beside it, because every walk
9//! over this tree reads the type of every node it touches, which is exactly not true of spans.
10//!
11//! One [`Tast`] does not own the [`Types`](rucc_types::Types) its nodes point into. A type
12//! outlives the tree that mentions it, the two are built together and handed on together, and
13//! putting the table inside the tree would mean a pass that only wants to ask what a type is
14//! has to borrow the tree to do it.
15
16use std::fmt;
17use std::ops::Index;
18
19use rucc_base::float::Float;
20use rucc_base::{Idx, IdxRange, Symbol};
21use rucc_diag::Span;
22use rucc_lex::StringLiteral;
23use rucc_types::VlaId;
24
25use crate::decl::{Decl, DeclId, DeclList, InitEntry};
26use crate::expr::{Expr, ExprId, ExprList};
27use crate::stmt::{Case, CaseId, Stmt, StmtId, StmtList};
28
29/// A folded constant, in the value table.
30pub type ConstId = Idx<Const>;
31
32/// A string literal, in the literal table.
33pub type StrId = Idx<StringLiteral>;
34
35/// A label, in the label table.
36pub type LabelId = Idx<Label>;
37
38/// The value of a constant expression, after folding.
39///
40/// Integers are held in a hundred and twenty eight bits whatever their type, which covers every
41/// integer type this compiler has including `__int128`. A `_BitInt(N)` wider than that is not
42/// representable here and is refused where it is written rather than silently truncated.
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub enum Const {
45    /// An integer, sign extended into the whole width from the type it has.
46    Int(i128),
47    /// A floating value, in the target's format rather than the host's.
48    Float(Float),
49    /// The address of an object, which is a number nobody knows until the link.
50    Address(Address),
51}
52
53/// An address constant: some object, and how far into it.
54///
55/// This is what `&x`, `a + 1` and `&s.field` fold to, and it is the reason folding hands back
56/// something richer than a number. The value is not known here and will not be known until the
57/// linker places the object, so what a static initializer needs is not the value but the pair
58/// that names it, which is what an object file's relocation records.
59///
60/// A pointer with no object behind it is not one of these. `(int *)4` folds to [`Const::Int`],
61/// because four is the whole answer and nothing has to be relocated.
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub struct Address {
64    /// The object the address is into.
65    pub base: Base,
66    /// How many bytes into it, which a member or a subscript adds to and which may be outside
67    /// the object: `&a[10]` on an `int a[10]` is a valid address constant and is one past it.
68    pub offset: i128,
69}
70
71/// What an address constant is an address of.
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub enum Base {
74    /// A declared object or function, which the linker knows by name.
75    Decl(DeclId),
76    /// A string literal, which has static storage duration and no name of its own.
77    Str(StrId),
78}
79
80/// A label, and the statement it names.
81#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub struct Label {
83    /// The name it was written with.
84    pub name: Symbol,
85    /// The statement it labels, absent for a label that was used and never defined, which is a
86    /// diagnostic rather than a reason to lose the reference.
87    pub stmt: Option<StmtId>,
88}
89
90/// One typed translation unit.
91#[derive(Default)]
92pub struct Tast {
93    exprs: Vec<Expr>,
94    expr_spans: Vec<Span>,
95    stmts: Vec<Stmt>,
96    stmt_spans: Vec<Span>,
97    decls: Vec<Decl>,
98    decl_spans: Vec<Span>,
99
100    consts: Vec<Const>,
101    strings: Vec<StringLiteral>,
102    labels: Vec<Label>,
103    vlas: Vec<ExprId>,
104
105    expr_refs: Vec<ExprId>,
106    stmt_refs: Vec<StmtId>,
107    decl_refs: Vec<DeclId>,
108    cases: Vec<Case>,
109    init_entries: Vec<InitEntry>,
110
111    top_level: Vec<DeclId>,
112}
113
114impl Tast {
115    /// An empty tree.
116    #[must_use]
117    pub fn new() -> Tast {
118        Tast::default()
119    }
120
121    /// The objects and functions of the translation unit, in the order they were declared.
122    #[must_use]
123    pub fn top_level(&self) -> &[DeclId] {
124        &self.top_level
125    }
126
127    /// Adds a declaration at file scope.
128    pub fn add_top_level(&mut self, decl: DeclId) {
129        self.top_level.push(decl);
130    }
131
132    /// Adds an expression, with the source it came from.
133    ///
134    /// # Panics
135    ///
136    /// Panics if the arena would exceed four billion nodes, which is not a translation unit
137    /// this compiler intends to accept.
138    pub fn expr(&mut self, expr: Expr, span: Span) -> ExprId {
139        let id = Idx::from_usize(self.exprs.len());
140        self.exprs.push(expr);
141        self.expr_spans.push(span);
142        id
143    }
144
145    /// Adds a statement, with the source it came from.
146    ///
147    /// # Panics
148    ///
149    /// Panics if the arena would exceed four billion nodes.
150    pub fn stmt(&mut self, stmt: Stmt, span: Span) -> StmtId {
151        let id = Idx::from_usize(self.stmts.len());
152        self.stmts.push(stmt);
153        self.stmt_spans.push(span);
154        id
155    }
156
157    /// Adds a declaration, with the source it came from.
158    ///
159    /// # Panics
160    ///
161    /// Panics if the arena would exceed four billion nodes.
162    pub fn decl(&mut self, decl: Decl, span: Span) -> DeclId {
163        let id = Idx::from_usize(self.decls.len());
164        self.decls.push(decl);
165        self.decl_spans.push(span);
166        id
167    }
168
169    /// Replaces a declaration, which is what a definition of something already declared does.
170    ///
171    /// # Panics
172    ///
173    /// Panics if `id` is not a declaration of this tree.
174    pub fn set_decl(&mut self, id: DeclId, decl: Decl) {
175        self.decls[id.index()] = decl;
176    }
177
178    /// Replaces a statement, which is what a `switch` does to the cases in its body.
179    ///
180    /// A `case` is checked before the table it is an entry of exists, since the table is a run
181    /// and the run is not known until the whole body has been walked. So the statement is written
182    /// with a placeholder entry and given its real one here.
183    ///
184    /// # Panics
185    ///
186    /// Panics if `id` is not a statement of this tree.
187    pub fn set_stmt(&mut self, id: StmtId, stmt: Stmt) {
188        self.stmts[id.index()] = stmt;
189    }
190
191    /// The source an expression came from.
192    #[must_use]
193    pub fn expr_span(&self, id: ExprId) -> Span {
194        self.expr_spans[id.index()]
195    }
196
197    /// The source a statement came from.
198    #[must_use]
199    pub fn stmt_span(&self, id: StmtId) -> Span {
200        self.stmt_spans[id.index()]
201    }
202
203    /// The source a declaration came from.
204    #[must_use]
205    pub fn decl_span(&self, id: DeclId) -> Span {
206        self.decl_spans[id.index()]
207    }
208
209    /// Records the size of one variable length array, and gives back its identity.
210    ///
211    /// The type table keeps a [`VlaId`] and nothing else, because two variable length arrays
212    /// written with the same element type are still distinct types and interning them together
213    /// would say they are not. The expression itself lives here, since it is evaluated once
214    /// where the declaration is reached and its value is what every `sizeof` of that type
215    /// afterwards answers with.
216    ///
217    /// # Panics
218    ///
219    /// Panics if the table would exceed four billion entries.
220    pub fn add_vla(&mut self, size: ExprId) -> VlaId {
221        let id = u32::try_from(self.vlas.len()).expect("too many variable length arrays");
222        self.vlas.push(size);
223        VlaId(id)
224    }
225
226    /// The size expression of one variable length array.
227    ///
228    /// # Panics
229    ///
230    /// Panics if `id` is not one of this tree's.
231    #[must_use]
232    pub fn vla_size(&self, id: VlaId) -> ExprId {
233        self.vlas[id.0 as usize]
234    }
235
236    /// Records that a label names a statement, which is not known when the label is created
237    /// because a `goto` may come first.
238    ///
239    /// # Panics
240    ///
241    /// Panics if `id` is not a label of this tree.
242    pub fn define_label(&mut self, id: LabelId, stmt: StmtId) {
243        self.labels[id.index()].stmt = Some(stmt);
244    }
245
246    /// How many expressions, statements and declarations the tree holds.
247    #[must_use]
248    pub fn counts(&self) -> Counts {
249        Counts { exprs: self.exprs.len(), stmts: self.stmts.len(), decls: self.decls.len() }
250    }
251
252    /// Whether nothing has been checked into this tree.
253    #[must_use]
254    pub fn is_empty(&self) -> bool {
255        self.exprs.is_empty() && self.stmts.is_empty() && self.decls.is_empty()
256    }
257}
258
259/// How many nodes of each kind a typed tree holds.
260#[derive(Debug, Clone, Copy, PartialEq, Eq)]
261pub struct Counts {
262    /// Expressions.
263    pub exprs: usize,
264    /// Statements.
265    pub stmts: usize,
266    /// Declarations.
267    pub decls: usize,
268}
269
270impl fmt::Debug for Tast {
271    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272        // The same reasoning as the untyped tree: nobody wants a translation unit as a `{:?}`,
273        // and the thing they did want has a printer.
274        let counts = self.counts();
275        f.debug_struct("Tast")
276            .field("exprs", &counts.exprs)
277            .field("stmts", &counts.stmts)
278            .field("decls", &counts.decls)
279            .field("top_level", &self.top_level.len())
280            .finish()
281    }
282}
283
284/// Generates the read side of a table that holds one item per index.
285macro_rules! node_table {
286    ($id:ty => $item:ty, $field:ident) => {
287        impl Index<$id> for Tast {
288            type Output = $item;
289
290            #[inline]
291            fn index(&self, id: $id) -> &$item {
292                &self.$field[id.index()]
293            }
294        }
295    };
296}
297
298/// Generates both sides of a side table whose items are added one at a time.
299macro_rules! side_table {
300    (
301        $(#[$doc:meta])*
302        $add:ident, $id:ty => $item:ty, $field:ident
303    ) => {
304        impl Tast {
305            $(#[$doc])*
306            ///
307            /// # Panics
308            ///
309            /// Panics if the table would exceed four billion entries.
310            pub fn $add(&mut self, item: $item) -> $id {
311                let id = Idx::from_usize(self.$field.len());
312                self.$field.push(item);
313                id
314            }
315        }
316
317        node_table!($id => $item, $field);
318    };
319}
320
321/// Generates both sides of a table that is read in runs.
322macro_rules! list_table {
323    (
324        $(#[$doc:meta])*
325        $add:ident, $list:ty => $item:ty, $field:ident
326    ) => {
327        impl Tast {
328            $(#[$doc])*
329            ///
330            /// # Panics
331            ///
332            /// Panics if the table would exceed four billion entries.
333            pub fn $add(&mut self, items: &[$item]) -> $list {
334                let start = Idx::from_usize(self.$field.len());
335                self.$field.extend_from_slice(items);
336                let end = Idx::from_usize(self.$field.len());
337                IdxRange::new(start, end)
338            }
339        }
340
341        impl Index<$list> for Tast {
342            type Output = [$item];
343
344            #[inline]
345            fn index(&self, list: $list) -> &[$item] {
346                &self.$field[list.as_usize_range()]
347            }
348        }
349    };
350}
351
352node_table!(ExprId => Expr, exprs);
353node_table!(StmtId => Stmt, stmts);
354node_table!(DeclId => Decl, decls);
355node_table!(CaseId => Case, cases);
356
357side_table! {
358    /// Adds a folded constant.
359    add_const, ConstId => Const, consts
360}
361side_table! {
362    /// Adds a string literal.
363    add_string, StrId => StringLiteral, strings
364}
365side_table! {
366    /// Adds a label, which is not defined until the statement it names has been seen.
367    add_label, LabelId => Label, labels
368}
369
370list_table! {
371    /// Adds a run of expression references, which is what a call's arguments are.
372    add_expr_refs, ExprList => ExprId, expr_refs
373}
374list_table! {
375    /// Adds a run of statement references, which is what a block is.
376    add_stmt_refs, StmtList => StmtId, stmt_refs
377}
378list_table! {
379    /// Adds a run of declaration references, which is what a declaration statement is.
380    add_decl_refs, DeclList => DeclId, decl_refs
381}
382list_table! {
383    /// Adds the cases of one `switch`, in the order a jump table wants them.
384    add_cases, crate::stmt::CaseList => Case, cases
385}
386list_table! {
387    /// Adds the values one initializer stores.
388    add_init_entries, crate::decl::InitList => InitEntry, init_entries
389}
390
391#[cfg(test)]
392mod tests {
393    use rucc_ast::BinaryOp;
394    use rucc_types::{IntKind, Types};
395
396    use super::*;
397    use crate::decl::{DeclKind, Definition, Linkage, StorageDuration};
398    use crate::expr::{Category, Conversion, ExprKind};
399
400    /// The sizes are asserted rather than left to whoever adds the next variant.
401    ///
402    /// A node that grows costs the whole arena, and the day one does is a day somebody should
403    /// have to say so out loud rather than a day the walk over a large translation unit gets
404    /// slower for no reason anybody can point at.
405    ///
406    /// A case is the outlier at forty eight bytes, because two `i128` bounds want sixteen byte
407    /// alignment and nothing smaller holds a `switch` over `__int128`. It buys its size back by
408    /// being rare: one entry per `case` rather than one per node.
409    ///
410    /// A declaration went from thirty six bytes to forty four when it was given the parameter
411    /// list of a function definition, which is a field only a definition fills in and every
412    /// declaration pays for. The alternative was a side table keyed by declaration, and it was
413    /// not taken: a lookup per function in a table that is empty for almost every entry is
414    /// worse than eight bytes on a node there are far fewer of than there are expressions.
415    #[test]
416    fn the_nodes_are_the_size_they_are_meant_to_be() {
417        assert_eq!(size_of::<Expr>(), 24);
418        assert_eq!(size_of::<Stmt>(), 24);
419        assert_eq!(size_of::<Decl>(), 44);
420        assert_eq!(size_of::<Case>(), 48);
421    }
422
423    #[test]
424    fn a_tree_hands_back_what_was_put_into_it() {
425        let types = Types::new();
426        let int = types.int(IntKind::Int);
427        let mut tast = Tast::new();
428
429        let one = tast.add_const(Const::Int(1));
430        let left = tast.expr(Expr::new(ExprKind::Const(one), int, Category::Rvalue), Span::DUMMY);
431        let right = tast.expr(Expr::new(ExprKind::Const(one), int, Category::Rvalue), Span::DUMMY);
432        let sum = Expr::new(
433            ExprKind::Binary { op: BinaryOp::Add, lhs: left, rhs: right },
434            int,
435            Category::Rvalue,
436        );
437        let sum = tast.expr(sum, Span::new(0, 5));
438
439        assert_eq!(tast[left].ty, int);
440        assert_eq!(tast[sum].category, Category::Rvalue);
441        assert_eq!(tast.expr_span(sum), Span::new(0, 5));
442        assert_eq!(tast.counts().exprs, 3);
443        assert_eq!(tast[one], Const::Int(1));
444    }
445
446    #[test]
447    fn a_conversion_is_a_node_and_not_a_difference_between_two_types() {
448        let types = Types::new();
449        let char_type = types.int(IntKind::Char);
450        let int = types.int(IntKind::Int);
451        let mut tast = Tast::new();
452
453        let object = tast.decl(
454            Decl {
455                name: None,
456                ty: char_type,
457                kind: DeclKind::Object,
458                linkage: Linkage::None,
459                duration: StorageDuration::Automatic,
460                state: Definition::Defined,
461                alignment: None,
462                init: None,
463                params: DeclList::EMPTY,
464                body: None,
465            },
466            Span::DUMMY,
467        );
468        let name =
469            tast.expr(Expr::new(ExprKind::Decl(object), char_type, Category::Lvalue), Span::DUMMY);
470        let read = tast.expr(
471            Expr::new(
472                ExprKind::Convert { kind: Conversion::Lvalue, operand: name },
473                char_type,
474                Category::Rvalue,
475            ),
476            Span::DUMMY,
477        );
478        let promoted = tast.expr(
479            Expr::new(
480                ExprKind::Convert { kind: Conversion::Arithmetic, operand: read },
481                int,
482                Category::Rvalue,
483            ),
484            Span::DUMMY,
485        );
486
487        // Nothing downstream has to work out that a `char` met an `int` somewhere: the two
488        // steps that got it there are in the tree, in the order they happened.
489        assert_eq!(tast[promoted].ty, int);
490        let ExprKind::Convert { kind, operand } = tast[promoted].kind else { panic!("a convert") };
491        assert_eq!(kind, Conversion::Arithmetic);
492        assert_eq!(tast[operand].ty, char_type);
493    }
494
495    #[test]
496    fn a_run_comes_back_as_a_slice() {
497        let types = Types::new();
498        let int = types.int(IntKind::Int);
499        let mut tast = Tast::new();
500
501        let zero = tast.add_const(Const::Int(0));
502        let args: Vec<ExprId> = (0..3)
503            .map(|_| {
504                tast.expr(Expr::new(ExprKind::Const(zero), int, Category::Rvalue), Span::DUMMY)
505            })
506            .collect();
507        let list = tast.add_expr_refs(&args);
508
509        assert_eq!(&tast[list], args.as_slice());
510    }
511
512    #[test]
513    fn a_label_is_made_before_it_is_defined_because_a_goto_may_come_first() {
514        let mut tast = Tast::new();
515        let mut names = rucc_base::Interner::new();
516        let name = names.intern("done");
517
518        let label = tast.add_label(Label { name, stmt: None });
519        let jump = tast.stmt(Stmt::Goto(label), Span::DUMMY);
520        let target = tast.stmt(Stmt::Empty, Span::DUMMY);
521        tast.define_label(label, target);
522
523        assert_eq!(tast[jump], Stmt::Goto(label));
524        assert_eq!(tast[label].stmt, Some(target));
525    }
526}