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