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