Skip to main content

rucc_ir/
lib.rs

1//! The SSA IR with block parameters, and its printer, parser and verifier.
2//!
3//! Design: `spec/08-ir.md`. Layer rank 8, see `spec/18-package-layout.md`.
4//!
5//! One IR, target-independent, in SSA form, produced by lowering the typed AST and consumed by
6//! the optimizer and the code generator. The MIR is a second, target-dependent representation
7//! and lives in its own crate.
8//!
9//! **Block parameters, not phi nodes.** A phi is a pseudo-instruction whose operands are
10//! positionally tied to a predecessor list stored somewhere else, and every IR built that way
11//! collects bugs where the two get out of step during a CFG edit. Block parameters put the
12//! correspondence in the branch, where it belongs: `br_if %c, block2(%a, %b), block3(%d)`.
13//! Removing a predecessor is then a local edit, and there is no such thing as a malformed phi.
14//!
15//! # What is here so far
16//!
17//! The vocabulary: [`Type`] and [`Float`] for the type system, [`Opcode`] with [`IntPred`] and
18//! [`FloatPred`] for the instruction set, [`Flags`] with [`MemOrder`] and [`RmwOp`] for what
19//! rides on an instruction, and [`Attrs`] for what is true of a whole function rather than of
20//! one instruction in it. The containers: [`Func`], holding [`BlockData`] and
21//! [`InstData`] and [`ValueData`] in flat tables, with [`Builder`] to append to it, and
22//! [`Module`], holding the functions with the [`Global`]s and the [`Alias`]es and the target
23//! they are all for. The textual form: [`print()`], which writes a module out, and [`parse()`],
24//! which reads it back byte for byte. And [`verify()`], which says whether a module is one the
25//! rest of the compiler may believe.
26//!
27//! Every crate in the workspace is published, and publishing implies a promise. This one is
28//! tier 3: its Rust API is explicitly unstable and will change without a major version bump.
29//! Depend on the `rucc` binary's behaviour, not on this.
30
31#![doc(html_root_url = "https://docs.rs/rucc-ir/0.2.13")]
32
33mod attrs;
34#[cfg(test)]
35mod fixtures;
36mod flags;
37mod func;
38mod inst;
39mod module;
40mod opcode;
41mod parse;
42mod print;
43mod ty;
44mod verify;
45
46pub use attrs::{AttrSet, Attrs, FpContract};
47pub use flags::{Flags, MemOrder, RmwOp};
48pub use func::{Builder, Counts, Func};
49pub use inst::{
50    AsmInfo, Block, BlockCall, BlockCallList, BlockData, CallInfo, Def, Extra, Imm, ImmList, Inst,
51    InstData, InstLayout, MemInfo, Meta, MetaNode, Sig, Signature, SwitchInfo, Value, ValueData,
52    ValueList, ValueRef,
53};
54pub use module::{
55    Alias, AliasId, AliasKind, Byte, ByteRange, DataLayout, DataList, Datum, FuncId, Global,
56    GlobalId, Linkage, Module, ModuleCounts, Reloc, SymbolRef, TlsModel, Visibility,
57};
58pub use opcode::{ExtraKind, FloatPred, IntPred, Opcode};
59pub use parse::{ParseError, parse};
60pub use print::{Printer, print, print_func};
61pub use ty::{Float, Kind, Type};
62pub use verify::{VerifyError, verify, verify_func};
63
64/// The milestone in `spec/17-milestones.md` that fills this crate in.
65pub const MILESTONE: &str = "M2";
66
67/// The version of the textual form, written in the module header.
68///
69/// The IR is not a stable interface before 1.0 and this number does not promise that it is.
70/// It exists so that a dump from one build read by another build fails with something a person
71/// can act on rather than with a parse error twenty lines in.
72pub const FORMAT_VERSION: u32 = 0;
73
74#[cfg(test)]
75mod tests {
76    #[test]
77    fn milestone_is_recorded() {
78        assert!(super::MILESTONE.starts_with('M'));
79    }
80}