1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! # ir_lang
//!
//! The SSA intermediate representation of the `-lang` family's native compiler
//! path: what a front end lowers into after monomorphization, closure conversion,
//! pattern compilation, and effect lowering, what the optimizer rewrites, and what
//! instruction selection reads.
//!
//! A [`Module`] holds functions (with [`Signature`]s and calling-convention tags),
//! globals, and aggregate types. A function body is a control-flow graph of
//! blocks; values cross control-flow joins as **block parameters** (no phi nodes);
//! every value has a [`Type`] and exactly one definition. Instructions cover every
//! operation of the shared operation semantics (`specs/OPS.md`), each instance
//! carrying its policy; conversions; comparisons; `select`; direct, indirect, and
//! tail calls; `invoke` with an exception edge; memory (stack slots, loads and
//! stores with alignment and volatility, atomics, `memcpy`/`memset`, address
//! computation); and safepoints that relocate GC references, so native frames
//! can be scanned by a moving collector.
//!
//! ## Quick start
//!
//! Build, validate, print, and parse back `fn add1(x: i64) -> i64 { x + 1 }`:
//!
//! ```
//! use ir_lang::{Linkage, Module, Overflow, Signature, Type};
//!
//! let mut m = Module::new("demo");
//! let f = m.declare_function("add1", &Signature::new(&[Type::I64], &[Type::I64]), Linkage::Export)?;
//! let mut b = m.build(f)?;
//! let x = b.param(0)?;
//! let one = b.iconst(Type::I64, 1)?;
//! let y = b.add(x, one, Overflow::Wrap)?;
//! b.ret(&[y])?;
//!
//! m.validate()?;
//! let text = m.to_string();
//! assert!(text.contains("v2: i64 = add<overflow=wrap> v0, v1"));
//! let again = ir_lang::parse(&text)?;
//! assert_eq!(again.to_string(), text);
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! ```
//!
//! ## What is checked
//!
//! [`Module::validate`] is total (it accepts or reports, never panics) and checks:
//! entry parameters against the signature, single definition, dominance (the
//! Cooper–Harvey–Kennedy dominator tree and one linear walk), types and exact
//! policies of every instruction, exception-edge rules (landing pads, `nounwind`,
//! `noreturn`, `nogc`), and the safepoint rules (no GC reference or pointer derived
//! from one is live across a safepoint). The [`Builder`] runs the same
//! per-instruction checks as it goes, so lowering bugs surface at the call that
//! made them. The normative rules are in `specs/IR.md`.
//!
//! ## Features
//!
//! - `std` (default): the standard library; without it the crate is `#![no_std]`
//! and needs only `alloc`.
//! - `interp`: the reference interpreter ([`interp`]), which implements the
//! operation semantics exactly and is the oracle for optimizers and backends.
//! Requires `std` (for the float functions of OPS §4).
//!
//! ## Stability
//!
//! This is `2.0.0-alpha.1`, a pre-release of the 2.0 redesign. The surface may
//! change before `2.0.0`; see `dev/ROADMAP.md`.
extern crate alloc;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
/// Runs the README's examples as doctests, so its claims stay true.
;
/// Runs the API reference's examples as doctests.
;