Skip to main content

rucc_ir/
parse.rs

1//! The parser: text back into a module.
2//!
3//! Design: `spec/08-ir.md` section 8.8.
4//!
5//! The other half of the round trip. What the printer wrote, this reads, and printing the
6//! result gives the same bytes back. That is what makes the IR testable without the front end,
7//! what makes a dump worth trusting, and what lets a fuzzer make IR directly.
8//!
9//! # Forward references
10//!
11//! A branch names a block that has not been read yet, and, less obviously, an instruction can
12//! use a value defined further down the text: the blocks are printed in layout order, and
13//! layout order is not required to be an order in which every definition comes before its uses.
14//!
15//! Blocks are easy, because a block is an index and the index is the number in the text. Values
16//! are not, because creating an instruction needs the types of the values it produces, and for
17//! most opcodes that type is the type of the first operand, which may be one of the values that
18//! have not been read yet.
19//!
20//! So a function is read in two passes. The first turns the text into a list of blocks holding
21//! instructions whose operands are still just the numbers they were written as. The second
22//! works out the type of every value and then builds the function. Working the types out
23//! terminates because the only cycles in the definition graph run through block parameters, and
24//! a block parameter has its type written at the block.
25//!
26//! # Numbering
27//!
28//! Values are numbered from zero in print order and so are blocks, so building the function in
29//! print order gives every value and every block the index its number in the text says. The
30//! parser checks that as it goes rather than assuming it, which is what catches a text whose
31//! numbering does not add up.
32
33use std::fmt;
34
35use rucc_base::float::Format;
36use rucc_base::{Idx, Interner, Symbol};
37use rucc_diag::Span;
38use rucc_target::{Slot, TargetInfo};
39use rucc_tuple::TargetTuple;
40
41use crate::attrs::{AttrSet, Attrs, FpContract};
42use crate::func::Func;
43use crate::inst::{
44    Abi, AsmInfo, Block, BlockCall, CallInfo, Imm, Inst, InstData, MemInfo, Meta, MetaNode, Param,
45    PlaneNode, Restrict, Signature, SwitchInfo, TbaaNode, VaInfo, Value,
46};
47use crate::module::{
48    Alias, AliasKind, DataLayout, Datum, Global, Linkage, Module, Reloc, TlsModel, Visibility,
49};
50use crate::{
51    Bounds, Extra, ExtraKind, FORMAT_VERSION, Facts, Flags, FloatPred, IntPred, MemOrder, Opcode,
52    Owner, RmwOp, StorageClass, Type,
53};
54
55/// Why a module could not be read.
56///
57/// One error and then nothing, rather than a list. A malformed IR dump is a bug in whatever
58/// wrote it or a file somebody edited by hand, and in both cases the first thing that does not
59/// add up is the thing worth reporting.
60#[derive(Clone, Debug, PartialEq, Eq)]
61pub struct ParseError {
62    /// Which line of the text, counting from one.
63    pub line: u32,
64    /// What was wrong with it.
65    pub message: String,
66}
67
68impl fmt::Display for ParseError {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        write!(f, "line {}: {}", self.line, self.message)
71    }
72}
73
74impl std::error::Error for ParseError {}
75
76/// Reads a module from the text the printer writes.
77///
78/// Names are interned into `names`, which is the same interner the printer will be given when
79/// the module is written back out.
80///
81/// # Errors
82///
83/// Gives back the first thing in the text that does not add up, with the line it is on.
84pub fn parse(text: &str, names: &mut Interner) -> Result<Module, ParseError> {
85    Parser::new(text, names).module()
86}
87
88/// Reading one text.
89struct Parser<'a, 'n> {
90    text: &'a str,
91    pos: usize,
92    line: u32,
93    names: &'n mut Interner,
94    /// The highest metadata node any instruction referred to, so that a reference to one that
95    /// is never defined is caught rather than left as an index into nothing.
96    meta_used: Option<(u32, u32)>,
97}
98
99/// A block, read but not yet built.
100struct PendingBlock<'a> {
101    params: Vec<(u32, Type)>,
102    insts: Vec<PendingInst<'a>>,
103}
104
105/// What is known about one value, read but not yet built. Every value is still its number.
106struct PendingFacts {
107    line: u32,
108    value: u32,
109    bounds: Option<(u32, u32)>,
110    init: Option<u64>,
111    align: Option<u32>,
112    live: bool,
113}
114
115impl PendingFacts {
116    fn new(line: u32, value: u32) -> Self {
117        Self { line, value, bounds: None, init: None, align: None, live: false }
118    }
119}
120
121/// An instruction, read but not yet built. Every value is still the number it was written as.
122struct PendingInst<'a> {
123    opcode: Opcode,
124    flags: Flags,
125    results: Vec<u32>,
126    /// The types written after the opcode, which is none when the operands say them.
127    written: Vec<Type>,
128    args: Vec<u32>,
129    /// The version of memory it reads, written as `[mem %3]` at the end of the line. It is kept
130    /// here as well as pushed onto `args`, because whether an instruction produces a new version
131    /// is not something the text says twice: it follows from being on the chain and writing.
132    mem: Option<u32>,
133    extra: PendingExtra<'a>,
134    line: u32,
135}
136
137/// A branch target, read but not yet built.
138struct PendingCall {
139    block: u32,
140    args: Vec<u32>,
141}
142
143/// The payload of an instruction, read but not yet built.
144enum PendingExtra<'a> {
145    None,
146    /// The text of the constant, which cannot be read until the result type is known.
147    Imm(&'a str),
148    Symbol(Symbol),
149    IntPred(IntPred),
150    FloatPred(FloatPred),
151    Mem(MemInfo),
152    /// The access, and the slots the object travelled in, which is empty for one that did not
153    /// travel in registers.
154    VaObject(MemInfo, Vec<Slot>),
155    Rmw(RmwOp, MemInfo),
156    Order(MemOrder),
157    Class(StorageClass),
158    Owner(Owner),
159    Node(Meta),
160    Reason(Symbol),
161    Targets(Vec<PendingCall>),
162    Call {
163        callee: Option<Symbol>,
164        signature: Signature,
165        /// One entry for each argument, whether or not the signature names it, since the
166        /// signature is written after the arguments and is not known yet.
167        abis: Vec<Abi>,
168    },
169    Switch {
170        targets: Vec<PendingCall>,
171        cases: Vec<&'a str>,
172    },
173    Asm {
174        template: Symbol,
175        constraints: Symbol,
176        clobbers: Symbol,
177        targets: Vec<PendingCall>,
178    },
179}
180
181impl<'a, 'n> Parser<'a, 'n> {
182    fn new(text: &'a str, names: &'n mut Interner) -> Self {
183        Parser { text, pos: 0, line: 1, names, meta_used: None }
184    }
185
186    // The whole module.
187
188    fn module(mut self) -> Result<Module, ParseError> {
189        let name = self.header_name()?;
190        self.expect("; format ")?;
191        let version = self.u32()?;
192        if version != FORMAT_VERSION {
193            return self.fail(format!(
194                "this build reads format {FORMAT_VERSION} and the text says format {version}"
195            ));
196        }
197        self.end_of_line()?;
198
199        self.expect("target triple = ")?;
200        let triple = self.quoted_str()?;
201        let Ok(tuple) = triple.parse::<TargetTuple>() else {
202            return self.fail(format!("`{triple}` is not a target triple"));
203        };
204        self.end_of_line()?;
205
206        self.expect("target datalayout = ")?;
207        let layout = self.quoted_str()?;
208        let Some(datalayout) = DataLayout::parse(&layout) else {
209            return self.fail(format!("`{layout}` is not a data layout"));
210        };
211        self.end_of_line()?;
212
213        let name = self.names.intern(&name);
214        let mut module = Module::new(name, &TargetInfo::for_tuple(tuple));
215        module.datalayout = datalayout;
216
217        loop {
218            self.skip_blank_lines();
219            if self.at_end() {
220                break;
221            }
222            match self.peek_word() {
223                "global" => self.global(&mut module)?,
224                "alias" | "ifunc" => self.alias(&mut module)?,
225                "func" => self.func(&mut module)?,
226                _ if self.at("!") => self.meta(&mut module)?,
227                other => return self.fail(format!("`{other}` does not start anything")),
228            }
229        }
230
231        if let Some((used, line)) = self.meta_used {
232            let count = module.counts().metadata as u32;
233            if used >= count {
234                self.line = line;
235                return self.fail(format!("!{used} is used and never defined"));
236            }
237        }
238        Ok(module)
239    }
240
241    /// The `; ModuleID = 'name'` line, whose name is not quoted the way everything else is.
242    fn header_name(&mut self) -> Result<String, ParseError> {
243        self.expect("; ModuleID = '")?;
244        let start = self.pos;
245        let Some(end) = self.text[start..].find('\'') else {
246            return self.fail("the module name is not closed");
247        };
248        let name = self.text[start..start + end].to_string();
249        self.pos = start + end + 1;
250        self.end_of_line()?;
251        Ok(name)
252    }
253
254    // Globals, aliases and metadata.
255
256    fn global(&mut self, module: &mut Module) -> Result<(), ParseError> {
257        self.expect("global")?;
258        let name = self.symbol()?;
259        self.expect(":")?;
260
261        let mut global = Global::new(name, 0, 1);
262        if self.eat_word("bytes") {
263            global.size = self.u64()?;
264            if self.eat("=") {
265                self.expect("{")?;
266                let mut data = Vec::new();
267                // The brace is looked for before a piece is asked for, because an image with
268                // nothing in it is a thing a zero sized object has and asking for a piece first
269                // met the closing brace and called it a type that does not exist.
270                if !self.eat("}") {
271                    loop {
272                        data.push(self.datum(module)?);
273                        if !self.eat(",") {
274                            break;
275                        }
276                    }
277                    self.expect("}")?;
278                }
279                global.init = Some(module.push_data(&data));
280            }
281        } else {
282            let ty = self.ty()?;
283            self.expect("=")?;
284            let text = self.imm_text()?;
285            let value = self.imm(text, ty)?;
286            let datum = Datum::Scalar { ty, value: module.add_imm(value) };
287            global.size = datum.size(module);
288            global.init = Some(module.push_data(&[datum]));
289        }
290
291        while self.eat(",") {
292            match self.word() {
293                "align" => global.align = self.u32()?,
294                "linkage" => {
295                    global.linkage = self.parenthesised(Linkage::from_name, "a linkage")?
296                }
297                "visibility" => {
298                    global.visibility =
299                        self.parenthesised(Visibility::from_name, "a visibility")?;
300                }
301                "tls" => {
302                    global.tls =
303                        Some(self.parenthesised(TlsModel::from_name, "a thread-local model")?);
304                }
305                "constant" => global.constant = true,
306                "section" => global.section = Some(self.symbol_from_string()?),
307                other => return self.fail(format!("a global has no `{other}`")),
308            }
309        }
310        self.end_of_line()?;
311        module.add_global(global);
312        Ok(())
313    }
314
315    /// One piece of a global's image.
316    fn datum(&mut self, module: &mut Module) -> Result<Datum, ParseError> {
317        match self.peek_word() {
318            "zero" => {
319                self.expect("zero")?;
320                Ok(Datum::Zero(self.u64()?))
321            }
322            "bytes" => {
323                self.expect("bytes")?;
324                let bytes = self.string()?;
325                Ok(Datum::Bytes(module.push_bytes(&bytes)))
326            }
327            "addr" => {
328                self.expect("addr")?;
329                self.expect(".")?;
330                let size = self.u32()?;
331                let symbol = self.symbol()?;
332                let addend = if self.eat("+") {
333                    self.i64()?
334                } else if self.eat("-") {
335                    let amount = self.i64()?;
336                    match amount.checked_neg() {
337                        Some(negated) => negated,
338                        None => return self.fail("that offset has no negative"),
339                    }
340                } else {
341                    0
342                };
343                Ok(Datum::Addr(module.add_reloc(Reloc { symbol, addend, size })))
344            }
345            _ => {
346                let ty = self.ty()?;
347                let text = self.imm_text()?;
348                let value = self.imm(text, ty)?;
349                Ok(Datum::Scalar { ty, value: module.add_imm(value) })
350            }
351        }
352    }
353
354    fn alias(&mut self, module: &mut Module) -> Result<(), ParseError> {
355        let word = self.word();
356        let Some(kind) = AliasKind::from_name(word) else {
357            return self.fail(format!("`{word}` is not a kind of alias"));
358        };
359        let name = self.symbol()?;
360        self.expect("=")?;
361        let target = self.symbol()?;
362        let mut alias = Alias::new(name, target);
363        alias.kind = kind;
364        while self.eat(",") {
365            match self.word() {
366                "linkage" => alias.linkage = self.parenthesised(Linkage::from_name, "a linkage")?,
367                "visibility" => {
368                    alias.visibility = self.parenthesised(Visibility::from_name, "a visibility")?;
369                }
370                other => return self.fail(format!("an alias has no `{other}`")),
371            }
372        }
373        self.end_of_line()?;
374        module.add_alias(alias);
375        Ok(())
376    }
377
378    fn meta(&mut self, module: &mut Module) -> Result<(), ParseError> {
379        let index = self.meta_ref()?;
380        let expected = module.counts().metadata as u32;
381        if index.raw() != expected {
382            return self.fail(format!("metadata is numbered in order and !{expected} comes next"));
383        }
384        self.expect("=")?;
385        let node = match self.word() {
386            "tbaa" => {
387                let name = self.symbol_from_string()?;
388                let mut node = TbaaNode { name, parent: None, offset: 0 };
389                while self.eat(",") {
390                    match self.word() {
391                        "parent" => node.parent = Some(self.meta_ref()?),
392                        "offset" => node.offset = self.u64()?,
393                        other => return self.fail(format!("a metadata node has no `{other}`")),
394                    }
395                }
396                MetaNode::Tbaa(node)
397            }
398            // A plane entry is one thing and not a list of fields, so it is written as that one
399            // thing: the aliasing node of the type it is, or one of the three names document 09
400            // section 9.1 gives the values that are not a type.
401            "plane" => MetaNode::Plane(if self.peek_is("!") {
402                PlaneNode::Type(self.meta_ref()?)
403            } else {
404                match self.word() {
405                    "no_type" => PlaneNode::NoType,
406                    "character" => PlaneNode::Character,
407                    "pointer_slot" => {
408                        let k = self.u32()?;
409                        match u8::try_from(k) {
410                            Ok(k) => PlaneNode::PointerSlot(k),
411                            Err(_) => return self.fail(format!("no pointer has a byte {k}")),
412                        }
413                    }
414                    other => return self.fail(format!("`{other}` is not a plane entry")),
415                }
416            }),
417            other => return self.fail(format!("`{other}` is not a kind of metadata node")),
418        };
419        if node.points_at().is_some_and(|at| at.raw() >= index.raw()) {
420            return self.fail("a metadata node names one that comes before it");
421        }
422        self.end_of_line()?;
423        module.add_meta(node);
424        Ok(())
425    }
426
427    // Functions.
428
429    fn func(&mut self, module: &mut Module) -> Result<(), ParseError> {
430        self.expect("func")?;
431        let name = self.symbol()?;
432        let signature = self.signature()?;
433        let mut func = Func::new(name, signature);
434        while self.eat(",") {
435            match self.word() {
436                "linkage" => func.linkage = self.parenthesised(Linkage::from_name, "a linkage")?,
437                "visibility" => {
438                    func.visibility = self.parenthesised(Visibility::from_name, "a visibility")?;
439                }
440                "attrs" => func.attrs = self.attrs()?,
441                "section" => func.section = Some(self.symbol_from_string()?),
442                other => return self.fail(format!("a function has no `{other}`")),
443            }
444        }
445        if self.eat(";") {
446            self.end_of_line()?;
447            module.add_func(func);
448            return Ok(());
449        }
450        self.expect("{")?;
451        self.end_of_line()?;
452        let (blocks, facts) = self.body()?;
453        self.build(&mut func, &blocks, &facts)?;
454        module.add_func(func);
455        Ok(())
456    }
457
458    /// The parameter and result types, in parentheses and after an arrow.
459    fn signature(&mut self) -> Result<Signature, ParseError> {
460        self.expect("(")?;
461        let mut signature = Signature::new();
462        if !self.eat(")") {
463            loop {
464                if self.eat("...") {
465                    signature.variadic = true;
466                    break;
467                }
468                signature.params.push(self.param()?);
469                if !self.eat(",") {
470                    break;
471                }
472            }
473            self.expect(")")?;
474        }
475        if self.eat("->") {
476            if self.eat("(") {
477                loop {
478                    signature.returns.push(self.param()?);
479                    if !self.eat(",") {
480                        break;
481                    }
482                }
483                self.expect(")")?;
484            } else {
485                signature.returns.push(self.param()?);
486            }
487        }
488        Ok(signature)
489    }
490
491    /// One parameter: a type, and what the ABI asks of it when the text says anything.
492    fn param(&mut self) -> Result<Param, ParseError> {
493        let ty = self.ty()?;
494        let abi = self.abi()?;
495        Ok(Param { ty, abi })
496    }
497
498    /// What the ABI asks of a value, which is [`Abi::Plain`] when the text says nothing.
499    fn abi(&mut self) -> Result<Abi, ParseError> {
500        let abi = match self.peek_word() {
501            "sext" => {
502                self.word();
503                Abi::Sext
504            }
505            "zext" => {
506                self.word();
507                Abi::Zext
508            }
509            word @ ("byval" | "sret") => {
510                let indirect = word == "byval";
511                self.word();
512                self.expect("(")?;
513                let size = self.u64()?;
514                self.expect(",")?;
515                self.expect("align")?;
516                let align = self.u32()?;
517                self.expect(")")?;
518                if indirect { Abi::ByVal { size, align } } else { Abi::Sret { size, align } }
519            }
520            _ => Abi::Plain,
521        };
522        Ok(abi)
523    }
524
525    fn attrs(&mut self) -> Result<Attrs, ParseError> {
526        self.expect("(")?;
527        let mut attrs = Attrs::NONE;
528        loop {
529            let word = self.word();
530            if self.eat("=") {
531                let value = self.word();
532                match word {
533                    "fp_contract" => match FpContract::from_name(value) {
534                        Some(contract) => attrs.fp_contract = contract,
535                        None => return self.fail(format!("`{value}` is not a contraction")),
536                    },
537                    other => return self.fail(format!("`{other}` takes no value")),
538                }
539            } else {
540                match AttrSet::from_name(word) {
541                    Some(attr) => attrs.set |= attr,
542                    None => return self.fail(format!("`{word}` is not an attribute")),
543                }
544            }
545            if !self.eat(",") {
546                break;
547            }
548        }
549        self.expect(")")?;
550        Ok(attrs)
551    }
552
553    /// The blocks of a function, up to the closing brace.
554    fn body(&mut self) -> Result<(Vec<PendingBlock<'a>>, Vec<PendingFacts>), ParseError> {
555        let mut blocks: Vec<PendingBlock<'a>> = Vec::new();
556        let mut facts: Vec<PendingFacts> = Vec::new();
557        loop {
558            self.skip_blank_lines();
559            if self.eat("}") {
560                self.end_of_line()?;
561                return Ok((blocks, facts));
562            }
563            if self.at_end() {
564                return self.fail("the function is not closed");
565            }
566            if self.peek_word() == "facts" {
567                // The facts come after the last block and are the last thing in the body, so
568                // this reads all of them and then goes back round to the closing brace.
569                self.word();
570                self.expect(":")?;
571                self.end_of_line()?;
572                loop {
573                    self.skip_blank_lines();
574                    if !self.peek_is("%") {
575                        break;
576                    }
577                    facts.push(self.fact_line()?);
578                }
579                continue;
580            }
581            if self.peek_word().starts_with("block") {
582                let number = self.block_ref()?;
583                if number as usize != blocks.len() {
584                    return self.fail(format!(
585                        "blocks are numbered in order and block{} comes next",
586                        blocks.len()
587                    ));
588                }
589                let mut params = Vec::new();
590                if self.eat("(") {
591                    loop {
592                        let value = self.value_ref()?;
593                        self.expect(":")?;
594                        params.push((value, self.ty()?));
595                        if !self.eat(",") {
596                            break;
597                        }
598                    }
599                    self.expect(")")?;
600                }
601                self.expect(":")?;
602                self.end_of_line()?;
603                blocks.push(PendingBlock { params, insts: Vec::new() });
604                continue;
605            }
606            let inst = self.inst()?;
607            match blocks.last_mut() {
608                Some(block) => block.insts.push(inst),
609                None => return self.fail("an instruction before any block"),
610            }
611        }
612    }
613
614    /// One line of the facts section: a value, and what is known about it.
615    fn fact_line(&mut self) -> Result<PendingFacts, ParseError> {
616        let line = self.line;
617        let value = self.value_ref()?;
618        self.expect("=")?;
619        let mut facts = PendingFacts::new(line, value);
620        loop {
621            self.expect("!")?;
622            let word = self.word();
623            match word {
624                "bounds" => {
625                    self.expect("(")?;
626                    let lo = self.value_ref()?;
627                    self.expect(",")?;
628                    let ext = self.value_ref()?;
629                    self.expect(")")?;
630                    facts.bounds = Some((lo, ext));
631                }
632                "live" => facts.live = true,
633                "init" => {
634                    self.expect("(")?;
635                    facts.init = Some(self.u64()?);
636                    self.expect(")")?;
637                }
638                "aligned" => {
639                    self.expect("(")?;
640                    facts.align = Some(self.u32()?);
641                    self.expect(")")?;
642                }
643                other => return self.fail(format!("`{other}` is not a fact")),
644            }
645            if !self.eat(",") {
646                break;
647            }
648        }
649        self.end_of_line()?;
650        Ok(facts)
651    }
652
653    /// One instruction line.
654    fn inst(&mut self) -> Result<PendingInst<'a>, ParseError> {
655        let line = self.line;
656        let mut results = Vec::new();
657        if self.peek_is("%") {
658            results = self.value_list()?;
659            self.expect("=")?;
660        }
661
662        let word = self.word();
663        let Some(opcode) = Opcode::from_name(word) else {
664            return self.fail(format!("`{word}` is not an opcode"));
665        };
666        let (written, flags) = self.suffixes()?;
667
668        let mut args = Vec::new();
669        let extra = match opcode.extra_kind() {
670            ExtraKind::None => {
671                args = self.value_list()?;
672                PendingExtra::None
673            }
674            ExtraKind::Imm => PendingExtra::Imm(self.imm_text()?),
675            ExtraKind::Symbol => {
676                let symbol = self.symbol()?;
677                if self.eat("(") {
678                    args = self.value_list()?;
679                    self.expect(")")?;
680                }
681                PendingExtra::Symbol(symbol)
682            }
683            ExtraKind::IntPred => {
684                let word = self.word();
685                let Some(pred) = IntPred::from_name(word) else {
686                    return self.fail(format!("`{word}` is not an integer comparison"));
687                };
688                args = self.value_list()?;
689                PendingExtra::IntPred(pred)
690            }
691            ExtraKind::FloatPred => {
692                let word = self.word();
693                let Some(pred) = FloatPred::from_name(word) else {
694                    return self.fail(format!("`{word}` is not a floating point comparison"));
695                };
696                args = self.value_list()?;
697                PendingExtra::FloatPred(pred)
698            }
699            ExtraKind::Mem => {
700                if matches!(opcode, Opcode::Store | Opcode::AtomicStore) {
701                    // A store reads left to right like the assignment it came from.
702                    let value = self.value_ref()?;
703                    self.expect("->")?;
704                    args = vec![value, self.value_ref()?];
705                } else {
706                    args = self.value_list()?;
707                }
708                PendingExtra::Mem(self.mem()?)
709            }
710            ExtraKind::VaObject => {
711                args = self.value_list()?;
712                let (info, slots) = self.va()?;
713                PendingExtra::VaObject(info, slots)
714            }
715            ExtraKind::Rmw => {
716                let word = self.word();
717                let Some(op) = RmwOp::from_name(word) else {
718                    return self.fail(format!("`{word}` is not a read-modify-write"));
719                };
720                args = self.value_list()?;
721                PendingExtra::Rmw(op, self.mem()?)
722            }
723            ExtraKind::Order => {
724                let word = self.word();
725                let Some(order) = MemOrder::from_name(word) else {
726                    return self.fail(format!("`{word}` is not an ordering"));
727                };
728                PendingExtra::Order(order)
729            }
730            // The plane writes. Each reads its range and then the one thing it needs beyond it,
731            // written with a name in front the way the fields of an access are.
732            ExtraKind::Class => {
733                args = self.value_list()?;
734                self.expect(",")?;
735                self.expect("class")?;
736                let word = self.word();
737                let Some(class) = StorageClass::from_name(word) else {
738                    return self.fail(format!("`{word}` is not a storage class"));
739                };
740                PendingExtra::Class(class)
741            }
742            ExtraKind::Owner => {
743                args = self.value_list()?;
744                self.expect(",")?;
745                self.expect("to")?;
746                let word = self.word();
747                let Some(owner) = Owner::from_name(word) else {
748                    return self.fail(format!("`{word}` is not somewhere a range can go"));
749                };
750                PendingExtra::Owner(owner)
751            }
752            ExtraKind::Node => {
753                args = self.value_list()?;
754                self.expect(",")?;
755                self.expect("tbaa")?;
756                PendingExtra::Node(self.meta_ref()?)
757            }
758            ExtraKind::Reason => PendingExtra::Reason(self.symbol_from_string()?),
759            ExtraKind::Targets => {
760                args = self.value_list()?;
761                if !args.is_empty() {
762                    self.expect(",")?;
763                }
764                let mut targets = Vec::new();
765                loop {
766                    targets.push(self.block_call()?);
767                    if !self.eat(",") {
768                        break;
769                    }
770                }
771                PendingExtra::Targets(targets)
772            }
773            ExtraKind::Call => {
774                let callee = if self.peek_is("@") {
775                    Some(self.symbol()?)
776                } else {
777                    args.push(self.value_ref()?);
778                    None
779                };
780                self.expect("(")?;
781                let (values, abis) = self.call_args()?;
782                args.extend(values);
783                self.expect(")")?;
784                self.expect(":")?;
785                PendingExtra::Call { callee, signature: self.signature()?, abis }
786            }
787            ExtraKind::Switch => {
788                args = self.value_list()?;
789                let mut targets = Vec::new();
790                let mut cases = Vec::new();
791                if self.eat(",") {
792                    targets.push(self.block_call()?);
793                    self.expect(",")?;
794                    self.expect("[")?;
795                    if !self.eat("]") {
796                        loop {
797                            cases.push(self.imm_text()?);
798                            self.expect("=>")?;
799                            targets.push(self.block_call()?);
800                            if !self.eat(",") {
801                                break;
802                            }
803                        }
804                        self.expect("]")?;
805                    }
806                }
807                PendingExtra::Switch { targets, cases }
808            }
809            ExtraKind::Asm => {
810                let template = self.symbol_from_string()?;
811                self.expect(",")?;
812                let constraints = self.symbol_from_string()?;
813                self.expect(",")?;
814                let clobbers = self.symbol_from_string()?;
815                self.expect("(")?;
816                args = self.value_list()?;
817                self.expect(")")?;
818                let mut targets = Vec::new();
819                if self.eat(",") {
820                    self.expect("labels")?;
821                    self.expect("[")?;
822                    loop {
823                        targets.push(self.block_call()?);
824                        if !self.eat(",") {
825                            break;
826                        }
827                    }
828                    self.expect("]")?;
829                }
830                PendingExtra::Asm { template, constraints, clobbers, targets }
831            }
832        };
833        // The memory operand comes last and outside the operand list, with no comma before it,
834        // so nothing above has to know it might be there.
835        let mut mem = None;
836        if self.eat("[") {
837            self.expect("mem")?;
838            let value = self.value_ref()?;
839            self.expect("]")?;
840            args.push(value);
841            mem = Some(value);
842        }
843        self.end_of_line()?;
844        Ok(PendingInst { opcode, flags, results, written, args, mem, extra, line })
845    }
846
847    /// The dotted things after an opcode: the result types, then the flags.
848    fn suffixes(&mut self) -> Result<(Vec<Type>, Flags), ParseError> {
849        let mut written = Vec::new();
850        let mut flags = Flags::NONE;
851        while self.at(".") {
852            self.pos += 1;
853            if self.at("(") {
854                self.pos += 1;
855                loop {
856                    written.push(self.ty()?);
857                    if !self.eat(",") {
858                        break;
859                    }
860                }
861                self.expect(")")?;
862                continue;
863            }
864            let word = self.glued_word();
865            if let Some(flag) = Flags::from_name(word) {
866                flags |= flag;
867            } else if let Some(ty) = Type::parse(word) {
868                written.push(ty);
869            } else {
870                return self.fail(format!("`{word}` is neither a type nor a flag"));
871            }
872        }
873        Ok((written, flags))
874    }
875
876    /// What an access carries beyond its address.
877    fn mem(&mut self) -> Result<MemInfo, ParseError> {
878        let mut info = MemInfo {
879            size: 0,
880            align: 1,
881            order: MemOrder::NotAtomic,
882            tbaa: None,
883            owns: 0,
884            restrict: Restrict::NONE,
885        };
886        while self.eat(",") {
887            let word = self.word();
888            if !self.mem_field(&mut info, word)? {
889                return self.fail(format!("an access has no `{word}`"));
890            }
891        }
892        Ok(info)
893    }
894
895    /// One `name value` pair of an access, and whether the name was one of them.
896    fn mem_field(&mut self, info: &mut MemInfo, word: &str) -> Result<bool, ParseError> {
897        match word {
898            "size" => info.size = self.u64()?,
899            "align" => info.align = self.u32()?,
900            "tbaa" => info.tbaa = Some(self.meta_ref()?),
901            "owns" => info.owns = self.u32()?,
902            "restrict" => info.restrict = self.restrict()?,
903            _ => match MemOrder::from_name(word) {
904                Some(order) => info.order = order,
905                None => return Ok(false),
906            },
907        }
908        Ok(true)
909    }
910
911    /// The clique and the base of a `restrict` scope, as `restrict(clique, base)`.
912    fn restrict(&mut self) -> Result<Restrict, ParseError> {
913        self.expect("(")?;
914        let clique = self.u16()?;
915        self.expect(",")?;
916        let base = self.u16()?;
917        self.expect(")")?;
918        Ok(Restrict { clique, base })
919    }
920
921    /// An access with the slots an object read off a variable argument list travelled in, which
922    /// is an access and nothing else for one that travelled in memory.
923    fn va(&mut self) -> Result<(MemInfo, Vec<Slot>), ParseError> {
924        let mut info = MemInfo {
925            size: 0,
926            align: 1,
927            order: MemOrder::NotAtomic,
928            tbaa: None,
929            owns: 0,
930            restrict: Restrict::NONE,
931        };
932        let mut slots = Vec::new();
933        while self.eat(",") {
934            let word = self.word();
935            if word == "in" {
936                self.expect("(")?;
937                loop {
938                    slots.push(self.slot()?);
939                    if !self.eat(",") {
940                        break;
941                    }
942                }
943                self.expect(")")?;
944            } else if !self.mem_field(&mut info, word)? {
945                return self
946                    .fail(format!("an object off a variable argument list has no `{word}`"));
947            }
948        }
949        Ok((info, slots))
950    }
951
952    /// One register's worth of an object, as what is read out of it and where its bytes are.
953    fn slot(&mut self) -> Result<Slot, ParseError> {
954        let word = self.word();
955        let slot = match word {
956            "int" => {
957                let size = self.u32()?;
958                self.expect("at")?;
959                Slot::Integer { offset: self.u64()?, size }
960            }
961            "float" => {
962                let name = self.word();
963                let Some(format) = Format::from_name(name) else {
964                    return self.fail(format!("`{name}` is not a floating point format"));
965                };
966                self.expect("at")?;
967                Slot::Float { offset: self.u64()?, format }
968            }
969            _ => return self.fail(format!("`{word}` is not how a slot is written")),
970        };
971        Ok(slot)
972    }
973
974    /// A branch target and the values it passes.
975    fn block_call(&mut self) -> Result<PendingCall, ParseError> {
976        let block = self.block_ref()?;
977        let mut args = Vec::new();
978        if self.eat("(") {
979            args = self.value_list()?;
980            self.expect(")")?;
981        }
982        Ok(PendingCall { block, args })
983    }
984
985    // Building the function.
986
987    /// Works out every value's type, then creates the blocks and instructions in print order.
988    fn build(
989        &mut self,
990        func: &mut Func,
991        blocks: &[PendingBlock<'a>],
992        facts: &[PendingFacts],
993    ) -> Result<(), ParseError> {
994        let count = self.check_numbering(blocks)?;
995        let types = self.value_types(blocks, count)?;
996
997        let mut next = 0;
998        for pending in blocks {
999            let block = func.create_block();
1000            for &(number, ty) in &pending.params {
1001                if number != next {
1002                    self.line = self.line_of(blocks, number);
1003                    return self
1004                        .fail(format!("values are numbered in order and %{next} comes next"));
1005                }
1006                func.append_param(block, ty);
1007                next += 1;
1008            }
1009            for inst in &pending.insts {
1010                if inst.results.first().is_some_and(|&first| first != next) {
1011                    self.line = inst.line;
1012                    return self
1013                        .fail(format!("values are numbered in order and %{next} comes next"));
1014                }
1015                let built = self.build_inst(func, inst, &types)?;
1016                func.append_inst(block, built);
1017                next += inst.results.len() as u32;
1018            }
1019        }
1020        self.build_facts(func, facts, next)?;
1021        Ok(())
1022    }
1023
1024    /// Puts what the facts section said onto the values it said it about.
1025    ///
1026    /// After the blocks, because a fact names values and every one of them has to exist before
1027    /// any of them can be looked up. The numbering is the same numbering the body uses, so a
1028    /// number here is a value index and nothing has to be mapped.
1029    fn build_facts(
1030        &mut self,
1031        func: &mut Func,
1032        facts: &[PendingFacts],
1033        count: u32,
1034    ) -> Result<(), ParseError> {
1035        for pending in facts {
1036            self.line = pending.line;
1037            for number in [
1038                Some(pending.value),
1039                pending.bounds.map(|(lo, _)| lo),
1040                pending.bounds.map(|(_, ext)| ext),
1041            ]
1042            .into_iter()
1043            .flatten()
1044            {
1045                if number >= count {
1046                    return self.fail(format!("%{number} is used and never defined"));
1047                }
1048            }
1049            let value = Value::from_usize(pending.value as usize);
1050            if !func.facts(value).is_empty() {
1051                return self.fail(format!("%{} is said twice", pending.value));
1052            }
1053            func.set_facts(
1054                value,
1055                Facts {
1056                    bounds: pending.bounds.map(|(lo, ext)| Bounds {
1057                        lo: Value::from_usize(lo as usize),
1058                        ext: Value::from_usize(ext as usize),
1059                    }),
1060                    init: pending.init,
1061                    align: pending.align,
1062                    live: pending.live,
1063                },
1064            );
1065        }
1066        Ok(())
1067    }
1068
1069    /// Checks that every number the text uses is one the text also defines.
1070    ///
1071    /// The answer is how many values there are, which is what everything after this is sized by.
1072    fn check_numbering(&mut self, blocks: &[PendingBlock<'a>]) -> Result<u32, ParseError> {
1073        let mut count = 0;
1074        for pending in blocks {
1075            count += pending.params.len();
1076            for inst in &pending.insts {
1077                count += inst.results.len();
1078            }
1079        }
1080        let count = count as u32;
1081        let total = blocks.len() as u32;
1082        for pending in blocks {
1083            for inst in &pending.insts {
1084                self.line = inst.line;
1085                for &arg in &inst.args {
1086                    if arg >= count {
1087                        return self.fail(format!("%{arg} is used and never defined"));
1088                    }
1089                }
1090                for call in inst_calls(inst) {
1091                    if call.block >= total {
1092                        return self.fail(format!("block{} is used and never defined", call.block));
1093                    }
1094                    for &arg in &call.args {
1095                        if arg >= count {
1096                            return self.fail(format!("%{arg} is used and never defined"));
1097                        }
1098                    }
1099                }
1100            }
1101        }
1102        Ok(count)
1103    }
1104
1105    /// The type of every value, worked out from the ones the text writes down.
1106    ///
1107    /// A block parameter has its type at the block and an instruction either has its written
1108    /// after the opcode or takes it from an operand, so this is a fixed point over a graph whose
1109    /// only cycles run through parameters. It converges in as many rounds as the longest chain
1110    /// of instructions each taking its type from the one below it in the text.
1111    fn value_types(
1112        &mut self,
1113        blocks: &[PendingBlock<'a>],
1114        count: u32,
1115    ) -> Result<Vec<Option<Type>>, ParseError> {
1116        let mut types = vec![None; count as usize];
1117        for pending in blocks {
1118            for &(number, ty) in &pending.params {
1119                types[number as usize] = Some(ty);
1120            }
1121        }
1122        loop {
1123            let mut progress = false;
1124            for pending in blocks {
1125                for inst in &pending.insts {
1126                    let Some(&first) = inst.results.first() else { continue };
1127                    if types[first as usize].is_some() {
1128                        continue;
1129                    }
1130                    let Some(resolved) = result_types(inst, &types) else { continue };
1131                    if resolved.len() != inst.results.len() {
1132                        self.line = inst.line;
1133                        return self.fail(format!(
1134                            "{} produces {} values and the text names {}",
1135                            inst.opcode.name(),
1136                            resolved.len(),
1137                            inst.results.len()
1138                        ));
1139                    }
1140                    for (&number, ty) in inst.results.iter().zip(resolved) {
1141                        types[number as usize] = Some(ty);
1142                    }
1143                    progress = true;
1144                }
1145            }
1146            if !progress {
1147                break;
1148            }
1149        }
1150        for pending in blocks {
1151            for inst in &pending.insts {
1152                if inst.results.first().is_some_and(|&first| types[first as usize].is_none()) {
1153                    self.line = inst.line;
1154                    return self.fail(format!(
1155                        "nothing in the text says what {} produces",
1156                        inst.opcode.name()
1157                    ));
1158                }
1159            }
1160        }
1161        Ok(types)
1162    }
1163
1164    fn build_inst(
1165        &mut self,
1166        func: &mut Func,
1167        pending: &PendingInst<'a>,
1168        types: &[Option<Type>],
1169    ) -> Result<Inst, ParseError> {
1170        let results: Vec<Type> = pending
1171            .results
1172            .iter()
1173            .map(|&number| types[number as usize].unwrap_or(Type::VOID))
1174            .collect();
1175        let args: Vec<Value> =
1176            pending.args.iter().map(|&number| Value::from_usize(number as usize)).collect();
1177        let arg_list = func.push_values(&args);
1178
1179        let extra = match &pending.extra {
1180            PendingExtra::None => Extra::None,
1181            PendingExtra::Imm(text) => {
1182                let ty = results.first().copied().unwrap_or(Type::VOID);
1183                self.line = pending.line;
1184                let imm = self.imm(text, ty)?;
1185                Extra::Imm(func.add_imm(imm))
1186            }
1187            PendingExtra::Symbol(symbol) => Extra::Symbol(*symbol),
1188            PendingExtra::IntPred(pred) => Extra::IntPred(*pred),
1189            PendingExtra::FloatPred(pred) => Extra::FloatPred(*pred),
1190            PendingExtra::Mem(info) => Extra::Mem(func.add_mem(*info)),
1191            PendingExtra::VaObject(info, slots) => {
1192                let mem = func.add_mem(*info);
1193                let slots = func.push_slots(slots);
1194                Extra::VaObject(func.add_va_object(VaInfo { mem, slots }))
1195            }
1196            PendingExtra::Rmw(op, info) => Extra::Rmw(*op, func.add_mem(*info)),
1197            PendingExtra::Order(order) => Extra::Order(*order),
1198            PendingExtra::Class(class) => Extra::Class(*class),
1199            PendingExtra::Owner(owner) => Extra::Owner(*owner),
1200            PendingExtra::Node(node) => Extra::Node(*node),
1201            PendingExtra::Reason(reason) => Extra::Reason(*reason),
1202            PendingExtra::Targets(targets) => {
1203                let calls = build_calls(func, targets);
1204                Extra::Targets(func.push_block_calls(&calls))
1205            }
1206            PendingExtra::Call { callee, signature, abis } => {
1207                let named = signature.params.len();
1208                if abis.iter().take(named).any(|&abi| abi != Abi::Plain) {
1209                    self.line = pending.line;
1210                    return self.fail(
1211                        "the signature is what says how an argument it names travels".to_string(),
1212                    );
1213                }
1214                let varargs = match abis.get(named.min(abis.len())..) {
1215                    Some(rest) if rest.iter().any(|&abi| abi != Abi::Plain) => rest,
1216                    _ => &[],
1217                };
1218                let varargs = func.push_abis(varargs);
1219                let sig = func.add_signature(signature.clone());
1220                Extra::Call(func.add_call(CallInfo { callee: *callee, signature: sig, varargs }))
1221            }
1222            PendingExtra::Switch { targets, cases } => {
1223                let ty = pending
1224                    .args
1225                    .first()
1226                    .and_then(|&number| types[number as usize])
1227                    .unwrap_or(Type::VOID);
1228                self.line = pending.line;
1229                let mut imms = Vec::with_capacity(cases.len());
1230                for case in cases {
1231                    imms.push(self.imm(case, ty)?);
1232                }
1233                let calls = build_calls(func, targets);
1234                let targets = func.push_block_calls(&calls);
1235                let cases = func.push_imms(&imms);
1236                Extra::Switch(func.add_switch(SwitchInfo { targets, cases }))
1237            }
1238            PendingExtra::Asm { template, constraints, clobbers, targets } => {
1239                let calls = build_calls(func, targets);
1240                let targets = func.push_block_calls(&calls);
1241                Extra::Asm(func.add_asm(AsmInfo {
1242                    template: *template,
1243                    constraints: *constraints,
1244                    clobbers: *clobbers,
1245                    targets,
1246                }))
1247            }
1248        };
1249
1250        let data = InstData {
1251            opcode: pending.opcode,
1252            flags: pending.flags,
1253            args: arg_list,
1254            extra,
1255            ..InstData::new(pending.opcode)
1256        };
1257        Ok(func.create_inst(data, &results, Span::DUMMY))
1258    }
1259
1260    /// The line a value number is defined on, for a message about the numbering.
1261    fn line_of(&self, blocks: &[PendingBlock<'a>], number: u32) -> u32 {
1262        for pending in blocks {
1263            for inst in &pending.insts {
1264                if inst.results.contains(&number) {
1265                    return inst.line;
1266                }
1267            }
1268        }
1269        self.line
1270    }
1271
1272    // Tokens.
1273
1274    /// A constant, read as the type it is a constant of.
1275    fn imm(&mut self, text: &str, ty: Type) -> Result<Imm, ParseError> {
1276        let scalar = if ty.is_vector() { ty.lane() } else { ty };
1277        if scalar.is_int() {
1278            match parse_i128(text) {
1279                Some(value) => Ok(Imm::int(value, scalar)),
1280                None => self.fail(format!("`{text}` is not an {scalar}")),
1281            }
1282        } else {
1283            match text.strip_prefix("0x").and_then(|rest| u128::from_str_radix(rest, 16).ok()) {
1284                Some(bits) => Ok(Imm::from_bits(bits)),
1285                None => self.fail(format!("`{text}` is not the bits of a {scalar}")),
1286            }
1287        }
1288    }
1289
1290    /// The text of a constant, which is a sign, digits, and the letters a hexadecimal one has.
1291    fn imm_text(&mut self) -> Result<&'a str, ParseError> {
1292        self.spaces();
1293        let start = self.pos;
1294        if self.at("-") {
1295            self.pos += 1;
1296        }
1297        while self.peek().is_some_and(|byte| byte.is_ascii_alphanumeric()) {
1298            self.pos += 1;
1299        }
1300        if self.pos == start {
1301            return self.fail("a constant was expected");
1302        }
1303        Ok(&self.text[start..self.pos])
1304    }
1305
1306    fn ty(&mut self) -> Result<Type, ParseError> {
1307        let word = self.word();
1308        match Type::parse(word) {
1309            Some(ty) => Ok(ty),
1310            None => self.fail(format!("`{word}` is not a type")),
1311        }
1312    }
1313
1314    /// A `%n`, giving back the number.
1315    fn value_ref(&mut self) -> Result<u32, ParseError> {
1316        self.expect("%")?;
1317        self.u32()
1318    }
1319
1320    /// A run of `%n` separated by commas, stopping at the first comma not followed by one.
1321    fn value_list(&mut self) -> Result<Vec<u32>, ParseError> {
1322        let mut values = Vec::new();
1323        if !self.peek_is("%") {
1324            return Ok(values);
1325        }
1326        loop {
1327            values.push(self.value_ref()?);
1328            let save = self.pos;
1329            if !self.eat(",") {
1330                return Ok(values);
1331            }
1332            if !self.peek_is("%") {
1333                self.pos = save;
1334                return Ok(values);
1335            }
1336        }
1337    }
1338
1339    /// The same, where each may say how the ABI asks it to travel, which is what a call writes
1340    /// on an argument its signature does not name.
1341    fn call_args(&mut self) -> Result<(Vec<u32>, Vec<Abi>), ParseError> {
1342        let mut values = Vec::new();
1343        let mut abis = Vec::new();
1344        if !self.peek_is("%") {
1345            return Ok((values, abis));
1346        }
1347        loop {
1348            values.push(self.value_ref()?);
1349            abis.push(self.abi()?);
1350            let save = self.pos;
1351            if !self.eat(",") {
1352                return Ok((values, abis));
1353            }
1354            if !self.peek_is("%") {
1355                self.pos = save;
1356                return Ok((values, abis));
1357            }
1358        }
1359    }
1360
1361    /// A `blockN`, giving back the number.
1362    fn block_ref(&mut self) -> Result<u32, ParseError> {
1363        let word = self.word();
1364        match word.strip_prefix("block").and_then(parse_u32) {
1365            Some(number) => Ok(number),
1366            None => self.fail(format!("`{word}` is not a block")),
1367        }
1368    }
1369
1370    /// A `!n`, remembering it so that one nothing defines is reported.
1371    fn meta_ref(&mut self) -> Result<Meta, ParseError> {
1372        self.expect("!")?;
1373        let index = self.u32()?;
1374        let seen = self.meta_used.is_none_or(|(used, _)| index > used);
1375        if seen {
1376            self.meta_used = Some((index, self.line));
1377        }
1378        Ok(Idx::from_usize(index as usize))
1379    }
1380
1381    /// An `@name`, interned.
1382    fn symbol(&mut self) -> Result<Symbol, ParseError> {
1383        self.expect("@")?;
1384        let start = self.pos;
1385        while self.peek().is_some_and(is_name_byte) {
1386            self.pos += 1;
1387        }
1388        if self.pos == start {
1389            return self.fail("a name was expected");
1390        }
1391        let name = &self.text[start..self.pos];
1392        Ok(self.names.intern(name))
1393    }
1394
1395    /// A quoted string, interned, which is what a section and a template are.
1396    fn symbol_from_string(&mut self) -> Result<Symbol, ParseError> {
1397        let text = self.quoted_str()?;
1398        Ok(self.names.intern(&text))
1399    }
1400
1401    /// A quoted string that has to be text rather than arbitrary bytes.
1402    fn quoted_str(&mut self) -> Result<String, ParseError> {
1403        let bytes = self.string()?;
1404        match String::from_utf8(bytes) {
1405            Ok(text) => Ok(text),
1406            Err(_) => self.fail("that string is not text"),
1407        }
1408    }
1409
1410    /// A quoted string, which may hold any bytes at all.
1411    fn string(&mut self) -> Result<Vec<u8>, ParseError> {
1412        self.expect("\"")?;
1413        let mut bytes = Vec::new();
1414        loop {
1415            let Some(byte) = self.peek() else {
1416                return self.fail("that string is not closed");
1417            };
1418            self.pos += 1;
1419            match byte {
1420                b'"' => return Ok(bytes),
1421                b'\n' => return self.fail("that string is not closed"),
1422                b'\\' => {
1423                    let escape = match self.peek() {
1424                        Some(b'"') => b'"',
1425                        Some(b'\\') => b'\\',
1426                        _ => {
1427                            let hex = self.text.get(self.pos..self.pos + 2);
1428                            match hex.and_then(|hex| u8::from_str_radix(hex, 16).ok()) {
1429                                Some(byte) => {
1430                                    self.pos += 2;
1431                                    bytes.push(byte);
1432                                    continue;
1433                                }
1434                                None => return self.fail("that is not an escape"),
1435                            }
1436                        }
1437                    };
1438                    self.pos += 1;
1439                    bytes.push(escape);
1440                }
1441                _ => bytes.push(byte),
1442            }
1443        }
1444    }
1445
1446    fn u32(&mut self) -> Result<u32, ParseError> {
1447        let word = self.word();
1448        match parse_u32(word) {
1449            Some(number) => Ok(number),
1450            None => self.fail(format!("`{word}` is not a number")),
1451        }
1452    }
1453
1454    fn u16(&mut self) -> Result<u16, ParseError> {
1455        let word = self.word();
1456        match parse_u32(word).and_then(|number| u16::try_from(number).ok()) {
1457            Some(number) => Ok(number),
1458            None => self.fail(format!("`{word}` is not a small number")),
1459        }
1460    }
1461
1462    fn u64(&mut self) -> Result<u64, ParseError> {
1463        let word = self.word();
1464        match parse_u64(word) {
1465            Some(number) => Ok(number),
1466            None => self.fail(format!("`{word}` is not a number")),
1467        }
1468    }
1469
1470    fn i64(&mut self) -> Result<i64, ParseError> {
1471        let word = self.word();
1472        match parse_u64(word).and_then(|number| i64::try_from(number).ok()) {
1473            Some(number) => Ok(number),
1474            None => self.fail(format!("`{word}` is not an offset")),
1475        }
1476    }
1477
1478    /// One of the keyword parenthesised after a name, as in `linkage(internal)`.
1479    fn parenthesised<T>(
1480        &mut self,
1481        from_name: impl Fn(&str) -> Option<T>,
1482        what: &str,
1483    ) -> Result<T, ParseError> {
1484        self.expect("(")?;
1485        let word = self.word();
1486        let Some(value) = from_name(word) else {
1487            return self.fail(format!("`{word}` is not {what}"));
1488        };
1489        self.expect(")")?;
1490        Ok(value)
1491    }
1492
1493    // The cursor.
1494
1495    fn fail<T>(&self, message: impl Into<String>) -> Result<T, ParseError> {
1496        Err(ParseError { line: self.line, message: message.into() })
1497    }
1498
1499    fn peek(&self) -> Option<u8> {
1500        self.text.as_bytes().get(self.pos).copied()
1501    }
1502
1503    fn at(&self, text: &str) -> bool {
1504        self.text[self.pos..].starts_with(text)
1505    }
1506
1507    fn at_end(&self) -> bool {
1508        self.pos >= self.text.len()
1509    }
1510
1511    /// Whether that text comes next, ignoring the spaces in front of it.
1512    fn peek_is(&self, text: &str) -> bool {
1513        self.text[self.pos..].trim_start_matches([' ', '\t']).starts_with(text)
1514    }
1515
1516    fn spaces(&mut self) {
1517        while matches!(self.peek(), Some(b' ' | b'\t')) {
1518            self.pos += 1;
1519        }
1520    }
1521
1522    fn eat(&mut self, text: &str) -> bool {
1523        self.spaces();
1524        if self.at(text) {
1525            self.pos += text.len();
1526            return true;
1527        }
1528        false
1529    }
1530
1531    fn expect(&mut self, text: &str) -> Result<(), ParseError> {
1532        if self.eat(text) {
1533            return Ok(());
1534        }
1535        self.fail(format!("`{text}` was expected"))
1536    }
1537
1538    /// A word of letters, digits and underscores, after the spaces in front of it.
1539    fn word(&mut self) -> &'a str {
1540        self.spaces();
1541        self.glued_word()
1542    }
1543
1544    /// The same, with nothing skipped, which is what a suffix after a dot is.
1545    fn glued_word(&mut self) -> &'a str {
1546        let start = self.pos;
1547        while self.peek().is_some_and(|byte| byte.is_ascii_alphanumeric() || byte == b'_') {
1548            self.pos += 1;
1549        }
1550        &self.text[start..self.pos]
1551    }
1552
1553    /// The next word without consuming it, for deciding what a line is.
1554    fn peek_word(&self) -> &'a str {
1555        let rest = self.text[self.pos..].trim_start_matches([' ', '\t']);
1556        let end =
1557            rest.find(|c: char| !(c.is_ascii_alphanumeric() || c == '_')).unwrap_or(rest.len());
1558        &rest[..end]
1559    }
1560
1561    /// Whether that word comes next, consuming it if so.
1562    fn eat_word(&mut self, word: &str) -> bool {
1563        if self.peek_word() == word {
1564            self.word();
1565            return true;
1566        }
1567        false
1568    }
1569
1570    fn end_of_line(&mut self) -> Result<(), ParseError> {
1571        self.spaces();
1572        if self.at_end() {
1573            return Ok(());
1574        }
1575        if self.at("\n") {
1576            self.pos += 1;
1577            self.line += 1;
1578            return Ok(());
1579        }
1580        let rest = &self.text[self.pos..];
1581        let end = rest.find('\n').unwrap_or(rest.len());
1582        self.fail(format!("`{}` is left over at the end of the line", &rest[..end]))
1583    }
1584
1585    fn skip_blank_lines(&mut self) {
1586        loop {
1587            let save = self.pos;
1588            self.spaces();
1589            if self.at("\n") {
1590                self.pos += 1;
1591                self.line += 1;
1592            } else {
1593                self.pos = save;
1594                return;
1595            }
1596        }
1597    }
1598}
1599
1600/// Every branch target an instruction has, whichever payload holds them.
1601fn inst_calls<'p>(inst: &'p PendingInst<'_>) -> &'p [PendingCall] {
1602    match &inst.extra {
1603        PendingExtra::Targets(targets)
1604        | PendingExtra::Switch { targets, .. }
1605        | PendingExtra::Asm { targets, .. } => targets,
1606        _ => &[],
1607    }
1608}
1609
1610/// The branch targets of an instruction, with their arguments put in the function's pool.
1611fn build_calls(func: &mut Func, targets: &[PendingCall]) -> Vec<BlockCall> {
1612    targets
1613        .iter()
1614        .map(|call| {
1615            let args: Vec<Value> =
1616                call.args.iter().map(|&number| Value::from_usize(number as usize)).collect();
1617            BlockCall {
1618                block: Block::from_usize(call.block as usize),
1619                args: func.push_values(&args),
1620            }
1621        })
1622        .collect()
1623}
1624
1625/// What an instruction produces, or `None` while an operand's type is still unknown.
1626///
1627/// This is the reading half of the rule the printer writes by, which is why the two of them
1628/// name the same opcodes: a type is in the text only where the operands do not say it.
1629fn result_types(inst: &PendingInst<'_>, types: &[Option<Type>]) -> Option<Vec<Type>> {
1630    let mem = gives_mem(inst);
1631    let mut written = ordinary_result_types(inst, types, mem)?;
1632    if mem {
1633        written.push(Type::MEM);
1634    }
1635    Some(written)
1636}
1637
1638/// Whether the instruction makes a new version of memory, which is its last result.
1639///
1640/// A `mem_entry` is where a chain starts and produces nothing else. Everything else produces one
1641/// where it is on the chain and it writes, which is the rule the verifier checks and the reason
1642/// the text does not say it a second time.
1643fn gives_mem(inst: &PendingInst<'_>) -> bool {
1644    inst.opcode == Opcode::MemEntry || (inst.mem.is_some() && inst.opcode.writes_memory())
1645}
1646
1647/// What an instruction produces apart from memory.
1648fn ordinary_result_types(
1649    inst: &PendingInst<'_>,
1650    types: &[Option<Type>],
1651    mem: bool,
1652) -> Option<Vec<Type>> {
1653    if inst.results.len().saturating_sub(usize::from(mem)) == 0 {
1654        return Some(Vec::new());
1655    }
1656    if !inst.written.is_empty() {
1657        return Some(inst.written.clone());
1658    }
1659    match inst.opcode {
1660        Opcode::GlobalAddr | Opcode::BlockAddr | Opcode::Alloca => Some(vec![Type::PTR]),
1661        Opcode::CapOf
1662        | Opcode::CapLoad
1663        | Opcode::CapNull
1664        | Opcode::CapNarrow
1665        | Opcode::CapRecover => Some(vec![Type::CAP]),
1666        Opcode::ICmp | Opcode::FCmp => {
1667            let ty = arg_type(inst, types)?;
1668            Some(vec![ty.with_lane(Type::I1)])
1669        }
1670        Opcode::Call | Opcode::CallIndirect | Opcode::TailCall => match &inst.extra {
1671            PendingExtra::Call { signature, .. } => Some(signature.return_types().collect()),
1672            _ => None,
1673        },
1674        _ => Some(vec![arg_type(inst, types)?]),
1675    }
1676}
1677
1678/// The type of an instruction's first operand, if it is known yet.
1679fn arg_type(inst: &PendingInst<'_>, types: &[Option<Type>]) -> Option<Type> {
1680    let &first = inst.args.first()?;
1681    *types.get(first as usize)?
1682}
1683
1684/// A decimal number with no sign and no leading zero, which is the only form the printer writes.
1685fn parse_u64(text: &str) -> Option<u64> {
1686    if text.is_empty() || (text.starts_with('0') && text.len() > 1) {
1687        return None;
1688    }
1689    if !text.bytes().all(|byte| byte.is_ascii_digit()) {
1690        return None;
1691    }
1692    text.parse().ok()
1693}
1694
1695fn parse_u32(text: &str) -> Option<u32> {
1696    parse_u64(text).and_then(|number| u32::try_from(number).ok())
1697}
1698
1699/// A decimal integer, with a minus sign for a negative one, as the printer writes them.
1700fn parse_i128(text: &str) -> Option<i128> {
1701    let (negative, digits) = match text.strip_prefix('-') {
1702        Some(rest) => (true, rest),
1703        None => (false, text),
1704    };
1705    if digits.is_empty() || (digits.starts_with('0') && digits.len() > 1) {
1706        return None;
1707    }
1708    if negative && digits == "0" {
1709        return None;
1710    }
1711    if !digits.bytes().all(|byte| byte.is_ascii_digit()) {
1712        return None;
1713    }
1714    let magnitude: u128 = digits.parse().ok()?;
1715    if negative {
1716        // The most negative number has no positive counterpart, so it is built by negating the
1717        // wrapped value rather than by converting first.
1718        (magnitude <= 1 << 127).then(|| (magnitude as i128).wrapping_neg())
1719    } else {
1720        i128::try_from(magnitude).ok()
1721    }
1722}
1723
1724/// Whether a byte can appear in a symbol name.
1725///
1726/// Dots are in, because a compiler names things `hi.str` and `memcpy.resolve` and the assembler
1727/// takes them. So is every byte above ASCII: C23 allows an identifier to be written in any script
1728/// and gcc allowed it long before that, so a name the front end read has to come back out of the
1729/// printer and go back in. Nothing is decoded here, because a name is a run of bytes either way
1730/// and the file it was read from was checked for being UTF-8 when it was read.
1731fn is_name_byte(byte: u8) -> bool {
1732    byte.is_ascii_alphanumeric() || matches!(byte, b'_' | b'.' | b'$') || byte >= 0x80
1733}
1734
1735#[cfg(test)]
1736mod tests {
1737    use rucc_base::Interner;
1738
1739    use super::*;
1740    use crate::fixtures::{EXAMPLE, SAFETY, SYMBOLS, ZOO};
1741    use crate::print;
1742
1743    /// Reads a module and writes it back out, which is the whole claim this file makes.
1744    fn round_trip(text: &str) -> String {
1745        let mut names = Interner::new();
1746        let module = match parse(text, &mut names) {
1747            Ok(module) => module,
1748            Err(error) => panic!("{error}"),
1749        };
1750        print(&module, &names)
1751    }
1752
1753    fn error(text: &str) -> String {
1754        let mut names = Interner::new();
1755        match parse(text, &mut names) {
1756            Ok(_) => panic!("that was expected to be turned down"),
1757            Err(error) => error.to_string(),
1758        }
1759    }
1760
1761    const HEADER: &str = "\
1762; ModuleID = 'example.c'
1763; format 0
1764target triple = \"x86_64-unknown-linux-gnu\"
1765target datalayout = \"e-p:64:64-i64:64-f80:128-S128\"
1766";
1767
1768    #[test]
1769    fn the_example_in_the_spec_comes_back_byte_for_byte() {
1770        assert_eq!(round_trip(EXAMPLE), EXAMPLE);
1771    }
1772
1773    #[test]
1774    fn one_of_almost_everything_comes_back_byte_for_byte() {
1775        assert_eq!(round_trip(ZOO), ZOO);
1776    }
1777
1778    #[test]
1779    fn a_memory_chain_comes_back_byte_for_byte() {
1780        let text = format!(
1781            "{HEADER}
1782func @f(ptr, i1) -> i32, linkage(external) {{
1783block0(%0: ptr, %1: i1):
1784    %2 = mem_entry
1785    %3 = iconst.i32 7
1786    %4 = store %3 -> %0, align 4 [mem %2]
1787    br_if %1, block1(%4), block2(%4)
1788
1789block1(%5: mem):
1790    %6 = load.i32 %0, align 4 [mem %5]
1791    %7 = memcpy %0, %0, size 4, align 4 [mem %5]
1792    return %6
1793
1794block2(%8: mem):
1795    %9 = atomic_load.i32 %0, align 4, acquire [mem %8]
1796    return %9
1797}}
1798"
1799        );
1800        assert_eq!(round_trip(&text), text);
1801    }
1802
1803    #[test]
1804    fn a_restrict_clique_and_base_come_back_byte_for_byte() {
1805        let text = format!(
1806            "{HEADER}
1807func @f(ptr, ptr), linkage(external) {{
1808block0(%0: ptr, %1: ptr):
1809    %2 = load.i32 %0, align 4, restrict(1, 1)
1810    store %2 -> %1, align 4, restrict(1, 2)
1811    return
1812}}
1813"
1814        );
1815        assert_eq!(round_trip(&text), text);
1816    }
1817
1818    #[test]
1819    fn the_padding_a_member_owns_comes_back_byte_for_byte() {
1820        // The number `-fsafety-init=nopadding` puts on a store through a member of a record, which
1821        // is the member's width plus whatever padding follows it. A store that owns no more than
1822        // it writes says nothing, so every access in every other test here stays as it was.
1823        let text = format!(
1824            "{HEADER}
1825func @f(ptr), linkage(external) {{
1826block0(%0: ptr):
1827    %1 = iconst.i8 1
1828    store %1 -> %0, align 1, owns 4
1829    return
1830}}
1831"
1832        );
1833        assert_eq!(round_trip(&text), text);
1834    }
1835
1836    #[test]
1837    fn a_restrict_base_in_no_clique_is_reported() {
1838        let text = format!(
1839            "{HEADER}
1840func @f(ptr), linkage(external) {{
1841block0(%0: ptr):
1842    %1 = load.i32 %0, align 4, restrict(0, 2)
1843    return
1844}}
1845"
1846        );
1847        // The parser reads it, because the shape is fine. The verifier is what turns it down,
1848        // and its test says so.
1849        assert!(round_trip(&text).contains("load.i32 %0, align 4\n"));
1850    }
1851
1852    #[test]
1853    fn the_shapes_a_symbol_comes_in_come_back_byte_for_byte() {
1854        assert_eq!(round_trip(SYMBOLS), SYMBOLS);
1855    }
1856
1857    #[test]
1858    fn every_safety_instruction_comes_back_byte_for_byte() {
1859        assert_eq!(round_trip(SAFETY), SAFETY);
1860    }
1861
1862    #[test]
1863    fn a_storage_class_nobody_has_heard_of_is_turned_down() {
1864        let text = format!(
1865            "{HEADER}\nfunc @f(ptr, i64), linkage(external) {{\n\
1866             block0(%0: ptr, %1: i64):\n    meta_begin %0, %1, class heap\n    return\n}}\n"
1867        );
1868        assert_eq!(error(&text), "line 8: `heap` is not a storage class");
1869    }
1870
1871    #[test]
1872    fn a_range_transferred_somewhere_there_is_no_name_for_is_turned_down() {
1873        let text = format!(
1874            "{HEADER}\nfunc @f(ptr, i64), linkage(external) {{\n\
1875             block0(%0: ptr, %1: i64):\n    meta_transfer %0, %1, to hardware\n    return\n}}\n"
1876        );
1877        assert_eq!(error(&text), "line 8: `hardware` is not somewhere a range can go");
1878    }
1879
1880    #[test]
1881    fn a_fact_nobody_has_heard_of_is_turned_down() {
1882        // The four are closed, the way the flags are. Something the reader lets through is
1883        // something a later pass silently does not act on, which is a fact that costs nothing
1884        // and buys nothing.
1885        let text = format!(
1886            "{HEADER}\nfunc @f(ptr), linkage(external) {{\n\
1887             block0(%0: ptr):\n    return\n\nfacts:\n    %0 = !sorted\n}}\n"
1888        );
1889        assert_eq!(error(&text), "line 11: `sorted` is not a fact");
1890    }
1891
1892    #[test]
1893    fn a_value_said_twice_is_turned_down() {
1894        // One line per value, so that what is known about a value is one thing to read rather
1895        // than something to be assembled out of however many lines happened to mention it.
1896        let text = format!(
1897            "{HEADER}\nfunc @f(ptr), linkage(external) {{\n\
1898             block0(%0: ptr):\n    return\n\nfacts:\n    %0 = !live\n    %0 = !aligned(4)\n}}\n"
1899        );
1900        assert_eq!(error(&text), "line 12: %0 is said twice");
1901    }
1902
1903    #[test]
1904    fn a_fact_about_a_value_that_does_not_exist_is_turned_down() {
1905        let text = format!(
1906            "{HEADER}\nfunc @f(ptr), linkage(external) {{\n\
1907             block0(%0: ptr):\n    return\n\nfacts:\n    %3 = !live\n}}\n"
1908        );
1909        assert_eq!(error(&text), "line 11: %3 is used and never defined");
1910    }
1911
1912    #[test]
1913    fn a_plane_entry_nobody_has_heard_of_is_turned_down() {
1914        let text = format!("{HEADER}\n!0 = plane unwritten\n");
1915        assert_eq!(error(&text), "line 6: `unwritten` is not a plane entry");
1916    }
1917
1918    #[test]
1919    fn a_metadata_node_of_no_known_kind_is_turned_down() {
1920        let text = format!("{HEADER}\n!0 = scope \"outer\"\n");
1921        assert_eq!(error(&text), "line 6: `scope` is not a kind of metadata node");
1922    }
1923
1924    #[test]
1925    fn a_plane_entry_naming_a_node_that_comes_later_is_turned_down() {
1926        // The table is read once from the top, so a node that looked forward would be a node
1927        // the reader could not resolve when it reached it.
1928        let text = format!("{HEADER}\n!0 = plane !1\n!1 = tbaa \"int\", offset 0\n");
1929        assert_eq!(error(&text), "line 6: a metadata node names one that comes before it");
1930    }
1931
1932    #[test]
1933    fn a_name_that_is_not_ascii_comes_back_byte_for_byte() {
1934        // C23 says an identifier may be written in any script and gcc has taken them for far
1935        // longer, so a program that uses one has to survive the printer and the reader. The
1936        // reader used to stop at the first byte above ASCII and say a name was expected.
1937        let text = format!("{HEADER}\nglobal @été : i32 = 1, align 4, linkage(external)\n");
1938        assert_eq!(round_trip(&text), text);
1939    }
1940
1941    #[test]
1942    fn a_value_defined_after_it_is_used() {
1943        // Block layout order is not required to put a definition before its uses, so the type
1944        // of %2 is only known after the whole function has been read. This is the case the two
1945        // passes exist for.
1946        let text = format!(
1947            "{HEADER}
1948func @late() -> i64, linkage(external) {{
1949block0:
1950    jump block2
1951
1952block1(%0: i64):
1953    %1 = add %2, %0
1954    return %1
1955
1956block2:
1957    %2 = iconst.i64 7
1958    jump block1(%2)
1959}}
1960"
1961        );
1962        assert_eq!(round_trip(&text), text);
1963    }
1964
1965    #[test]
1966    fn what_the_abi_asks_of_a_parameter_comes_back_byte_for_byte() {
1967        // A `struct` return, a `struct` argument, and a `char` the callee may read a whole
1968        // register of. None of it is written on a type, because none of it is a fact about one.
1969        let text = format!(
1970            "{HEADER}
1971func @f(ptr sret(24, align 8), ptr byval(16, align 8), i8 zext), linkage(external) {{
1972block0(%0: ptr, %1: ptr, %2: i8):
1973    return
1974}}
1975
1976func @g(i8 sext) -> i8 sext, linkage(external);
1977"
1978        );
1979        assert_eq!(round_trip(&text), text);
1980    }
1981
1982    #[test]
1983    fn a_word_that_is_not_an_attribute_is_not_read_as_one() {
1984        let text = format!(
1985            "{HEADER}
1986func @f(ptr inreg), linkage(external);
1987"
1988        );
1989        assert_eq!(error(&text), "line 6: `)` was expected");
1990    }
1991
1992    #[test]
1993    fn an_empty_module_is_its_header() {
1994        assert_eq!(round_trip(HEADER), HEADER);
1995    }
1996
1997    #[test]
1998    fn the_format_version_is_checked_before_anything_else() {
1999        let text = "; ModuleID = 'a.c'\n; format 99\n";
2000        assert_eq!(error(text), "line 2: this build reads format 0 and the text says format 99");
2001    }
2002
2003    #[test]
2004    fn an_opcode_nobody_has_is_reported_with_its_line() {
2005        let text = format!(
2006            "{HEADER}
2007func @f(), linkage(external) {{
2008block0:
2009    getelementptr %0
2010}}
2011"
2012        );
2013        assert_eq!(error(&text), "line 8: `getelementptr` is not an opcode");
2014    }
2015
2016    /// The slots of an object read off a list are the one thing in the text with a shape of their
2017    /// own, so a word in the wrong place there says so rather than being read as something else.
2018    #[test]
2019    fn a_slot_written_as_something_that_is_not_one_is_reported() {
2020        let text = format!(
2021            "{HEADER}
2022func @f(ptr) -> ptr, linkage(external) {{
2023block0(%0: ptr):
2024    %1 = va_object %0, size 16, align 8, in(short 8 at 0)
2025    return %1
2026}}
2027"
2028        );
2029        assert_eq!(error(&text), "line 8: `short` is not how a slot is written");
2030    }
2031
2032    #[test]
2033    fn an_abi_on_an_argument_the_signature_names_is_turned_down() {
2034        // It would be two answers to one question, and the signature's is the one the callee
2035        // reads, so the text is wrong rather than one of them winning.
2036        let text = format!(
2037            "{HEADER}
2038func @f(ptr), linkage(external) {{
2039block0(%0: ptr):
2040    call @p(%0 byval(8, align 8)) : (ptr, ...)
2041    return
2042}}
2043"
2044        );
2045        assert_eq!(
2046            error(&text),
2047            "line 8: the signature is what says how an argument it names travels"
2048        );
2049    }
2050
2051    #[test]
2052    fn a_value_nothing_defines_is_reported() {
2053        let text = format!(
2054            "{HEADER}
2055func @f(i32) -> i32, linkage(external) {{
2056block0(%0: i32):
2057    %1 = add %0, %9
2058    return %1
2059}}
2060"
2061        );
2062        assert_eq!(error(&text), "line 8: %9 is used and never defined");
2063    }
2064
2065    #[test]
2066    fn a_block_nothing_defines_is_reported() {
2067        let text = format!(
2068            "{HEADER}
2069func @f(), linkage(external) {{
2070block0:
2071    jump block7
2072}}
2073"
2074        );
2075        assert_eq!(error(&text), "line 8: block7 is used and never defined");
2076    }
2077
2078    #[test]
2079    fn values_have_to_be_numbered_in_print_order() {
2080        let text = format!(
2081            "{HEADER}
2082func @f() -> i32, linkage(external) {{
2083block0:
2084    %1 = iconst.i32 0
2085    %0 = iconst.i32 1
2086    return %1
2087}}
2088"
2089        );
2090        assert_eq!(error(&text), "line 8: values are numbered in order and %0 comes next");
2091    }
2092
2093    #[test]
2094    fn blocks_have_to_be_numbered_in_print_order() {
2095        let text = format!(
2096            "{HEADER}
2097func @f(), linkage(external) {{
2098block1:
2099    return
2100}}
2101"
2102        );
2103        assert_eq!(error(&text), "line 7: blocks are numbered in order and block0 comes next");
2104    }
2105
2106    #[test]
2107    fn metadata_nobody_defines_is_reported() {
2108        let text = format!(
2109            "{HEADER}
2110func @f(ptr), linkage(external) {{
2111block0(%0: ptr):
2112    %1 = load.i32 %0, align 4, tbaa !3
2113    return
2114}}
2115"
2116        );
2117        assert_eq!(error(&text), "line 8: !3 is used and never defined");
2118    }
2119
2120    #[test]
2121    fn a_type_nothing_says_is_reported_rather_than_guessed() {
2122        let text = format!(
2123            "{HEADER}
2124func @f(), linkage(external) {{
2125block0:
2126    %0 = add
2127    return
2128}}
2129"
2130        );
2131        assert_eq!(error(&text), "line 8: nothing in the text says what add produces");
2132    }
2133
2134    #[test]
2135    fn a_line_with_something_left_on_it_is_turned_down() {
2136        let text = format!(
2137            "{HEADER}
2138global @x : i32 = 0, align 4, linkage(internal) and then some
2139"
2140        );
2141        assert_eq!(error(&text), "line 6: `and then some` is left over at the end of the line");
2142    }
2143
2144    #[test]
2145    fn a_constant_that_is_not_one_is_turned_down() {
2146        let text = format!(
2147            "{HEADER}
2148global @x : i32 = 007, align 4, linkage(internal)
2149"
2150        );
2151        assert_eq!(error(&text), "line 6: `007` is not an i32");
2152    }
2153
2154    #[test]
2155    fn an_image_that_holds_a_capability_is_turned_down() {
2156        // A capability has no bits the reader could take, per section 5.2 of
2157        // `spec/safe-memory/05-representation.md`, so there is nothing to write between the equals
2158        // sign and the comma. This is the one place a `cap` is refused before the verifier ever
2159        // sees the module.
2160        let text = format!(
2161            "{HEADER}
2162global @x : cap = 0, align 8, linkage(internal)
2163"
2164        );
2165        assert_eq!(error(&text), "line 6: `0` is not the bits of a cap");
2166    }
2167
2168    #[test]
2169    fn a_number_is_read_the_way_the_printer_writes_it() {
2170        assert_eq!(parse_i128("-1"), Some(-1));
2171        assert_eq!(parse_i128("0"), Some(0));
2172        assert_eq!(parse_i128("-0"), None);
2173        assert_eq!(parse_i128("+1"), None);
2174        assert_eq!(parse_i128("01"), None);
2175        assert_eq!(parse_i128(""), None);
2176        assert_eq!(parse_i128("170141183460469231731687303715884105728"), None);
2177        assert_eq!(parse_i128("-170141183460469231731687303715884105728"), Some(i128::MIN));
2178    }
2179
2180    #[test]
2181    fn every_opcode_says_which_payload_it_carries() {
2182        // A payload the parser does not expect for that opcode is text it cannot read back, so
2183        // the two of them agreeing is what this file rests on.
2184        for opcode in Opcode::all() {
2185            let kind = opcode.extra_kind();
2186            let expected = match opcode {
2187                Opcode::IConst | Opcode::FConst | Opcode::Splat => ExtraKind::Imm,
2188                Opcode::GlobalAddr | Opcode::TargetIntrinsic => ExtraKind::Symbol,
2189                Opcode::ICmp => ExtraKind::IntPred,
2190                Opcode::FCmp => ExtraKind::FloatPred,
2191                Opcode::Fence => ExtraKind::Order,
2192                Opcode::AtomicRmw => ExtraKind::Rmw,
2193                Opcode::Switch => ExtraKind::Switch,
2194                Opcode::InlineAsm => ExtraKind::Asm,
2195                Opcode::Jump | Opcode::BrIf | Opcode::BlockAddr | Opcode::IndirectBr => {
2196                    ExtraKind::Targets
2197                }
2198                Opcode::Call | Opcode::CallIndirect | Opcode::TailCall => ExtraKind::Call,
2199                Opcode::Alloca
2200                | Opcode::Load
2201                | Opcode::Store
2202                | Opcode::Memcpy
2203                | Opcode::Memmove
2204                | Opcode::Memset
2205                | Opcode::AtomicLoad
2206                | Opcode::AtomicStore
2207                | Opcode::Cmpxchg
2208                | Opcode::CheckBounds
2209                | Opcode::CheckType
2210                | Opcode::CheckInit
2211                | Opcode::CheckRestrictRead
2212                | Opcode::CheckRestrictWrite
2213                | Opcode::RestrictEnter => ExtraKind::Mem,
2214                Opcode::VaObject => ExtraKind::VaObject,
2215                Opcode::MetaBegin => ExtraKind::Class,
2216                Opcode::MetaTransfer => ExtraKind::Owner,
2217                Opcode::MetaType => ExtraKind::Node,
2218                Opcode::SafeRegionBegin => ExtraKind::Reason,
2219                _ => ExtraKind::None,
2220            };
2221            assert_eq!(kind, expected, "{}", opcode.name());
2222        }
2223    }
2224}