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}