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