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