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