cranelift_reader/
parser.rs

1//! Parser for .clif files.
2
3use crate::error::{Location, ParseError, ParseResult};
4use crate::isaspec;
5use crate::lexer::{LexError, Lexer, LocatedError, LocatedToken, Token};
6use crate::run_command::{Comparison, Invocation, RunCommand};
7use crate::sourcemap::SourceMap;
8use crate::testcommand::TestCommand;
9use crate::testfile::{Comment, Details, Feature, TestFile};
10use cranelift_codegen::data_value::DataValue;
11use cranelift_codegen::entity::{EntityRef, PrimaryMap};
12use cranelift_codegen::ir::entities::{AnyEntity, DynamicType, MemoryType};
13use cranelift_codegen::ir::immediates::{
14    Ieee128, Ieee16, Ieee32, Ieee64, Imm64, Offset32, Uimm32, Uimm64,
15};
16use cranelift_codegen::ir::instructions::{InstructionData, InstructionFormat, VariableArgs};
17use cranelift_codegen::ir::pcc::{BaseExpr, Expr, Fact};
18use cranelift_codegen::ir::types;
19use cranelift_codegen::ir::types::*;
20use cranelift_codegen::ir::{self, UserExternalNameRef};
21use cranelift_codegen::ir::{
22    AbiParam, ArgumentExtension, ArgumentPurpose, Block, Constant, ConstantData, DynamicStackSlot,
23    DynamicStackSlotData, DynamicTypeData, ExtFuncData, ExternalName, FuncRef, Function,
24    GlobalValue, GlobalValueData, JumpTableData, MemFlags, MemoryTypeData, MemoryTypeField, Opcode,
25    SigRef, Signature, StackSlot, StackSlotData, StackSlotKind, UserFuncName, Value,
26};
27use cranelift_codegen::isa::{self, CallConv};
28use cranelift_codegen::packed_option::ReservedValue;
29use cranelift_codegen::{settings, settings::Configurable, timing};
30use smallvec::SmallVec;
31use std::mem;
32use std::str::FromStr;
33use std::{u16, u32};
34use target_lexicon::Triple;
35
36macro_rules! match_imm {
37    ($signed:ty, $unsigned:ty, $parser:expr, $err_msg:expr) => {{
38        if let Some(Token::Integer(text)) = $parser.token() {
39            $parser.consume();
40            let negative = text.starts_with('-');
41            let positive = text.starts_with('+');
42            let text = if negative || positive {
43                // Strip sign prefix.
44                &text[1..]
45            } else {
46                text
47            };
48
49            // Parse the text value; the lexer gives us raw text that looks like an integer.
50            let value = if text.starts_with("0x") {
51                // Skip underscores.
52                let text = text.replace("_", "");
53                // Parse it in hexadecimal form.
54                <$unsigned>::from_str_radix(&text[2..], 16).map_err(|_| {
55                    $parser.error(&format!(
56                        "unable to parse '{}' value as a hexadecimal {} immediate",
57                        &text[2..],
58                        stringify!($unsigned),
59                    ))
60                })?
61            } else {
62                // Parse it as a signed type to check for overflow and other issues.
63                text.parse()
64                    .map_err(|_| $parser.error("expected decimal immediate"))?
65            };
66
67            // Apply sign if necessary.
68            let signed = if negative {
69                let value = value.wrapping_neg() as $signed;
70                if value > 0 {
71                    return Err($parser.error("negative number too small"));
72                }
73                value
74            } else {
75                value as $signed
76            };
77
78            Ok(signed)
79        } else {
80            err!($parser.loc, $err_msg)
81        }
82    }};
83}
84
85/// After some quick benchmarks a program should never have more than 100,000 blocks.
86const MAX_BLOCKS_IN_A_FUNCTION: u32 = 100_000;
87
88/// Parse the entire `text` into a list of functions.
89///
90/// Any test commands or target declarations are ignored.
91pub fn parse_functions(text: &str) -> ParseResult<Vec<Function>> {
92    let _tt = timing::parse_text();
93    parse_test(text, ParseOptions::default())
94        .map(|file| file.functions.into_iter().map(|(func, _)| func).collect())
95}
96
97/// Options for configuring the parsing of filetests.
98pub struct ParseOptions<'a> {
99    /// Compiler passes to run on the parsed functions.
100    pub passes: Option<&'a [String]>,
101    /// Target ISA for compiling the parsed functions, e.g. "x86_64 skylake".
102    pub target: Option<&'a str>,
103    /// Default calling convention used when none is specified for a parsed function.
104    pub default_calling_convention: CallConv,
105    /// Default for unwind-info setting (enabled or disabled).
106    pub unwind_info: bool,
107    /// Default for machine_code_cfg_info setting (enabled or disabled).
108    pub machine_code_cfg_info: bool,
109}
110
111impl Default for ParseOptions<'_> {
112    fn default() -> Self {
113        Self {
114            passes: None,
115            target: None,
116            default_calling_convention: CallConv::Fast,
117            unwind_info: false,
118            machine_code_cfg_info: false,
119        }
120    }
121}
122
123/// Parse the entire `text` as a test case file.
124///
125/// The returned `TestFile` contains direct references to substrings of `text`.
126pub fn parse_test<'a>(text: &'a str, options: ParseOptions<'a>) -> ParseResult<TestFile<'a>> {
127    let _tt = timing::parse_text();
128    let mut parser = Parser::new(text);
129
130    // Gather the preamble comments.
131    parser.start_gathering_comments();
132
133    let isa_spec: isaspec::IsaSpec;
134    let commands: Vec<TestCommand<'a>>;
135
136    // Check for specified passes and target, if present throw out test commands/targets specified
137    // in file.
138    match options.passes {
139        Some(pass_vec) => {
140            parser.parse_test_commands();
141            commands = parser.parse_cmdline_passes(pass_vec);
142            parser.parse_target_specs(&options)?;
143            isa_spec = parser.parse_cmdline_target(options.target)?;
144        }
145        None => {
146            commands = parser.parse_test_commands();
147            isa_spec = parser.parse_target_specs(&options)?;
148        }
149    };
150    let features = parser.parse_cranelift_features()?;
151
152    // Decide between using the calling convention passed in the options or using the
153    // host's calling convention--if any tests are to be run on the host we should default to the
154    // host's calling convention.
155    parser = if commands.iter().any(|tc| tc.command == "run") {
156        let host_default_calling_convention = CallConv::triple_default(&Triple::host());
157        parser.with_default_calling_convention(host_default_calling_convention)
158    } else {
159        parser.with_default_calling_convention(options.default_calling_convention)
160    };
161
162    parser.token();
163    parser.claim_gathered_comments(AnyEntity::Function);
164
165    let preamble_comments = parser.take_comments();
166    let functions = parser.parse_function_list()?;
167
168    Ok(TestFile {
169        commands,
170        isa_spec,
171        features,
172        preamble_comments,
173        functions,
174    })
175}
176
177/// Parse a CLIF comment `text` as a run command.
178///
179/// Return:
180///  - `Ok(None)` if the comment is not intended to be a `RunCommand` (i.e. does not start with `run`
181///    or `print`
182///  - `Ok(Some(command))` if the comment is intended as a `RunCommand` and can be parsed to one
183///  - `Err` otherwise.
184pub fn parse_run_command(text: &str, signature: &Signature) -> ParseResult<Option<RunCommand>> {
185    let _tt = timing::parse_text();
186    // We remove leading spaces and semi-colons for convenience here instead of at the call sites
187    // since this function will be attempting to parse a RunCommand from a CLIF comment.
188    let trimmed_text = text.trim_start_matches(|c| c == ' ' || c == ';');
189    let mut parser = Parser::new(trimmed_text);
190    match parser.token() {
191        Some(Token::Identifier("run")) | Some(Token::Identifier("print")) => {
192            parser.parse_run_command(signature).map(|c| Some(c))
193        }
194        Some(_) | None => Ok(None),
195    }
196}
197
198pub struct Parser<'a> {
199    lex: Lexer<'a>,
200
201    lex_error: Option<LexError>,
202
203    /// Current lookahead token.
204    lookahead: Option<Token<'a>>,
205
206    /// Location of lookahead.
207    loc: Location,
208
209    /// Are we gathering any comments that we encounter?
210    gathering_comments: bool,
211
212    /// The gathered comments; claim them with `claim_gathered_comments`.
213    gathered_comments: Vec<&'a str>,
214
215    /// Comments collected so far.
216    comments: Vec<Comment<'a>>,
217
218    /// Maps inlined external names to a ref value, so they can be declared before parsing the rest
219    /// of the function later.
220    ///
221    /// This maintains backward compatibility with previous ways for declaring external names.
222    predeclared_external_names: PrimaryMap<UserExternalNameRef, ir::UserExternalName>,
223
224    /// Default calling conventions; used when none is specified.
225    default_calling_convention: CallConv,
226}
227
228/// Context for resolving references when parsing a single function.
229struct Context {
230    function: Function,
231    map: SourceMap,
232
233    /// Aliases to resolve once value definitions are known.
234    aliases: Vec<Value>,
235}
236
237impl Context {
238    fn new(f: Function) -> Self {
239        Self {
240            function: f,
241            map: SourceMap::new(),
242            aliases: Vec::new(),
243        }
244    }
245
246    // Allocate a new stack slot.
247    fn add_ss(&mut self, ss: StackSlot, data: StackSlotData, loc: Location) -> ParseResult<()> {
248        self.map.def_ss(ss, loc)?;
249        while self.function.sized_stack_slots.next_key().index() <= ss.index() {
250            self.function.create_sized_stack_slot(StackSlotData::new(
251                StackSlotKind::ExplicitSlot,
252                0,
253                0,
254            ));
255        }
256        self.function.sized_stack_slots[ss] = data;
257        Ok(())
258    }
259
260    // Resolve a reference to a stack slot.
261    fn check_ss(&self, ss: StackSlot, loc: Location) -> ParseResult<()> {
262        if !self.map.contains_ss(ss) {
263            err!(loc, "undefined stack slot {}", ss)
264        } else {
265            Ok(())
266        }
267    }
268
269    // Allocate a new stack slot.
270    fn add_dss(
271        &mut self,
272        ss: DynamicStackSlot,
273        data: DynamicStackSlotData,
274        loc: Location,
275    ) -> ParseResult<()> {
276        self.map.def_dss(ss, loc)?;
277        while self.function.dynamic_stack_slots.next_key().index() <= ss.index() {
278            self.function
279                .create_dynamic_stack_slot(DynamicStackSlotData::new(
280                    StackSlotKind::ExplicitDynamicSlot,
281                    data.dyn_ty,
282                ));
283        }
284        self.function.dynamic_stack_slots[ss] = data;
285        Ok(())
286    }
287
288    // Resolve a reference to a dynamic stack slot.
289    fn check_dss(&self, dss: DynamicStackSlot, loc: Location) -> ParseResult<()> {
290        if !self.map.contains_dss(dss) {
291            err!(loc, "undefined dynamic stack slot {}", dss)
292        } else {
293            Ok(())
294        }
295    }
296
297    // Allocate a new dynamic type.
298    fn add_dt(&mut self, dt: DynamicType, data: DynamicTypeData, loc: Location) -> ParseResult<()> {
299        self.map.def_dt(dt, loc)?;
300        while self.function.dfg.dynamic_types.next_key().index() <= dt.index() {
301            self.function.dfg.make_dynamic_ty(DynamicTypeData::new(
302                data.base_vector_ty,
303                data.dynamic_scale,
304            ));
305        }
306        self.function.dfg.dynamic_types[dt] = data;
307        Ok(())
308    }
309
310    // Allocate a global value slot.
311    fn add_gv(
312        &mut self,
313        gv: GlobalValue,
314        data: GlobalValueData,
315        maybe_fact: Option<Fact>,
316        loc: Location,
317    ) -> ParseResult<()> {
318        self.map.def_gv(gv, loc)?;
319        while self.function.global_values.next_key().index() <= gv.index() {
320            self.function.create_global_value(GlobalValueData::Symbol {
321                name: ExternalName::testcase(""),
322                offset: Imm64::new(0),
323                colocated: false,
324                tls: false,
325            });
326        }
327        self.function.global_values[gv] = data;
328        if let Some(fact) = maybe_fact {
329            self.function.global_value_facts[gv] = Some(fact);
330        }
331        Ok(())
332    }
333
334    // Allocate a memory-type slot.
335    fn add_mt(&mut self, mt: MemoryType, data: MemoryTypeData, loc: Location) -> ParseResult<()> {
336        self.map.def_mt(mt, loc)?;
337        while self.function.memory_types.next_key().index() <= mt.index() {
338            self.function.create_memory_type(MemoryTypeData::default());
339        }
340        self.function.memory_types[mt] = data;
341        Ok(())
342    }
343
344    // Resolve a reference to a global value.
345    fn check_gv(&self, gv: GlobalValue, loc: Location) -> ParseResult<()> {
346        if !self.map.contains_gv(gv) {
347            err!(loc, "undefined global value {}", gv)
348        } else {
349            Ok(())
350        }
351    }
352
353    // Allocate a new signature.
354    fn add_sig(
355        &mut self,
356        sig: SigRef,
357        data: Signature,
358        loc: Location,
359        defaultcc: CallConv,
360    ) -> ParseResult<()> {
361        self.map.def_sig(sig, loc)?;
362        while self.function.dfg.signatures.next_key().index() <= sig.index() {
363            self.function.import_signature(Signature::new(defaultcc));
364        }
365        self.function.dfg.signatures[sig] = data;
366        Ok(())
367    }
368
369    // Resolve a reference to a signature.
370    fn check_sig(&self, sig: SigRef, loc: Location) -> ParseResult<()> {
371        if !self.map.contains_sig(sig) {
372            err!(loc, "undefined signature {}", sig)
373        } else {
374            Ok(())
375        }
376    }
377
378    // Allocate a new external function.
379    fn add_fn(&mut self, fn_: FuncRef, data: ExtFuncData, loc: Location) -> ParseResult<()> {
380        self.map.def_fn(fn_, loc)?;
381        while self.function.dfg.ext_funcs.next_key().index() <= fn_.index() {
382            self.function.import_function(ExtFuncData {
383                name: ExternalName::testcase(""),
384                signature: SigRef::reserved_value(),
385                colocated: false,
386            });
387        }
388        self.function.dfg.ext_funcs[fn_] = data;
389        Ok(())
390    }
391
392    // Resolve a reference to a function.
393    fn check_fn(&self, fn_: FuncRef, loc: Location) -> ParseResult<()> {
394        if !self.map.contains_fn(fn_) {
395            err!(loc, "undefined function {}", fn_)
396        } else {
397            Ok(())
398        }
399    }
400
401    // Allocate a new constant.
402    fn add_constant(
403        &mut self,
404        constant: Constant,
405        data: ConstantData,
406        loc: Location,
407    ) -> ParseResult<()> {
408        self.map.def_constant(constant, loc)?;
409        self.function.dfg.constants.set(constant, data);
410        Ok(())
411    }
412
413    // Configure the stack limit of the current function.
414    fn add_stack_limit(&mut self, limit: GlobalValue, loc: Location) -> ParseResult<()> {
415        if self.function.stack_limit.is_some() {
416            return err!(loc, "stack limit defined twice");
417        }
418        self.function.stack_limit = Some(limit);
419        Ok(())
420    }
421
422    // Resolve a reference to a constant.
423    fn check_constant(&self, c: Constant, loc: Location) -> ParseResult<()> {
424        if !self.map.contains_constant(c) {
425            err!(loc, "undefined constant {}", c)
426        } else {
427            Ok(())
428        }
429    }
430
431    // Allocate a new block.
432    fn add_block(&mut self, block: Block, loc: Location) -> ParseResult<Block> {
433        self.map.def_block(block, loc)?;
434        while self.function.dfg.num_blocks() <= block.index() {
435            self.function.dfg.make_block();
436        }
437        self.function.layout.append_block(block);
438        Ok(block)
439    }
440
441    /// Set a block as cold.
442    fn set_cold_block(&mut self, block: Block) {
443        self.function.layout.set_cold(block);
444    }
445}
446
447impl<'a> Parser<'a> {
448    /// Create a new `Parser` which reads `text`. The referenced text must outlive the parser.
449    pub fn new(text: &'a str) -> Self {
450        Self {
451            lex: Lexer::new(text),
452            lex_error: None,
453            lookahead: None,
454            loc: Location { line_number: 0 },
455            gathering_comments: false,
456            gathered_comments: Vec::new(),
457            comments: Vec::new(),
458            default_calling_convention: CallConv::Fast,
459            predeclared_external_names: Default::default(),
460        }
461    }
462
463    /// Modify the default calling convention; returns a new parser with the changed calling
464    /// convention.
465    pub fn with_default_calling_convention(self, default_calling_convention: CallConv) -> Self {
466        Self {
467            default_calling_convention,
468            ..self
469        }
470    }
471
472    // Consume the current lookahead token and return it.
473    fn consume(&mut self) -> Token<'a> {
474        self.lookahead.take().expect("No token to consume")
475    }
476
477    // Consume the whole line following the current lookahead token.
478    // Return the text of the line tail.
479    fn consume_line(&mut self) -> &'a str {
480        let rest = self.lex.rest_of_line();
481        self.consume();
482        rest
483    }
484
485    // Get the current lookahead token, after making sure there is one.
486    fn token(&mut self) -> Option<Token<'a>> {
487        while self.lookahead.is_none() {
488            match self.lex.next() {
489                Some(Ok(LocatedToken { token, location })) => {
490                    match token {
491                        Token::Comment(text) => {
492                            if self.gathering_comments {
493                                self.gathered_comments.push(text);
494                            }
495                        }
496                        _ => self.lookahead = Some(token),
497                    }
498                    self.loc = location;
499                }
500                Some(Err(LocatedError { error, location })) => {
501                    self.lex_error = Some(error);
502                    self.loc = location;
503                    break;
504                }
505                None => break,
506            }
507        }
508        self.lookahead
509    }
510
511    // Enable gathering of all comments encountered.
512    fn start_gathering_comments(&mut self) {
513        debug_assert!(!self.gathering_comments);
514        self.gathering_comments = true;
515        debug_assert!(self.gathered_comments.is_empty());
516    }
517
518    // Claim the comments gathered up to the current position for the
519    // given entity.
520    fn claim_gathered_comments<E: Into<AnyEntity>>(&mut self, entity: E) {
521        debug_assert!(self.gathering_comments);
522        let entity = entity.into();
523        self.comments.extend(
524            self.gathered_comments
525                .drain(..)
526                .map(|text| Comment { entity, text }),
527        );
528        self.gathering_comments = false;
529    }
530
531    // Get the comments collected so far, clearing out the internal list.
532    fn take_comments(&mut self) -> Vec<Comment<'a>> {
533        debug_assert!(!self.gathering_comments);
534        mem::replace(&mut self.comments, Vec::new())
535    }
536
537    // Match and consume a token without payload.
538    fn match_token(&mut self, want: Token<'a>, err_msg: &str) -> ParseResult<Token<'a>> {
539        if self.token() == Some(want) {
540            Ok(self.consume())
541        } else {
542            err!(self.loc, err_msg)
543        }
544    }
545
546    // If the next token is a `want`, consume it, otherwise do nothing.
547    fn optional(&mut self, want: Token<'a>) -> bool {
548        if self.token() == Some(want) {
549            self.consume();
550            true
551        } else {
552            false
553        }
554    }
555
556    // Match and consume a specific identifier string.
557    // Used for pseudo-keywords like "stack_slot" that only appear in certain contexts.
558    fn match_identifier(&mut self, want: &'static str, err_msg: &str) -> ParseResult<Token<'a>> {
559        if self.token() == Some(Token::Identifier(want)) {
560            Ok(self.consume())
561        } else {
562            err!(self.loc, err_msg)
563        }
564    }
565
566    // Match and consume a type.
567    fn match_type(&mut self, err_msg: &str) -> ParseResult<Type> {
568        if let Some(Token::Type(t)) = self.token() {
569            self.consume();
570            Ok(t)
571        } else {
572            err!(self.loc, err_msg)
573        }
574    }
575
576    // Match and consume a stack slot reference.
577    fn match_ss(&mut self, err_msg: &str) -> ParseResult<StackSlot> {
578        if let Some(Token::StackSlot(ss)) = self.token() {
579            self.consume();
580            if let Some(ss) = StackSlot::with_number(ss) {
581                return Ok(ss);
582            }
583        }
584        err!(self.loc, err_msg)
585    }
586
587    // Match and consume a dynamic stack slot reference.
588    fn match_dss(&mut self, err_msg: &str) -> ParseResult<DynamicStackSlot> {
589        if let Some(Token::DynamicStackSlot(ss)) = self.token() {
590            self.consume();
591            if let Some(ss) = DynamicStackSlot::with_number(ss) {
592                return Ok(ss);
593            }
594        }
595        err!(self.loc, err_msg)
596    }
597
598    // Match and consume a dynamic type reference.
599    fn match_dt(&mut self, err_msg: &str) -> ParseResult<DynamicType> {
600        if let Some(Token::DynamicType(dt)) = self.token() {
601            self.consume();
602            if let Some(dt) = DynamicType::with_number(dt) {
603                return Ok(dt);
604            }
605        }
606        err!(self.loc, err_msg)
607    }
608
609    // Extract Type from DynamicType
610    fn concrete_from_dt(&mut self, dt: DynamicType, ctx: &mut Context) -> Option<Type> {
611        ctx.function.get_concrete_dynamic_ty(dt)
612    }
613
614    // Match and consume a global value reference.
615    fn match_gv(&mut self, err_msg: &str) -> ParseResult<GlobalValue> {
616        if let Some(Token::GlobalValue(gv)) = self.token() {
617            self.consume();
618            if let Some(gv) = GlobalValue::with_number(gv) {
619                return Ok(gv);
620            }
621        }
622        err!(self.loc, err_msg)
623    }
624
625    // Match and consume a function reference.
626    fn match_fn(&mut self, err_msg: &str) -> ParseResult<FuncRef> {
627        if let Some(Token::FuncRef(fnref)) = self.token() {
628            self.consume();
629            if let Some(fnref) = FuncRef::with_number(fnref) {
630                return Ok(fnref);
631            }
632        }
633        err!(self.loc, err_msg)
634    }
635
636    // Match and consume a signature reference.
637    fn match_sig(&mut self, err_msg: &str) -> ParseResult<SigRef> {
638        if let Some(Token::SigRef(sigref)) = self.token() {
639            self.consume();
640            if let Some(sigref) = SigRef::with_number(sigref) {
641                return Ok(sigref);
642            }
643        }
644        err!(self.loc, err_msg)
645    }
646
647    // Match and consume a memory-type reference.
648    fn match_mt(&mut self, err_msg: &str) -> ParseResult<MemoryType> {
649        if let Some(Token::MemoryType(mt)) = self.token() {
650            self.consume();
651            if let Some(mt) = MemoryType::with_number(mt) {
652                return Ok(mt);
653            }
654        }
655        err!(self.loc, err_msg)
656    }
657
658    // Match and consume a constant reference.
659    fn match_constant(&mut self) -> ParseResult<Constant> {
660        if let Some(Token::Constant(c)) = self.token() {
661            self.consume();
662            if let Some(c) = Constant::with_number(c) {
663                return Ok(c);
664            }
665        }
666        err!(self.loc, "expected constant number: const«n»")
667    }
668
669    // Match and consume a stack limit token
670    fn match_stack_limit(&mut self) -> ParseResult<()> {
671        if let Some(Token::Identifier("stack_limit")) = self.token() {
672            self.consume();
673            return Ok(());
674        }
675        err!(self.loc, "expected identifier: stack_limit")
676    }
677
678    // Match and consume a block reference.
679    fn match_block(&mut self, err_msg: &str) -> ParseResult<Block> {
680        if let Some(Token::Block(block)) = self.token() {
681            self.consume();
682            Ok(block)
683        } else {
684            err!(self.loc, err_msg)
685        }
686    }
687
688    // Match and consume a value reference.
689    fn match_value(&mut self, err_msg: &str) -> ParseResult<Value> {
690        if let Some(Token::Value(v)) = self.token() {
691            self.consume();
692            Ok(v)
693        } else {
694            err!(self.loc, err_msg)
695        }
696    }
697
698    fn error(&self, message: &str) -> ParseError {
699        ParseError {
700            location: self.loc,
701            message: message.to_string(),
702            is_warning: false,
703        }
704    }
705
706    // Match and consume an Imm64 immediate.
707    fn match_imm64(&mut self, err_msg: &str) -> ParseResult<Imm64> {
708        if let Some(Token::Integer(text)) = self.token() {
709            self.consume();
710            // Lexer just gives us raw text that looks like an integer.
711            // Parse it as an Imm64 to check for overflow and other issues.
712            text.parse().map_err(|e| self.error(e))
713        } else {
714            err!(self.loc, err_msg)
715        }
716    }
717
718    // Match and consume a hexadeximal immediate
719    fn match_hexadecimal_constant(&mut self, err_msg: &str) -> ParseResult<ConstantData> {
720        if let Some(Token::Integer(text)) = self.token() {
721            self.consume();
722            text.parse().map_err(|e| {
723                self.error(&format!(
724                    "expected hexadecimal immediate, failed to parse: {e}"
725                ))
726            })
727        } else {
728            err!(self.loc, err_msg)
729        }
730    }
731
732    // Match and consume either a hexadecimal Uimm128 immediate (e.g. 0x000102...) or its literal
733    // list form (e.g. [0 1 2...]). For convenience, since uimm128 values are stored in the
734    // `ConstantPool`, this returns `ConstantData`.
735    fn match_uimm128(&mut self, controlling_type: Type) -> ParseResult<ConstantData> {
736        let expected_size = controlling_type.bytes() as usize;
737        let constant_data = if self.optional(Token::LBracket) {
738            // parse using a list of values, e.g. vconst.i32x4 [0 1 2 3]
739            let uimm128 = self.parse_literals_to_constant_data(controlling_type)?;
740            self.match_token(Token::RBracket, "expected a terminating right bracket")?;
741            uimm128
742        } else {
743            // parse using a hexadecimal value, e.g. 0x000102...
744            let uimm128 =
745                self.match_hexadecimal_constant("expected an immediate hexadecimal operand")?;
746            uimm128.expand_to(expected_size)
747        };
748
749        if constant_data.len() == expected_size {
750            Ok(constant_data)
751        } else {
752            Err(self.error(&format!(
753                "expected parsed constant to have {expected_size} bytes"
754            )))
755        }
756    }
757
758    // Match and consume a Uimm64 immediate.
759    fn match_uimm64(&mut self, err_msg: &str) -> ParseResult<Uimm64> {
760        if let Some(Token::Integer(text)) = self.token() {
761            self.consume();
762            // Lexer just gives us raw text that looks like an integer.
763            // Parse it as an Uimm64 to check for overflow and other issues.
764            text.parse()
765                .map_err(|_| self.error("expected u64 decimal immediate"))
766        } else {
767            err!(self.loc, err_msg)
768        }
769    }
770
771    // Match and consume a Uimm32 immediate.
772    fn match_uimm32(&mut self, err_msg: &str) -> ParseResult<Uimm32> {
773        if let Some(Token::Integer(text)) = self.token() {
774            self.consume();
775            // Lexer just gives us raw text that looks like an integer.
776            // Parse it as an Uimm32 to check for overflow and other issues.
777            text.parse().map_err(|e| self.error(e))
778        } else {
779            err!(self.loc, err_msg)
780        }
781    }
782
783    // Match and consume a u8 immediate.
784    // This is used for lane numbers in SIMD vectors.
785    fn match_uimm8(&mut self, err_msg: &str) -> ParseResult<u8> {
786        if let Some(Token::Integer(text)) = self.token() {
787            self.consume();
788            // Lexer just gives us raw text that looks like an integer.
789            if let Some(num) = text.strip_prefix("0x") {
790                // Parse it as a u8 in hexadecimal form.
791                u8::from_str_radix(num, 16)
792                    .map_err(|_| self.error("unable to parse u8 as a hexadecimal immediate"))
793            } else {
794                // Parse it as a u8 to check for overflow and other issues.
795                text.parse()
796                    .map_err(|_| self.error("expected u8 decimal immediate"))
797            }
798        } else {
799            err!(self.loc, err_msg)
800        }
801    }
802
803    // Match and consume an i8 immediate.
804    fn match_imm8(&mut self, err_msg: &str) -> ParseResult<i8> {
805        match_imm!(i8, u8, self, err_msg)
806    }
807
808    // Match and consume a signed 16-bit immediate.
809    fn match_imm16(&mut self, err_msg: &str) -> ParseResult<i16> {
810        match_imm!(i16, u16, self, err_msg)
811    }
812
813    // Match and consume an i32 immediate.
814    // This is used for stack argument byte offsets.
815    fn match_imm32(&mut self, err_msg: &str) -> ParseResult<i32> {
816        match_imm!(i32, u32, self, err_msg)
817    }
818
819    // Match and consume an i128 immediate.
820    fn match_imm128(&mut self, err_msg: &str) -> ParseResult<i128> {
821        match_imm!(i128, u128, self, err_msg)
822    }
823
824    // Match and consume an optional offset32 immediate.
825    //
826    // Note that this will match an empty string as an empty offset, and that if an offset is
827    // present, it must contain a sign.
828    fn optional_offset32(&mut self) -> ParseResult<Offset32> {
829        if let Some(Token::Integer(text)) = self.token() {
830            if text.starts_with('+') || text.starts_with('-') {
831                self.consume();
832                // Lexer just gives us raw text that looks like an integer.
833                // Parse it as an `Offset32` to check for overflow and other issues.
834                return text.parse().map_err(|e| self.error(e));
835            }
836        }
837        // An offset32 operand can be absent.
838        Ok(Offset32::new(0))
839    }
840
841    // Match and consume an optional offset32 immediate.
842    //
843    // Note that this will match an empty string as an empty offset, and that if an offset is
844    // present, it must contain a sign.
845    fn optional_offset_imm64(&mut self) -> ParseResult<Imm64> {
846        if let Some(Token::Integer(text)) = self.token() {
847            if text.starts_with('+') || text.starts_with('-') {
848                self.consume();
849                // Lexer just gives us raw text that looks like an integer.
850                // Parse it as an `Offset32` to check for overflow and other issues.
851                return text.parse().map_err(|e| self.error(e));
852            }
853        }
854        // If no explicit offset is present, the offset is 0.
855        Ok(Imm64::new(0))
856    }
857
858    // Match and consume an Ieee16 immediate.
859    fn match_ieee16(&mut self, err_msg: &str) -> ParseResult<Ieee16> {
860        if let Some(Token::Float(text)) = self.token() {
861            self.consume();
862            // Lexer just gives us raw text that looks like a float.
863            // Parse it as an Ieee16 to check for the right number of digits and other issues.
864            text.parse().map_err(|e| self.error(e))
865        } else {
866            err!(self.loc, err_msg)
867        }
868    }
869
870    // Match and consume an Ieee32 immediate.
871    fn match_ieee32(&mut self, err_msg: &str) -> ParseResult<Ieee32> {
872        if let Some(Token::Float(text)) = self.token() {
873            self.consume();
874            // Lexer just gives us raw text that looks like a float.
875            // Parse it as an Ieee32 to check for the right number of digits and other issues.
876            text.parse().map_err(|e| self.error(e))
877        } else {
878            err!(self.loc, err_msg)
879        }
880    }
881
882    // Match and consume an Ieee64 immediate.
883    fn match_ieee64(&mut self, err_msg: &str) -> ParseResult<Ieee64> {
884        if let Some(Token::Float(text)) = self.token() {
885            self.consume();
886            // Lexer just gives us raw text that looks like a float.
887            // Parse it as an Ieee64 to check for the right number of digits and other issues.
888            text.parse().map_err(|e| self.error(e))
889        } else {
890            err!(self.loc, err_msg)
891        }
892    }
893
894    // Match and consume an Ieee128 immediate.
895    fn match_ieee128(&mut self, err_msg: &str) -> ParseResult<Ieee128> {
896        if let Some(Token::Float(text)) = self.token() {
897            self.consume();
898            // Lexer just gives us raw text that looks like a float.
899            // Parse it as an Ieee128 to check for the right number of digits and other issues.
900            text.parse().map_err(|e| self.error(e))
901        } else {
902            err!(self.loc, err_msg)
903        }
904    }
905
906    // Match and consume an enumerated immediate, like one of the condition codes.
907    fn match_enum<T: FromStr>(&mut self, err_msg: &str) -> ParseResult<T> {
908        if let Some(Token::Identifier(text)) = self.token() {
909            self.consume();
910            text.parse().map_err(|_| self.error(err_msg))
911        } else {
912            err!(self.loc, err_msg)
913        }
914    }
915
916    // Match and a consume a possibly empty sequence of memory operation flags.
917    fn optional_memflags(&mut self) -> ParseResult<MemFlags> {
918        let mut flags = MemFlags::new();
919        while let Some(Token::Identifier(text)) = self.token() {
920            match flags.set_by_name(text) {
921                Ok(true) => {
922                    self.consume();
923                }
924                Ok(false) => break,
925                Err(msg) => return err!(self.loc, msg),
926            }
927        }
928        Ok(flags)
929    }
930
931    // Match and consume an identifier.
932    fn match_any_identifier(&mut self, err_msg: &str) -> ParseResult<&'a str> {
933        if let Some(Token::Identifier(text)) = self.token() {
934            self.consume();
935            Ok(text)
936        } else {
937            err!(self.loc, err_msg)
938        }
939    }
940
941    /// Parse an optional source location.
942    ///
943    /// Return an optional source location if no real location is present.
944    fn optional_srcloc(&mut self) -> ParseResult<ir::SourceLoc> {
945        if let Some(Token::SourceLoc(text)) = self.token() {
946            match u32::from_str_radix(text, 16) {
947                Ok(num) => {
948                    self.consume();
949                    Ok(ir::SourceLoc::new(num))
950                }
951                Err(_) => return err!(self.loc, "invalid source location: {}", text),
952            }
953        } else {
954            Ok(Default::default())
955        }
956    }
957
958    /// Parse a list of literals (i.e. integers, floats, booleans); e.g. `0 1 2 3`, usually as
959    /// part of something like `vconst.i32x4 [0 1 2 3]`.
960    fn parse_literals_to_constant_data(&mut self, ty: Type) -> ParseResult<ConstantData> {
961        macro_rules! consume {
962            ( $ty:ident, $match_fn:expr ) => {{
963                assert!($ty.is_vector());
964                let mut data = ConstantData::default();
965                for _ in 0..$ty.lane_count() {
966                    data = data.append($match_fn);
967                }
968                data
969            }};
970        }
971
972        if !ty.is_vector() && !ty.is_dynamic_vector() {
973            err!(self.loc, "Expected a controlling vector type, not {}", ty)
974        } else {
975            let constant_data = match ty.lane_type() {
976                I8 => consume!(ty, self.match_imm8("Expected an 8-bit integer")?),
977                I16 => consume!(ty, self.match_imm16("Expected a 16-bit integer")?),
978                I32 => consume!(ty, self.match_imm32("Expected a 32-bit integer")?),
979                I64 => consume!(ty, self.match_imm64("Expected a 64-bit integer")?),
980                F32 => consume!(ty, self.match_ieee32("Expected a 32-bit float")?),
981                F64 => consume!(ty, self.match_ieee64("Expected a 64-bit float")?),
982                _ => return err!(self.loc, "Expected a type of: float, int, bool"),
983            };
984            Ok(constant_data)
985        }
986    }
987
988    /// Parse a list of test command passes specified in command line.
989    pub fn parse_cmdline_passes(&mut self, passes: &'a [String]) -> Vec<TestCommand<'a>> {
990        let mut list = Vec::new();
991        for pass in passes {
992            list.push(TestCommand::new(pass));
993        }
994        list
995    }
996
997    /// Parse a list of test commands.
998    pub fn parse_test_commands(&mut self) -> Vec<TestCommand<'a>> {
999        let mut list = Vec::new();
1000        while self.token() == Some(Token::Identifier("test")) {
1001            list.push(TestCommand::new(self.consume_line()));
1002        }
1003        list
1004    }
1005
1006    /// Parse a target spec.
1007    ///
1008    /// Accept the target from the command line for pass command.
1009    ///
1010    fn parse_cmdline_target(&mut self, target_pass: Option<&str>) -> ParseResult<isaspec::IsaSpec> {
1011        // Were there any `target` commands specified?
1012        let mut specified_target = false;
1013
1014        let mut targets = Vec::new();
1015        let flag_builder = settings::builder();
1016
1017        if let Some(targ) = target_pass {
1018            let loc = self.loc;
1019            let triple = match Triple::from_str(targ) {
1020                Ok(triple) => triple,
1021                Err(err) => return err!(loc, err),
1022            };
1023            let isa_builder = match isa::lookup(triple) {
1024                Err(isa::LookupError::SupportDisabled) => {
1025                    return err!(loc, "support disabled target '{}'", targ);
1026                }
1027                Err(isa::LookupError::Unsupported) => {
1028                    return warn!(loc, "unsupported target '{}'", targ);
1029                }
1030                Ok(b) => b,
1031            };
1032            specified_target = true;
1033
1034            // Construct a trait object with the aggregate settings.
1035            targets.push(
1036                isa_builder
1037                    .finish(settings::Flags::new(flag_builder.clone()))
1038                    .map_err(|e| ParseError {
1039                        location: loc,
1040                        message: format!("invalid ISA flags for '{targ}': {e:?}"),
1041                        is_warning: false,
1042                    })?,
1043            );
1044        }
1045
1046        if !specified_target {
1047            // No `target` commands.
1048            Ok(isaspec::IsaSpec::None(settings::Flags::new(flag_builder)))
1049        } else {
1050            Ok(isaspec::IsaSpec::Some(targets))
1051        }
1052    }
1053
1054    /// Parse a list of target specs.
1055    ///
1056    /// Accept a mix of `target` and `set` command lines. The `set` commands are cumulative.
1057    ///
1058    fn parse_target_specs(&mut self, options: &ParseOptions) -> ParseResult<isaspec::IsaSpec> {
1059        // Were there any `target` commands?
1060        let mut seen_target = false;
1061        // Location of last `set` command since the last `target`.
1062        let mut last_set_loc = None;
1063
1064        let mut targets = Vec::new();
1065        let mut flag_builder = settings::builder();
1066
1067        let bool_to_str = |val: bool| {
1068            if val {
1069                "true"
1070            } else {
1071                "false"
1072            }
1073        };
1074
1075        // default to enabling cfg info
1076        flag_builder
1077            .set(
1078                "machine_code_cfg_info",
1079                bool_to_str(options.machine_code_cfg_info),
1080            )
1081            .expect("machine_code_cfg_info option should be present");
1082
1083        flag_builder
1084            .set("unwind_info", bool_to_str(options.unwind_info))
1085            .expect("unwind_info option should be present");
1086
1087        while let Some(Token::Identifier(command)) = self.token() {
1088            match command {
1089                "set" => {
1090                    last_set_loc = Some(self.loc);
1091                    isaspec::parse_options(
1092                        self.consume_line().trim().split_whitespace(),
1093                        &mut flag_builder,
1094                        self.loc,
1095                    )
1096                    .map_err(|err| ParseError::from(err))?;
1097                }
1098                "target" => {
1099                    let loc = self.loc;
1100                    // Grab the whole line so the lexer won't go looking for tokens on the
1101                    // following lines.
1102                    let mut words = self.consume_line().trim().split_whitespace().peekable();
1103                    // Look for `target foo`.
1104                    let target_name = match words.next() {
1105                        Some(w) => w,
1106                        None => return err!(loc, "expected target triple"),
1107                    };
1108                    let triple = match Triple::from_str(target_name) {
1109                        Ok(triple) => triple,
1110                        Err(err) => return err!(loc, err),
1111                    };
1112                    let mut isa_builder = match isa::lookup(triple) {
1113                        Err(isa::LookupError::SupportDisabled) => {
1114                            continue;
1115                        }
1116                        Err(isa::LookupError::Unsupported) => {
1117                            return warn!(loc, "unsupported target '{}'", target_name);
1118                        }
1119                        Ok(b) => b,
1120                    };
1121                    last_set_loc = None;
1122                    seen_target = true;
1123                    // Apply the target-specific settings to `isa_builder`.
1124                    isaspec::parse_options(words, &mut isa_builder, self.loc)?;
1125
1126                    // Construct a trait object with the aggregate settings.
1127                    targets.push(
1128                        isa_builder
1129                            .finish(settings::Flags::new(flag_builder.clone()))
1130                            .map_err(|e| ParseError {
1131                                location: loc,
1132                                message: format!("invalid ISA flags for '{target_name}': {e:?}"),
1133                                is_warning: false,
1134                            })?,
1135                    );
1136                }
1137                _ => break,
1138            }
1139        }
1140
1141        if !seen_target {
1142            // No `target` commands, but we allow for `set` commands.
1143            Ok(isaspec::IsaSpec::None(settings::Flags::new(flag_builder)))
1144        } else if let Some(loc) = last_set_loc {
1145            err!(
1146                loc,
1147                "dangling 'set' command after ISA specification has no effect."
1148            )
1149        } else {
1150            Ok(isaspec::IsaSpec::Some(targets))
1151        }
1152    }
1153
1154    /// Parse a list of expected features that Cranelift should be compiled with, or without.
1155    pub fn parse_cranelift_features(&mut self) -> ParseResult<Vec<Feature<'a>>> {
1156        let mut list = Vec::new();
1157        while self.token() == Some(Token::Identifier("feature")) {
1158            self.consume();
1159            let has = !self.optional(Token::Bang);
1160            match (self.token(), has) {
1161                (Some(Token::String(flag)), true) => list.push(Feature::With(flag)),
1162                (Some(Token::String(flag)), false) => list.push(Feature::Without(flag)),
1163                (tok, _) => {
1164                    return err!(
1165                        self.loc,
1166                        format!("Expected feature flag string, got {:?}", tok)
1167                    )
1168                }
1169            }
1170            self.consume();
1171        }
1172        Ok(list)
1173    }
1174
1175    /// Parse a list of function definitions.
1176    ///
1177    /// This is the top-level parse function matching the whole contents of a file.
1178    pub fn parse_function_list(&mut self) -> ParseResult<Vec<(Function, Details<'a>)>> {
1179        let mut list = Vec::new();
1180        while self.token().is_some() {
1181            list.push(self.parse_function()?);
1182        }
1183        if let Some(err) = self.lex_error {
1184            return match err {
1185                LexError::InvalidChar => err!(self.loc, "invalid character"),
1186            };
1187        }
1188        Ok(list)
1189    }
1190
1191    // Parse a whole function definition.
1192    //
1193    // function ::= * "function" name signature "{" preamble function-body "}"
1194    //
1195    fn parse_function(&mut self) -> ParseResult<(Function, Details<'a>)> {
1196        // Begin gathering comments.
1197        // Make sure we don't include any comments before the `function` keyword.
1198        self.token();
1199        debug_assert!(self.comments.is_empty());
1200        self.start_gathering_comments();
1201
1202        self.match_identifier("function", "expected 'function'")?;
1203
1204        let location = self.loc;
1205
1206        // function ::= "function" * name signature "{" preamble function-body "}"
1207        let name = self.parse_user_func_name()?;
1208
1209        // function ::= "function" name * signature "{" preamble function-body "}"
1210        let sig = self.parse_signature()?;
1211
1212        let mut ctx = Context::new(Function::with_name_signature(name, sig));
1213
1214        // function ::= "function" name signature * "{" preamble function-body "}"
1215        self.match_token(Token::LBrace, "expected '{' before function body")?;
1216
1217        self.token();
1218        self.claim_gathered_comments(AnyEntity::Function);
1219
1220        // function ::= "function" name signature "{" * preamble function-body "}"
1221        self.parse_preamble(&mut ctx)?;
1222        // function ::= "function" name signature "{"  preamble * function-body "}"
1223        self.parse_function_body(&mut ctx)?;
1224        // function ::= "function" name signature "{" preamble function-body * "}"
1225        self.match_token(Token::RBrace, "expected '}' after function body")?;
1226
1227        // Collect any comments following the end of the function, then stop gathering comments.
1228        self.start_gathering_comments();
1229        self.token();
1230        self.claim_gathered_comments(AnyEntity::Function);
1231
1232        // Claim all the declared user-defined function names.
1233        for (user_func_ref, user_external_name) in
1234            std::mem::take(&mut self.predeclared_external_names)
1235        {
1236            let actual_ref = ctx
1237                .function
1238                .declare_imported_user_function(user_external_name);
1239            assert_eq!(user_func_ref, actual_ref);
1240        }
1241
1242        let details = Details {
1243            location,
1244            comments: self.take_comments(),
1245            map: ctx.map,
1246        };
1247
1248        Ok((ctx.function, details))
1249    }
1250
1251    // Parse a user-defined function name
1252    //
1253    // For example, in a function decl, the parser would be in this state:
1254    //
1255    // function ::= "function" * name signature { ... }
1256    //
1257    fn parse_user_func_name(&mut self) -> ParseResult<UserFuncName> {
1258        match self.token() {
1259            Some(Token::Name(s)) => {
1260                self.consume();
1261                Ok(UserFuncName::testcase(s))
1262            }
1263            Some(Token::UserRef(namespace)) => {
1264                self.consume();
1265                match self.token() {
1266                    Some(Token::Colon) => {
1267                        self.consume();
1268                        match self.token() {
1269                            Some(Token::Integer(index_str)) => {
1270                                self.consume();
1271                                let index: u32 =
1272                                    u32::from_str_radix(index_str, 10).map_err(|_| {
1273                                        self.error("the integer given overflows the u32 type")
1274                                    })?;
1275                                Ok(UserFuncName::user(namespace, index))
1276                            }
1277                            _ => err!(self.loc, "expected integer"),
1278                        }
1279                    }
1280                    _ => {
1281                        err!(self.loc, "expected user function name in the form uX:Y")
1282                    }
1283                }
1284            }
1285            _ => err!(self.loc, "expected external name"),
1286        }
1287    }
1288
1289    // Parse an external name.
1290    //
1291    // For example, in a function reference decl, the parser would be in this state:
1292    //
1293    // fn0 = * name signature
1294    //
1295    fn parse_external_name(&mut self) -> ParseResult<ExternalName> {
1296        match self.token() {
1297            Some(Token::Name(s)) => {
1298                self.consume();
1299                s.parse()
1300                    .map_err(|_| self.error("invalid test case or libcall name"))
1301            }
1302
1303            Some(Token::UserNameRef(name_ref)) => {
1304                self.consume();
1305                Ok(ExternalName::user(UserExternalNameRef::new(
1306                    name_ref as usize,
1307                )))
1308            }
1309
1310            Some(Token::UserRef(namespace)) => {
1311                self.consume();
1312                if let Some(Token::Colon) = self.token() {
1313                    self.consume();
1314                    match self.token() {
1315                        Some(Token::Integer(index_str)) => {
1316                            let index: u32 = u32::from_str_radix(index_str, 10).map_err(|_| {
1317                                self.error("the integer given overflows the u32 type")
1318                            })?;
1319                            self.consume();
1320
1321                            // Deduplicate the reference (O(n), but should be fine for tests),
1322                            // to follow `FunctionParameters::declare_imported_user_function`,
1323                            // otherwise this will cause ref mismatches when asserted below.
1324                            let name_ref = self
1325                                .predeclared_external_names
1326                                .iter()
1327                                .find_map(|(reff, name)| {
1328                                    if name.index == index && name.namespace == namespace {
1329                                        Some(reff)
1330                                    } else {
1331                                        None
1332                                    }
1333                                })
1334                                .unwrap_or_else(|| {
1335                                    self.predeclared_external_names
1336                                        .push(ir::UserExternalName { namespace, index })
1337                                });
1338
1339                            Ok(ExternalName::user(name_ref))
1340                        }
1341                        _ => err!(self.loc, "expected integer"),
1342                    }
1343                } else {
1344                    err!(self.loc, "expected colon")
1345                }
1346            }
1347
1348            _ => err!(self.loc, "expected external name"),
1349        }
1350    }
1351
1352    // Parse a function signature.
1353    //
1354    // signature ::=  * "(" [paramlist] ")" ["->" retlist] [callconv]
1355    //
1356    fn parse_signature(&mut self) -> ParseResult<Signature> {
1357        // Calling convention defaults to `fast`, but can be changed.
1358        let mut sig = Signature::new(self.default_calling_convention);
1359
1360        self.match_token(Token::LPar, "expected function signature: ( args... )")?;
1361        // signature ::=  "(" * [abi-param-list] ")" ["->" retlist] [callconv]
1362        if self.token() != Some(Token::RPar) {
1363            sig.params = self.parse_abi_param_list()?;
1364        }
1365        self.match_token(Token::RPar, "expected ')' after function arguments")?;
1366        if self.optional(Token::Arrow) {
1367            sig.returns = self.parse_abi_param_list()?;
1368        }
1369
1370        // The calling convention is optional.
1371        match self.token() {
1372            Some(Token::Identifier(text)) => match text.parse() {
1373                Ok(cc) => {
1374                    self.consume();
1375                    sig.call_conv = cc;
1376                }
1377                _ => return err!(self.loc, "unknown calling convention: {}", text),
1378            },
1379
1380            Some(Token::Cold) => {
1381                self.consume();
1382                sig.call_conv = CallConv::Cold;
1383            }
1384            _ => {}
1385        }
1386
1387        Ok(sig)
1388    }
1389
1390    // Parse list of function parameter / return value types.
1391    //
1392    // paramlist ::= * param { "," param }
1393    //
1394    fn parse_abi_param_list(&mut self) -> ParseResult<Vec<AbiParam>> {
1395        let mut list = Vec::new();
1396
1397        // abi-param-list ::= * abi-param { "," abi-param }
1398        list.push(self.parse_abi_param()?);
1399
1400        // abi-param-list ::= abi-param * { "," abi-param }
1401        while self.optional(Token::Comma) {
1402            // abi-param-list ::= abi-param { "," * abi-param }
1403            list.push(self.parse_abi_param()?);
1404        }
1405
1406        Ok(list)
1407    }
1408
1409    // Parse a single argument type with flags.
1410    fn parse_abi_param(&mut self) -> ParseResult<AbiParam> {
1411        // abi-param ::= * type { flag }
1412        let mut arg = AbiParam::new(self.match_type("expected parameter type")?);
1413
1414        // abi-param ::= type * { flag }
1415        while let Some(Token::Identifier(s)) = self.token() {
1416            match s {
1417                "uext" => arg.extension = ArgumentExtension::Uext,
1418                "sext" => arg.extension = ArgumentExtension::Sext,
1419                "sarg" => {
1420                    self.consume();
1421                    self.match_token(Token::LPar, "expected '(' to begin sarg size")?;
1422                    let size = self.match_uimm32("expected byte-size in sarg decl")?;
1423                    self.match_token(Token::RPar, "expected ')' to end sarg size")?;
1424                    arg.purpose = ArgumentPurpose::StructArgument(size.into());
1425                    continue;
1426                }
1427                _ => {
1428                    if let Ok(purpose) = s.parse() {
1429                        arg.purpose = purpose;
1430                    } else {
1431                        break;
1432                    }
1433                }
1434            }
1435            self.consume();
1436        }
1437
1438        Ok(arg)
1439    }
1440
1441    // Parse the function preamble.
1442    //
1443    // preamble      ::= * { preamble-decl }
1444    // preamble-decl ::= * stack-slot-decl
1445    //                   * function-decl
1446    //                   * signature-decl
1447    //                   * jump-table-decl
1448    //                   * stack-limit-decl
1449    //
1450    // The parsed decls are added to `ctx` rather than returned.
1451    fn parse_preamble(&mut self, ctx: &mut Context) -> ParseResult<()> {
1452        loop {
1453            match self.token() {
1454                Some(Token::StackSlot(..)) => {
1455                    self.start_gathering_comments();
1456                    let loc = self.loc;
1457                    self.parse_stack_slot_decl()
1458                        .and_then(|(ss, dat)| ctx.add_ss(ss, dat, loc))
1459                }
1460                Some(Token::DynamicStackSlot(..)) => {
1461                    self.start_gathering_comments();
1462                    let loc = self.loc;
1463                    self.parse_dynamic_stack_slot_decl()
1464                        .and_then(|(dss, dat)| ctx.add_dss(dss, dat, loc))
1465                }
1466                Some(Token::DynamicType(..)) => {
1467                    self.start_gathering_comments();
1468                    let loc = self.loc;
1469                    self.parse_dynamic_type_decl()
1470                        .and_then(|(dt, dat)| ctx.add_dt(dt, dat, loc))
1471                }
1472                Some(Token::GlobalValue(..)) => {
1473                    self.start_gathering_comments();
1474                    self.parse_global_value_decl()
1475                        .and_then(|(gv, dat, maybe_fact)| ctx.add_gv(gv, dat, maybe_fact, self.loc))
1476                }
1477                Some(Token::MemoryType(..)) => {
1478                    self.start_gathering_comments();
1479                    self.parse_memory_type_decl()
1480                        .and_then(|(mt, dat)| ctx.add_mt(mt, dat, self.loc))
1481                }
1482                Some(Token::SigRef(..)) => {
1483                    self.start_gathering_comments();
1484                    self.parse_signature_decl().and_then(|(sig, dat)| {
1485                        ctx.add_sig(sig, dat, self.loc, self.default_calling_convention)
1486                    })
1487                }
1488                Some(Token::FuncRef(..)) => {
1489                    self.start_gathering_comments();
1490                    self.parse_function_decl(ctx)
1491                        .and_then(|(fn_, dat)| ctx.add_fn(fn_, dat, self.loc))
1492                }
1493                Some(Token::Constant(..)) => {
1494                    self.start_gathering_comments();
1495                    self.parse_constant_decl()
1496                        .and_then(|(c, v)| ctx.add_constant(c, v, self.loc))
1497                }
1498                Some(Token::Identifier("stack_limit")) => {
1499                    self.start_gathering_comments();
1500                    self.parse_stack_limit_decl()
1501                        .and_then(|gv| ctx.add_stack_limit(gv, self.loc))
1502                }
1503                // More to come..
1504                _ => return Ok(()),
1505            }?;
1506        }
1507    }
1508
1509    // Parse a stack slot decl.
1510    //
1511    // stack-slot-decl ::= * StackSlot(ss) "=" stack-slot-kind Bytes {"," stack-slot-flag}
1512    // stack-slot-kind ::= "explicit_slot"
1513    //                   | "spill_slot"
1514    //                   | "incoming_arg"
1515    //                   | "outgoing_arg"
1516    // stack-slot-flag ::= "align" "=" Bytes
1517    fn parse_stack_slot_decl(&mut self) -> ParseResult<(StackSlot, StackSlotData)> {
1518        let ss = self.match_ss("expected stack slot number: ss«n»")?;
1519        self.match_token(Token::Equal, "expected '=' in stack slot declaration")?;
1520        let kind = self.match_enum("expected stack slot kind")?;
1521
1522        // stack-slot-decl ::= StackSlot(ss) "=" stack-slot-kind * Bytes {"," stack-slot-flag}
1523        let bytes: i64 = self
1524            .match_imm64("expected byte-size in stack_slot decl")?
1525            .into();
1526        if bytes < 0 {
1527            return err!(self.loc, "negative stack slot size");
1528        }
1529        if bytes > i64::from(u32::MAX) {
1530            return err!(self.loc, "stack slot too large");
1531        }
1532
1533        // Parse flags.
1534        let align = if self.token() == Some(Token::Comma) {
1535            self.consume();
1536            self.match_token(
1537                Token::Identifier("align"),
1538                "expected a valid stack-slot flag (currently only `align`)",
1539            )?;
1540            self.match_token(Token::Equal, "expected `=` after flag")?;
1541            let align: i64 = self
1542                .match_imm64("expected alignment-size after `align` flag")?
1543                .into();
1544            u32::try_from(align)
1545                .map_err(|_| self.error("alignment must be a 32-bit unsigned integer"))?
1546        } else {
1547            1
1548        };
1549
1550        if !align.is_power_of_two() {
1551            return err!(self.loc, "stack slot alignment is not a power of two");
1552        }
1553        let align_shift = u8::try_from(align.ilog2()).unwrap(); // Always succeeds: range 0..=31.
1554
1555        let data = StackSlotData::new(kind, bytes as u32, align_shift);
1556
1557        // Collect any trailing comments.
1558        self.token();
1559        self.claim_gathered_comments(ss);
1560
1561        // TBD: stack-slot-decl ::= StackSlot(ss) "=" stack-slot-kind Bytes * {"," stack-slot-flag}
1562        Ok((ss, data))
1563    }
1564
1565    fn parse_dynamic_stack_slot_decl(
1566        &mut self,
1567    ) -> ParseResult<(DynamicStackSlot, DynamicStackSlotData)> {
1568        let dss = self.match_dss("expected stack slot number: dss«n»")?;
1569        self.match_token(Token::Equal, "expected '=' in stack slot declaration")?;
1570        let kind = self.match_enum("expected stack slot kind")?;
1571        let dt = self.match_dt("expected dynamic type")?;
1572        let data = DynamicStackSlotData::new(kind, dt);
1573        // Collect any trailing comments.
1574        self.token();
1575        self.claim_gathered_comments(dss);
1576
1577        // TBD: stack-slot-decl ::= StackSlot(ss) "=" stack-slot-kind Bytes * {"," stack-slot-flag}
1578        Ok((dss, data))
1579    }
1580
1581    fn parse_dynamic_type_decl(&mut self) -> ParseResult<(DynamicType, DynamicTypeData)> {
1582        let dt = self.match_dt("expected dynamic type number: dt«n»")?;
1583        self.match_token(Token::Equal, "expected '=' in stack slot declaration")?;
1584        let vector_base_ty = self.match_type("expected base type")?;
1585        assert!(vector_base_ty.is_vector(), "expected vector type");
1586        self.match_token(
1587            Token::Multiply,
1588            "expected '*' followed by a dynamic scale value",
1589        )?;
1590        let dyn_scale = self.match_gv("expected dynamic scale global value")?;
1591        let data = DynamicTypeData::new(vector_base_ty, dyn_scale);
1592        // Collect any trailing comments.
1593        self.token();
1594        self.claim_gathered_comments(dt);
1595        Ok((dt, data))
1596    }
1597
1598    // Parse a global value decl.
1599    //
1600    // global-val-decl ::= * GlobalValue(gv) [ "!" fact ] "=" global-val-desc
1601    // global-val-desc ::= "vmctx"
1602    //                   | "load" "." type "notrap" "aligned" GlobalValue(base) [offset]
1603    //                   | "iadd_imm" "(" GlobalValue(base) ")" imm64
1604    //                   | "symbol" ["colocated"] name + imm64
1605    //                   | "dyn_scale_target_const" "." type
1606    //
1607    fn parse_global_value_decl(
1608        &mut self,
1609    ) -> ParseResult<(GlobalValue, GlobalValueData, Option<Fact>)> {
1610        let gv = self.match_gv("expected global value number: gv«n»")?;
1611
1612        let fact = if self.token() == Some(Token::Bang) {
1613            self.consume();
1614            Some(self.parse_fact()?)
1615        } else {
1616            None
1617        };
1618
1619        self.match_token(Token::Equal, "expected '=' in global value declaration")?;
1620
1621        let data = match self.match_any_identifier("expected global value kind")? {
1622            "vmctx" => GlobalValueData::VMContext,
1623            "load" => {
1624                self.match_token(
1625                    Token::Dot,
1626                    "expected '.' followed by type in load global value decl",
1627                )?;
1628                let global_type = self.match_type("expected load type")?;
1629                let flags = self.optional_memflags()?;
1630                let base = self.match_gv("expected global value: gv«n»")?;
1631                let offset = self.optional_offset32()?;
1632
1633                if !(flags.notrap() && flags.aligned()) {
1634                    return err!(self.loc, "global-value load must be notrap and aligned");
1635                }
1636                GlobalValueData::Load {
1637                    base,
1638                    offset,
1639                    global_type,
1640                    flags,
1641                }
1642            }
1643            "iadd_imm" => {
1644                self.match_token(
1645                    Token::Dot,
1646                    "expected '.' followed by type in iadd_imm global value decl",
1647                )?;
1648                let global_type = self.match_type("expected iadd type")?;
1649                let base = self.match_gv("expected global value: gv«n»")?;
1650                self.match_token(
1651                    Token::Comma,
1652                    "expected ',' followed by rhs in iadd_imm global value decl",
1653                )?;
1654                let offset = self.match_imm64("expected iadd_imm immediate")?;
1655                GlobalValueData::IAddImm {
1656                    base,
1657                    offset,
1658                    global_type,
1659                }
1660            }
1661            "symbol" => {
1662                let colocated = self.optional(Token::Identifier("colocated"));
1663                let tls = self.optional(Token::Identifier("tls"));
1664                let name = self.parse_external_name()?;
1665                let offset = self.optional_offset_imm64()?;
1666                GlobalValueData::Symbol {
1667                    name,
1668                    offset,
1669                    colocated,
1670                    tls,
1671                }
1672            }
1673            "dyn_scale_target_const" => {
1674                self.match_token(
1675                    Token::Dot,
1676                    "expected '.' followed by type in dynamic scale global value decl",
1677                )?;
1678                let vector_type = self.match_type("expected load type")?;
1679                assert!(vector_type.is_vector(), "Expected vector type");
1680                GlobalValueData::DynScaleTargetConst { vector_type }
1681            }
1682            other => return err!(self.loc, "Unknown global value kind '{}'", other),
1683        };
1684
1685        // Collect any trailing comments.
1686        self.token();
1687        self.claim_gathered_comments(gv);
1688
1689        Ok((gv, data, fact))
1690    }
1691
1692    // Parse one field definition in a memory-type struct decl.
1693    //
1694    // memory-type-field ::=  offset ":" type ["readonly"] [ "!" fact ]
1695    // offset ::= uimm64
1696    fn parse_memory_type_field(&mut self) -> ParseResult<MemoryTypeField> {
1697        let offset: u64 = self
1698            .match_uimm64(
1699                "expected u64 constant value for field offset in struct memory-type declaration",
1700            )?
1701            .into();
1702        self.match_token(
1703            Token::Colon,
1704            "expected colon after field offset in struct memory-type declaration",
1705        )?;
1706        let ty = self.match_type("expected type for field in struct memory-type declaration")?;
1707        let readonly = if self.token() == Some(Token::Identifier("readonly")) {
1708            self.consume();
1709            true
1710        } else {
1711            false
1712        };
1713        let fact = if self.token() == Some(Token::Bang) {
1714            self.consume();
1715            let fact = self.parse_fact()?;
1716            Some(fact)
1717        } else {
1718            None
1719        };
1720        Ok(MemoryTypeField {
1721            offset,
1722            ty,
1723            readonly,
1724            fact,
1725        })
1726    }
1727
1728    // Parse a memory-type decl.
1729    //
1730    // memory-type-decl ::= MemoryType(mt) "=" memory-type-desc
1731    // memory-type-desc ::= "struct" size "{" memory-type-field,* "}"
1732    //                    | "memory" size
1733    //                    | "dynamic_memory" GlobalValue "+" offset
1734    //                    | "empty"
1735    // size ::= uimm64
1736    // offset ::= uimm64
1737    fn parse_memory_type_decl(&mut self) -> ParseResult<(MemoryType, MemoryTypeData)> {
1738        let mt = self.match_mt("expected memory type number: mt«n»")?;
1739        self.match_token(Token::Equal, "expected '=' in memory type declaration")?;
1740
1741        let data = match self.token() {
1742            Some(Token::Identifier("struct")) => {
1743                self.consume();
1744                let size: u64 = self.match_uimm64("expected u64 constant value for struct size in struct memory-type declaration")?.into();
1745                self.match_token(Token::LBrace, "expected opening brace to start struct fields in struct memory-type declaration")?;
1746                let mut fields = vec![];
1747                while self.token() != Some(Token::RBrace) {
1748                    let field = self.parse_memory_type_field()?;
1749                    fields.push(field);
1750                    if self.token() == Some(Token::Comma) {
1751                        self.consume();
1752                    } else {
1753                        break;
1754                    }
1755                }
1756                self.match_token(
1757                    Token::RBrace,
1758                    "expected closing brace after struct fields in struct memory-type declaration",
1759                )?;
1760                MemoryTypeData::Struct { size, fields }
1761            }
1762            Some(Token::Identifier("memory")) => {
1763                self.consume();
1764                let size: u64 = self.match_uimm64("expected u64 constant value for size in static-memory memory-type declaration")?.into();
1765                MemoryTypeData::Memory { size }
1766            }
1767            Some(Token::Identifier("dynamic_memory")) => {
1768                self.consume();
1769                let gv = self.match_gv(
1770                    "expected a global value for `dynamic_memory` memory-type declaration",
1771                )?;
1772                self.match_token(
1773                    Token::Plus,
1774                    "expected `+` after global value in `dynamic_memory` memory-type declaration",
1775                )?;
1776                let size: u64 = self.match_uimm64("expected u64 constant value for size offset in `dynamic_memory` memory-type declaration")?.into();
1777                MemoryTypeData::DynamicMemory { gv, size }
1778            }
1779            Some(Token::Identifier("empty")) => {
1780                self.consume();
1781                MemoryTypeData::Empty
1782            }
1783            other => {
1784                return err!(
1785                    self.loc,
1786                    "Unknown memory type declaration kind '{:?}'",
1787                    other
1788                )
1789            }
1790        };
1791
1792        // Collect any trailing comments.
1793        self.token();
1794        self.claim_gathered_comments(mt);
1795
1796        Ok((mt, data))
1797    }
1798
1799    // Parse a signature decl.
1800    //
1801    // signature-decl ::= SigRef(sigref) "=" signature
1802    //
1803    fn parse_signature_decl(&mut self) -> ParseResult<(SigRef, Signature)> {
1804        let sig = self.match_sig("expected signature number: sig«n»")?;
1805        self.match_token(Token::Equal, "expected '=' in signature decl")?;
1806        let data = self.parse_signature()?;
1807
1808        // Collect any trailing comments.
1809        self.token();
1810        self.claim_gathered_comments(sig);
1811
1812        Ok((sig, data))
1813    }
1814
1815    // Parse a function decl.
1816    //
1817    // Two variants:
1818    //
1819    // function-decl ::= FuncRef(fnref) "=" ["colocated"]" name function-decl-sig
1820    // function-decl-sig ::= SigRef(sig) | signature
1821    //
1822    // The first variant allocates a new signature reference. The second references an existing
1823    // signature which must be declared first.
1824    //
1825    fn parse_function_decl(&mut self, ctx: &mut Context) -> ParseResult<(FuncRef, ExtFuncData)> {
1826        let fn_ = self.match_fn("expected function number: fn«n»")?;
1827        self.match_token(Token::Equal, "expected '=' in function decl")?;
1828
1829        let loc = self.loc;
1830
1831        // function-decl ::= FuncRef(fnref) "=" * ["colocated"] name function-decl-sig
1832        let colocated = self.optional(Token::Identifier("colocated"));
1833
1834        // function-decl ::= FuncRef(fnref) "=" ["colocated"] * name function-decl-sig
1835        let name = self.parse_external_name()?;
1836
1837        // function-decl ::= FuncRef(fnref) "=" ["colocated"] name * function-decl-sig
1838        let data = match self.token() {
1839            Some(Token::LPar) => {
1840                // function-decl ::= FuncRef(fnref) "=" ["colocated"] name * signature
1841                let sig = self.parse_signature()?;
1842                let sigref = ctx.function.import_signature(sig);
1843                ctx.map
1844                    .def_entity(sigref.into(), loc)
1845                    .expect("duplicate SigRef entities created");
1846                ExtFuncData {
1847                    name,
1848                    signature: sigref,
1849                    colocated,
1850                }
1851            }
1852            Some(Token::SigRef(sig_src)) => {
1853                let sig = match SigRef::with_number(sig_src) {
1854                    None => {
1855                        return err!(self.loc, "attempted to use invalid signature ss{}", sig_src);
1856                    }
1857                    Some(sig) => sig,
1858                };
1859                ctx.check_sig(sig, self.loc)?;
1860                self.consume();
1861                ExtFuncData {
1862                    name,
1863                    signature: sig,
1864                    colocated,
1865                }
1866            }
1867            _ => return err!(self.loc, "expected 'function' or sig«n» in function decl"),
1868        };
1869
1870        // Collect any trailing comments.
1871        self.token();
1872        self.claim_gathered_comments(fn_);
1873
1874        Ok((fn_, data))
1875    }
1876
1877    // Parse a jump table literal.
1878    //
1879    // jump-table-lit ::= "[" block(args) {"," block(args) } "]"
1880    //                  | "[]"
1881    fn parse_jump_table(
1882        &mut self,
1883        ctx: &mut Context,
1884        def: ir::BlockCall,
1885    ) -> ParseResult<ir::JumpTable> {
1886        self.match_token(Token::LBracket, "expected '[' before jump table contents")?;
1887
1888        let mut data = Vec::new();
1889
1890        match self.token() {
1891            Some(Token::Block(dest)) => {
1892                self.consume();
1893                let args = self.parse_opt_value_list()?;
1894                data.push(ctx.function.dfg.block_call(dest, &args));
1895
1896                loop {
1897                    match self.token() {
1898                        Some(Token::Comma) => {
1899                            self.consume();
1900                            if let Some(Token::Block(dest)) = self.token() {
1901                                self.consume();
1902                                let args = self.parse_opt_value_list()?;
1903                                data.push(ctx.function.dfg.block_call(dest, &args));
1904                            } else {
1905                                return err!(self.loc, "expected jump_table entry");
1906                            }
1907                        }
1908                        Some(Token::RBracket) => break,
1909                        _ => return err!(self.loc, "expected ']' after jump table contents"),
1910                    }
1911                }
1912            }
1913            Some(Token::RBracket) => (),
1914            _ => return err!(self.loc, "expected jump_table entry"),
1915        }
1916
1917        self.consume();
1918
1919        Ok(ctx
1920            .function
1921            .dfg
1922            .jump_tables
1923            .push(JumpTableData::new(def, &data)))
1924    }
1925
1926    // Parse a constant decl.
1927    //
1928    // constant-decl ::= * Constant(c) "=" ty? "[" literal {"," literal} "]"
1929    fn parse_constant_decl(&mut self) -> ParseResult<(Constant, ConstantData)> {
1930        let name = self.match_constant()?;
1931        self.match_token(Token::Equal, "expected '=' in constant decl")?;
1932        let data = if let Some(Token::Type(_)) = self.token() {
1933            let ty = self.match_type("expected type of constant")?;
1934            self.match_uimm128(ty)
1935        } else {
1936            self.match_hexadecimal_constant("expected an immediate hexadecimal operand")
1937        }?;
1938
1939        // Collect any trailing comments.
1940        self.token();
1941        self.claim_gathered_comments(name);
1942
1943        Ok((name, data))
1944    }
1945
1946    // Parse a stack limit decl
1947    //
1948    // stack-limit-decl ::= * StackLimit "=" GlobalValue(gv)
1949    fn parse_stack_limit_decl(&mut self) -> ParseResult<GlobalValue> {
1950        self.match_stack_limit()?;
1951        self.match_token(Token::Equal, "expected '=' in stack limit decl")?;
1952        let limit = match self.token() {
1953            Some(Token::GlobalValue(base_num)) => match GlobalValue::with_number(base_num) {
1954                Some(gv) => gv,
1955                None => return err!(self.loc, "invalid global value number for stack limit"),
1956            },
1957            _ => return err!(self.loc, "expected global value"),
1958        };
1959        self.consume();
1960
1961        // Collect any trailing comments.
1962        self.token();
1963        self.claim_gathered_comments(AnyEntity::StackLimit);
1964
1965        Ok(limit)
1966    }
1967
1968    // Parse a function body, add contents to `ctx`.
1969    //
1970    // function-body ::= * { extended-basic-block }
1971    //
1972    fn parse_function_body(&mut self, ctx: &mut Context) -> ParseResult<()> {
1973        while self.token() != Some(Token::RBrace) {
1974            self.parse_basic_block(ctx)?;
1975        }
1976
1977        // Now that we've seen all defined values in the function, ensure that
1978        // all references refer to a definition.
1979        for block in &ctx.function.layout {
1980            for inst in ctx.function.layout.block_insts(block) {
1981                for value in ctx.function.dfg.inst_values(inst) {
1982                    if !ctx.map.contains_value(value) {
1983                        return err!(
1984                            ctx.map.location(AnyEntity::Inst(inst)).unwrap(),
1985                            "undefined operand value {}",
1986                            value
1987                        );
1988                    }
1989                }
1990            }
1991        }
1992
1993        for alias in &ctx.aliases {
1994            if !ctx.function.dfg.set_alias_type_for_parser(*alias) {
1995                let loc = ctx.map.location(AnyEntity::Value(*alias)).unwrap();
1996                return err!(loc, "alias cycle involving {}", alias);
1997            }
1998        }
1999
2000        Ok(())
2001    }
2002
2003    // Parse a basic block, add contents to `ctx`.
2004    //
2005    // extended-basic-block ::= * block-header { instruction }
2006    // block-header         ::= Block(block) [block-params] [block-flags] ":"
2007    // block-flags          ::= [Cold]
2008    //
2009    fn parse_basic_block(&mut self, ctx: &mut Context) -> ParseResult<()> {
2010        // Collect comments for the next block.
2011        self.start_gathering_comments();
2012
2013        let block_num = self.match_block("expected block header")?;
2014        let block = ctx.add_block(block_num, self.loc)?;
2015
2016        if block_num.as_u32() >= MAX_BLOCKS_IN_A_FUNCTION {
2017            return Err(self.error("too many blocks"));
2018        }
2019
2020        if self.token() == Some(Token::LPar) {
2021            self.parse_block_params(ctx, block)?;
2022        }
2023
2024        if self.optional(Token::Cold) {
2025            ctx.set_cold_block(block);
2026        }
2027
2028        self.match_token(Token::Colon, "expected ':' after block parameters")?;
2029
2030        // Collect any trailing comments.
2031        self.token();
2032        self.claim_gathered_comments(block);
2033
2034        // extended-basic-block ::= block-header * { instruction }
2035        while match self.token() {
2036            Some(Token::Value(_))
2037            | Some(Token::Identifier(_))
2038            | Some(Token::LBracket)
2039            | Some(Token::SourceLoc(_)) => true,
2040            _ => false,
2041        } {
2042            let srcloc = self.optional_srcloc()?;
2043
2044            // We need to parse instruction results here because they are shared
2045            // between the parsing of value aliases and the parsing of instructions.
2046            //
2047            // inst-results ::= Value(v) { "," Value(v) }
2048            let results = self.parse_inst_results(ctx)?;
2049
2050            for result in &results {
2051                while ctx.function.dfg.num_values() <= result.index() {
2052                    ctx.function.dfg.make_invalid_value_for_parser();
2053                }
2054            }
2055
2056            match self.token() {
2057                Some(Token::Arrow) => {
2058                    self.consume();
2059                    self.parse_value_alias(&results, ctx)?;
2060                }
2061                Some(Token::Equal) => {
2062                    self.consume();
2063                    self.parse_instruction(&results, srcloc, ctx, block)?;
2064                }
2065                _ if !results.is_empty() => return err!(self.loc, "expected -> or ="),
2066                _ => self.parse_instruction(&results, srcloc, ctx, block)?,
2067            }
2068        }
2069
2070        Ok(())
2071    }
2072
2073    // Parse parenthesized list of block parameters.
2074    //
2075    // block-params ::= * "(" ( block-param { "," block-param } )? ")"
2076    fn parse_block_params(&mut self, ctx: &mut Context, block: Block) -> ParseResult<()> {
2077        // block-params ::= * "(" ( block-param { "," block-param } )? ")"
2078        self.match_token(Token::LPar, "expected '(' before block parameters")?;
2079
2080        // block-params ::= "(" * ")"
2081        if self.token() == Some(Token::RPar) {
2082            self.consume();
2083            return Ok(());
2084        }
2085
2086        // block-params ::= "(" * block-param { "," block-param } ")"
2087        self.parse_block_param(ctx, block)?;
2088
2089        // block-params ::= "(" block-param * { "," block-param } ")"
2090        while self.optional(Token::Comma) {
2091            // block-params ::= "(" block-param { "," * block-param } ")"
2092            self.parse_block_param(ctx, block)?;
2093        }
2094
2095        // block-params ::= "(" block-param { "," block-param } * ")"
2096        self.match_token(Token::RPar, "expected ')' after block parameters")?;
2097
2098        Ok(())
2099    }
2100
2101    // Parse a single block parameter declaration, and append it to `block`.
2102    //
2103    // block-param ::= * Value(v) [ "!" fact ]  ":" Type(t) arg-loc?
2104    // arg-loc ::= "[" value-location "]"
2105    //
2106    fn parse_block_param(&mut self, ctx: &mut Context, block: Block) -> ParseResult<()> {
2107        // block-param ::= * Value(v) [ "!" fact ] ":" Type(t) arg-loc?
2108        let v = self.match_value("block argument must be a value")?;
2109        let v_location = self.loc;
2110        // block-param ::= Value(v) * [ "!" fact ]  ":" Type(t) arg-loc?
2111        let fact = if self.token() == Some(Token::Bang) {
2112            self.consume();
2113            // block-param ::= Value(v) [ "!" * fact ]  ":" Type(t) arg-loc?
2114            Some(self.parse_fact()?)
2115        } else {
2116            None
2117        };
2118        self.match_token(Token::Colon, "expected ':' after block argument")?;
2119        // block-param ::= Value(v) [ "!" fact ] ":" * Type(t) arg-loc?
2120
2121        while ctx.function.dfg.num_values() <= v.index() {
2122            ctx.function.dfg.make_invalid_value_for_parser();
2123        }
2124
2125        let t = self.match_type("expected block argument type")?;
2126        // Allocate the block argument.
2127        ctx.function.dfg.append_block_param_for_parser(block, t, v);
2128        ctx.map.def_value(v, v_location)?;
2129        ctx.function.dfg.facts[v] = fact;
2130
2131        Ok(())
2132    }
2133
2134    // Parse a "fact" for proof-carrying code, attached to a value.
2135    //
2136    // fact ::= "range" "(" bit-width "," min-value "," max-value ")"
2137    //        | "dynamic_range" "(" bit-width "," expr "," expr ")"
2138    //        | "mem" "(" memory-type "," mt-offset "," mt-offset [ "," "nullable" ] ")"
2139    //        | "dynamic_mem" "(" memory-type "," expr "," expr [ "," "nullable" ] ")"
2140    //        | "conflict"
2141    // bit-width ::= uimm64
2142    // min-value ::= uimm64
2143    // max-value ::= uimm64
2144    // valid-range ::= uimm64
2145    // mt-offset ::= uimm64
2146    fn parse_fact(&mut self) -> ParseResult<Fact> {
2147        match self.token() {
2148            Some(Token::Identifier("range")) => {
2149                self.consume();
2150                self.match_token(Token::LPar, "`range` fact needs an opening `(`")?;
2151                let bit_width: u64 = self
2152                    .match_uimm64("expected a bit-width value for `range` fact")?
2153                    .into();
2154                self.match_token(Token::Comma, "expected a comma")?;
2155                let min: u64 = self
2156                    .match_uimm64("expected a min value for `range` fact")?
2157                    .into();
2158                self.match_token(Token::Comma, "expected a comma")?;
2159                let max: u64 = self
2160                    .match_uimm64("expected a max value for `range` fact")?
2161                    .into();
2162                self.match_token(Token::RPar, "`range` fact needs a closing `)`")?;
2163                let bit_width_max = match bit_width {
2164                    x if x > 64 => {
2165                        return Err(self.error("bitwidth must be <= 64 bits on a `range` fact"));
2166                    }
2167                    64 => u64::MAX,
2168                    x => (1u64 << x) - 1,
2169                };
2170                if min > max {
2171                    return Err(self.error(
2172                        "min value must be less than or equal to max value on a `range` fact",
2173                    ));
2174                }
2175                if max > bit_width_max {
2176                    return Err(
2177                        self.error("max value is out of range for bitwidth on a `range` fact")
2178                    );
2179                }
2180                Ok(Fact::Range {
2181                    bit_width: u16::try_from(bit_width).unwrap(),
2182                    min: min.into(),
2183                    max: max.into(),
2184                })
2185            }
2186            Some(Token::Identifier("dynamic_range")) => {
2187                self.consume();
2188                self.match_token(Token::LPar, "`dynamic_range` fact needs an opening `(`")?;
2189                let bit_width: u64 = self
2190                    .match_uimm64("expected a bit-width value for `dynamic_range` fact")?
2191                    .into();
2192                self.match_token(Token::Comma, "expected a comma")?;
2193                let min = self.parse_expr()?;
2194                self.match_token(Token::Comma, "expected a comma")?;
2195                let max = self.parse_expr()?;
2196                self.match_token(Token::RPar, "`dynamic_range` fact needs a closing `)`")?;
2197                Ok(Fact::DynamicRange {
2198                    bit_width: u16::try_from(bit_width).unwrap(),
2199                    min,
2200                    max,
2201                })
2202            }
2203            Some(Token::Identifier("mem")) => {
2204                self.consume();
2205                self.match_token(Token::LPar, "expected a `(`")?;
2206                let ty = self.match_mt("expected a memory type for `mem` fact")?;
2207                self.match_token(
2208                    Token::Comma,
2209                    "expected a comma after memory type in `mem` fact",
2210                )?;
2211                let min_offset: u64 = self
2212                    .match_uimm64("expected a uimm64 minimum pointer offset for `mem` fact")?
2213                    .into();
2214                self.match_token(Token::Comma, "expected a comma after offset in `mem` fact")?;
2215                let max_offset: u64 = self
2216                    .match_uimm64("expected a uimm64 maximum pointer offset for `mem` fact")?
2217                    .into();
2218                let nullable = if self.token() == Some(Token::Comma) {
2219                    self.consume();
2220                    self.match_token(
2221                        Token::Identifier("nullable"),
2222                        "expected `nullable` in last optional field of `dynamic_mem`",
2223                    )?;
2224                    true
2225                } else {
2226                    false
2227                };
2228                self.match_token(Token::RPar, "expected a `)`")?;
2229                Ok(Fact::Mem {
2230                    ty,
2231                    min_offset,
2232                    max_offset,
2233                    nullable,
2234                })
2235            }
2236            Some(Token::Identifier("dynamic_mem")) => {
2237                self.consume();
2238                self.match_token(Token::LPar, "expected a `(`")?;
2239                let ty = self.match_mt("expected a memory type for `dynamic_mem` fact")?;
2240                self.match_token(
2241                    Token::Comma,
2242                    "expected a comma after memory type in `dynamic_mem` fact",
2243                )?;
2244                let min = self.parse_expr()?;
2245                self.match_token(
2246                    Token::Comma,
2247                    "expected a comma after offset in `dynamic_mem` fact",
2248                )?;
2249                let max = self.parse_expr()?;
2250                let nullable = if self.token() == Some(Token::Comma) {
2251                    self.consume();
2252                    self.match_token(
2253                        Token::Identifier("nullable"),
2254                        "expected `nullable` in last optional field of `dynamic_mem`",
2255                    )?;
2256                    true
2257                } else {
2258                    false
2259                };
2260                self.match_token(Token::RPar, "expected a `)`")?;
2261                Ok(Fact::DynamicMem {
2262                    ty,
2263                    min,
2264                    max,
2265                    nullable,
2266                })
2267            }
2268            Some(Token::Identifier("def")) => {
2269                self.consume();
2270                self.match_token(Token::LPar, "expected a `(`")?;
2271                let value = self.match_value("expected a value number in `def` fact")?;
2272                self.match_token(Token::RPar, "expected a `)`")?;
2273                Ok(Fact::Def { value })
2274            }
2275            Some(Token::Identifier("compare")) => {
2276                self.consume();
2277                self.match_token(Token::LPar, "expected a `(`")?;
2278                let kind = self.match_enum("expected intcc condition code in `compare` fact")?;
2279                self.match_token(
2280                    Token::Comma,
2281                    "expected comma in `compare` fact after condition code",
2282                )?;
2283                let lhs = self.parse_expr()?;
2284                self.match_token(Token::Comma, "expected comma in `compare` fact after LHS")?;
2285                let rhs = self.parse_expr()?;
2286                self.match_token(Token::RPar, "expected a `)`")?;
2287                Ok(Fact::Compare { kind, lhs, rhs })
2288            }
2289            Some(Token::Identifier("conflict")) => {
2290                self.consume();
2291                Ok(Fact::Conflict)
2292            }
2293            _ => Err(self.error(
2294                "expected a `range`, 'dynamic_range', `mem`, `dynamic_mem`, `def`, `compare` or `conflict` fact",
2295            )),
2296        }
2297    }
2298
2299    // Parse a dynamic expression used in some kinds of PCC facts.
2300    //
2301    // expr ::= base-expr
2302    //        | base-expr + uimm64  // but in-range for imm64
2303    //        | base-expr - uimm64  // but in-range for imm64
2304    //        | imm64
2305    fn parse_expr(&mut self) -> ParseResult<Expr> {
2306        if let Some(Token::Integer(_)) = self.token() {
2307            let offset: i64 = self
2308                .match_imm64("expected imm64 for dynamic expression")?
2309                .into();
2310            Ok(Expr {
2311                base: BaseExpr::None,
2312                offset,
2313            })
2314        } else {
2315            let base = self.parse_base_expr()?;
2316            match self.token() {
2317                Some(Token::Plus) => {
2318                    self.consume();
2319                    let offset: u64 = self
2320                        .match_uimm64(
2321                            "expected uimm64 in imm64 range for offset in dynamic expression",
2322                        )?
2323                        .into();
2324                    let offset: i64 = i64::try_from(offset).map_err(|_| {
2325                        self.error("integer offset in dynamic expression is out of range")
2326                    })?;
2327                    Ok(Expr { base, offset })
2328                }
2329                Some(Token::Integer(x)) if x.starts_with("-") => {
2330                    let offset: i64 = self
2331                        .match_imm64("expected an imm64 range for offset in dynamic expression")?
2332                        .into();
2333                    Ok(Expr { base, offset })
2334                }
2335                _ => Ok(Expr { base, offset: 0 }),
2336            }
2337        }
2338    }
2339
2340    // Parse the base part of a dynamic expression, used in some PCC facts.
2341    //
2342    // base-expr ::= GlobalValue(base)
2343    //             | Value(base)
2344    //             | "max"
2345    //             | (epsilon)
2346    fn parse_base_expr(&mut self) -> ParseResult<BaseExpr> {
2347        match self.token() {
2348            Some(Token::Identifier("max")) => {
2349                self.consume();
2350                Ok(BaseExpr::Max)
2351            }
2352            Some(Token::GlobalValue(..)) => {
2353                let gv = self.match_gv("expected global value")?;
2354                Ok(BaseExpr::GlobalValue(gv))
2355            }
2356            Some(Token::Value(..)) => {
2357                let value = self.match_value("expected value")?;
2358                Ok(BaseExpr::Value(value))
2359            }
2360            _ => Ok(BaseExpr::None),
2361        }
2362    }
2363
2364    // Parse instruction results and return them.
2365    //
2366    // inst-results ::= Value(v) { "," Value(v) }
2367    //
2368    fn parse_inst_results(&mut self, ctx: &mut Context) -> ParseResult<SmallVec<[Value; 1]>> {
2369        // Result value numbers.
2370        let mut results = SmallVec::new();
2371
2372        // instruction  ::=  * [inst-results "="] Opcode(opc) ["." Type] ...
2373        // inst-results ::= * Value(v) { "," Value(v) }
2374        if let Some(Token::Value(v)) = self.token() {
2375            self.consume();
2376
2377            results.push(v);
2378
2379            let fact = if self.token() == Some(Token::Bang) {
2380                self.consume();
2381                // block-param ::= Value(v) [ "!" * fact ]  ":" Type(t) arg-loc?
2382                Some(self.parse_fact()?)
2383            } else {
2384                None
2385            };
2386            ctx.function.dfg.facts[v] = fact;
2387
2388            // inst-results ::= Value(v) * { "," Value(v) }
2389            while self.optional(Token::Comma) {
2390                // inst-results ::= Value(v) { "," * Value(v) }
2391                let v = self.match_value("expected result value")?;
2392                results.push(v);
2393
2394                let fact = if self.token() == Some(Token::Bang) {
2395                    self.consume();
2396                    // block-param ::= Value(v) [ "!" * fact ]  ":" Type(t) arg-loc?
2397                    Some(self.parse_fact()?)
2398                } else {
2399                    None
2400                };
2401                ctx.function.dfg.facts[v] = fact;
2402            }
2403        }
2404
2405        Ok(results)
2406    }
2407
2408    // Parse a value alias, and append it to `block`.
2409    //
2410    // value_alias ::= [inst-results] "->" Value(v)
2411    //
2412    fn parse_value_alias(&mut self, results: &[Value], ctx: &mut Context) -> ParseResult<()> {
2413        if results.len() != 1 {
2414            return err!(self.loc, "wrong number of aliases");
2415        }
2416        let result = results[0];
2417        let dest = self.match_value("expected value alias")?;
2418
2419        // Allow duplicate definitions of aliases, as long as they are identical.
2420        if ctx.map.contains_value(result) {
2421            if let Some(old) = ctx.function.dfg.value_alias_dest_for_serialization(result) {
2422                if old != dest {
2423                    return err!(
2424                        self.loc,
2425                        "value {} is already defined as an alias with destination {}",
2426                        result,
2427                        old
2428                    );
2429                }
2430            } else {
2431                return err!(self.loc, "value {} is already defined");
2432            }
2433        } else {
2434            ctx.map.def_value(result, self.loc)?;
2435        }
2436
2437        if !ctx.map.contains_value(dest) {
2438            return err!(self.loc, "value {} is not yet defined", dest);
2439        }
2440
2441        ctx.function
2442            .dfg
2443            .make_value_alias_for_serialization(dest, result);
2444
2445        ctx.aliases.push(result);
2446        Ok(())
2447    }
2448
2449    // Parse an instruction, append it to `block`.
2450    //
2451    // instruction ::= [inst-results "="] Opcode(opc) ["." Type] ...
2452    //
2453    fn parse_instruction(
2454        &mut self,
2455        results: &[Value],
2456        srcloc: ir::SourceLoc,
2457        ctx: &mut Context,
2458        block: Block,
2459    ) -> ParseResult<()> {
2460        // Define the result values.
2461        for val in results {
2462            ctx.map.def_value(*val, self.loc)?;
2463        }
2464
2465        // Collect comments for the next instruction.
2466        self.start_gathering_comments();
2467
2468        // instruction ::=  [inst-results "="] * Opcode(opc) ["." Type] ...
2469        let opcode = if let Some(Token::Identifier(text)) = self.token() {
2470            match text.parse() {
2471                Ok(opc) => opc,
2472                Err(msg) => return err!(self.loc, "{}: '{}'", msg, text),
2473            }
2474        } else {
2475            return err!(self.loc, "expected instruction opcode");
2476        };
2477        let opcode_loc = self.loc;
2478        self.consume();
2479
2480        // Look for a controlling type variable annotation.
2481        // instruction ::=  [inst-results "="] Opcode(opc) * ["." Type] ...
2482        let explicit_ctrl_type = if self.optional(Token::Dot) {
2483            if let Some(Token::Type(_t)) = self.token() {
2484                Some(self.match_type("expected type after 'opcode.'")?)
2485            } else {
2486                let dt = self.match_dt("expected dynamic type")?;
2487                self.concrete_from_dt(dt, ctx)
2488            }
2489        } else {
2490            None
2491        };
2492
2493        // instruction ::=  [inst-results "="] Opcode(opc) ["." Type] * ...
2494        let inst_data = self.parse_inst_operands(ctx, opcode, explicit_ctrl_type)?;
2495
2496        // We're done parsing the instruction data itself.
2497        //
2498        // We still need to check that the number of result values in the source
2499        // matches the opcode or function call signature. We also need to create
2500        // values with the right type for all the instruction results and parse
2501        // and attach stack map entries, if present.
2502        let ctrl_typevar = self.infer_typevar(ctx, opcode, explicit_ctrl_type, &inst_data)?;
2503        let inst = ctx.function.dfg.make_inst(inst_data);
2504        if opcode.is_call() && !opcode.is_return() && self.optional(Token::Comma) {
2505            self.match_identifier("stack_map", "expected `stack_map = [...]`")?;
2506            self.match_token(Token::Equal, "expected `= [...]`")?;
2507            self.match_token(Token::LBracket, "expected `[...]`")?;
2508            while !self.optional(Token::RBracket) {
2509                let ty = self.match_type("expected `<type> @ <slot> + <offset>`")?;
2510                self.match_token(Token::At, "expected `@ <slot> + <offset>`")?;
2511                let slot = self.match_ss("expected `<slot> + <offset>`")?;
2512                let offset: u32 = match self.token() {
2513                    Some(Token::Integer(s)) if s.starts_with('+') => {
2514                        self.match_uimm32("expected a u32 offset")?.into()
2515                    }
2516                    _ => {
2517                        self.match_token(Token::Plus, "expected `+ <offset>`")?;
2518                        self.match_uimm32("expected a u32 offset")?.into()
2519                    }
2520                };
2521                ctx.function
2522                    .dfg
2523                    .append_user_stack_map_entry(inst, ir::UserStackMapEntry { ty, slot, offset });
2524                if !self.optional(Token::Comma) {
2525                    self.match_token(Token::RBracket, "expected `,` or `]`")?;
2526                    break;
2527                }
2528            }
2529        }
2530        let num_results =
2531            ctx.function
2532                .dfg
2533                .make_inst_results_for_parser(inst, ctrl_typevar, results);
2534        ctx.function.layout.append_inst(inst, block);
2535        ctx.map
2536            .def_entity(inst.into(), opcode_loc)
2537            .expect("duplicate inst references created");
2538
2539        if !srcloc.is_default() {
2540            ctx.function.set_srcloc(inst, srcloc);
2541        }
2542
2543        if results.len() != num_results {
2544            return err!(
2545                self.loc,
2546                "instruction produces {} result values, {} given",
2547                num_results,
2548                results.len()
2549            );
2550        }
2551
2552        // Collect any trailing comments.
2553        self.token();
2554        self.claim_gathered_comments(inst);
2555
2556        Ok(())
2557    }
2558
2559    // Type inference for polymorphic instructions.
2560    //
2561    // The controlling type variable can be specified explicitly as 'splat.i32x4 v5', or it can be
2562    // inferred from `inst_data.typevar_operand` for some opcodes.
2563    //
2564    // Returns the controlling typevar for a polymorphic opcode, or `INVALID` for a non-polymorphic
2565    // opcode.
2566    fn infer_typevar(
2567        &self,
2568        ctx: &Context,
2569        opcode: Opcode,
2570        explicit_ctrl_type: Option<Type>,
2571        inst_data: &InstructionData,
2572    ) -> ParseResult<Type> {
2573        let constraints = opcode.constraints();
2574        let ctrl_type = match explicit_ctrl_type {
2575            Some(t) => t,
2576            None => {
2577                if constraints.use_typevar_operand() {
2578                    // This is an opcode that supports type inference, AND there was no
2579                    // explicit type specified. Look up `ctrl_value` to see if it was defined
2580                    // already.
2581                    // TBD: If it is defined in another block, the type should have been
2582                    // specified explicitly. It is unfortunate that the correctness of IR
2583                    // depends on the layout of the blocks.
2584                    let ctrl_src_value = inst_data
2585                        .typevar_operand(&ctx.function.dfg.value_lists)
2586                        .expect("Constraints <-> Format inconsistency");
2587                    if !ctx.map.contains_value(ctrl_src_value) {
2588                        return err!(
2589                            self.loc,
2590                            "type variable required for polymorphic opcode, e.g. '{}.{}'; \
2591                             can't infer from {} which is not yet defined",
2592                            opcode,
2593                            constraints.ctrl_typeset().unwrap().example(),
2594                            ctrl_src_value
2595                        );
2596                    }
2597                    if !ctx.function.dfg.value_is_valid_for_parser(ctrl_src_value) {
2598                        return err!(
2599                            self.loc,
2600                            "type variable required for polymorphic opcode, e.g. '{}.{}'; \
2601                             can't infer from {} which is not yet resolved",
2602                            opcode,
2603                            constraints.ctrl_typeset().unwrap().example(),
2604                            ctrl_src_value
2605                        );
2606                    }
2607                    ctx.function.dfg.value_type(ctrl_src_value)
2608                } else if constraints.is_polymorphic() {
2609                    // This opcode does not support type inference, so the explicit type
2610                    // variable is required.
2611                    return err!(
2612                        self.loc,
2613                        "type variable required for polymorphic opcode, e.g. '{}.{}'",
2614                        opcode,
2615                        constraints.ctrl_typeset().unwrap().example()
2616                    );
2617                } else {
2618                    // This is a non-polymorphic opcode. No typevar needed.
2619                    INVALID
2620                }
2621            }
2622        };
2623
2624        // Verify that `ctrl_type` is valid for the controlling type variable. We don't want to
2625        // attempt deriving types from an incorrect basis.
2626        // This is not a complete type check. The verifier does that.
2627        if let Some(typeset) = constraints.ctrl_typeset() {
2628            // This is a polymorphic opcode.
2629            if !typeset.contains(ctrl_type) {
2630                return err!(
2631                    self.loc,
2632                    "{} is not a valid typevar for {}",
2633                    ctrl_type,
2634                    opcode
2635                );
2636            }
2637        // Treat it as a syntax error to specify a typevar on a non-polymorphic opcode.
2638        } else if ctrl_type != INVALID {
2639            return err!(self.loc, "{} does not take a typevar", opcode);
2640        }
2641
2642        Ok(ctrl_type)
2643    }
2644
2645    // Parse comma-separated value list into a VariableArgs struct.
2646    //
2647    // value_list ::= [ value { "," value } ]
2648    //
2649    fn parse_value_list(&mut self) -> ParseResult<VariableArgs> {
2650        let mut args = VariableArgs::new();
2651
2652        if let Some(Token::Value(v)) = self.token() {
2653            args.push(v);
2654            self.consume();
2655        } else {
2656            return Ok(args);
2657        }
2658
2659        while self.optional(Token::Comma) {
2660            args.push(self.match_value("expected value in argument list")?);
2661        }
2662
2663        Ok(args)
2664    }
2665
2666    // Parse an optional value list enclosed in parentheses.
2667    fn parse_opt_value_list(&mut self) -> ParseResult<VariableArgs> {
2668        if !self.optional(Token::LPar) {
2669            return Ok(VariableArgs::new());
2670        }
2671
2672        let args = self.parse_value_list()?;
2673
2674        self.match_token(Token::RPar, "expected ')' after arguments")?;
2675
2676        Ok(args)
2677    }
2678
2679    /// Parse a CLIF run command.
2680    ///
2681    /// run-command ::= "run" [":" invocation comparison expected]
2682    ///               \ "print" [":" invocation]
2683    fn parse_run_command(&mut self, sig: &Signature) -> ParseResult<RunCommand> {
2684        // skip semicolon
2685        match self.token() {
2686            Some(Token::Identifier("run")) => {
2687                self.consume();
2688                if self.optional(Token::Colon) {
2689                    let invocation = self.parse_run_invocation(sig)?;
2690                    let comparison = self.parse_run_comparison()?;
2691                    let expected = self.parse_run_returns(sig)?;
2692                    Ok(RunCommand::Run(invocation, comparison, expected))
2693                } else if sig.params.is_empty()
2694                    && sig.returns.len() == 1
2695                    && sig.returns[0].value_type.is_int()
2696                {
2697                    // To match the existing run behavior that does not require an explicit
2698                    // invocation, we create an invocation from a function like `() -> i*` and
2699                    // require the result to be non-zero.
2700                    let invocation = Invocation::new("default", vec![]);
2701                    let expected = vec![DataValue::I8(0)];
2702                    let comparison = Comparison::NotEquals;
2703                    Ok(RunCommand::Run(invocation, comparison, expected))
2704                } else {
2705                    Err(self.error("unable to parse the run command"))
2706                }
2707            }
2708            Some(Token::Identifier("print")) => {
2709                self.consume();
2710                if self.optional(Token::Colon) {
2711                    Ok(RunCommand::Print(self.parse_run_invocation(sig)?))
2712                } else if sig.params.is_empty() {
2713                    // To allow printing of functions like `() -> *`, we create a no-arg invocation.
2714                    let invocation = Invocation::new("default", vec![]);
2715                    Ok(RunCommand::Print(invocation))
2716                } else {
2717                    Err(self.error("unable to parse the print command"))
2718                }
2719            }
2720            _ => Err(self.error("expected a 'run:' or 'print:' command")),
2721        }
2722    }
2723
2724    /// Parse the invocation of a CLIF function.
2725    ///
2726    /// This is different from parsing a CLIF `call`; it is used in parsing run commands like
2727    /// `run: %fn(42, 4.2) == false`.
2728    ///
2729    /// invocation ::= name "(" [data-value-list] ")"
2730    fn parse_run_invocation(&mut self, sig: &Signature) -> ParseResult<Invocation> {
2731        if let Some(Token::Name(name)) = self.token() {
2732            self.consume();
2733            self.match_token(
2734                Token::LPar,
2735                "expected invocation parentheses, e.g. %fn(...)",
2736            )?;
2737
2738            let arg_types = sig
2739                .params
2740                .iter()
2741                .map(|abi| abi.value_type)
2742                .collect::<Vec<_>>();
2743            let args = self.parse_data_value_list(&arg_types)?;
2744
2745            self.match_token(
2746                Token::RPar,
2747                "expected invocation parentheses, e.g. %fn(...)",
2748            )?;
2749            Ok(Invocation::new(name, args))
2750        } else {
2751            Err(self.error("expected a function name, e.g. %my_fn"))
2752        }
2753    }
2754
2755    /// Parse a comparison operator for run commands.
2756    ///
2757    /// comparison ::= "==" | "!="
2758    fn parse_run_comparison(&mut self) -> ParseResult<Comparison> {
2759        if self.optional(Token::Equal) {
2760            self.match_token(Token::Equal, "expected another =")?;
2761            Ok(Comparison::Equals)
2762        } else if self.optional(Token::Bang) {
2763            self.match_token(Token::Equal, "expected a =")?;
2764            Ok(Comparison::NotEquals)
2765        } else {
2766            Err(self.error("unable to parse a valid comparison operator"))
2767        }
2768    }
2769
2770    /// Parse the expected return values of a run invocation.
2771    ///
2772    /// expected ::= "[" "]"
2773    ///            | data-value
2774    ///            | "[" data-value-list "]"
2775    fn parse_run_returns(&mut self, sig: &Signature) -> ParseResult<Vec<DataValue>> {
2776        if sig.returns.len() != 1 {
2777            self.match_token(Token::LBracket, "expected a left bracket [")?;
2778        }
2779
2780        let returns = self
2781            .parse_data_value_list(&sig.returns.iter().map(|a| a.value_type).collect::<Vec<_>>())?;
2782
2783        if sig.returns.len() != 1 {
2784            self.match_token(Token::RBracket, "expected a right bracket ]")?;
2785        }
2786        Ok(returns)
2787    }
2788
2789    /// Parse a comma-separated list of data values.
2790    ///
2791    /// data-value-list ::= [data-value {"," data-value-list}]
2792    fn parse_data_value_list(&mut self, types: &[Type]) -> ParseResult<Vec<DataValue>> {
2793        let mut values = vec![];
2794        for ty in types.iter().take(1) {
2795            values.push(self.parse_data_value(*ty)?);
2796        }
2797        for ty in types.iter().skip(1) {
2798            self.match_token(
2799                Token::Comma,
2800                "expected a comma between invocation arguments",
2801            )?;
2802            values.push(self.parse_data_value(*ty)?);
2803        }
2804        Ok(values)
2805    }
2806
2807    /// Parse a data value; e.g. `42`, `4.2`, `true`.
2808    ///
2809    /// data-value-list ::= [data-value {"," data-value-list}]
2810    fn parse_data_value(&mut self, ty: Type) -> ParseResult<DataValue> {
2811        let dv = match ty {
2812            I8 => DataValue::from(self.match_imm8("expected a i8")?),
2813            I16 => DataValue::from(self.match_imm16("expected an i16")?),
2814            I32 => DataValue::from(self.match_imm32("expected an i32")?),
2815            I64 => DataValue::from(Into::<i64>::into(self.match_imm64("expected an i64")?)),
2816            I128 => DataValue::from(self.match_imm128("expected an i128")?),
2817            F16 => DataValue::from(self.match_ieee16("expected an f16")?),
2818            F32 => DataValue::from(self.match_ieee32("expected an f32")?),
2819            F64 => DataValue::from(self.match_ieee64("expected an f64")?),
2820            F128 => DataValue::from(self.match_ieee128("expected an f128")?),
2821            _ if (ty.is_vector() || ty.is_dynamic_vector()) => {
2822                let as_vec = self.match_uimm128(ty)?.into_vec();
2823                if as_vec.len() == 16 {
2824                    let mut as_array = [0; 16];
2825                    as_array.copy_from_slice(&as_vec[..]);
2826                    DataValue::from(as_array)
2827                } else if as_vec.len() == 8 {
2828                    let mut as_array = [0; 8];
2829                    as_array.copy_from_slice(&as_vec[..]);
2830                    DataValue::from(as_array)
2831                } else {
2832                    return Err(self.error("only 128-bit vectors are currently supported"));
2833                }
2834            }
2835            _ => return Err(self.error(&format!("don't know how to parse data values of: {ty}"))),
2836        };
2837        Ok(dv)
2838    }
2839
2840    // Parse the operands following the instruction opcode.
2841    // This depends on the format of the opcode.
2842    fn parse_inst_operands(
2843        &mut self,
2844        ctx: &mut Context,
2845        opcode: Opcode,
2846        explicit_control_type: Option<Type>,
2847    ) -> ParseResult<InstructionData> {
2848        let idata = match opcode.format() {
2849            InstructionFormat::Unary => InstructionData::Unary {
2850                opcode,
2851                arg: self.match_value("expected SSA value operand")?,
2852            },
2853            InstructionFormat::UnaryImm => {
2854                let msg = |bits| format!("expected immediate {bits}-bit integer operand");
2855                let unsigned = match explicit_control_type {
2856                    Some(types::I8) => self.match_imm8(&msg(8))? as u8 as i64,
2857                    Some(types::I16) => self.match_imm16(&msg(16))? as u16 as i64,
2858                    Some(types::I32) => self.match_imm32(&msg(32))? as u32 as i64,
2859                    Some(types::I64) => self.match_imm64(&msg(64))?.bits(),
2860                    _ => {
2861                        return err!(
2862                            self.loc,
2863                            "expected one of the following type: i8, i16, i32 or i64"
2864                        )
2865                    }
2866                };
2867                InstructionData::UnaryImm {
2868                    opcode,
2869                    imm: Imm64::new(unsigned),
2870                }
2871            }
2872            InstructionFormat::UnaryIeee16 => InstructionData::UnaryIeee16 {
2873                opcode,
2874                imm: self.match_ieee16("expected immediate 16-bit float operand")?,
2875            },
2876            InstructionFormat::UnaryIeee32 => InstructionData::UnaryIeee32 {
2877                opcode,
2878                imm: self.match_ieee32("expected immediate 32-bit float operand")?,
2879            },
2880            InstructionFormat::UnaryIeee64 => InstructionData::UnaryIeee64 {
2881                opcode,
2882                imm: self.match_ieee64("expected immediate 64-bit float operand")?,
2883            },
2884            InstructionFormat::UnaryConst => {
2885                let constant_handle = if let Some(Token::Constant(_)) = self.token() {
2886                    // If handed a `const?`, use that.
2887                    let c = self.match_constant()?;
2888                    ctx.check_constant(c, self.loc)?;
2889                    c
2890                } else if opcode == Opcode::F128const {
2891                    let ieee128 = self.match_ieee128("expected immediate 128-bit float operand")?;
2892                    ctx.function.dfg.constants.insert(ieee128.into())
2893                } else if let Some(controlling_type) = explicit_control_type {
2894                    // If an explicit control type is present, we expect a sized value and insert
2895                    // it in the constant pool.
2896                    let uimm128 = self.match_uimm128(controlling_type)?;
2897                    ctx.function.dfg.constants.insert(uimm128)
2898                } else {
2899                    return err!(
2900                        self.loc,
2901                        "Expected either a const entity or a typed value, e.g. inst.i32x4 [...]"
2902                    );
2903                };
2904                InstructionData::UnaryConst {
2905                    opcode,
2906                    constant_handle,
2907                }
2908            }
2909            InstructionFormat::UnaryGlobalValue => {
2910                let gv = self.match_gv("expected global value")?;
2911                ctx.check_gv(gv, self.loc)?;
2912                InstructionData::UnaryGlobalValue {
2913                    opcode,
2914                    global_value: gv,
2915                }
2916            }
2917            InstructionFormat::Binary => {
2918                let lhs = self.match_value("expected SSA value first operand")?;
2919                self.match_token(Token::Comma, "expected ',' between operands")?;
2920                let rhs = self.match_value("expected SSA value second operand")?;
2921                InstructionData::Binary {
2922                    opcode,
2923                    args: [lhs, rhs],
2924                }
2925            }
2926            InstructionFormat::BinaryImm8 => {
2927                let arg = self.match_value("expected SSA value first operand")?;
2928                self.match_token(Token::Comma, "expected ',' between operands")?;
2929                let imm = self.match_uimm8("expected unsigned 8-bit immediate")?;
2930                InstructionData::BinaryImm8 { opcode, arg, imm }
2931            }
2932            InstructionFormat::BinaryImm64 => {
2933                let lhs = self.match_value("expected SSA value first operand")?;
2934                self.match_token(Token::Comma, "expected ',' between operands")?;
2935                let rhs = self.match_imm64("expected immediate integer second operand")?;
2936                InstructionData::BinaryImm64 {
2937                    opcode,
2938                    arg: lhs,
2939                    imm: rhs,
2940                }
2941            }
2942            InstructionFormat::Ternary => {
2943                // Names here refer to the `select` instruction.
2944                // This format is also use by `fma`.
2945                let ctrl_arg = self.match_value("expected SSA value control operand")?;
2946                self.match_token(Token::Comma, "expected ',' between operands")?;
2947                let true_arg = self.match_value("expected SSA value true operand")?;
2948                self.match_token(Token::Comma, "expected ',' between operands")?;
2949                let false_arg = self.match_value("expected SSA value false operand")?;
2950                InstructionData::Ternary {
2951                    opcode,
2952                    args: [ctrl_arg, true_arg, false_arg],
2953                }
2954            }
2955            InstructionFormat::MultiAry => {
2956                let args = self.parse_value_list()?;
2957                InstructionData::MultiAry {
2958                    opcode,
2959                    args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists),
2960                }
2961            }
2962            InstructionFormat::NullAry => InstructionData::NullAry { opcode },
2963            InstructionFormat::Jump => {
2964                // Parse the destination block number.
2965                let block_num = self.match_block("expected jump destination block")?;
2966                let args = self.parse_opt_value_list()?;
2967                let destination = ctx.function.dfg.block_call(block_num, &args);
2968                InstructionData::Jump {
2969                    opcode,
2970                    destination,
2971                }
2972            }
2973            InstructionFormat::Brif => {
2974                let arg = self.match_value("expected SSA value control operand")?;
2975                self.match_token(Token::Comma, "expected ',' between operands")?;
2976                let block_then = {
2977                    let block_num = self.match_block("expected branch then block")?;
2978                    let args = self.parse_opt_value_list()?;
2979                    ctx.function.dfg.block_call(block_num, &args)
2980                };
2981                self.match_token(Token::Comma, "expected ',' between operands")?;
2982                let block_else = {
2983                    let block_num = self.match_block("expected branch else block")?;
2984                    let args = self.parse_opt_value_list()?;
2985                    ctx.function.dfg.block_call(block_num, &args)
2986                };
2987                InstructionData::Brif {
2988                    opcode,
2989                    arg,
2990                    blocks: [block_then, block_else],
2991                }
2992            }
2993            InstructionFormat::BranchTable => {
2994                let arg = self.match_value("expected SSA value operand")?;
2995                self.match_token(Token::Comma, "expected ',' between operands")?;
2996                let block_num = self.match_block("expected branch destination block")?;
2997                let args = self.parse_opt_value_list()?;
2998                let destination = ctx.function.dfg.block_call(block_num, &args);
2999                self.match_token(Token::Comma, "expected ',' between operands")?;
3000                let table = self.parse_jump_table(ctx, destination)?;
3001                InstructionData::BranchTable { opcode, arg, table }
3002            }
3003            InstructionFormat::TernaryImm8 => {
3004                let lhs = self.match_value("expected SSA value first operand")?;
3005                self.match_token(Token::Comma, "expected ',' between operands")?;
3006                let rhs = self.match_value("expected SSA value last operand")?;
3007                self.match_token(Token::Comma, "expected ',' between operands")?;
3008                let imm = self.match_uimm8("expected 8-bit immediate")?;
3009                InstructionData::TernaryImm8 {
3010                    opcode,
3011                    imm,
3012                    args: [lhs, rhs],
3013                }
3014            }
3015            InstructionFormat::Shuffle => {
3016                let a = self.match_value("expected SSA value first operand")?;
3017                self.match_token(Token::Comma, "expected ',' between operands")?;
3018                let b = self.match_value("expected SSA value second operand")?;
3019                self.match_token(Token::Comma, "expected ',' between operands")?;
3020                let uimm128 = self.match_uimm128(I8X16)?;
3021                let imm = ctx.function.dfg.immediates.push(uimm128);
3022                InstructionData::Shuffle {
3023                    opcode,
3024                    imm,
3025                    args: [a, b],
3026                }
3027            }
3028            InstructionFormat::IntCompare => {
3029                let cond = self.match_enum("expected intcc condition code")?;
3030                let lhs = self.match_value("expected SSA value first operand")?;
3031                self.match_token(Token::Comma, "expected ',' between operands")?;
3032                let rhs = self.match_value("expected SSA value second operand")?;
3033                InstructionData::IntCompare {
3034                    opcode,
3035                    cond,
3036                    args: [lhs, rhs],
3037                }
3038            }
3039            InstructionFormat::IntCompareImm => {
3040                let cond = self.match_enum("expected intcc condition code")?;
3041                let lhs = self.match_value("expected SSA value first operand")?;
3042                self.match_token(Token::Comma, "expected ',' between operands")?;
3043                let rhs = self.match_imm64("expected immediate second operand")?;
3044                InstructionData::IntCompareImm {
3045                    opcode,
3046                    cond,
3047                    arg: lhs,
3048                    imm: rhs,
3049                }
3050            }
3051            InstructionFormat::FloatCompare => {
3052                let cond = self.match_enum("expected floatcc condition code")?;
3053                let lhs = self.match_value("expected SSA value first operand")?;
3054                self.match_token(Token::Comma, "expected ',' between operands")?;
3055                let rhs = self.match_value("expected SSA value second operand")?;
3056                InstructionData::FloatCompare {
3057                    opcode,
3058                    cond,
3059                    args: [lhs, rhs],
3060                }
3061            }
3062            InstructionFormat::Call => {
3063                let func_ref = self.match_fn("expected function reference")?;
3064                ctx.check_fn(func_ref, self.loc)?;
3065                self.match_token(Token::LPar, "expected '(' before arguments")?;
3066                let args = self.parse_value_list()?;
3067                self.match_token(Token::RPar, "expected ')' after arguments")?;
3068                InstructionData::Call {
3069                    opcode,
3070                    func_ref,
3071                    args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists),
3072                }
3073            }
3074            InstructionFormat::CallIndirect => {
3075                let sig_ref = self.match_sig("expected signature reference")?;
3076                ctx.check_sig(sig_ref, self.loc)?;
3077                self.match_token(Token::Comma, "expected ',' between operands")?;
3078                let callee = self.match_value("expected SSA value callee operand")?;
3079                self.match_token(Token::LPar, "expected '(' before arguments")?;
3080                let args = self.parse_value_list()?;
3081                self.match_token(Token::RPar, "expected ')' after arguments")?;
3082                InstructionData::CallIndirect {
3083                    opcode,
3084                    sig_ref,
3085                    args: args.into_value_list(&[callee], &mut ctx.function.dfg.value_lists),
3086                }
3087            }
3088            InstructionFormat::FuncAddr => {
3089                let func_ref = self.match_fn("expected function reference")?;
3090                ctx.check_fn(func_ref, self.loc)?;
3091                InstructionData::FuncAddr { opcode, func_ref }
3092            }
3093            InstructionFormat::StackLoad => {
3094                let ss = self.match_ss("expected stack slot number: ss«n»")?;
3095                ctx.check_ss(ss, self.loc)?;
3096                let offset = self.optional_offset32()?;
3097                InstructionData::StackLoad {
3098                    opcode,
3099                    stack_slot: ss,
3100                    offset,
3101                }
3102            }
3103            InstructionFormat::StackStore => {
3104                let arg = self.match_value("expected SSA value operand")?;
3105                self.match_token(Token::Comma, "expected ',' between operands")?;
3106                let ss = self.match_ss("expected stack slot number: ss«n»")?;
3107                ctx.check_ss(ss, self.loc)?;
3108                let offset = self.optional_offset32()?;
3109                InstructionData::StackStore {
3110                    opcode,
3111                    arg,
3112                    stack_slot: ss,
3113                    offset,
3114                }
3115            }
3116            InstructionFormat::DynamicStackLoad => {
3117                let dss = self.match_dss("expected dynamic stack slot number: dss«n»")?;
3118                ctx.check_dss(dss, self.loc)?;
3119                InstructionData::DynamicStackLoad {
3120                    opcode,
3121                    dynamic_stack_slot: dss,
3122                }
3123            }
3124            InstructionFormat::DynamicStackStore => {
3125                let arg = self.match_value("expected SSA value operand")?;
3126                self.match_token(Token::Comma, "expected ',' between operands")?;
3127                let dss = self.match_dss("expected dynamic stack slot number: dss«n»")?;
3128                ctx.check_dss(dss, self.loc)?;
3129                InstructionData::DynamicStackStore {
3130                    opcode,
3131                    arg,
3132                    dynamic_stack_slot: dss,
3133                }
3134            }
3135            InstructionFormat::Load => {
3136                let flags = self.optional_memflags()?;
3137                let addr = self.match_value("expected SSA value address")?;
3138                let offset = self.optional_offset32()?;
3139                InstructionData::Load {
3140                    opcode,
3141                    flags,
3142                    arg: addr,
3143                    offset,
3144                }
3145            }
3146            InstructionFormat::Store => {
3147                let flags = self.optional_memflags()?;
3148                let arg = self.match_value("expected SSA value operand")?;
3149                self.match_token(Token::Comma, "expected ',' between operands")?;
3150                let addr = self.match_value("expected SSA value address")?;
3151                let offset = self.optional_offset32()?;
3152                InstructionData::Store {
3153                    opcode,
3154                    flags,
3155                    args: [arg, addr],
3156                    offset,
3157                }
3158            }
3159            InstructionFormat::Trap => {
3160                let code = self.match_enum("expected trap code")?;
3161                InstructionData::Trap { opcode, code }
3162            }
3163            InstructionFormat::CondTrap => {
3164                let arg = self.match_value("expected SSA value operand")?;
3165                self.match_token(Token::Comma, "expected ',' between operands")?;
3166                let code = self.match_enum("expected trap code")?;
3167                InstructionData::CondTrap { opcode, arg, code }
3168            }
3169            InstructionFormat::AtomicCas => {
3170                let flags = self.optional_memflags()?;
3171                let addr = self.match_value("expected SSA value address")?;
3172                self.match_token(Token::Comma, "expected ',' between operands")?;
3173                let expected = self.match_value("expected SSA value address")?;
3174                self.match_token(Token::Comma, "expected ',' between operands")?;
3175                let replacement = self.match_value("expected SSA value address")?;
3176                InstructionData::AtomicCas {
3177                    opcode,
3178                    flags,
3179                    args: [addr, expected, replacement],
3180                }
3181            }
3182            InstructionFormat::AtomicRmw => {
3183                let flags = self.optional_memflags()?;
3184                let op = self.match_enum("expected AtomicRmwOp")?;
3185                let addr = self.match_value("expected SSA value address")?;
3186                self.match_token(Token::Comma, "expected ',' between operands")?;
3187                let arg2 = self.match_value("expected SSA value address")?;
3188                InstructionData::AtomicRmw {
3189                    opcode,
3190                    flags,
3191                    op,
3192                    args: [addr, arg2],
3193                }
3194            }
3195            InstructionFormat::LoadNoOffset => {
3196                let flags = self.optional_memflags()?;
3197                let addr = self.match_value("expected SSA value address")?;
3198                InstructionData::LoadNoOffset {
3199                    opcode,
3200                    flags,
3201                    arg: addr,
3202                }
3203            }
3204            InstructionFormat::StoreNoOffset => {
3205                let flags = self.optional_memflags()?;
3206                let arg = self.match_value("expected SSA value operand")?;
3207                self.match_token(Token::Comma, "expected ',' between operands")?;
3208                let addr = self.match_value("expected SSA value address")?;
3209                InstructionData::StoreNoOffset {
3210                    opcode,
3211                    flags,
3212                    args: [arg, addr],
3213                }
3214            }
3215            InstructionFormat::IntAddTrap => {
3216                let a = self.match_value("expected SSA value operand")?;
3217                self.match_token(Token::Comma, "expected ',' between operands")?;
3218                let b = self.match_value("expected SSA value operand")?;
3219                self.match_token(Token::Comma, "expected ',' between operands")?;
3220                let code = self.match_enum("expected trap code")?;
3221                InstructionData::IntAddTrap {
3222                    opcode,
3223                    args: [a, b],
3224                    code,
3225                }
3226            }
3227        };
3228        Ok(idata)
3229    }
3230}
3231
3232#[cfg(test)]
3233mod tests {
3234    use super::*;
3235    use crate::isaspec::IsaSpec;
3236
3237    #[test]
3238    fn argument_type() {
3239        let mut p = Parser::new("i32 sext");
3240        let arg = p.parse_abi_param().unwrap();
3241        assert_eq!(arg.value_type, types::I32);
3242        assert_eq!(arg.extension, ArgumentExtension::Sext);
3243        assert_eq!(arg.purpose, ArgumentPurpose::Normal);
3244        let ParseError {
3245            location,
3246            message,
3247            is_warning,
3248        } = p.parse_abi_param().unwrap_err();
3249        assert_eq!(location.line_number, 1);
3250        assert_eq!(message, "expected parameter type");
3251        assert!(!is_warning);
3252    }
3253
3254    #[test]
3255    fn aliases() {
3256        let (func, details) = Parser::new(
3257            "function %qux() system_v {
3258                                           block0:
3259                                             v4 = iconst.i8 6
3260                                             v3 -> v4
3261                                             v1 = iadd_imm v3, 17
3262                                           }",
3263        )
3264        .parse_function()
3265        .unwrap();
3266        assert_eq!(func.name.to_string(), "%qux");
3267        let v4 = details.map.lookup_str("v4").unwrap();
3268        assert_eq!(v4.to_string(), "v4");
3269        let v3 = details.map.lookup_str("v3").unwrap();
3270        assert_eq!(v3.to_string(), "v3");
3271        match v3 {
3272            AnyEntity::Value(v3) => {
3273                let aliased_to = func.dfg.resolve_aliases(v3);
3274                assert_eq!(aliased_to.to_string(), "v4");
3275            }
3276            _ => panic!("expected value: {v3}"),
3277        }
3278    }
3279
3280    #[test]
3281    fn signature() {
3282        let sig = Parser::new("()system_v").parse_signature().unwrap();
3283        assert_eq!(sig.params.len(), 0);
3284        assert_eq!(sig.returns.len(), 0);
3285        assert_eq!(sig.call_conv, CallConv::SystemV);
3286
3287        let sig2 =
3288            Parser::new("(i8 uext, f16, f32, f64, f128, i32 sret) -> i32 sext, f64 system_v")
3289                .parse_signature()
3290                .unwrap();
3291        assert_eq!(
3292            sig2.to_string(),
3293            "(i8 uext, f16, f32, f64, f128, i32 sret) -> i32 sext, f64 system_v"
3294        );
3295        assert_eq!(sig2.call_conv, CallConv::SystemV);
3296
3297        // Old-style signature without a calling convention.
3298        assert_eq!(
3299            Parser::new("()").parse_signature().unwrap().to_string(),
3300            "() fast"
3301        );
3302        assert_eq!(
3303            Parser::new("() notacc")
3304                .parse_signature()
3305                .unwrap_err()
3306                .to_string(),
3307            "1: unknown calling convention: notacc"
3308        );
3309
3310        // `void` is not recognized as a type by the lexer. It should not appear in files.
3311        assert_eq!(
3312            Parser::new("() -> void")
3313                .parse_signature()
3314                .unwrap_err()
3315                .to_string(),
3316            "1: expected parameter type"
3317        );
3318        assert_eq!(
3319            Parser::new("i8 -> i8")
3320                .parse_signature()
3321                .unwrap_err()
3322                .to_string(),
3323            "1: expected function signature: ( args... )"
3324        );
3325        assert_eq!(
3326            Parser::new("(i8 -> i8")
3327                .parse_signature()
3328                .unwrap_err()
3329                .to_string(),
3330            "1: expected ')' after function arguments"
3331        );
3332    }
3333
3334    #[test]
3335    fn stack_slot_decl() {
3336        let (func, _) = Parser::new(
3337            "function %foo() system_v {
3338                                       ss3 = explicit_slot 13
3339                                       ss1 = explicit_slot 1
3340                                     }",
3341        )
3342        .parse_function()
3343        .unwrap();
3344        assert_eq!(func.name.to_string(), "%foo");
3345        let mut iter = func.sized_stack_slots.keys();
3346        let _ss0 = iter.next().unwrap();
3347        let ss1 = iter.next().unwrap();
3348        assert_eq!(ss1.to_string(), "ss1");
3349        assert_eq!(
3350            func.sized_stack_slots[ss1].kind,
3351            StackSlotKind::ExplicitSlot
3352        );
3353        assert_eq!(func.sized_stack_slots[ss1].size, 1);
3354        let _ss2 = iter.next().unwrap();
3355        let ss3 = iter.next().unwrap();
3356        assert_eq!(ss3.to_string(), "ss3");
3357        assert_eq!(
3358            func.sized_stack_slots[ss3].kind,
3359            StackSlotKind::ExplicitSlot
3360        );
3361        assert_eq!(func.sized_stack_slots[ss3].size, 13);
3362        assert_eq!(iter.next(), None);
3363
3364        // Catch duplicate definitions.
3365        assert_eq!(
3366            Parser::new(
3367                "function %bar() system_v {
3368                                    ss1  = explicit_slot 13
3369                                    ss1  = explicit_slot 1
3370                                }",
3371            )
3372            .parse_function()
3373            .unwrap_err()
3374            .to_string(),
3375            "3: duplicate entity: ss1"
3376        );
3377    }
3378
3379    #[test]
3380    fn block_header() {
3381        let (func, _) = Parser::new(
3382            "function %blocks() system_v {
3383                                     block0:
3384                                     block4(v3: i32):
3385                                     }",
3386        )
3387        .parse_function()
3388        .unwrap();
3389        assert_eq!(func.name.to_string(), "%blocks");
3390
3391        let mut blocks = func.layout.blocks();
3392
3393        let block0 = blocks.next().unwrap();
3394        assert_eq!(func.dfg.block_params(block0), &[]);
3395
3396        let block4 = blocks.next().unwrap();
3397        let block4_args = func.dfg.block_params(block4);
3398        assert_eq!(block4_args.len(), 1);
3399        assert_eq!(func.dfg.value_type(block4_args[0]), types::I32);
3400    }
3401
3402    #[test]
3403    fn duplicate_block() {
3404        let ParseError {
3405            location,
3406            message,
3407            is_warning,
3408        } = Parser::new(
3409            "function %blocks() system_v {
3410                block0:
3411                block0:
3412                    return 2",
3413        )
3414        .parse_function()
3415        .unwrap_err();
3416
3417        assert_eq!(location.line_number, 3);
3418        assert_eq!(message, "duplicate entity: block0");
3419        assert!(!is_warning);
3420    }
3421
3422    #[test]
3423    fn number_of_blocks() {
3424        let ParseError {
3425            location,
3426            message,
3427            is_warning,
3428        } = Parser::new(
3429            "function %a() {
3430                block100000:",
3431        )
3432        .parse_function()
3433        .unwrap_err();
3434
3435        assert_eq!(location.line_number, 2);
3436        assert_eq!(message, "too many blocks");
3437        assert!(!is_warning);
3438    }
3439
3440    #[test]
3441    fn duplicate_ss() {
3442        let ParseError {
3443            location,
3444            message,
3445            is_warning,
3446        } = Parser::new(
3447            "function %blocks() system_v {
3448                ss0 = explicit_slot 8
3449                ss0 = explicit_slot 8",
3450        )
3451        .parse_function()
3452        .unwrap_err();
3453
3454        assert_eq!(location.line_number, 3);
3455        assert_eq!(message, "duplicate entity: ss0");
3456        assert!(!is_warning);
3457    }
3458
3459    #[test]
3460    fn duplicate_gv() {
3461        let ParseError {
3462            location,
3463            message,
3464            is_warning,
3465        } = Parser::new(
3466            "function %blocks() system_v {
3467                gv0 = vmctx
3468                gv0 = vmctx",
3469        )
3470        .parse_function()
3471        .unwrap_err();
3472
3473        assert_eq!(location.line_number, 3);
3474        assert_eq!(message, "duplicate entity: gv0");
3475        assert!(!is_warning);
3476    }
3477
3478    #[test]
3479    fn duplicate_sig() {
3480        let ParseError {
3481            location,
3482            message,
3483            is_warning,
3484        } = Parser::new(
3485            "function %blocks() system_v {
3486                sig0 = ()
3487                sig0 = ()",
3488        )
3489        .parse_function()
3490        .unwrap_err();
3491
3492        assert_eq!(location.line_number, 3);
3493        assert_eq!(message, "duplicate entity: sig0");
3494        assert!(!is_warning);
3495    }
3496
3497    #[test]
3498    fn duplicate_fn() {
3499        let ParseError {
3500            location,
3501            message,
3502            is_warning,
3503        } = Parser::new(
3504            "function %blocks() system_v {
3505                sig0 = ()
3506                fn0 = %foo sig0
3507                fn0 = %foo sig0",
3508        )
3509        .parse_function()
3510        .unwrap_err();
3511
3512        assert_eq!(location.line_number, 4);
3513        assert_eq!(message, "duplicate entity: fn0");
3514        assert!(!is_warning);
3515    }
3516
3517    #[test]
3518    fn comments() {
3519        let (func, Details { comments, .. }) = Parser::new(
3520            "; before
3521                         function %comment() system_v { ; decl
3522                            ss10  = explicit_slot 13 ; stackslot.
3523                            ; Still stackslot.
3524                         block0: ; Basic block
3525                         trap user42; Instruction
3526                         } ; Trailing.
3527                         ; More trailing.",
3528        )
3529        .parse_function()
3530        .unwrap();
3531        assert_eq!(func.name.to_string(), "%comment");
3532        assert_eq!(comments.len(), 7); // no 'before' comment.
3533        assert_eq!(
3534            comments[0],
3535            Comment {
3536                entity: AnyEntity::Function,
3537                text: "; decl",
3538            }
3539        );
3540        assert_eq!(comments[1].entity.to_string(), "ss10");
3541        assert_eq!(comments[2].entity.to_string(), "ss10");
3542        assert_eq!(comments[2].text, "; Still stackslot.");
3543        assert_eq!(comments[3].entity.to_string(), "block0");
3544        assert_eq!(comments[3].text, "; Basic block");
3545
3546        assert_eq!(comments[4].entity.to_string(), "inst0");
3547        assert_eq!(comments[4].text, "; Instruction");
3548
3549        assert_eq!(comments[5].entity, AnyEntity::Function);
3550        assert_eq!(comments[6].entity, AnyEntity::Function);
3551    }
3552
3553    #[test]
3554    fn test_file() {
3555        let tf = parse_test(
3556            r#"; before
3557                             test cfg option=5
3558                             test verify
3559                             set enable_float=false
3560                             feature "foo"
3561                             feature !"bar"
3562                             ; still preamble
3563                             function %comment() system_v {}"#,
3564            ParseOptions::default(),
3565        )
3566        .unwrap();
3567        assert_eq!(tf.commands.len(), 2);
3568        assert_eq!(tf.commands[0].command, "cfg");
3569        assert_eq!(tf.commands[1].command, "verify");
3570        match tf.isa_spec {
3571            IsaSpec::None(s) => {
3572                assert!(s.enable_verifier());
3573                assert!(!s.enable_float());
3574            }
3575            _ => panic!("unexpected ISAs"),
3576        }
3577        assert_eq!(tf.features[0], Feature::With(&"foo"));
3578        assert_eq!(tf.features[1], Feature::Without(&"bar"));
3579        assert_eq!(tf.preamble_comments.len(), 2);
3580        assert_eq!(tf.preamble_comments[0].text, "; before");
3581        assert_eq!(tf.preamble_comments[1].text, "; still preamble");
3582        assert_eq!(tf.functions.len(), 1);
3583        assert_eq!(tf.functions[0].0.name.to_string(), "%comment");
3584    }
3585
3586    #[test]
3587    fn isa_spec() {
3588        assert!(parse_test(
3589            "target
3590                            function %foo() system_v {}",
3591            ParseOptions::default()
3592        )
3593        .is_err());
3594
3595        assert!(parse_test(
3596            "target x86_64
3597                            set enable_float=false
3598                            function %foo() system_v {}",
3599            ParseOptions::default()
3600        )
3601        .is_err());
3602
3603        match parse_test(
3604            "set enable_float=false
3605                          target x86_64
3606                          function %foo() system_v {}",
3607            ParseOptions::default(),
3608        )
3609        .unwrap()
3610        .isa_spec
3611        {
3612            IsaSpec::None(_) => panic!("Expected some ISA"),
3613            IsaSpec::Some(v) => {
3614                assert_eq!(v.len(), 1);
3615                assert!(v[0].name() == "x64" || v[0].name() == "x86");
3616            }
3617        }
3618    }
3619
3620    #[test]
3621    fn user_function_name() {
3622        // Valid characters in the name:
3623        let func = Parser::new(
3624            "function u1:2() system_v {
3625                                           block0:
3626                                             trap int_divz
3627                                           }",
3628        )
3629        .parse_function()
3630        .unwrap()
3631        .0;
3632        assert_eq!(func.name.to_string(), "u1:2");
3633
3634        // Invalid characters in the name:
3635        let mut parser = Parser::new(
3636            "function u123:abc() system_v {
3637                                           block0:
3638                                             trap stk_ovf
3639                                           }",
3640        );
3641        assert!(parser.parse_function().is_err());
3642
3643        // Incomplete function names should not be valid:
3644        let mut parser = Parser::new(
3645            "function u() system_v {
3646                                           block0:
3647                                             trap int_ovf
3648                                           }",
3649        );
3650        assert!(parser.parse_function().is_err());
3651
3652        let mut parser = Parser::new(
3653            "function u0() system_v {
3654                                           block0:
3655                                             trap int_ovf
3656                                           }",
3657        );
3658        assert!(parser.parse_function().is_err());
3659
3660        let mut parser = Parser::new(
3661            "function u0:() system_v {
3662                                           block0:
3663                                             trap int_ovf
3664                                           }",
3665        );
3666        assert!(parser.parse_function().is_err());
3667    }
3668
3669    #[test]
3670    fn change_default_calling_convention() {
3671        let code = "function %test() {
3672        block0:
3673            return
3674        }";
3675
3676        // By default the parser will use the fast calling convention if none is specified.
3677        let mut parser = Parser::new(code);
3678        assert_eq!(
3679            parser.parse_function().unwrap().0.signature.call_conv,
3680            CallConv::Fast
3681        );
3682
3683        // However, we can specify a different calling convention to be the default.
3684        let mut parser = Parser::new(code).with_default_calling_convention(CallConv::Cold);
3685        assert_eq!(
3686            parser.parse_function().unwrap().0.signature.call_conv,
3687            CallConv::Cold
3688        );
3689    }
3690
3691    #[test]
3692    fn u8_as_hex() {
3693        fn parse_as_uimm8(text: &str) -> ParseResult<u8> {
3694            Parser::new(text).match_uimm8("unable to parse u8")
3695        }
3696
3697        assert_eq!(parse_as_uimm8("0").unwrap(), 0);
3698        assert_eq!(parse_as_uimm8("0xff").unwrap(), 255);
3699        assert!(parse_as_uimm8("-1").is_err());
3700        assert!(parse_as_uimm8("0xffa").is_err());
3701    }
3702
3703    #[test]
3704    fn i16_as_hex() {
3705        fn parse_as_imm16(text: &str) -> ParseResult<i16> {
3706            Parser::new(text).match_imm16("unable to parse i16")
3707        }
3708
3709        assert_eq!(parse_as_imm16("0x8000").unwrap(), -32768);
3710        assert_eq!(parse_as_imm16("0xffff").unwrap(), -1);
3711        assert_eq!(parse_as_imm16("0").unwrap(), 0);
3712        assert_eq!(parse_as_imm16("0x7fff").unwrap(), 32767);
3713        assert_eq!(
3714            parse_as_imm16("-0x0001").unwrap(),
3715            parse_as_imm16("0xffff").unwrap()
3716        );
3717        assert_eq!(
3718            parse_as_imm16("-0x7fff").unwrap(),
3719            parse_as_imm16("0x8001").unwrap()
3720        );
3721        assert!(parse_as_imm16("0xffffa").is_err());
3722    }
3723
3724    #[test]
3725    fn i32_as_hex() {
3726        fn parse_as_imm32(text: &str) -> ParseResult<i32> {
3727            Parser::new(text).match_imm32("unable to parse i32")
3728        }
3729
3730        assert_eq!(parse_as_imm32("0x80000000").unwrap(), -2147483648);
3731        assert_eq!(parse_as_imm32("0xffffffff").unwrap(), -1);
3732        assert_eq!(parse_as_imm32("0").unwrap(), 0);
3733        assert_eq!(parse_as_imm32("0x7fffffff").unwrap(), 2147483647);
3734        assert_eq!(
3735            parse_as_imm32("-0x00000001").unwrap(),
3736            parse_as_imm32("0xffffffff").unwrap()
3737        );
3738        assert_eq!(
3739            parse_as_imm32("-0x7fffffff").unwrap(),
3740            parse_as_imm32("0x80000001").unwrap()
3741        );
3742        assert!(parse_as_imm32("0xffffffffa").is_err());
3743    }
3744
3745    #[test]
3746    fn i64_as_hex() {
3747        fn parse_as_imm64(text: &str) -> ParseResult<Imm64> {
3748            Parser::new(text).match_imm64("unable to parse Imm64")
3749        }
3750
3751        assert_eq!(
3752            parse_as_imm64("0x8000000000000000").unwrap(),
3753            Imm64::new(-9223372036854775808)
3754        );
3755        assert_eq!(
3756            parse_as_imm64("0xffffffffffffffff").unwrap(),
3757            Imm64::new(-1)
3758        );
3759        assert_eq!(parse_as_imm64("0").unwrap(), Imm64::new(0));
3760        assert_eq!(
3761            parse_as_imm64("0x7fffffffffffffff").unwrap(),
3762            Imm64::new(9223372036854775807)
3763        );
3764        assert_eq!(
3765            parse_as_imm64("-0x0000000000000001").unwrap(),
3766            parse_as_imm64("0xffffffffffffffff").unwrap()
3767        );
3768        assert_eq!(
3769            parse_as_imm64("-0x7fffffffffffffff").unwrap(),
3770            parse_as_imm64("0x8000000000000001").unwrap()
3771        );
3772        assert!(parse_as_imm64("0xffffffffffffffffa").is_err());
3773    }
3774
3775    #[test]
3776    fn uimm128() {
3777        macro_rules! parse_as_constant_data {
3778            ($text:expr, $type:expr) => {{
3779                Parser::new($text).parse_literals_to_constant_data($type)
3780            }};
3781        }
3782        macro_rules! can_parse_as_constant_data {
3783            ($text:expr, $type:expr) => {{
3784                assert!(parse_as_constant_data!($text, $type).is_ok())
3785            }};
3786        }
3787        macro_rules! cannot_parse_as_constant_data {
3788            ($text:expr, $type:expr) => {{
3789                assert!(parse_as_constant_data!($text, $type).is_err())
3790            }};
3791        }
3792
3793        can_parse_as_constant_data!("1 2 3 4", I32X4);
3794        can_parse_as_constant_data!("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16", I8X16);
3795        can_parse_as_constant_data!("0x1.1 0x2.2 0x3.3 0x4.4", F32X4);
3796        can_parse_as_constant_data!("0x0 0x1 0x2 0x3", I32X4);
3797        can_parse_as_constant_data!("-1 0 -1 0 -1 0 -1 0", I16X8);
3798        can_parse_as_constant_data!("0 -1", I64X2);
3799        can_parse_as_constant_data!("-1 0", I64X2);
3800        can_parse_as_constant_data!("-1 -1 -1 -1 -1", I32X4); // note that parse_literals_to_constant_data will leave extra tokens unconsumed
3801
3802        cannot_parse_as_constant_data!("1 2 3", I32X4);
3803        cannot_parse_as_constant_data!(" ", F32X4);
3804    }
3805
3806    #[test]
3807    fn parse_constant_from_booleans() {
3808        let c = Parser::new("-1 0 -1 0")
3809            .parse_literals_to_constant_data(I32X4)
3810            .unwrap();
3811        assert_eq!(
3812            c.into_vec(),
3813            [0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0]
3814        )
3815    }
3816
3817    #[test]
3818    fn parse_unbounded_constants() {
3819        // Unlike match_uimm128, match_hexadecimal_constant can parse byte sequences of any size:
3820        assert_eq!(
3821            Parser::new("0x0100")
3822                .match_hexadecimal_constant("err message")
3823                .unwrap(),
3824            vec![0, 1].into()
3825        );
3826
3827        // Only parse hexadecimal constants:
3828        assert!(Parser::new("228")
3829            .match_hexadecimal_constant("err message")
3830            .is_err());
3831    }
3832
3833    #[test]
3834    fn parse_run_commands() {
3835        // Helper for creating signatures.
3836        fn sig(ins: &[Type], outs: &[Type]) -> Signature {
3837            let mut sig = Signature::new(CallConv::Fast);
3838            for i in ins {
3839                sig.params.push(AbiParam::new(*i));
3840            }
3841            for o in outs {
3842                sig.returns.push(AbiParam::new(*o));
3843            }
3844            sig
3845        }
3846
3847        // Helper for parsing run commands.
3848        fn parse(text: &str, sig: &Signature) -> ParseResult<RunCommand> {
3849            Parser::new(text).parse_run_command(sig)
3850        }
3851
3852        // Check that we can parse and display the same set of run commands.
3853        fn assert_roundtrip(text: &str, sig: &Signature) {
3854            assert_eq!(parse(text, sig).unwrap().to_string(), text);
3855        }
3856        assert_roundtrip("run: %fn0() == 42", &sig(&[], &[I32]));
3857        assert_roundtrip(
3858            "run: %fn0(8, 16, 32, 64) == 1",
3859            &sig(&[I8, I16, I32, I64], &[I8]),
3860        );
3861        assert_roundtrip(
3862            "run: %my_func(1) == 0x0f0e0d0c0b0a09080706050403020100",
3863            &sig(&[I32], &[I8X16]),
3864        );
3865
3866        // Verify that default invocations are created when not specified.
3867        assert_eq!(
3868            parse("run", &sig(&[], &[I32])).unwrap().to_string(),
3869            "run: %default() != 0"
3870        );
3871        assert_eq!(
3872            parse("print", &sig(&[], &[F32X4, I16X8]))
3873                .unwrap()
3874                .to_string(),
3875            "print: %default()"
3876        );
3877
3878        // Demonstrate some unparsable cases.
3879        assert!(parse("print", &sig(&[I32], &[I32])).is_err());
3880        assert!(parse("print:", &sig(&[], &[])).is_err());
3881        assert!(parse("run: ", &sig(&[], &[])).is_err());
3882    }
3883
3884    #[test]
3885    fn parse_data_values() {
3886        fn parse(text: &str, ty: Type) -> DataValue {
3887            Parser::new(text).parse_data_value(ty).unwrap()
3888        }
3889
3890        assert_eq!(parse("8", I8).to_string(), "8");
3891        assert_eq!(parse("16", I16).to_string(), "16");
3892        assert_eq!(parse("32", I32).to_string(), "32");
3893        assert_eq!(parse("64", I64).to_string(), "64");
3894        assert_eq!(
3895            parse("0x01234567_01234567_01234567_01234567", I128).to_string(),
3896            "1512366032949150931280199141537564007"
3897        );
3898        assert_eq!(parse("1234567", I128).to_string(), "1234567");
3899        assert_eq!(parse("0x16.1", F16).to_string(), "0x1.610p4");
3900        assert_eq!(parse("0x32.32", F32).to_string(), "0x1.919000p5");
3901        assert_eq!(parse("0x64.64", F64).to_string(), "0x1.9190000000000p6");
3902        assert_eq!(
3903            parse("0x128.128", F128).to_string(),
3904            "0x1.2812800000000000000000000000p8"
3905        );
3906        assert_eq!(
3907            parse("[0 1 2 3]", I32X4).to_string(),
3908            "0x00000003000000020000000100000000"
3909        );
3910    }
3911
3912    #[test]
3913    fn parse_cold_blocks() {
3914        let code = "function %test() {
3915        block0 cold:
3916            return
3917        block1(v0: i32) cold:
3918            return
3919        block2(v1: i32):
3920            return
3921        }";
3922
3923        let mut parser = Parser::new(code);
3924        let func = parser.parse_function().unwrap().0;
3925        assert_eq!(func.layout.blocks().count(), 3);
3926        assert!(func.layout.is_cold(Block::from_u32(0)));
3927        assert!(func.layout.is_cold(Block::from_u32(1)));
3928        assert!(!func.layout.is_cold(Block::from_u32(2)));
3929    }
3930}