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