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::{Idx, Interner, Symbol};
36use rucc_diag::Span;
37use rucc_target::{TargetInfo, Triple};
38
39use crate::attrs::{AttrSet, Attrs, FpContract};
40use crate::func::Func;
41use crate::inst::{
42    Abi, AsmInfo, Block, BlockCall, CallInfo, Imm, Inst, InstData, MemInfo, Meta, MetaNode, Param,
43    Signature, SwitchInfo, Value,
44};
45use crate::module::{
46    Alias, AliasKind, DataLayout, Datum, Global, Linkage, Module, Reloc, TlsModel, Visibility,
47};
48use crate::{
49    Extra, ExtraKind, FORMAT_VERSION, Flags, FloatPred, IntPred, MemOrder, Opcode, RmwOp, Type,
50};
51
52/// Why a module could not be read.
53///
54/// One error and then nothing, rather than a list. A malformed IR dump is a bug in whatever
55/// wrote it or a file somebody edited by hand, and in both cases the first thing that does not
56/// add up is the thing worth reporting.
57#[derive(Clone, Debug, PartialEq, Eq)]
58pub struct ParseError {
59    /// Which line of the text, counting from one.
60    pub line: u32,
61    /// What was wrong with it.
62    pub message: String,
63}
64
65impl fmt::Display for ParseError {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        write!(f, "line {}: {}", self.line, self.message)
68    }
69}
70
71impl std::error::Error for ParseError {}
72
73/// Reads a module from the text the printer writes.
74///
75/// Names are interned into `names`, which is the same interner the printer will be given when
76/// the module is written back out.
77///
78/// # Errors
79///
80/// Gives back the first thing in the text that does not add up, with the line it is on.
81pub fn parse(text: &str, names: &mut Interner) -> Result<Module, ParseError> {
82    Parser::new(text, names).module()
83}
84
85/// Reading one text.
86struct Parser<'a, 'n> {
87    text: &'a str,
88    pos: usize,
89    line: u32,
90    names: &'n mut Interner,
91    /// The highest metadata node any instruction referred to, so that a reference to one that
92    /// is never defined is caught rather than left as an index into nothing.
93    meta_used: Option<(u32, u32)>,
94}
95
96/// A block, read but not yet built.
97struct PendingBlock<'a> {
98    params: Vec<(u32, Type)>,
99    insts: Vec<PendingInst<'a>>,
100}
101
102/// An instruction, read but not yet built. Every value is still the number it was written as.
103struct PendingInst<'a> {
104    opcode: Opcode,
105    flags: Flags,
106    results: Vec<u32>,
107    /// The types written after the opcode, which is none when the operands say them.
108    written: Vec<Type>,
109    args: Vec<u32>,
110    extra: PendingExtra<'a>,
111    line: u32,
112}
113
114/// A branch target, read but not yet built.
115struct PendingCall {
116    block: u32,
117    args: Vec<u32>,
118}
119
120/// The payload of an instruction, read but not yet built.
121enum PendingExtra<'a> {
122    None,
123    /// The text of the constant, which cannot be read until the result type is known.
124    Imm(&'a str),
125    Symbol(Symbol),
126    IntPred(IntPred),
127    FloatPred(FloatPred),
128    Mem(MemInfo),
129    Rmw(RmwOp, MemInfo),
130    Order(MemOrder),
131    Targets(Vec<PendingCall>),
132    Call {
133        callee: Option<Symbol>,
134        signature: Signature,
135        /// One entry for each argument, whether or not the signature names it, since the
136        /// signature is written after the arguments and is not known yet.
137        abis: Vec<Abi>,
138    },
139    Switch {
140        targets: Vec<PendingCall>,
141        cases: Vec<&'a str>,
142    },
143    Asm {
144        template: Symbol,
145        constraints: Symbol,
146        clobbers: Symbol,
147        targets: Vec<PendingCall>,
148    },
149}
150
151impl<'a, 'n> Parser<'a, 'n> {
152    fn new(text: &'a str, names: &'n mut Interner) -> Self {
153        Parser { text, pos: 0, line: 1, names, meta_used: None }
154    }
155
156    // The whole module.
157
158    fn module(mut self) -> Result<Module, ParseError> {
159        let name = self.header_name()?;
160        self.expect("; format ")?;
161        let version = self.u32()?;
162        if version != FORMAT_VERSION {
163            return self.fail(format!(
164                "this build reads format {FORMAT_VERSION} and the text says format {version}"
165            ));
166        }
167        self.end_of_line()?;
168
169        self.expect("target triple = ")?;
170        let triple = self.quoted_str()?;
171        let Ok(triple) = triple.parse::<Triple>() else {
172            return self.fail(format!("`{triple}` is not a target triple"));
173        };
174        self.end_of_line()?;
175
176        self.expect("target datalayout = ")?;
177        let layout = self.quoted_str()?;
178        let Some(datalayout) = DataLayout::parse(&layout) else {
179            return self.fail(format!("`{layout}` is not a data layout"));
180        };
181        self.end_of_line()?;
182
183        let name = self.names.intern(&name);
184        let mut module = Module::new(name, &TargetInfo::new(triple));
185        module.datalayout = datalayout;
186
187        loop {
188            self.skip_blank_lines();
189            if self.at_end() {
190                break;
191            }
192            match self.peek_word() {
193                "global" => self.global(&mut module)?,
194                "alias" | "ifunc" => self.alias(&mut module)?,
195                "func" => self.func(&mut module)?,
196                _ if self.at("!") => self.meta(&mut module)?,
197                other => return self.fail(format!("`{other}` does not start anything")),
198            }
199        }
200
201        if let Some((used, line)) = self.meta_used {
202            let count = module.counts().metadata as u32;
203            if used >= count {
204                self.line = line;
205                return self.fail(format!("!{used} is used and never defined"));
206            }
207        }
208        Ok(module)
209    }
210
211    /// The `; ModuleID = 'name'` line, whose name is not quoted the way everything else is.
212    fn header_name(&mut self) -> Result<String, ParseError> {
213        self.expect("; ModuleID = '")?;
214        let start = self.pos;
215        let Some(end) = self.text[start..].find('\'') else {
216            return self.fail("the module name is not closed");
217        };
218        let name = self.text[start..start + end].to_string();
219        self.pos = start + end + 1;
220        self.end_of_line()?;
221        Ok(name)
222    }
223
224    // Globals, aliases and metadata.
225
226    fn global(&mut self, module: &mut Module) -> Result<(), ParseError> {
227        self.expect("global")?;
228        let name = self.symbol()?;
229        self.expect(":")?;
230
231        let mut global = Global::new(name, 0, 1);
232        if self.eat_word("bytes") {
233            global.size = self.u64()?;
234            if self.eat("=") {
235                self.expect("{")?;
236                let mut data = Vec::new();
237                // The brace is looked for before a piece is asked for, because an image with
238                // nothing in it is a thing a zero sized object has and asking for a piece first
239                // met the closing brace and called it a type that does not exist.
240                if !self.eat("}") {
241                    loop {
242                        data.push(self.datum(module)?);
243                        if !self.eat(",") {
244                            break;
245                        }
246                    }
247                    self.expect("}")?;
248                }
249                global.init = Some(module.push_data(&data));
250            }
251        } else {
252            let ty = self.ty()?;
253            self.expect("=")?;
254            let text = self.imm_text()?;
255            let value = self.imm(text, ty)?;
256            let datum = Datum::Scalar { ty, value: module.add_imm(value) };
257            global.size = datum.size(module);
258            global.init = Some(module.push_data(&[datum]));
259        }
260
261        while self.eat(",") {
262            match self.word() {
263                "align" => global.align = self.u32()?,
264                "linkage" => {
265                    global.linkage = self.parenthesised(Linkage::from_name, "a linkage")?
266                }
267                "visibility" => {
268                    global.visibility =
269                        self.parenthesised(Visibility::from_name, "a visibility")?;
270                }
271                "tls" => {
272                    global.tls =
273                        Some(self.parenthesised(TlsModel::from_name, "a thread-local model")?);
274                }
275                "constant" => global.constant = true,
276                "section" => global.section = Some(self.symbol_from_string()?),
277                other => return self.fail(format!("a global has no `{other}`")),
278            }
279        }
280        self.end_of_line()?;
281        module.add_global(global);
282        Ok(())
283    }
284
285    /// One piece of a global's image.
286    fn datum(&mut self, module: &mut Module) -> Result<Datum, ParseError> {
287        match self.peek_word() {
288            "zero" => {
289                self.expect("zero")?;
290                Ok(Datum::Zero(self.u64()?))
291            }
292            "bytes" => {
293                self.expect("bytes")?;
294                let bytes = self.string()?;
295                Ok(Datum::Bytes(module.push_bytes(&bytes)))
296            }
297            "addr" => {
298                self.expect("addr")?;
299                self.expect(".")?;
300                let size = self.u32()?;
301                let symbol = self.symbol()?;
302                let addend = if self.eat("+") {
303                    self.i64()?
304                } else if self.eat("-") {
305                    let amount = self.i64()?;
306                    match amount.checked_neg() {
307                        Some(negated) => negated,
308                        None => return self.fail("that offset has no negative"),
309                    }
310                } else {
311                    0
312                };
313                Ok(Datum::Addr(module.add_reloc(Reloc { symbol, addend, size })))
314            }
315            _ => {
316                let ty = self.ty()?;
317                let text = self.imm_text()?;
318                let value = self.imm(text, ty)?;
319                Ok(Datum::Scalar { ty, value: module.add_imm(value) })
320            }
321        }
322    }
323
324    fn alias(&mut self, module: &mut Module) -> Result<(), ParseError> {
325        let word = self.word();
326        let Some(kind) = AliasKind::from_name(word) else {
327            return self.fail(format!("`{word}` is not a kind of alias"));
328        };
329        let name = self.symbol()?;
330        self.expect("=")?;
331        let target = self.symbol()?;
332        let mut alias = Alias::new(name, target);
333        alias.kind = kind;
334        while self.eat(",") {
335            match self.word() {
336                "linkage" => alias.linkage = self.parenthesised(Linkage::from_name, "a linkage")?,
337                "visibility" => {
338                    alias.visibility = self.parenthesised(Visibility::from_name, "a visibility")?;
339                }
340                other => return self.fail(format!("an alias has no `{other}`")),
341            }
342        }
343        self.end_of_line()?;
344        module.add_alias(alias);
345        Ok(())
346    }
347
348    fn meta(&mut self, module: &mut Module) -> Result<(), ParseError> {
349        let index = self.meta_ref()?;
350        let expected = module.counts().metadata as u32;
351        if index.raw() != expected {
352            return self.fail(format!("metadata is numbered in order and !{expected} comes next"));
353        }
354        self.expect("=")?;
355        self.expect("tbaa")?;
356        let name = self.symbol_from_string()?;
357        let mut node = MetaNode { name, parent: None, offset: 0 };
358        while self.eat(",") {
359            match self.word() {
360                "parent" => node.parent = Some(self.meta_ref()?),
361                "offset" => node.offset = self.u64()?,
362                other => return self.fail(format!("a metadata node has no `{other}`")),
363            }
364        }
365        if node.parent.is_some_and(|parent| parent.raw() >= index.raw()) {
366            return self.fail("a metadata node's parent comes before it");
367        }
368        self.end_of_line()?;
369        module.add_meta(node);
370        Ok(())
371    }
372
373    // Functions.
374
375    fn func(&mut self, module: &mut Module) -> Result<(), ParseError> {
376        self.expect("func")?;
377        let name = self.symbol()?;
378        let signature = self.signature()?;
379        let mut func = Func::new(name, signature);
380        while self.eat(",") {
381            match self.word() {
382                "linkage" => func.linkage = self.parenthesised(Linkage::from_name, "a linkage")?,
383                "visibility" => {
384                    func.visibility = self.parenthesised(Visibility::from_name, "a visibility")?;
385                }
386                "attrs" => func.attrs = self.attrs()?,
387                "section" => func.section = Some(self.symbol_from_string()?),
388                other => return self.fail(format!("a function has no `{other}`")),
389            }
390        }
391        if self.eat(";") {
392            self.end_of_line()?;
393            module.add_func(func);
394            return Ok(());
395        }
396        self.expect("{")?;
397        self.end_of_line()?;
398        let blocks = self.body()?;
399        self.build(&mut func, &blocks)?;
400        module.add_func(func);
401        Ok(())
402    }
403
404    /// The parameter and result types, in parentheses and after an arrow.
405    fn signature(&mut self) -> Result<Signature, ParseError> {
406        self.expect("(")?;
407        let mut signature = Signature::new();
408        if !self.eat(")") {
409            loop {
410                if self.eat("...") {
411                    signature.variadic = true;
412                    break;
413                }
414                signature.params.push(self.param()?);
415                if !self.eat(",") {
416                    break;
417                }
418            }
419            self.expect(")")?;
420        }
421        if self.eat("->") {
422            if self.eat("(") {
423                loop {
424                    signature.returns.push(self.param()?);
425                    if !self.eat(",") {
426                        break;
427                    }
428                }
429                self.expect(")")?;
430            } else {
431                signature.returns.push(self.param()?);
432            }
433        }
434        Ok(signature)
435    }
436
437    /// One parameter: a type, and what the ABI asks of it when the text says anything.
438    fn param(&mut self) -> Result<Param, ParseError> {
439        let ty = self.ty()?;
440        let abi = self.abi()?;
441        Ok(Param { ty, abi })
442    }
443
444    /// What the ABI asks of a value, which is [`Abi::Plain`] when the text says nothing.
445    fn abi(&mut self) -> Result<Abi, ParseError> {
446        let abi = match self.peek_word() {
447            "sext" => {
448                self.word();
449                Abi::Sext
450            }
451            "zext" => {
452                self.word();
453                Abi::Zext
454            }
455            word @ ("byval" | "sret") => {
456                let indirect = word == "byval";
457                self.word();
458                self.expect("(")?;
459                let size = self.u64()?;
460                self.expect(",")?;
461                self.expect("align")?;
462                let align = self.u32()?;
463                self.expect(")")?;
464                if indirect { Abi::ByVal { size, align } } else { Abi::Sret { size, align } }
465            }
466            _ => Abi::Plain,
467        };
468        Ok(abi)
469    }
470
471    fn attrs(&mut self) -> Result<Attrs, ParseError> {
472        self.expect("(")?;
473        let mut attrs = Attrs::NONE;
474        loop {
475            let word = self.word();
476            if self.eat("=") {
477                let value = self.word();
478                match word {
479                    "fp_contract" => match FpContract::from_name(value) {
480                        Some(contract) => attrs.fp_contract = contract,
481                        None => return self.fail(format!("`{value}` is not a contraction")),
482                    },
483                    other => return self.fail(format!("`{other}` takes no value")),
484                }
485            } else {
486                match AttrSet::from_name(word) {
487                    Some(attr) => attrs.set |= attr,
488                    None => return self.fail(format!("`{word}` is not an attribute")),
489                }
490            }
491            if !self.eat(",") {
492                break;
493            }
494        }
495        self.expect(")")?;
496        Ok(attrs)
497    }
498
499    /// The blocks of a function, up to the closing brace.
500    fn body(&mut self) -> Result<Vec<PendingBlock<'a>>, ParseError> {
501        let mut blocks: Vec<PendingBlock<'a>> = Vec::new();
502        loop {
503            self.skip_blank_lines();
504            if self.eat("}") {
505                self.end_of_line()?;
506                return Ok(blocks);
507            }
508            if self.at_end() {
509                return self.fail("the function is not closed");
510            }
511            if self.peek_word().starts_with("block") {
512                let number = self.block_ref()?;
513                if number as usize != blocks.len() {
514                    return self.fail(format!(
515                        "blocks are numbered in order and block{} comes next",
516                        blocks.len()
517                    ));
518                }
519                let mut params = Vec::new();
520                if self.eat("(") {
521                    loop {
522                        let value = self.value_ref()?;
523                        self.expect(":")?;
524                        params.push((value, self.ty()?));
525                        if !self.eat(",") {
526                            break;
527                        }
528                    }
529                    self.expect(")")?;
530                }
531                self.expect(":")?;
532                self.end_of_line()?;
533                blocks.push(PendingBlock { params, insts: Vec::new() });
534                continue;
535            }
536            let inst = self.inst()?;
537            match blocks.last_mut() {
538                Some(block) => block.insts.push(inst),
539                None => return self.fail("an instruction before any block"),
540            }
541        }
542    }
543
544    /// One instruction line.
545    fn inst(&mut self) -> Result<PendingInst<'a>, ParseError> {
546        let line = self.line;
547        let mut results = Vec::new();
548        if self.peek_is("%") {
549            results = self.value_list()?;
550            self.expect("=")?;
551        }
552
553        let word = self.word();
554        let Some(opcode) = Opcode::from_name(word) else {
555            return self.fail(format!("`{word}` is not an opcode"));
556        };
557        let (written, flags) = self.suffixes()?;
558
559        let mut args = Vec::new();
560        let extra = match opcode.extra_kind() {
561            ExtraKind::None => {
562                args = self.value_list()?;
563                PendingExtra::None
564            }
565            ExtraKind::Imm => PendingExtra::Imm(self.imm_text()?),
566            ExtraKind::Symbol => {
567                let symbol = self.symbol()?;
568                if self.eat("(") {
569                    args = self.value_list()?;
570                    self.expect(")")?;
571                }
572                PendingExtra::Symbol(symbol)
573            }
574            ExtraKind::IntPred => {
575                let word = self.word();
576                let Some(pred) = IntPred::from_name(word) else {
577                    return self.fail(format!("`{word}` is not an integer comparison"));
578                };
579                args = self.value_list()?;
580                PendingExtra::IntPred(pred)
581            }
582            ExtraKind::FloatPred => {
583                let word = self.word();
584                let Some(pred) = FloatPred::from_name(word) else {
585                    return self.fail(format!("`{word}` is not a floating point comparison"));
586                };
587                args = self.value_list()?;
588                PendingExtra::FloatPred(pred)
589            }
590            ExtraKind::Mem => {
591                if matches!(opcode, Opcode::Store | Opcode::AtomicStore) {
592                    // A store reads left to right like the assignment it came from.
593                    let value = self.value_ref()?;
594                    self.expect("->")?;
595                    args = vec![value, self.value_ref()?];
596                } else {
597                    args = self.value_list()?;
598                }
599                PendingExtra::Mem(self.mem()?)
600            }
601            ExtraKind::Rmw => {
602                let word = self.word();
603                let Some(op) = RmwOp::from_name(word) else {
604                    return self.fail(format!("`{word}` is not a read-modify-write"));
605                };
606                args = self.value_list()?;
607                PendingExtra::Rmw(op, self.mem()?)
608            }
609            ExtraKind::Order => {
610                let word = self.word();
611                let Some(order) = MemOrder::from_name(word) else {
612                    return self.fail(format!("`{word}` is not an ordering"));
613                };
614                PendingExtra::Order(order)
615            }
616            ExtraKind::Targets => {
617                args = self.value_list()?;
618                if !args.is_empty() {
619                    self.expect(",")?;
620                }
621                let mut targets = Vec::new();
622                loop {
623                    targets.push(self.block_call()?);
624                    if !self.eat(",") {
625                        break;
626                    }
627                }
628                PendingExtra::Targets(targets)
629            }
630            ExtraKind::Call => {
631                let callee = if self.peek_is("@") {
632                    Some(self.symbol()?)
633                } else {
634                    args.push(self.value_ref()?);
635                    None
636                };
637                self.expect("(")?;
638                let (values, abis) = self.call_args()?;
639                args.extend(values);
640                self.expect(")")?;
641                self.expect(":")?;
642                PendingExtra::Call { callee, signature: self.signature()?, abis }
643            }
644            ExtraKind::Switch => {
645                args = self.value_list()?;
646                let mut targets = Vec::new();
647                let mut cases = Vec::new();
648                if self.eat(",") {
649                    targets.push(self.block_call()?);
650                    self.expect(",")?;
651                    self.expect("[")?;
652                    if !self.eat("]") {
653                        loop {
654                            cases.push(self.imm_text()?);
655                            self.expect("=>")?;
656                            targets.push(self.block_call()?);
657                            if !self.eat(",") {
658                                break;
659                            }
660                        }
661                        self.expect("]")?;
662                    }
663                }
664                PendingExtra::Switch { targets, cases }
665            }
666            ExtraKind::Asm => {
667                let template = self.symbol_from_string()?;
668                self.expect(",")?;
669                let constraints = self.symbol_from_string()?;
670                self.expect(",")?;
671                let clobbers = self.symbol_from_string()?;
672                self.expect("(")?;
673                args = self.value_list()?;
674                self.expect(")")?;
675                let mut targets = Vec::new();
676                if self.eat(",") {
677                    self.expect("labels")?;
678                    self.expect("[")?;
679                    loop {
680                        targets.push(self.block_call()?);
681                        if !self.eat(",") {
682                            break;
683                        }
684                    }
685                    self.expect("]")?;
686                }
687                PendingExtra::Asm { template, constraints, clobbers, targets }
688            }
689        };
690        self.end_of_line()?;
691        Ok(PendingInst { opcode, flags, results, written, args, extra, line })
692    }
693
694    /// The dotted things after an opcode: the result types, then the flags.
695    fn suffixes(&mut self) -> Result<(Vec<Type>, Flags), ParseError> {
696        let mut written = Vec::new();
697        let mut flags = Flags::NONE;
698        while self.at(".") {
699            self.pos += 1;
700            if self.at("(") {
701                self.pos += 1;
702                loop {
703                    written.push(self.ty()?);
704                    if !self.eat(",") {
705                        break;
706                    }
707                }
708                self.expect(")")?;
709                continue;
710            }
711            let word = self.glued_word();
712            if let Some(flag) = Flags::from_name(word) {
713                flags |= flag;
714            } else if let Some(ty) = Type::parse(word) {
715                written.push(ty);
716            } else {
717                return self.fail(format!("`{word}` is neither a type nor a flag"));
718            }
719        }
720        Ok((written, flags))
721    }
722
723    /// What an access carries beyond its address.
724    fn mem(&mut self) -> Result<MemInfo, ParseError> {
725        let mut info = MemInfo { size: 0, align: 1, order: MemOrder::NotAtomic, tbaa: None };
726        while self.eat(",") {
727            let word = self.word();
728            match word {
729                "size" => info.size = self.u64()?,
730                "align" => info.align = self.u32()?,
731                "tbaa" => info.tbaa = Some(self.meta_ref()?),
732                _ => match MemOrder::from_name(word) {
733                    Some(order) => info.order = order,
734                    None => return self.fail(format!("an access has no `{word}`")),
735                },
736            }
737        }
738        Ok(info)
739    }
740
741    /// A branch target and the values it passes.
742    fn block_call(&mut self) -> Result<PendingCall, ParseError> {
743        let block = self.block_ref()?;
744        let mut args = Vec::new();
745        if self.eat("(") {
746            args = self.value_list()?;
747            self.expect(")")?;
748        }
749        Ok(PendingCall { block, args })
750    }
751
752    // Building the function.
753
754    /// Works out every value's type, then creates the blocks and instructions in print order.
755    fn build(&mut self, func: &mut Func, blocks: &[PendingBlock<'a>]) -> Result<(), ParseError> {
756        let count = self.check_numbering(blocks)?;
757        let types = self.value_types(blocks, count)?;
758
759        let mut next = 0;
760        for pending in blocks {
761            let block = func.create_block();
762            for &(number, ty) in &pending.params {
763                if number != next {
764                    self.line = self.line_of(blocks, number);
765                    return self
766                        .fail(format!("values are numbered in order and %{next} comes next"));
767                }
768                func.append_param(block, ty);
769                next += 1;
770            }
771            for inst in &pending.insts {
772                if inst.results.first().is_some_and(|&first| first != next) {
773                    self.line = inst.line;
774                    return self
775                        .fail(format!("values are numbered in order and %{next} comes next"));
776                }
777                let built = self.build_inst(func, inst, &types)?;
778                func.append_inst(block, built);
779                next += inst.results.len() as u32;
780            }
781        }
782        Ok(())
783    }
784
785    /// Checks that every number the text uses is one the text also defines.
786    ///
787    /// The answer is how many values there are, which is what everything after this is sized by.
788    fn check_numbering(&mut self, blocks: &[PendingBlock<'a>]) -> Result<u32, ParseError> {
789        let mut count = 0;
790        for pending in blocks {
791            count += pending.params.len();
792            for inst in &pending.insts {
793                count += inst.results.len();
794            }
795        }
796        let count = count as u32;
797        let total = blocks.len() as u32;
798        for pending in blocks {
799            for inst in &pending.insts {
800                self.line = inst.line;
801                for &arg in &inst.args {
802                    if arg >= count {
803                        return self.fail(format!("%{arg} is used and never defined"));
804                    }
805                }
806                for call in inst_calls(inst) {
807                    if call.block >= total {
808                        return self.fail(format!("block{} is used and never defined", call.block));
809                    }
810                    for &arg in &call.args {
811                        if arg >= count {
812                            return self.fail(format!("%{arg} is used and never defined"));
813                        }
814                    }
815                }
816            }
817        }
818        Ok(count)
819    }
820
821    /// The type of every value, worked out from the ones the text writes down.
822    ///
823    /// A block parameter has its type at the block and an instruction either has its written
824    /// after the opcode or takes it from an operand, so this is a fixed point over a graph whose
825    /// only cycles run through parameters. It converges in as many rounds as the longest chain
826    /// of instructions each taking its type from the one below it in the text.
827    fn value_types(
828        &mut self,
829        blocks: &[PendingBlock<'a>],
830        count: u32,
831    ) -> Result<Vec<Option<Type>>, ParseError> {
832        let mut types = vec![None; count as usize];
833        for pending in blocks {
834            for &(number, ty) in &pending.params {
835                types[number as usize] = Some(ty);
836            }
837        }
838        loop {
839            let mut progress = false;
840            for pending in blocks {
841                for inst in &pending.insts {
842                    let Some(&first) = inst.results.first() else { continue };
843                    if types[first as usize].is_some() {
844                        continue;
845                    }
846                    let Some(resolved) = result_types(inst, &types) else { continue };
847                    if resolved.len() != inst.results.len() {
848                        self.line = inst.line;
849                        return self.fail(format!(
850                            "{} produces {} values and the text names {}",
851                            inst.opcode.name(),
852                            resolved.len(),
853                            inst.results.len()
854                        ));
855                    }
856                    for (&number, ty) in inst.results.iter().zip(resolved) {
857                        types[number as usize] = Some(ty);
858                    }
859                    progress = true;
860                }
861            }
862            if !progress {
863                break;
864            }
865        }
866        for pending in blocks {
867            for inst in &pending.insts {
868                if inst.results.first().is_some_and(|&first| types[first as usize].is_none()) {
869                    self.line = inst.line;
870                    return self.fail(format!(
871                        "nothing in the text says what {} produces",
872                        inst.opcode.name()
873                    ));
874                }
875            }
876        }
877        Ok(types)
878    }
879
880    fn build_inst(
881        &mut self,
882        func: &mut Func,
883        pending: &PendingInst<'a>,
884        types: &[Option<Type>],
885    ) -> Result<Inst, ParseError> {
886        let results: Vec<Type> = pending
887            .results
888            .iter()
889            .map(|&number| types[number as usize].unwrap_or(Type::VOID))
890            .collect();
891        let args: Vec<Value> =
892            pending.args.iter().map(|&number| Value::from_usize(number as usize)).collect();
893        let arg_list = func.push_values(&args);
894
895        let extra = match &pending.extra {
896            PendingExtra::None => Extra::None,
897            PendingExtra::Imm(text) => {
898                let ty = results.first().copied().unwrap_or(Type::VOID);
899                self.line = pending.line;
900                let imm = self.imm(text, ty)?;
901                Extra::Imm(func.add_imm(imm))
902            }
903            PendingExtra::Symbol(symbol) => Extra::Symbol(*symbol),
904            PendingExtra::IntPred(pred) => Extra::IntPred(*pred),
905            PendingExtra::FloatPred(pred) => Extra::FloatPred(*pred),
906            PendingExtra::Mem(info) => Extra::Mem(func.add_mem(*info)),
907            PendingExtra::Rmw(op, info) => Extra::Rmw(*op, func.add_mem(*info)),
908            PendingExtra::Order(order) => Extra::Order(*order),
909            PendingExtra::Targets(targets) => {
910                let calls = build_calls(func, targets);
911                Extra::Targets(func.push_block_calls(&calls))
912            }
913            PendingExtra::Call { callee, signature, abis } => {
914                let named = signature.params.len();
915                if abis.iter().take(named).any(|&abi| abi != Abi::Plain) {
916                    self.line = pending.line;
917                    return self.fail(
918                        "the signature is what says how an argument it names travels".to_string(),
919                    );
920                }
921                let varargs = match abis.get(named.min(abis.len())..) {
922                    Some(rest) if rest.iter().any(|&abi| abi != Abi::Plain) => rest,
923                    _ => &[],
924                };
925                let varargs = func.push_abis(varargs);
926                let sig = func.add_signature(signature.clone());
927                Extra::Call(func.add_call(CallInfo { callee: *callee, signature: sig, varargs }))
928            }
929            PendingExtra::Switch { targets, cases } => {
930                let ty = pending
931                    .args
932                    .first()
933                    .and_then(|&number| types[number as usize])
934                    .unwrap_or(Type::VOID);
935                self.line = pending.line;
936                let mut imms = Vec::with_capacity(cases.len());
937                for case in cases {
938                    imms.push(self.imm(case, ty)?);
939                }
940                let calls = build_calls(func, targets);
941                let targets = func.push_block_calls(&calls);
942                let cases = func.push_imms(&imms);
943                Extra::Switch(func.add_switch(SwitchInfo { targets, cases }))
944            }
945            PendingExtra::Asm { template, constraints, clobbers, targets } => {
946                let calls = build_calls(func, targets);
947                let targets = func.push_block_calls(&calls);
948                Extra::Asm(func.add_asm(AsmInfo {
949                    template: *template,
950                    constraints: *constraints,
951                    clobbers: *clobbers,
952                    targets,
953                }))
954            }
955        };
956
957        let data = InstData {
958            opcode: pending.opcode,
959            flags: pending.flags,
960            args: arg_list,
961            extra,
962            ..InstData::new(pending.opcode)
963        };
964        Ok(func.create_inst(data, &results, Span::DUMMY))
965    }
966
967    /// The line a value number is defined on, for a message about the numbering.
968    fn line_of(&self, blocks: &[PendingBlock<'a>], number: u32) -> u32 {
969        for pending in blocks {
970            for inst in &pending.insts {
971                if inst.results.contains(&number) {
972                    return inst.line;
973                }
974            }
975        }
976        self.line
977    }
978
979    // Tokens.
980
981    /// A constant, read as the type it is a constant of.
982    fn imm(&mut self, text: &str, ty: Type) -> Result<Imm, ParseError> {
983        let scalar = if ty.is_vector() { ty.lane() } else { ty };
984        if scalar.is_int() {
985            match parse_i128(text) {
986                Some(value) => Ok(Imm::int(value, scalar)),
987                None => self.fail(format!("`{text}` is not an {scalar}")),
988            }
989        } else {
990            match text.strip_prefix("0x").and_then(|rest| u128::from_str_radix(rest, 16).ok()) {
991                Some(bits) => Ok(Imm::from_bits(bits)),
992                None => self.fail(format!("`{text}` is not the bits of a {scalar}")),
993            }
994        }
995    }
996
997    /// The text of a constant, which is a sign, digits, and the letters a hexadecimal one has.
998    fn imm_text(&mut self) -> Result<&'a str, ParseError> {
999        self.spaces();
1000        let start = self.pos;
1001        if self.at("-") {
1002            self.pos += 1;
1003        }
1004        while self.peek().is_some_and(|byte| byte.is_ascii_alphanumeric()) {
1005            self.pos += 1;
1006        }
1007        if self.pos == start {
1008            return self.fail("a constant was expected");
1009        }
1010        Ok(&self.text[start..self.pos])
1011    }
1012
1013    fn ty(&mut self) -> Result<Type, ParseError> {
1014        let word = self.word();
1015        match Type::parse(word) {
1016            Some(ty) => Ok(ty),
1017            None => self.fail(format!("`{word}` is not a type")),
1018        }
1019    }
1020
1021    /// A `%n`, giving back the number.
1022    fn value_ref(&mut self) -> Result<u32, ParseError> {
1023        self.expect("%")?;
1024        self.u32()
1025    }
1026
1027    /// A run of `%n` separated by commas, stopping at the first comma not followed by one.
1028    fn value_list(&mut self) -> Result<Vec<u32>, ParseError> {
1029        let mut values = Vec::new();
1030        if !self.peek_is("%") {
1031            return Ok(values);
1032        }
1033        loop {
1034            values.push(self.value_ref()?);
1035            let save = self.pos;
1036            if !self.eat(",") {
1037                return Ok(values);
1038            }
1039            if !self.peek_is("%") {
1040                self.pos = save;
1041                return Ok(values);
1042            }
1043        }
1044    }
1045
1046    /// The same, where each may say how the ABI asks it to travel, which is what a call writes
1047    /// on an argument its signature does not name.
1048    fn call_args(&mut self) -> Result<(Vec<u32>, Vec<Abi>), ParseError> {
1049        let mut values = Vec::new();
1050        let mut abis = Vec::new();
1051        if !self.peek_is("%") {
1052            return Ok((values, abis));
1053        }
1054        loop {
1055            values.push(self.value_ref()?);
1056            abis.push(self.abi()?);
1057            let save = self.pos;
1058            if !self.eat(",") {
1059                return Ok((values, abis));
1060            }
1061            if !self.peek_is("%") {
1062                self.pos = save;
1063                return Ok((values, abis));
1064            }
1065        }
1066    }
1067
1068    /// A `blockN`, giving back the number.
1069    fn block_ref(&mut self) -> Result<u32, ParseError> {
1070        let word = self.word();
1071        match word.strip_prefix("block").and_then(parse_u32) {
1072            Some(number) => Ok(number),
1073            None => self.fail(format!("`{word}` is not a block")),
1074        }
1075    }
1076
1077    /// A `!n`, remembering it so that one nothing defines is reported.
1078    fn meta_ref(&mut self) -> Result<Meta, ParseError> {
1079        self.expect("!")?;
1080        let index = self.u32()?;
1081        let seen = self.meta_used.is_none_or(|(used, _)| index > used);
1082        if seen {
1083            self.meta_used = Some((index, self.line));
1084        }
1085        Ok(Idx::from_usize(index as usize))
1086    }
1087
1088    /// An `@name`, interned.
1089    fn symbol(&mut self) -> Result<Symbol, ParseError> {
1090        self.expect("@")?;
1091        let start = self.pos;
1092        while self.peek().is_some_and(is_name_byte) {
1093            self.pos += 1;
1094        }
1095        if self.pos == start {
1096            return self.fail("a name was expected");
1097        }
1098        let name = &self.text[start..self.pos];
1099        Ok(self.names.intern(name))
1100    }
1101
1102    /// A quoted string, interned, which is what a section and a template are.
1103    fn symbol_from_string(&mut self) -> Result<Symbol, ParseError> {
1104        let text = self.quoted_str()?;
1105        Ok(self.names.intern(&text))
1106    }
1107
1108    /// A quoted string that has to be text rather than arbitrary bytes.
1109    fn quoted_str(&mut self) -> Result<String, ParseError> {
1110        let bytes = self.string()?;
1111        match String::from_utf8(bytes) {
1112            Ok(text) => Ok(text),
1113            Err(_) => self.fail("that string is not text"),
1114        }
1115    }
1116
1117    /// A quoted string, which may hold any bytes at all.
1118    fn string(&mut self) -> Result<Vec<u8>, ParseError> {
1119        self.expect("\"")?;
1120        let mut bytes = Vec::new();
1121        loop {
1122            let Some(byte) = self.peek() else {
1123                return self.fail("that string is not closed");
1124            };
1125            self.pos += 1;
1126            match byte {
1127                b'"' => return Ok(bytes),
1128                b'\n' => return self.fail("that string is not closed"),
1129                b'\\' => {
1130                    let escape = match self.peek() {
1131                        Some(b'"') => b'"',
1132                        Some(b'\\') => b'\\',
1133                        _ => {
1134                            let hex = self.text.get(self.pos..self.pos + 2);
1135                            match hex.and_then(|hex| u8::from_str_radix(hex, 16).ok()) {
1136                                Some(byte) => {
1137                                    self.pos += 2;
1138                                    bytes.push(byte);
1139                                    continue;
1140                                }
1141                                None => return self.fail("that is not an escape"),
1142                            }
1143                        }
1144                    };
1145                    self.pos += 1;
1146                    bytes.push(escape);
1147                }
1148                _ => bytes.push(byte),
1149            }
1150        }
1151    }
1152
1153    fn u32(&mut self) -> Result<u32, ParseError> {
1154        let word = self.word();
1155        match parse_u32(word) {
1156            Some(number) => Ok(number),
1157            None => self.fail(format!("`{word}` is not a number")),
1158        }
1159    }
1160
1161    fn u64(&mut self) -> Result<u64, ParseError> {
1162        let word = self.word();
1163        match parse_u64(word) {
1164            Some(number) => Ok(number),
1165            None => self.fail(format!("`{word}` is not a number")),
1166        }
1167    }
1168
1169    fn i64(&mut self) -> Result<i64, ParseError> {
1170        let word = self.word();
1171        match parse_u64(word).and_then(|number| i64::try_from(number).ok()) {
1172            Some(number) => Ok(number),
1173            None => self.fail(format!("`{word}` is not an offset")),
1174        }
1175    }
1176
1177    /// One of the keyword parenthesised after a name, as in `linkage(internal)`.
1178    fn parenthesised<T>(
1179        &mut self,
1180        from_name: impl Fn(&str) -> Option<T>,
1181        what: &str,
1182    ) -> Result<T, ParseError> {
1183        self.expect("(")?;
1184        let word = self.word();
1185        let Some(value) = from_name(word) else {
1186            return self.fail(format!("`{word}` is not {what}"));
1187        };
1188        self.expect(")")?;
1189        Ok(value)
1190    }
1191
1192    // The cursor.
1193
1194    fn fail<T>(&self, message: impl Into<String>) -> Result<T, ParseError> {
1195        Err(ParseError { line: self.line, message: message.into() })
1196    }
1197
1198    fn peek(&self) -> Option<u8> {
1199        self.text.as_bytes().get(self.pos).copied()
1200    }
1201
1202    fn at(&self, text: &str) -> bool {
1203        self.text[self.pos..].starts_with(text)
1204    }
1205
1206    fn at_end(&self) -> bool {
1207        self.pos >= self.text.len()
1208    }
1209
1210    /// Whether that text comes next, ignoring the spaces in front of it.
1211    fn peek_is(&self, text: &str) -> bool {
1212        self.text[self.pos..].trim_start_matches([' ', '\t']).starts_with(text)
1213    }
1214
1215    fn spaces(&mut self) {
1216        while matches!(self.peek(), Some(b' ' | b'\t')) {
1217            self.pos += 1;
1218        }
1219    }
1220
1221    fn eat(&mut self, text: &str) -> bool {
1222        self.spaces();
1223        if self.at(text) {
1224            self.pos += text.len();
1225            return true;
1226        }
1227        false
1228    }
1229
1230    fn expect(&mut self, text: &str) -> Result<(), ParseError> {
1231        if self.eat(text) {
1232            return Ok(());
1233        }
1234        self.fail(format!("`{text}` was expected"))
1235    }
1236
1237    /// A word of letters, digits and underscores, after the spaces in front of it.
1238    fn word(&mut self) -> &'a str {
1239        self.spaces();
1240        self.glued_word()
1241    }
1242
1243    /// The same, with nothing skipped, which is what a suffix after a dot is.
1244    fn glued_word(&mut self) -> &'a str {
1245        let start = self.pos;
1246        while self.peek().is_some_and(|byte| byte.is_ascii_alphanumeric() || byte == b'_') {
1247            self.pos += 1;
1248        }
1249        &self.text[start..self.pos]
1250    }
1251
1252    /// The next word without consuming it, for deciding what a line is.
1253    fn peek_word(&self) -> &'a str {
1254        let rest = self.text[self.pos..].trim_start_matches([' ', '\t']);
1255        let end =
1256            rest.find(|c: char| !(c.is_ascii_alphanumeric() || c == '_')).unwrap_or(rest.len());
1257        &rest[..end]
1258    }
1259
1260    /// Whether that word comes next, consuming it if so.
1261    fn eat_word(&mut self, word: &str) -> bool {
1262        if self.peek_word() == word {
1263            self.word();
1264            return true;
1265        }
1266        false
1267    }
1268
1269    fn end_of_line(&mut self) -> Result<(), ParseError> {
1270        self.spaces();
1271        if self.at_end() {
1272            return Ok(());
1273        }
1274        if self.at("\n") {
1275            self.pos += 1;
1276            self.line += 1;
1277            return Ok(());
1278        }
1279        let rest = &self.text[self.pos..];
1280        let end = rest.find('\n').unwrap_or(rest.len());
1281        self.fail(format!("`{}` is left over at the end of the line", &rest[..end]))
1282    }
1283
1284    fn skip_blank_lines(&mut self) {
1285        loop {
1286            let save = self.pos;
1287            self.spaces();
1288            if self.at("\n") {
1289                self.pos += 1;
1290                self.line += 1;
1291            } else {
1292                self.pos = save;
1293                return;
1294            }
1295        }
1296    }
1297}
1298
1299/// Every branch target an instruction has, whichever payload holds them.
1300fn inst_calls<'p>(inst: &'p PendingInst<'_>) -> &'p [PendingCall] {
1301    match &inst.extra {
1302        PendingExtra::Targets(targets)
1303        | PendingExtra::Switch { targets, .. }
1304        | PendingExtra::Asm { targets, .. } => targets,
1305        _ => &[],
1306    }
1307}
1308
1309/// The branch targets of an instruction, with their arguments put in the function's pool.
1310fn build_calls(func: &mut Func, targets: &[PendingCall]) -> Vec<BlockCall> {
1311    targets
1312        .iter()
1313        .map(|call| {
1314            let args: Vec<Value> =
1315                call.args.iter().map(|&number| Value::from_usize(number as usize)).collect();
1316            BlockCall {
1317                block: Block::from_usize(call.block as usize),
1318                args: func.push_values(&args),
1319            }
1320        })
1321        .collect()
1322}
1323
1324/// What an instruction produces, or `None` while an operand's type is still unknown.
1325///
1326/// This is the reading half of the rule the printer writes by, which is why the two of them
1327/// name the same opcodes: a type is in the text only where the operands do not say it.
1328fn result_types(inst: &PendingInst<'_>, types: &[Option<Type>]) -> Option<Vec<Type>> {
1329    if inst.results.is_empty() {
1330        return Some(Vec::new());
1331    }
1332    if !inst.written.is_empty() {
1333        return Some(inst.written.clone());
1334    }
1335    match inst.opcode {
1336        Opcode::GlobalAddr | Opcode::BlockAddr | Opcode::Alloca => Some(vec![Type::PTR]),
1337        Opcode::ICmp | Opcode::FCmp => {
1338            let ty = arg_type(inst, types)?;
1339            Some(vec![ty.with_lane(Type::I1)])
1340        }
1341        Opcode::Call | Opcode::CallIndirect | Opcode::TailCall => match &inst.extra {
1342            PendingExtra::Call { signature, .. } => Some(signature.return_types().collect()),
1343            _ => None,
1344        },
1345        _ => Some(vec![arg_type(inst, types)?]),
1346    }
1347}
1348
1349/// The type of an instruction's first operand, if it is known yet.
1350fn arg_type(inst: &PendingInst<'_>, types: &[Option<Type>]) -> Option<Type> {
1351    let &first = inst.args.first()?;
1352    *types.get(first as usize)?
1353}
1354
1355/// A decimal number with no sign and no leading zero, which is the only form the printer writes.
1356fn parse_u64(text: &str) -> Option<u64> {
1357    if text.is_empty() || (text.starts_with('0') && text.len() > 1) {
1358        return None;
1359    }
1360    if !text.bytes().all(|byte| byte.is_ascii_digit()) {
1361        return None;
1362    }
1363    text.parse().ok()
1364}
1365
1366fn parse_u32(text: &str) -> Option<u32> {
1367    parse_u64(text).and_then(|number| u32::try_from(number).ok())
1368}
1369
1370/// A decimal integer, with a minus sign for a negative one, as the printer writes them.
1371fn parse_i128(text: &str) -> Option<i128> {
1372    let (negative, digits) = match text.strip_prefix('-') {
1373        Some(rest) => (true, rest),
1374        None => (false, text),
1375    };
1376    if digits.is_empty() || (digits.starts_with('0') && digits.len() > 1) {
1377        return None;
1378    }
1379    if negative && digits == "0" {
1380        return None;
1381    }
1382    if !digits.bytes().all(|byte| byte.is_ascii_digit()) {
1383        return None;
1384    }
1385    let magnitude: u128 = digits.parse().ok()?;
1386    if negative {
1387        // The most negative number has no positive counterpart, so it is built by negating the
1388        // wrapped value rather than by converting first.
1389        (magnitude <= 1 << 127).then(|| (magnitude as i128).wrapping_neg())
1390    } else {
1391        i128::try_from(magnitude).ok()
1392    }
1393}
1394
1395/// Whether a byte can appear in a symbol name.
1396///
1397/// Dots are in, because a compiler names things `hi.str` and `memcpy.resolve` and the assembler
1398/// takes them. So is every byte above ASCII: C23 allows an identifier to be written in any script
1399/// and gcc allowed it long before that, so a name the front end read has to come back out of the
1400/// printer and go back in. Nothing is decoded here, because a name is a run of bytes either way
1401/// and the file it was read from was checked for being UTF-8 when it was read.
1402fn is_name_byte(byte: u8) -> bool {
1403    byte.is_ascii_alphanumeric() || matches!(byte, b'_' | b'.' | b'$') || byte >= 0x80
1404}
1405
1406#[cfg(test)]
1407mod tests {
1408    use rucc_base::Interner;
1409
1410    use super::*;
1411    use crate::fixtures::{EXAMPLE, SYMBOLS, ZOO};
1412    use crate::print;
1413
1414    /// Reads a module and writes it back out, which is the whole claim this file makes.
1415    fn round_trip(text: &str) -> String {
1416        let mut names = Interner::new();
1417        let module = match parse(text, &mut names) {
1418            Ok(module) => module,
1419            Err(error) => panic!("{error}"),
1420        };
1421        print(&module, &names)
1422    }
1423
1424    fn error(text: &str) -> String {
1425        let mut names = Interner::new();
1426        match parse(text, &mut names) {
1427            Ok(_) => panic!("that was expected to be turned down"),
1428            Err(error) => error.to_string(),
1429        }
1430    }
1431
1432    const HEADER: &str = "\
1433; ModuleID = 'example.c'
1434; format 0
1435target triple = \"x86_64-unknown-linux-gnu\"
1436target datalayout = \"e-p:64:64-i64:64-f80:128-S128\"
1437";
1438
1439    #[test]
1440    fn the_example_in_the_spec_comes_back_byte_for_byte() {
1441        assert_eq!(round_trip(EXAMPLE), EXAMPLE);
1442    }
1443
1444    #[test]
1445    fn one_of_almost_everything_comes_back_byte_for_byte() {
1446        assert_eq!(round_trip(ZOO), ZOO);
1447    }
1448
1449    #[test]
1450    fn the_shapes_a_symbol_comes_in_come_back_byte_for_byte() {
1451        assert_eq!(round_trip(SYMBOLS), SYMBOLS);
1452    }
1453
1454    #[test]
1455    fn a_name_that_is_not_ascii_comes_back_byte_for_byte() {
1456        // C23 says an identifier may be written in any script and gcc has taken them for far
1457        // longer, so a program that uses one has to survive the printer and the reader. The
1458        // reader used to stop at the first byte above ASCII and say a name was expected.
1459        let text = format!("{HEADER}\nglobal @été : i32 = 1, align 4, linkage(external)\n");
1460        assert_eq!(round_trip(&text), text);
1461    }
1462
1463    #[test]
1464    fn a_value_defined_after_it_is_used() {
1465        // Block layout order is not required to put a definition before its uses, so the type
1466        // of %2 is only known after the whole function has been read. This is the case the two
1467        // passes exist for.
1468        let text = format!(
1469            "{HEADER}
1470func @late() -> i64, linkage(external) {{
1471block0:
1472    jump block2
1473
1474block1(%0: i64):
1475    %1 = add %2, %0
1476    return %1
1477
1478block2:
1479    %2 = iconst.i64 7
1480    jump block1(%2)
1481}}
1482"
1483        );
1484        assert_eq!(round_trip(&text), text);
1485    }
1486
1487    #[test]
1488    fn what_the_abi_asks_of_a_parameter_comes_back_byte_for_byte() {
1489        // A `struct` return, a `struct` argument, and a `char` the callee may read a whole
1490        // register of. None of it is written on a type, because none of it is a fact about one.
1491        let text = format!(
1492            "{HEADER}
1493func @f(ptr sret(24, align 8), ptr byval(16, align 8), i8 zext), linkage(external) {{
1494block0(%0: ptr, %1: ptr, %2: i8):
1495    return
1496}}
1497
1498func @g(i8 sext) -> i8 sext, linkage(external);
1499"
1500        );
1501        assert_eq!(round_trip(&text), text);
1502    }
1503
1504    #[test]
1505    fn a_word_that_is_not_an_attribute_is_not_read_as_one() {
1506        let text = format!(
1507            "{HEADER}
1508func @f(ptr inreg), linkage(external);
1509"
1510        );
1511        assert_eq!(error(&text), "line 6: `)` was expected");
1512    }
1513
1514    #[test]
1515    fn an_empty_module_is_its_header() {
1516        assert_eq!(round_trip(HEADER), HEADER);
1517    }
1518
1519    #[test]
1520    fn the_format_version_is_checked_before_anything_else() {
1521        let text = "; ModuleID = 'a.c'\n; format 99\n";
1522        assert_eq!(error(text), "line 2: this build reads format 0 and the text says format 99");
1523    }
1524
1525    #[test]
1526    fn an_opcode_nobody_has_is_reported_with_its_line() {
1527        let text = format!(
1528            "{HEADER}
1529func @f(), linkage(external) {{
1530block0:
1531    getelementptr %0
1532}}
1533"
1534        );
1535        assert_eq!(error(&text), "line 8: `getelementptr` is not an opcode");
1536    }
1537
1538    #[test]
1539    fn an_abi_on_an_argument_the_signature_names_is_turned_down() {
1540        // It would be two answers to one question, and the signature's is the one the callee
1541        // reads, so the text is wrong rather than one of them winning.
1542        let text = format!(
1543            "{HEADER}
1544func @f(ptr), linkage(external) {{
1545block0(%0: ptr):
1546    call @p(%0 byval(8, align 8)) : (ptr, ...)
1547    return
1548}}
1549"
1550        );
1551        assert_eq!(
1552            error(&text),
1553            "line 8: the signature is what says how an argument it names travels"
1554        );
1555    }
1556
1557    #[test]
1558    fn a_value_nothing_defines_is_reported() {
1559        let text = format!(
1560            "{HEADER}
1561func @f(i32) -> i32, linkage(external) {{
1562block0(%0: i32):
1563    %1 = add %0, %9
1564    return %1
1565}}
1566"
1567        );
1568        assert_eq!(error(&text), "line 8: %9 is used and never defined");
1569    }
1570
1571    #[test]
1572    fn a_block_nothing_defines_is_reported() {
1573        let text = format!(
1574            "{HEADER}
1575func @f(), linkage(external) {{
1576block0:
1577    jump block7
1578}}
1579"
1580        );
1581        assert_eq!(error(&text), "line 8: block7 is used and never defined");
1582    }
1583
1584    #[test]
1585    fn values_have_to_be_numbered_in_print_order() {
1586        let text = format!(
1587            "{HEADER}
1588func @f() -> i32, linkage(external) {{
1589block0:
1590    %1 = iconst.i32 0
1591    %0 = iconst.i32 1
1592    return %1
1593}}
1594"
1595        );
1596        assert_eq!(error(&text), "line 8: values are numbered in order and %0 comes next");
1597    }
1598
1599    #[test]
1600    fn blocks_have_to_be_numbered_in_print_order() {
1601        let text = format!(
1602            "{HEADER}
1603func @f(), linkage(external) {{
1604block1:
1605    return
1606}}
1607"
1608        );
1609        assert_eq!(error(&text), "line 7: blocks are numbered in order and block0 comes next");
1610    }
1611
1612    #[test]
1613    fn metadata_nobody_defines_is_reported() {
1614        let text = format!(
1615            "{HEADER}
1616func @f(ptr), linkage(external) {{
1617block0(%0: ptr):
1618    %1 = load.i32 %0, align 4, tbaa !3
1619    return
1620}}
1621"
1622        );
1623        assert_eq!(error(&text), "line 8: !3 is used and never defined");
1624    }
1625
1626    #[test]
1627    fn a_type_nothing_says_is_reported_rather_than_guessed() {
1628        let text = format!(
1629            "{HEADER}
1630func @f(), linkage(external) {{
1631block0:
1632    %0 = add
1633    return
1634}}
1635"
1636        );
1637        assert_eq!(error(&text), "line 8: nothing in the text says what add produces");
1638    }
1639
1640    #[test]
1641    fn a_line_with_something_left_on_it_is_turned_down() {
1642        let text = format!(
1643            "{HEADER}
1644global @x : i32 = 0, align 4, linkage(internal) and then some
1645"
1646        );
1647        assert_eq!(error(&text), "line 6: `and then some` is left over at the end of the line");
1648    }
1649
1650    #[test]
1651    fn a_constant_that_is_not_one_is_turned_down() {
1652        let text = format!(
1653            "{HEADER}
1654global @x : i32 = 007, align 4, linkage(internal)
1655"
1656        );
1657        assert_eq!(error(&text), "line 6: `007` is not an i32");
1658    }
1659
1660    #[test]
1661    fn a_number_is_read_the_way_the_printer_writes_it() {
1662        assert_eq!(parse_i128("-1"), Some(-1));
1663        assert_eq!(parse_i128("0"), Some(0));
1664        assert_eq!(parse_i128("-0"), None);
1665        assert_eq!(parse_i128("+1"), None);
1666        assert_eq!(parse_i128("01"), None);
1667        assert_eq!(parse_i128(""), None);
1668        assert_eq!(parse_i128("170141183460469231731687303715884105728"), None);
1669        assert_eq!(parse_i128("-170141183460469231731687303715884105728"), Some(i128::MIN));
1670    }
1671
1672    #[test]
1673    fn every_opcode_says_which_payload_it_carries() {
1674        // A payload the parser does not expect for that opcode is text it cannot read back, so
1675        // the two of them agreeing is what this file rests on.
1676        for opcode in Opcode::all() {
1677            let kind = opcode.extra_kind();
1678            let expected = match opcode {
1679                Opcode::IConst | Opcode::FConst | Opcode::Splat => ExtraKind::Imm,
1680                Opcode::GlobalAddr | Opcode::TargetIntrinsic => ExtraKind::Symbol,
1681                Opcode::ICmp => ExtraKind::IntPred,
1682                Opcode::FCmp => ExtraKind::FloatPred,
1683                Opcode::Fence => ExtraKind::Order,
1684                Opcode::AtomicRmw => ExtraKind::Rmw,
1685                Opcode::Switch => ExtraKind::Switch,
1686                Opcode::InlineAsm => ExtraKind::Asm,
1687                Opcode::Jump | Opcode::BrIf | Opcode::BlockAddr | Opcode::IndirectBr => {
1688                    ExtraKind::Targets
1689                }
1690                Opcode::Call | Opcode::CallIndirect | Opcode::TailCall => ExtraKind::Call,
1691                Opcode::Alloca
1692                | Opcode::Load
1693                | Opcode::Store
1694                | Opcode::Memcpy
1695                | Opcode::Memmove
1696                | Opcode::Memset
1697                | Opcode::AtomicLoad
1698                | Opcode::AtomicStore
1699                | Opcode::Cmpxchg
1700                | Opcode::VaObject => ExtraKind::Mem,
1701                _ => ExtraKind::None,
1702            };
1703            assert_eq!(kind, expected, "{}", opcode.name());
1704        }
1705    }
1706}