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};
20
21use crate::expr::ExprId;
22use crate::tast::StrId;
23
24/// An assembly statement, in the side table.
25pub type AsmId = Idx<Asm>;
26
27/// The table of references to string literals, which is what a clobber list is a run of.
28#[derive(Debug)]
29pub struct StrRef;
30
31/// A run of string literals.
32pub type StrList = IdxRange<StrRef>;
33
34/// The table of references to labels, which is what an `asm goto` label list is a run of.
35#[derive(Debug)]
36pub struct LabelRef;
37
38/// A run of labels.
39pub type LabelList = IdxRange<LabelRef>;
40
41/// A run of operands.
42pub type AsmOperandList = IdxRange<AsmOperand>;
43
44/// One `asm` statement.
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub struct Asm {
47    /// The template, which is passed to the assembler with the operands substituted into it.
48    pub template: StrId,
49    /// The output operands, which are numbered from zero.
50    pub outputs: AsmOperandList,
51    /// The input operands, which are numbered after the outputs.
52    pub inputs: AsmOperandList,
53    /// The clobber list.
54    pub clobbers: StrList,
55    /// The labels of an `asm goto`, empty for everything else.
56    pub labels: LabelList,
57    /// The qualifiers, with `volatile` set for a statement that implies it.
58    pub quals: AsmQuals,
59}
60
61/// One operand of an assembly statement.
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub struct AsmOperand {
64    /// The `[name]` it was written with, which is what `%[name]` in the template refers to.
65    pub name: Option<Symbol>,
66    /// The constraint, as written, including the `=` or `+` of an output.
67    pub constraint: StrId,
68    /// The operand itself, which is an lvalue for an output and for anything in memory, and a
69    /// value everywhere else.
70    pub value: ExprId,
71    /// Whether the assembly is given the address of an object rather than a value.
72    ///
73    /// True for a constraint that allows nothing but memory and for a structure or a union,
74    /// which is not something a register holds.
75    pub memory: bool,
76}