Skip to main content

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