Skip to main content

rucc_sema/
expr.rs

1//! Typed expressions.
2//!
3//! Design: `spec/07-types-and-semantics.md` sections 7.2 and 7.14.
4//!
5//! Every node here has a type and a value category, and every conversion the language performs
6//! without being asked is a [`Conversion`] node written into the tree. That is the whole point
7//! of the typed tree: nothing downstream is allowed to work out that an `int` and a `long` must
8//! have met somewhere, because if the two operands of an addition do not already have the same
9//! type then semantic analysis has a bug and the verifier is entitled to say so.
10//!
11//! The operators are [`rucc_ast::UnaryOp`] and [`rucc_ast::BinaryOp`], the same ones the parser
12//! read, rather than a second set with the same names. What the typed tree adds is not different
13//! operators, it is knowing what they are applied to.
14
15use rucc_ast::{BinaryOp, UnaryOp};
16use rucc_base::{Idx, IdxRange};
17use rucc_types::TypeId;
18
19use crate::decl::DeclId;
20use crate::stmt::StmtId;
21use crate::tast::{ConstId, LabelId, StrId};
22
23/// One typed expression in the arena.
24pub type ExprId = Idx<Expr>;
25
26/// The table of references to expressions, which is what a call's arguments are a run of.
27#[derive(Debug)]
28pub struct ExprRef;
29
30/// A run of expressions.
31pub type ExprList = IdxRange<ExprRef>;
32
33/// An expression, its type, and what may be done with it.
34///
35/// Twenty four bytes: the kind, the type it has, and the category it is in. The type is in the
36/// node rather than in a table beside it, which is the opposite of what the untyped tree does
37/// with spans, because everything that walks this tree reads the type at every node and almost
38/// nothing reads the span at any node.
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub struct Expr {
41    /// What the expression is.
42    pub kind: ExprKind,
43    /// The type it has, after every conversion that applies to it.
44    pub ty: TypeId,
45    /// What may be done with it.
46    pub category: Category,
47}
48
49impl Expr {
50    /// An expression of the given kind, type and category.
51    #[must_use]
52    pub const fn new(kind: ExprKind, ty: TypeId, category: Category) -> Expr {
53        Expr { kind, ty, category }
54    }
55}
56
57/// What may be done with an expression, which C decides rather than the programmer.
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum Category {
60    /// A value. It has no address and nothing may be assigned to it.
61    Rvalue,
62    /// An object. It has an address, it may be assigned to when it is not `const`, and reading
63    /// it is a [`Conversion::Lvalue`] rather than something a reader has to remember.
64    Lvalue,
65    /// A bit-field, which is an lvalue whose address cannot be taken and whose assignment
66    /// truncates to the declared width. Kept apart from an ordinary lvalue because the two
67    /// rules above are the ones a compiler forgets.
68    Bitfield,
69    /// A function designator, which is not an lvalue and which decays to a pointer everywhere
70    /// except under `sizeof` and `&`.
71    Function,
72}
73
74/// What an expression is.
75#[derive(Debug, Clone, Copy, PartialEq, Eq)]
76pub enum ExprKind {
77    /// A node that was already the subject of a diagnostic.
78    ///
79    /// Poisoned, in the sense of `spec/06-lexer-and-parser.md` section 6.8: nothing is reported
80    /// about one of these, which is what stops one bad declaration becoming forty bad uses.
81    Error,
82    /// A constant, in the value table. Every constant that could be folded already has been.
83    Const(ConstId),
84    /// A string literal, which is an array of characters with static storage duration.
85    Str(StrId),
86    /// A use of a declared object or function.
87    Decl(DeclId),
88    /// `base.field` or, after the pointer has been dereferenced, `base->field`.
89    Member {
90        /// The object the field is in.
91        base: ExprId,
92        /// Which field, as an index into the record's field list rather than as a name, since
93        /// the lookup happened here and nothing after this should repeat it.
94        field: u32,
95    },
96    /// `base[index]`, with the pointer operand first however it was written.
97    ///
98    /// Kept as a subscript rather than rewritten into `*(base + index)` because the rewriting
99    /// has exactly one home, which is the walk to the IR, and because a diagnostic about a
100    /// subscript should talk about a subscript.
101    Subscript {
102        /// The pointer, which has already decayed if it was an array.
103        base: ExprId,
104        /// The integer.
105        index: ExprId,
106    },
107    /// `callee(args)`, with the arguments already converted to the parameter types.
108    Call {
109        /// The function, which is a pointer to a function after its decay.
110        callee: ExprId,
111        /// The arguments, in order, each converted to what the prototype asks for and each
112        /// promoted where the prototype does not say.
113        args: ExprList,
114    },
115    /// A prefix or postfix operator on one operand.
116    Unary {
117        /// Which operator.
118        op: UnaryOp,
119        /// What it applies to.
120        operand: ExprId,
121    },
122    /// A binary operator on two operands of the same type, except for the shifts and the
123    /// pointer arithmetic, where the two sides legitimately differ.
124    Binary {
125        /// Which operator.
126        op: BinaryOp,
127        /// The left side.
128        lhs: ExprId,
129        /// The right side.
130        rhs: ExprId,
131    },
132    /// `lhs = rhs`, or a compound assignment with the operator kept as written.
133    Assign {
134        /// The operator of a compound assignment, absent for a plain one.
135        op: Option<BinaryOp>,
136        /// The type the operation is performed in, which is the node's own type for a plain
137        /// assignment and for most compound ones.
138        ///
139        /// It is here because `a op= b` is not `a = a op b` with the conversions left out, and
140        /// the difference is not academic: in `int i = 5; i /= 0.5;` the division happens in
141        /// `double` and the answer is ten, and a compiler that converts the right side to `int`
142        /// first divides by zero. The left side is an lvalue and cannot carry a conversion node
143        /// of its own, so the type it is read into is written here instead, which is what clang
144        /// calls the computation type and for the same reason.
145        computation: TypeId,
146        /// What is assigned to, which is an lvalue.
147        lhs: ExprId,
148        /// What is assigned.
149        rhs: ExprId,
150    },
151    /// `cond ? then : otherwise`, with both arms already converted to the common type.
152    Cond {
153        /// The condition, converted to `bool`.
154        cond: ExprId,
155        /// The arm taken when it is true. GNU's `cond ?: otherwise` has this equal to the
156        /// condition before its conversion, so the value is computed once.
157        then: ExprId,
158        /// The arm taken when it is false.
159        otherwise: ExprId,
160    },
161    /// `lhs, rhs`, whose value is the right side and whose left side is evaluated and dropped.
162    Comma {
163        /// Evaluated first, for its effects.
164        lhs: ExprId,
165        /// The value.
166        rhs: ExprId,
167    },
168    /// A cast the program wrote. The type is the node's type.
169    Cast(ExprId),
170    /// A conversion the language performed. The type is the node's type.
171    Convert {
172        /// Which conversion, so that a reader and the verifier can both tell what happened
173        /// rather than comparing the two types and guessing.
174        kind: Conversion,
175        /// What was converted.
176        operand: ExprId,
177    },
178    /// `(T){ ... }`, which is an unnamed object with an initializer and not a conversion.
179    CompoundLiteral(DeclId),
180    /// `({ ... })`, GNU's statement expression, whose value is its last expression statement.
181    StmtExpr(StmtId),
182    /// `&&label`, GNU's label address.
183    LabelAddr(LabelId),
184    /// `va_arg(list, T)`, which reads the next argument and moves the list on.
185    ///
186    /// The type it fetches is the node's own type, so there is nothing else to hold. It is a
187    /// node rather than a call because what it becomes is the target's own sequence of loads
188    /// and not a function anything links against.
189    VaArg {
190        /// The address of the list, which is what this reads through and moves on.
191        list: ExprId,
192    },
193    /// `va_start(list, last)`, which sets a list to the first argument past the named ones.
194    ///
195    /// What the source wrote as the second argument is not here. It names where the named
196    /// arguments stopped, which the enclosing function's own type already says, and it is not
197    /// evaluated: gcc rewrites `va_start(ap, last)` to a call with a zero in that place and C23
198    /// lets the program leave it out altogether.
199    VaStart {
200        /// The address of the list, which this writes.
201        list: ExprId,
202    },
203    /// `va_end(list)`, which is the end of the reading and is nothing at all on most targets.
204    VaEnd {
205        /// The address of the list.
206        list: ExprId,
207    },
208    /// `va_copy(dst, src)`, which makes a second list standing where the first one stands.
209    VaCopy {
210        /// The address of the list being written.
211        dst: ExprId,
212        /// The address of the list being read, which stays where it is.
213        src: ExprId,
214    },
215    /// One of the floating point classification builtins, which asks about a value rather than
216    /// computing one.
217    ///
218    /// A node rather than a call because there is nothing to call: `isnan` and the rest are
219    /// macros in `math.h` that expand to exactly these, so the name has no function under it on
220    /// any platform. What each becomes is a comparison, and the four of the family that C
221    /// already has an operator for are [`ExprKind::Binary`] instead. See
222    /// `check/builtin/classify.rs` for which are here and why.
223    Classify {
224        /// Which question is being asked.
225        op: Classify,
226        /// The value asked about, converted to the type the question is asked in.
227        lhs: ExprId,
228        /// The value it is asked against, for the two questions that are about a pair of them.
229        rhs: Option<ExprId>,
230    },
231    /// `__builtin_fpclassify(nan, inf, normal, subnormal, zero, x)`, which answers with whichever
232    /// of the five the value is.
233    ///
234    /// A node of its own rather than one of [`ExprKind::Classify`] because it has five operands
235    /// besides the value, and a node rather than the chain of conditionals it turns into because
236    /// the value is asked about four times and a program that writes `__builtin_fpclassify(..,
237    /// f())` calls `f` once.
238    FpClassify {
239        /// The value asked about.
240        value: ExprId,
241        /// The five answers, in the order the call writes them: a NaN, an infinity, a normal
242        /// number, a subnormal and a zero. gcc requires each to be an integer constant
243        /// expression and so does this.
244        answers: ExprList,
245    },
246    /// `__builtin_fabs` or `__builtin_copysign`, which set the sign bit of a value from somewhere
247    /// and leave every other bit of it alone.
248    ///
249    /// A node rather than a call because the call would be to the math library, which is not on
250    /// the link line of a program that never asked for it, and because neither one needs anything
251    /// the library has: both are a mask and an or over the bits. See `check/builtin/sign.rs`.
252    Sign {
253        /// Where the sign of the answer comes from.
254        op: Sign,
255        /// The value whose magnitude the answer has.
256        lhs: ExprId,
257        /// The value whose sign the answer has, for `copysign`, which is the only one that reads
258        /// a sign from anywhere other than nowhere.
259        rhs: Option<ExprId>,
260    },
261    /// `abs`, `labs` and `llabs`, which are the magnitude of an integer.
262    ///
263    /// A node rather than a call because the names are the C library's and the compiler is allowed
264    /// to know what they do, which is what lets a program define one of them and still get the
265    /// magnitude. See `check/builtin/abs.rs` for when a call becomes one of these and when it
266    /// stays a call.
267    ///
268    /// The operand has already been converted to the type of the answer, which is the type the
269    /// declaration gave the parameter, so nothing downstream has to widen it.
270    Abs {
271        /// The value whose magnitude this is.
272        operand: ExprId,
273    },
274    /// `__builtin_bswap16`, `__builtin_bswap32` and `__builtin_bswap64`, which are the bytes of a
275    /// value in the other order.
276    ///
277    /// A node rather than a call because no object file defines one of these, and because a byte
278    /// order swap is arithmetic: every machine can do it and most have an instruction for it. See
279    /// `check/builtin/bswap.rs`.
280    ///
281    /// The operand has already been converted to the unsigned type the declaration gave the
282    /// parameter, which is also the type of the answer, so the width the bytes are reversed in is
283    /// the width of the node and nothing downstream has to work it out.
284    ByteSwap {
285        /// The value whose bytes these are.
286        operand: ExprId,
287    },
288    /// The bit counting builtins, which are five questions about which bits of a value are set.
289    ///
290    /// `__builtin_clz`, `__builtin_ctz`, `__builtin_popcount`, `__builtin_parity` and
291    /// `__builtin_ffs`, each in the plain, `l` and `ll` widths. Nodes rather than calls for the
292    /// reason [`ExprKind::ByteSwap`] is one: no object file defines any of them, and every machine
293    /// can answer them with instructions it already has. See `check/builtin/count.rs`.
294    ///
295    /// The operand keeps the width its declaration gave it, because that width is the question. The
296    /// type of the whole node is `int` whatever that width is, which is the one place this differs
297    /// from the byte swaps, so the walk to the IR counts at the operand's width and then narrows
298    /// the answer.
299    BitCount {
300        /// The value whose bits are being counted.
301        operand: ExprId,
302        /// Which of the five questions this asks.
303        count: BitCount,
304    },
305    /// The overflow checking builtins, which do the arithmetic exactly and say whether it fit.
306    ///
307    /// `__builtin_add_overflow`, `__builtin_sub_overflow` and `__builtin_mul_overflow`. A node
308    /// rather than a call for the reason [`ExprKind::ByteSwap`] is one, and for a second reason
309    /// besides: the answer is two things, a value and a bit, and a call in C can only give back
310    /// one. See `check/builtin/overflow.rs`.
311    ///
312    /// The operands keep the types they were written with, because the arithmetic is defined as
313    /// happening in infinite precision and then being put somewhere. What stands in for infinite
314    /// precision is `at`, a type wide enough to hold every value all three of the written types
315    /// can hold, and the walk to the IR converts both operands to it before doing anything.
316    ///
317    /// The three operands are a run rather than three fields, because three of them and a type
318    /// would be the widest variant here and every expression in the program is the size of the
319    /// widest one. See [`Tast`](crate::Tast) for the same trade made about a declaration.
320    Overflow {
321        /// Which of the three operations this is.
322        op: OverflowOp,
323        /// The type the arithmetic is done at, which represents every value of both operand types
324        /// and of what the third operand points at. Working it out is the whole of the type
325        /// checking here.
326        at: TypeId,
327        /// The two operands in the types they were written with, and then the pointer the exact
328        /// result is written through whether or not it fit. Always exactly three.
329        args: ExprList,
330    },
331    /// The atomic accesses and the barriers, which carry a memory ordering.
332    ///
333    /// `__atomic_load_n`, `__atomic_store_n`, `__atomic_thread_fence`, `__atomic_signal_fence` and
334    /// `__sync_synchronize`. A node rather than a call because none of them is a function anywhere:
335    /// what they are is an access with an ordering on it, and an ordering is a thing the IR says
336    /// about an access rather than an argument something is passed. See `check/builtin/atomic.rs`.
337    ///
338    /// The order is a value here rather than an operand, because it was a constant in the source
339    /// and the ordering of an access has to be known when the access is built. A call that wrote a
340    /// value the compiler cannot fold gets the strongest ordering, which is what gcc does and is
341    /// the only safe reading of a question that has to be answered before the program runs.
342    Atomic {
343        /// Which of the three shapes this is.
344        op: AtomicOp,
345        /// How strongly it is ordered, after the source's number has been read and checked.
346        order: Ordering,
347        /// The address for a load, the address and then the value for a store, and nothing at all
348        /// for a barrier.
349        args: ExprList,
350    },
351    /// `__builtin_unreachable()`, which is the program promising control does not get here.
352    ///
353    /// It has no operands and no value, and it is a node rather than a call for the reason
354    /// [`ExprKind::VaArg`] is one: there is no function of the name for a call to reach. What it
355    /// carries is the promise itself, which the optimizer is where it will pay, and until then
356    /// what it costs to honour is nothing at all. See `check/builtin/unreachable.rs`.
357    Unreachable,
358}
359
360/// Which question one of the bit counting builtins asks.
361///
362/// Three of these are an instruction on most machines and the other two are one of those and a
363/// little arithmetic, which is why they are one node with a question rather than five nodes.
364#[derive(Debug, Clone, Copy, PartialEq, Eq)]
365pub enum BitCount {
366    /// `__builtin_clz`, the number of zero bits above the highest set one. Undefined for a zero
367    /// argument, which is gcc's rule and not an accident of any machine: `bsr` leaves its
368    /// destination alone for a zero input rather than writing an answer to it.
369    Leading,
370    /// `__builtin_ctz`, the number of zero bits below the lowest set one. Undefined for a zero
371    /// argument for the same reason.
372    Trailing,
373    /// `__builtin_popcount`, how many bits are set. Defined everywhere, including at zero.
374    Ones,
375    /// `__builtin_parity`, whether the number of set bits is odd. Defined everywhere. Not the
376    /// machine's parity flag, which on x86-64 is over the low byte of the result and so answers a
377    /// different question.
378    Parity,
379    /// `__builtin_ffs`, the position of the lowest set bit counting from one, and zero for a zero
380    /// argument. The one in the family that is defined at zero, and the one whose operand is
381    /// signed, because that is the signature the C library's `ffs` has.
382    FirstSet,
383}
384
385impl BitCount {
386    /// How the question is written in the typed tree's textual form.
387    #[must_use]
388    pub const fn as_str(self) -> &'static str {
389        match self {
390            BitCount::Leading => "leading-zeroes",
391            BitCount::Trailing => "trailing-zeroes",
392            BitCount::Ones => "set-bits",
393            BitCount::Parity => "parity",
394            BitCount::FirstSet => "first-set",
395        }
396    }
397}
398
399/// Which arithmetic one of the overflow checking builtins does.
400///
401/// One node with an operation rather than three nodes, because everything around the arithmetic
402/// itself is the same for all three: the same rule picks the type it happens at, the same narrowing
403/// decides whether the answer fit, and the same store puts it where it was asked for.
404#[derive(Debug, Clone, Copy, PartialEq, Eq)]
405pub enum OverflowOp {
406    /// `__builtin_add_overflow`.
407    Add,
408    /// `__builtin_sub_overflow`.
409    Sub,
410    /// `__builtin_mul_overflow`.
411    Mul,
412}
413
414impl OverflowOp {
415    /// How the operation is written in the typed tree's textual form.
416    #[must_use]
417    pub const fn as_str(self) -> &'static str {
418        match self {
419            OverflowOp::Add => "add",
420            OverflowOp::Sub => "sub",
421            OverflowOp::Mul => "mul",
422        }
423    }
424}
425
426/// Which of the atomic shapes a call is, once the family it came from stops mattering.
427///
428/// Fewer of these than there are names, because `__sync_synchronize()` and
429/// `__atomic_thread_fence(__ATOMIC_SEQ_CST)` are the same node with the same ordering, and the
430/// only difference between the two families is which orderings a name can be written with.
431///
432/// The three compare and exchange shapes are three rather than one because they differ in what
433/// they answer and in where they were handed the value to compare against, and those are the two
434/// things the walk to the IR has to know. What they do to the object is the same in all three.
435#[derive(Debug, Clone, Copy, PartialEq, Eq)]
436pub enum AtomicOp {
437    /// A read of the object the first operand points at.
438    Load,
439    /// The same read, written into the object the second operand points at rather than answered.
440    ///
441    /// The unsuffixed `__atomic_load`, which is the form for an object too big to come back in a
442    /// register. A separate shape rather than the same one with an operand on the end, because what
443    /// the walk to the IR does with it differs: this one answers nothing and writes twice.
444    LoadInto,
445    /// A write of the second operand into the object the first points at.
446    Store,
447    /// A barrier, which touches no object and is the ordering by itself.
448    Fence,
449    /// A compare and exchange whose second operand is a pointer to the value expected, which is
450    /// where what was found is written back when the two did not match. Answers whether they did.
451    CompareExchange,
452    /// A compare and exchange whose second operand is the expected value itself, answering whether
453    /// it matched. The older family's `__sync_bool_compare_and_swap`.
454    SwapBool,
455    /// The same, answering what was found rather than whether it matched.
456    SwapValue,
457    /// The second operand goes into the object and what was there comes back.
458    ///
459    /// One shape rather than two, because an exchange is the one read modify write whose answer
460    /// afterwards is a value the caller already has, so no name in the family asks for it.
461    Exchange,
462    /// The same exchange, with what was there written into the object the third operand points at
463    /// rather than answered. The unsuffixed `__atomic_exchange`.
464    ExchangeInto,
465    /// An exchange of a one into the byte the first operand points at, answering whether that byte
466    /// held anything before.
467    ///
468    /// `__atomic_test_and_set`, which is the one name in the family whose object is a byte whatever
469    /// the pointer it was handed points at. It is a shape of its own rather than an exchange with
470    /// the comparison written around it because the value that goes in is the implementation's to
471    /// choose, and choosing it in one place is what keeps it the same value `__atomic_clear` puts
472    /// back.
473    TestAndSet,
474    /// A read, an operation on what was read, and a write back, answering what was there before.
475    Fetch(Rmw),
476    /// The same, answering what is there afterwards.
477    ///
478    /// A separate shape rather than the arithmetic written around a [`AtomicOp::Fetch`] by whatever
479    /// checked the call, because the two are one instruction on most machines and the one that
480    /// answers afterwards is the one that is a subtraction away from it. Which of the two a machine
481    /// has is the back end's business, and this is where the difference is written down until it
482    /// gets there.
483    Update(Rmw),
484}
485
486impl AtomicOp {
487    /// How the operation is written in the typed tree's textual form.
488    #[must_use]
489    pub const fn as_str(self) -> &'static str {
490        match self {
491            AtomicOp::Load => "load",
492            AtomicOp::LoadInto => "load_into",
493            AtomicOp::Store => "store",
494            AtomicOp::Fence => "fence",
495            AtomicOp::CompareExchange => "compare_exchange",
496            AtomicOp::SwapBool => "swap_bool",
497            AtomicOp::SwapValue => "swap_value",
498            AtomicOp::Exchange => "exchange",
499            AtomicOp::ExchangeInto => "exchange_into",
500            AtomicOp::TestAndSet => "test_and_set",
501            AtomicOp::Fetch(Rmw::Add) => "fetch_add",
502            AtomicOp::Fetch(Rmw::Sub) => "fetch_sub",
503            AtomicOp::Fetch(Rmw::And) => "fetch_and",
504            AtomicOp::Fetch(Rmw::Nand) => "fetch_nand",
505            AtomicOp::Fetch(Rmw::Or) => "fetch_or",
506            AtomicOp::Fetch(Rmw::Xor) => "fetch_xor",
507            AtomicOp::Update(Rmw::Add) => "add_fetch",
508            AtomicOp::Update(Rmw::Sub) => "sub_fetch",
509            AtomicOp::Update(Rmw::And) => "and_fetch",
510            AtomicOp::Update(Rmw::Nand) => "nand_fetch",
511            AtomicOp::Update(Rmw::Or) => "or_fetch",
512            AtomicOp::Update(Rmw::Xor) => "xor_fetch",
513        }
514    }
515}
516
517/// What a read modify write does to the value it read.
518///
519/// The six gcc has, which is every operation either family names. What a machine has a single
520/// instruction for is not decided here: the back end reads this and either finds an instruction or
521/// writes the loop around a compare and exchange that stands in for one.
522#[derive(Debug, Clone, Copy, PartialEq, Eq)]
523pub enum Rmw {
524    /// Addition, which is `lock xadd` on this machine.
525    Add,
526    /// Subtraction, which is the same instruction over the negated operand.
527    Sub,
528    /// Bitwise and.
529    And,
530    /// Bitwise and with every bit of the answer flipped, which is the one of the six that is two
531    /// operations rather than one and the one no machine here has anything for.
532    Nand,
533    /// Bitwise or.
534    Or,
535    /// Bitwise exclusive or.
536    Xor,
537}
538
539/// How strongly an atomic access or a barrier is ordered against everything around it.
540///
541/// The C11 memory model's orderings, which gcc's `__atomic_` family took from the same place. This
542/// is spelled here rather than reused from the IR because nothing in this crate knows what an IR
543/// is, and the walk that builds one is where the two are put side by side.
544///
545/// `memory_order_consume` is not here. Every compiler in use today gives it the same code as
546/// `acquire`, C++17 discourages it, and a spelling of it that means acquire would be a name whose
547/// only effect is to make a reader think something was implemented. The number the source wrote is
548/// read and turned into [`Ordering::Acquire`] where it appears, and the fact that it was written is
549/// not carried any further.
550#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
551pub enum Ordering {
552    /// Atomic, and ordered against nothing.
553    Relaxed,
554    /// Nothing after this moves before it.
555    Acquire,
556    /// Nothing before this moves after it.
557    Release,
558    /// Both, which only a read-modify-write or a barrier can ask for.
559    AcqRel,
560    /// Both, and one total order over every sequentially consistent operation in the program.
561    SeqCst,
562}
563
564impl Ordering {
565    /// How the ordering is written in the typed tree's textual form.
566    #[must_use]
567    pub const fn as_str(self) -> &'static str {
568        match self {
569            Ordering::Relaxed => "relaxed",
570            Ordering::Acquire => "acquire",
571            Ordering::Release => "release",
572            Ordering::AcqRel => "acq_rel",
573            Ordering::SeqCst => "seq_cst",
574        }
575    }
576}
577
578/// Which question one of the floating point classification builtins asks.
579///
580/// The four that this does not have are `isgreater`, `isgreaterequal`, `isless` and
581/// `islessequal`, which are `>`, `>=`, `<` and `<=` and are those.
582#[derive(Debug, Clone, Copy, PartialEq, Eq)]
583pub enum Classify {
584    /// `isunordered(a, b)`, true when either of the two is a NaN and so the two cannot be put
585    /// in an order at all. C has no operator for this one.
586    Unordered,
587    /// `islessgreater(a, b)`, which is `a < b || a > b` and so is false when either is a NaN.
588    /// That is not `a != b`, which is true of a NaN, so C has no operator for this one either.
589    LessGreater,
590    /// `isnan(x)`, the value that is not in an order with itself.
591    Nan,
592    /// `isinf(x)`, either infinity.
593    Infinite,
594    /// `isfinite(x)`, which is neither an infinity nor a NaN.
595    Finite,
596    /// `isnormal(x)`, which is finite and whose magnitude is at least the smallest normal of its
597    /// format, so it is false of a zero and of a subnormal as well as of the two `isfinite`
598    /// rules out.
599    Normal,
600    /// `signbit(x)`, which asks about the sign and not about the value, so it is true of a
601    /// negative zero and of a NaN whose sign bit is set.
602    SignBit,
603    /// `isinf_sign(x)`, which is `isinf` with a sign: one for a positive infinity, minus one for
604    /// a negative one and zero for everything else. It is the one question in the family whose
605    /// answer is a number rather than a bit.
606    InfiniteSign,
607}
608
609impl Classify {
610    /// How the question is written in the typed tree's textual form.
611    #[must_use]
612    pub const fn as_str(self) -> &'static str {
613        match self {
614            Classify::Unordered => "unordered",
615            Classify::LessGreater => "less-greater",
616            Classify::Nan => "nan",
617            Classify::Infinite => "infinite",
618            Classify::Finite => "finite",
619            Classify::Normal => "normal",
620            Classify::SignBit => "signbit",
621            Classify::InfiniteSign => "infinite-sign",
622        }
623    }
624
625    /// Whether the question is about a pair of values rather than about one.
626    #[must_use]
627    pub const fn is_pair(self) -> bool {
628        matches!(self, Classify::Unordered | Classify::LessGreater)
629    }
630
631    /// Whether the answer is one bit, which is every question here but `isinf_sign`.
632    ///
633    /// The type of the whole node is `int` either way. What this decides is whether the walk to
634    /// the IR has a bit to widen into one or a number that is already one.
635    #[must_use]
636    pub const fn answers_a_bit(self) -> bool {
637        !matches!(self, Classify::InfiniteSign)
638    }
639}
640
641/// Where the sign of the answer to one of the sign builtins comes from.
642///
643/// Neither of these is a computation on the value. `fabs` of a NaN is that NaN with its sign bit
644/// clear, payload and all, and `copysign` of one is that NaN with the other value's sign bit, so
645/// what both do is described entirely in terms of the bits.
646#[derive(Debug, Clone, Copy, PartialEq, Eq)]
647pub enum Sign {
648    /// `fabs(x)`, whose sign is always clear.
649    Clear,
650    /// `copysign(x, y)`, whose sign is the sign of the second operand.
651    Of,
652}
653
654impl Sign {
655    /// How the operation is written in the typed tree's textual form.
656    #[must_use]
657    pub const fn as_str(self) -> &'static str {
658        match self {
659            Sign::Clear => "clear",
660            Sign::Of => "of",
661        }
662    }
663
664    /// Whether it reads a sign from a second operand.
665    #[must_use]
666    pub const fn is_pair(self) -> bool {
667        matches!(self, Sign::Of)
668    }
669}
670
671/// A conversion the language performs without being asked.
672///
673/// Each of these is a node in the tree rather than a difference between two types that a later
674/// pass notices. The IR builder is entitled to assume it never has to insert one, and the
675/// verifier in `spec/08-ir.md` checks that assumption on every function.
676#[derive(Debug, Clone, Copy, PartialEq, Eq)]
677pub enum Conversion {
678    /// Reading an object, which drops the qualifiers and turns an lvalue into a value.
679    Lvalue,
680    /// An array becoming a pointer to its first element.
681    ArrayDecay,
682    /// A function becoming a pointer to itself.
683    FunctionDecay,
684    /// One arithmetic type to another. The integer promotions, the usual arithmetic
685    /// conversions, and the conversions an assignment or an argument performs are all this.
686    Arithmetic,
687    /// A pointer to another pointer type, which includes both directions of `void *`.
688    Pointer,
689    /// A scalar to `bool`, which is a comparison against zero rather than a truncation, and
690    /// which is why it is not [`Conversion::Arithmetic`].
691    Bool,
692    /// A null pointer constant becoming a pointer, which is not the same as converting the
693    /// integer zero, because the constant may have any integer type and `(void *)0` is one.
694    NullPointer,
695    /// A value being discarded, which is what a cast to `void` and an expression statement do.
696    Void,
697    /// A scalar becoming a vector, by being copied into every lane of it.
698    ///
699    /// Written where a scalar stands beside a vector in an operator, which GNU C reads as that
700    /// scalar in every lane. It is not [`Conversion::Arithmetic`] because the lane type and the
701    /// scalar's type are already the same by the time this is reached: the narrowing that a
702    /// lane asks for is an arithmetic conversion of its own underneath this one, so that the
703    /// two questions are answered where each of them is usually answered.
704    Broadcast,
705}
706
707impl Conversion {
708    /// How the conversion is written in the typed tree's textual form.
709    #[must_use]
710    pub const fn as_str(self) -> &'static str {
711        match self {
712            Conversion::Lvalue => "lvalue",
713            Conversion::ArrayDecay => "array-decay",
714            Conversion::FunctionDecay => "function-decay",
715            Conversion::Arithmetic => "arithmetic",
716            Conversion::Pointer => "pointer",
717            Conversion::Bool => "bool",
718            Conversion::NullPointer => "null-pointer",
719            Conversion::Void => "void",
720            Conversion::Broadcast => "broadcast",
721        }
722    }
723}