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