Skip to main content

rucc_sema/
asm.rs

1//! Inline assembly, after checking.
2//!
3//! Design: `spec/13-gnu-compat.md` and `spec/11-asm-objects-debug.md`, which owns what a
4//! constraint means. Nothing here looks inside a template.
5//!
6//! The shape is the one the parser produced, with the operands still in source order, because
7//! the template refers to them by the position they were written in and renumbering them would
8//! make `%1` name something the program did not write. What checking adds is the type of every
9//! operand, the labels resolved to the ones the function declares, and one answer per operand
10//! that the walk to the IR would otherwise have to work out for itself: whether the operand
11//! travels as a value or as the address of an object.
12//!
13//! That last answer is here rather than in the walk because two passes need it and they have to
14//! agree. The walk builds the address of a memory operand, and the scan that runs before it
15//! decides which locals need a stack slot, so an operand the walk takes the address of has to be
16//! an operand the scan already knew about. One field read twice is how they agree.
17
18use rucc_ast::AsmQuals;
19use rucc_base::{Idx, IdxRange, Symbol};
20use rucc_diag::Span;
21
22use crate::expr::ExprId;
23use crate::tast::StrId;
24
25/// An assembly statement, in the side table.
26pub type AsmId = Idx<Asm>;
27
28/// The table of references to string literals, which is what a clobber list is a run of.
29#[derive(Debug)]
30pub struct StrRef;
31
32/// A run of string literals.
33pub type StrList = IdxRange<StrRef>;
34
35/// The table of references to labels, which is what an `asm goto` label list is a run of.
36#[derive(Debug)]
37pub struct LabelRef;
38
39/// A run of labels.
40pub type LabelList = IdxRange<LabelRef>;
41
42/// A run of operands.
43pub type AsmOperandList = IdxRange<AsmOperand>;
44
45/// One `asm` statement.
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub struct Asm {
48    /// The template, which is passed to the assembler with the operands substituted into it.
49    pub template: StrId,
50    /// The output operands, which are numbered from zero.
51    pub outputs: AsmOperandList,
52    /// The input operands, which are numbered after the outputs.
53    pub inputs: AsmOperandList,
54    /// The clobber list.
55    pub clobbers: StrList,
56    /// The labels of an `asm goto`, empty for everything else.
57    pub labels: LabelList,
58    /// The qualifiers, with `volatile` set for a statement that implies it.
59    pub quals: AsmQuals,
60}
61
62/// One `asm` written at file scope, outside any function.
63///
64/// Its own type rather than an [`Asm`] with empty lists, because the two are different things
65/// under the same keyword. A statement's template refers to operands by number and is one
66/// instruction of a function; a file-scope one has no operands to refer to, so `%` in it means
67/// nothing in particular, and what it says is what the translation unit itself contains. Keeping
68/// them apart is what lets the walk over the tree read the template as written rather than as a
69/// format string with nothing filled into it.
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub struct FileAsm {
72    /// The template, as the program wrote it.
73    pub template: StrId,
74    /// Where it was written, for the messages about what is in it.
75    pub span: Span,
76}
77
78/// One operand of an assembly statement.
79#[derive(Debug, Clone, Copy, PartialEq, Eq)]
80pub struct AsmOperand {
81    /// The `[name]` it was written with, which is what `%[name]` in the template refers to.
82    pub name: Option<Symbol>,
83    /// The constraint, as written, including the `=` or `+` of an output.
84    pub constraint: StrId,
85    /// The operand itself, which is an lvalue for an output and for anything in memory, and a
86    /// value everywhere else.
87    pub value: ExprId,
88    /// Whether the assembly is given the address of an object rather than a value.
89    ///
90    /// True for a constraint that allows nothing but memory and for a structure or a union,
91    /// which is not something a register holds.
92    pub memory: bool,
93}