1 //! Parser for .clif files. 2 3 use crate::error::{Location, ParseError, ParseResult}; 4 use crate::isaspec; 5 use crate::lexer::{LexError, Lexer, LocatedError, LocatedToken, Token}; 6 use crate::run_command::{Comparison, Invocation, RunCommand}; 7 use crate::sourcemap::SourceMap; 8 use crate::testcommand::TestCommand; 9 use crate::testfile::{Comment, Details, Feature, TestFile}; 10 use cranelift_codegen::data_value::DataValue; 11 use cranelift_codegen::entity::{EntityRef, PrimaryMap}; 12 use cranelift_codegen::ir::entities::{AnyEntity, DynamicType}; 13 use cranelift_codegen::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm32, Uimm64}; 14 use cranelift_codegen::ir::instructions::{InstructionData, InstructionFormat, VariableArgs}; 15 use cranelift_codegen::ir::types::INVALID; 16 use cranelift_codegen::ir::types::*; 17 use cranelift_codegen::ir::{self, UserExternalNameRef}; 18 use cranelift_codegen::ir::{ 19 AbiParam, ArgumentExtension, ArgumentPurpose, Block, Constant, ConstantData, DynamicStackSlot, 20 DynamicStackSlotData, DynamicTypeData, ExtFuncData, ExternalName, FuncRef, Function, 21 GlobalValue, GlobalValueData, JumpTableData, MemFlags, Opcode, SigRef, Signature, StackSlot, 22 StackSlotData, StackSlotKind, Table, TableData, Type, UserFuncName, Value, 23 }; 24 use cranelift_codegen::isa::{self, CallConv}; 25 use cranelift_codegen::packed_option::ReservedValue; 26 use cranelift_codegen::{settings, settings::Configurable, timing}; 27 use smallvec::SmallVec; 28 use std::mem; 29 use std::str::FromStr; 30 use std::{u16, u32}; 31 use target_lexicon::Triple; 32 33 macro_rules! match_imm { 34 ($signed:ty, $unsigned:ty, $parser:expr, $err_msg:expr) => {{ 35 if let Some(Token::Integer(text)) = $parser.token() { 36 $parser.consume(); 37 let negative = text.starts_with('-'); 38 let positive = text.starts_with('+'); 39 let text = if negative || positive { 40 // Strip sign prefix. 41 &text[1..] 42 } else { 43 text 44 }; 45 46 // Parse the text value; the lexer gives us raw text that looks like an integer. 47 let value = if text.starts_with("0x") { 48 // Skip underscores. 49 let text = text.replace("_", ""); 50 // Parse it in hexadecimal form. 51 <$unsigned>::from_str_radix(&text[2..], 16).map_err(|_| { 52 $parser.error(&format!( 53 "unable to parse '{}' value as a hexadecimal {} immediate", 54 &text[2..], 55 stringify!($unsigned), 56 )) 57 })? 58 } else { 59 // Parse it as a signed type to check for overflow and other issues. 60 text.parse() 61 .map_err(|_| $parser.error("expected decimal immediate"))? 62 }; 63 64 // Apply sign if necessary. 65 let signed = if negative { 66 let value = value.wrapping_neg() as $signed; 67 if value > 0 { 68 return Err($parser.error("negative number too small")); 69 } 70 value 71 } else { 72 value as $signed 73 }; 74 75 Ok(signed) 76 } else { 77 err!($parser.loc, $err_msg) 78 } 79 }}; 80 } 81 82 /// After some quick benchmarks a program should never have more than 100,000 blocks. 83 const MAX_BLOCKS_IN_A_FUNCTION: u32 = 100_000; 84 85 /// Parse the entire `text` into a list of functions. 86 /// 87 /// Any test commands or target declarations are ignored. 88 pub fn parse_functions(text: &str) -> ParseResult<Vec<Function>> { 89 let _tt = timing::parse_text(); 90 parse_test(text, ParseOptions::default()) 91 .map(|file| file.functions.into_iter().map(|(func, _)| func).collect()) 92 } 93 94 /// Options for configuring the parsing of filetests. 95 pub struct ParseOptions<'a> { 96 /// Compiler passes to run on the parsed functions. 97 pub passes: Option<&'a [String]>, 98 /// Target ISA for compiling the parsed functions, e.g. "x86_64 skylake". 99 pub target: Option<&'a str>, 100 /// Default calling convention used when none is specified for a parsed function. 101 pub default_calling_convention: CallConv, 102 /// Default for unwind-info setting (enabled or disabled). 103 pub unwind_info: bool, 104 /// Default for machine_code_cfg_info setting (enabled or disabled). 105 pub machine_code_cfg_info: bool, 106 } 107 108 impl Default for ParseOptions<'_> { 109 fn default() -> Self { 110 Self { 111 passes: None, 112 target: None, 113 default_calling_convention: CallConv::Fast, 114 unwind_info: false, 115 machine_code_cfg_info: false, 116 } 117 } 118 } 119 120 /// Parse the entire `text` as a test case file. 121 /// 122 /// The returned `TestFile` contains direct references to substrings of `text`. 123 pub fn parse_test<'a>(text: &'a str, options: ParseOptions<'a>) -> ParseResult<TestFile<'a>> { 124 let _tt = timing::parse_text(); 125 let mut parser = Parser::new(text); 126 127 // Gather the preamble comments. 128 parser.start_gathering_comments(); 129 130 let isa_spec: isaspec::IsaSpec; 131 let commands: Vec<TestCommand<'a>>; 132 133 // Check for specified passes and target, if present throw out test commands/targets specified 134 // in file. 135 match options.passes { 136 Some(pass_vec) => { 137 parser.parse_test_commands(); 138 commands = parser.parse_cmdline_passes(pass_vec); 139 parser.parse_target_specs(&options)?; 140 isa_spec = parser.parse_cmdline_target(options.target)?; 141 } 142 None => { 143 commands = parser.parse_test_commands(); 144 isa_spec = parser.parse_target_specs(&options)?; 145 } 146 }; 147 let features = parser.parse_cranelift_features()?; 148 149 // Decide between using the calling convention passed in the options or using the 150 // host's calling convention--if any tests are to be run on the host we should default to the 151 // host's calling convention. 152 parser = if commands.iter().any(|tc| tc.command == "run") { 153 let host_default_calling_convention = CallConv::triple_default(&Triple::host()); 154 parser.with_default_calling_convention(host_default_calling_convention) 155 } else { 156 parser.with_default_calling_convention(options.default_calling_convention) 157 }; 158 159 parser.token(); 160 parser.claim_gathered_comments(AnyEntity::Function); 161 162 let preamble_comments = parser.take_comments(); 163 let functions = parser.parse_function_list()?; 164 165 Ok(TestFile { 166 commands, 167 isa_spec, 168 features, 169 preamble_comments, 170 functions, 171 }) 172 } 173 174 /// Parse a CLIF comment `text` as a run command. 175 /// 176 /// Return: 177 /// - `Ok(None)` if the comment is not intended to be a `RunCommand` (i.e. does not start with `run` 178 /// or `print` 179 /// - `Ok(Some(command))` if the comment is intended as a `RunCommand` and can be parsed to one 180 /// - `Err` otherwise. 181 pub fn parse_run_command<'a>(text: &str, signature: &Signature) -> ParseResult<Option<RunCommand>> { 182 let _tt = timing::parse_text(); 183 // We remove leading spaces and semi-colons for convenience here instead of at the call sites 184 // since this function will be attempting to parse a RunCommand from a CLIF comment. 185 let trimmed_text = text.trim_start_matches(|c| c == ' ' || c == ';'); 186 let mut parser = Parser::new(trimmed_text); 187 match parser.token() { 188 Some(Token::Identifier("run")) | Some(Token::Identifier("print")) => { 189 parser.parse_run_command(signature).map(|c| Some(c)) 190 } 191 Some(_) | None => Ok(None), 192 } 193 } 194 195 pub struct Parser<'a> { 196 lex: Lexer<'a>, 197 198 lex_error: Option<LexError>, 199 200 /// Current lookahead token. 201 lookahead: Option<Token<'a>>, 202 203 /// Location of lookahead. 204 loc: Location, 205 206 /// Are we gathering any comments that we encounter? 207 gathering_comments: bool, 208 209 /// The gathered comments; claim them with `claim_gathered_comments`. 210 gathered_comments: Vec<&'a str>, 211 212 /// Comments collected so far. 213 comments: Vec<Comment<'a>>, 214 215 /// Maps inlined external names to a ref value, so they can be declared before parsing the rest 216 /// of the function later. 217 /// 218 /// This maintains backward compatibility with previous ways for declaring external names. 219 predeclared_external_names: PrimaryMap<UserExternalNameRef, ir::UserExternalName>, 220 221 /// Default calling conventions; used when none is specified. 222 default_calling_convention: CallConv, 223 } 224 225 /// Context for resolving references when parsing a single function. 226 struct Context { 227 function: Function, 228 map: SourceMap, 229 230 /// Aliases to resolve once value definitions are known. 231 aliases: Vec<Value>, 232 } 233 234 impl Context { 235 fn new(f: Function) -> Self { 236 Self { 237 function: f, 238 map: SourceMap::new(), 239 aliases: Vec::new(), 240 } 241 } 242 243 // Allocate a new stack slot. 244 fn add_ss(&mut self, ss: StackSlot, data: StackSlotData, loc: Location) -> ParseResult<()> { 245 self.map.def_ss(ss, loc)?; 246 while self.function.sized_stack_slots.next_key().index() <= ss.index() { 247 self.function 248 .create_sized_stack_slot(StackSlotData::new(StackSlotKind::ExplicitSlot, 0)); 249 } 250 self.function.sized_stack_slots[ss] = data; 251 Ok(()) 252 } 253 254 // Resolve a reference to a stack slot. 255 fn check_ss(&self, ss: StackSlot, loc: Location) -> ParseResult<()> { 256 if !self.map.contains_ss(ss) { 257 err!(loc, "undefined stack slot {}", ss) 258 } else { 259 Ok(()) 260 } 261 } 262 263 // Allocate a new stack slot. 264 fn add_dss( 265 &mut self, 266 ss: DynamicStackSlot, 267 data: DynamicStackSlotData, 268 loc: Location, 269 ) -> ParseResult<()> { 270 self.map.def_dss(ss, loc)?; 271 while self.function.dynamic_stack_slots.next_key().index() <= ss.index() { 272 self.function 273 .create_dynamic_stack_slot(DynamicStackSlotData::new( 274 StackSlotKind::ExplicitDynamicSlot, 275 data.dyn_ty, 276 )); 277 } 278 self.function.dynamic_stack_slots[ss] = data; 279 Ok(()) 280 } 281 282 // Resolve a reference to a dynamic stack slot. 283 fn check_dss(&self, dss: DynamicStackSlot, loc: Location) -> ParseResult<()> { 284 if !self.map.contains_dss(dss) { 285 err!(loc, "undefined dynamic stack slot {}", dss) 286 } else { 287 Ok(()) 288 } 289 } 290 291 // Allocate a new dynamic type. 292 fn add_dt(&mut self, dt: DynamicType, data: DynamicTypeData, loc: Location) -> ParseResult<()> { 293 self.map.def_dt(dt, loc)?; 294 while self.function.dfg.dynamic_types.next_key().index() <= dt.index() { 295 self.function.dfg.make_dynamic_ty(DynamicTypeData::new( 296 data.base_vector_ty, 297 data.dynamic_scale, 298 )); 299 } 300 self.function.dfg.dynamic_types[dt] = data; 301 Ok(()) 302 } 303 304 // Allocate a global value slot. 305 fn add_gv(&mut self, gv: GlobalValue, data: GlobalValueData, loc: Location) -> ParseResult<()> { 306 self.map.def_gv(gv, loc)?; 307 while self.function.global_values.next_key().index() <= gv.index() { 308 self.function.create_global_value(GlobalValueData::Symbol { 309 name: ExternalName::testcase(""), 310 offset: Imm64::new(0), 311 colocated: false, 312 tls: false, 313 }); 314 } 315 self.function.global_values[gv] = data; 316 Ok(()) 317 } 318 319 // Resolve a reference to a global value. 320 fn check_gv(&self, gv: GlobalValue, loc: Location) -> ParseResult<()> { 321 if !self.map.contains_gv(gv) { 322 err!(loc, "undefined global value {}", gv) 323 } else { 324 Ok(()) 325 } 326 } 327 328 // Allocate a table slot. 329 fn add_table(&mut self, table: Table, data: TableData, loc: Location) -> ParseResult<()> { 330 while self.function.tables.next_key().index() <= table.index() { 331 self.function.create_table(TableData { 332 base_gv: GlobalValue::reserved_value(), 333 min_size: Uimm64::new(0), 334 bound_gv: GlobalValue::reserved_value(), 335 element_size: Uimm64::new(0), 336 index_type: INVALID, 337 }); 338 } 339 self.function.tables[table] = data; 340 self.map.def_table(table, loc) 341 } 342 343 // Resolve a reference to a table. 344 fn check_table(&self, table: Table, loc: Location) -> ParseResult<()> { 345 if !self.map.contains_table(table) { 346 err!(loc, "undefined table {}", table) 347 } else { 348 Ok(()) 349 } 350 } 351 352 // Allocate a new signature. 353 fn add_sig( 354 &mut self, 355 sig: SigRef, 356 data: Signature, 357 loc: Location, 358 defaultcc: CallConv, 359 ) -> ParseResult<()> { 360 self.map.def_sig(sig, loc)?; 361 while self.function.dfg.signatures.next_key().index() <= sig.index() { 362 self.function.import_signature(Signature::new(defaultcc)); 363 } 364 self.function.dfg.signatures[sig] = data; 365 Ok(()) 366 } 367 368 // Resolve a reference to a signature. 369 fn check_sig(&self, sig: SigRef, loc: Location) -> ParseResult<()> { 370 if !self.map.contains_sig(sig) { 371 err!(loc, "undefined signature {}", sig) 372 } else { 373 Ok(()) 374 } 375 } 376 377 // Allocate a new external function. 378 fn add_fn(&mut self, fn_: FuncRef, data: ExtFuncData, loc: Location) -> ParseResult<()> { 379 self.map.def_fn(fn_, loc)?; 380 while self.function.dfg.ext_funcs.next_key().index() <= fn_.index() { 381 self.function.import_function(ExtFuncData { 382 name: ExternalName::testcase(""), 383 signature: SigRef::reserved_value(), 384 colocated: false, 385 }); 386 } 387 self.function.dfg.ext_funcs[fn_] = data; 388 Ok(()) 389 } 390 391 // Resolve a reference to a function. 392 fn check_fn(&self, fn_: FuncRef, loc: Location) -> ParseResult<()> { 393 if !self.map.contains_fn(fn_) { 394 err!(loc, "undefined function {}", fn_) 395 } else { 396 Ok(()) 397 } 398 } 399 400 // Allocate a new constant. 401 fn add_constant( 402 &mut self, 403 constant: Constant, 404 data: ConstantData, 405 loc: Location, 406 ) -> ParseResult<()> { 407 self.map.def_constant(constant, loc)?; 408 self.function.dfg.constants.set(constant, data); 409 Ok(()) 410 } 411 412 // Configure the stack limit of the current function. 413 fn add_stack_limit(&mut self, limit: GlobalValue, loc: Location) -> ParseResult<()> { 414 if self.function.stack_limit.is_some() { 415 return err!(loc, "stack limit defined twice"); 416 } 417 self.function.stack_limit = Some(limit); 418 Ok(()) 419 } 420 421 // Resolve a reference to a constant. 422 fn check_constant(&self, c: Constant, loc: Location) -> ParseResult<()> { 423 if !self.map.contains_constant(c) { 424 err!(loc, "undefined constant {}", c) 425 } else { 426 Ok(()) 427 } 428 } 429 430 // Allocate a new block. 431 fn add_block(&mut self, block: Block, loc: Location) -> ParseResult<Block> { 432 self.map.def_block(block, loc)?; 433 while self.function.dfg.num_blocks() <= block.index() { 434 self.function.dfg.make_block(); 435 } 436 self.function.layout.append_block(block); 437 Ok(block) 438 } 439 440 /// Set a block as cold. 441 fn set_cold_block(&mut self, block: Block) { 442 self.function.layout.set_cold(block); 443 } 444 } 445 446 impl<'a> Parser<'a> { 447 /// Create a new `Parser` which reads `text`. The referenced text must outlive the parser. 448 pub fn new(text: &'a str) -> Self { 449 Self { 450 lex: Lexer::new(text), 451 lex_error: None, 452 lookahead: None, 453 loc: Location { line_number: 0 }, 454 gathering_comments: false, 455 gathered_comments: Vec::new(), 456 comments: Vec::new(), 457 default_calling_convention: CallConv::Fast, 458 predeclared_external_names: Default::default(), 459 } 460 } 461 462 /// Modify the default calling convention; returns a new parser with the changed calling 463 /// convention. 464 pub fn with_default_calling_convention(self, default_calling_convention: CallConv) -> Self { 465 Self { 466 default_calling_convention, 467 ..self 468 } 469 } 470 471 // Consume the current lookahead token and return it. 472 fn consume(&mut self) -> Token<'a> { 473 self.lookahead.take().expect("No token to consume") 474 } 475 476 // Consume the whole line following the current lookahead token. 477 // Return the text of the line tail. 478 fn consume_line(&mut self) -> &'a str { 479 let rest = self.lex.rest_of_line(); 480 self.consume(); 481 rest 482 } 483 484 // Get the current lookahead token, after making sure there is one. 485 fn token(&mut self) -> Option<Token<'a>> { 486 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 .map(|abi| abi.value_type) 2350 .collect::<Vec<_>>(); 2351 let args = self.parse_data_value_list(&arg_types)?; 2352 2353 self.match_token( 2354 Token::RPar, 2355 "expected invocation parentheses, e.g. %fn(...)", 2356 )?; 2357 Ok(Invocation::new(name, args)) 2358 } else { 2359 Err(self.error("expected a function name, e.g. %my_fn")) 2360 } 2361 } 2362 2363 /// Parse a comparison operator for run commands. 2364 /// 2365 /// comparison ::= "==" | "!=" 2366 fn parse_run_comparison(&mut self) -> ParseResult<Comparison> { 2367 if self.optional(Token::Equal) { 2368 self.match_token(Token::Equal, "expected another =")?; 2369 Ok(Comparison::Equals) 2370 } else if self.optional(Token::Not) { 2371 self.match_token(Token::Equal, "expected a =")?; 2372 Ok(Comparison::NotEquals) 2373 } else { 2374 Err(self.error("unable to parse a valid comparison operator")) 2375 } 2376 } 2377 2378 /// Parse the expected return values of a run invocation. 2379 /// 2380 /// expected ::= "[" "]" 2381 /// | data-value 2382 /// | "[" data-value-list "]" 2383 fn parse_run_returns(&mut self, sig: &Signature) -> ParseResult<Vec<DataValue>> { 2384 if sig.returns.len() != 1 { 2385 self.match_token(Token::LBracket, "expected a left bracket [")?; 2386 } 2387 2388 let returns = self 2389 .parse_data_value_list(&sig.returns.iter().map(|a| a.value_type).collect::<Vec<_>>())?; 2390 2391 if sig.returns.len() != 1 { 2392 self.match_token(Token::RBracket, "expected a right bracket ]")?; 2393 } 2394 Ok(returns) 2395 } 2396 2397 /// Parse a comma-separated list of data values. 2398 /// 2399 /// data-value-list ::= [data-value {"," data-value-list}] 2400 fn parse_data_value_list(&mut self, types: &[Type]) -> ParseResult<Vec<DataValue>> { 2401 let mut values = vec![]; 2402 for ty in types.iter().take(1) { 2403 values.push(self.parse_data_value(*ty)?); 2404 } 2405 for ty in types.iter().skip(1) { 2406 self.match_token( 2407 Token::Comma, 2408 "expected a comma between invocation arguments", 2409 )?; 2410 values.push(self.parse_data_value(*ty)?); 2411 } 2412 Ok(values) 2413 } 2414 2415 /// Parse a data value; e.g. `42`, `4.2`, `true`. 2416 /// 2417 /// data-value-list ::= [data-value {"," data-value-list}] 2418 fn parse_data_value(&mut self, ty: Type) -> ParseResult<DataValue> { 2419 let dv = match ty { 2420 I8 => DataValue::from(self.match_imm8("expected a i8")?), 2421 I16 => DataValue::from(self.match_imm16("expected an i16")?), 2422 I32 => DataValue::from(self.match_imm32("expected an i32")?), 2423 I64 => DataValue::from(Into::<i64>::into(self.match_imm64("expected an i64")?)), 2424 I128 => DataValue::from(self.match_imm128("expected an i128")?), 2425 F32 => DataValue::from(self.match_ieee32("expected an f32")?), 2426 F64 => DataValue::from(self.match_ieee64("expected an f64")?), 2427 _ if (ty.is_vector() || ty.is_dynamic_vector()) => { 2428 let as_vec = self.match_uimm128(ty)?.into_vec(); 2429 if as_vec.len() == 16 { 2430 let mut as_array = [0; 16]; 2431 as_array.copy_from_slice(&as_vec[..]); 2432 DataValue::from(as_array) 2433 } else if as_vec.len() == 8 { 2434 let mut as_array = [0; 8]; 2435 as_array.copy_from_slice(&as_vec[..]); 2436 DataValue::from(as_array) 2437 } else { 2438 return Err(self.error("only 128-bit vectors are currently supported")); 2439 } 2440 } 2441 _ => return Err(self.error(&format!("don't know how to parse data values of: {}", ty))), 2442 }; 2443 Ok(dv) 2444 } 2445 2446 // Parse the operands following the instruction opcode. 2447 // This depends on the format of the opcode. 2448 fn parse_inst_operands( 2449 &mut self, 2450 ctx: &mut Context, 2451 opcode: Opcode, 2452 explicit_control_type: Option<Type>, 2453 ) -> ParseResult<InstructionData> { 2454 let idata = match opcode.format() { 2455 InstructionFormat::Unary => InstructionData::Unary { 2456 opcode, 2457 arg: self.match_value("expected SSA value operand")?, 2458 }, 2459 InstructionFormat::UnaryImm => InstructionData::UnaryImm { 2460 opcode, 2461 imm: self.match_imm64("expected immediate integer operand")?, 2462 }, 2463 InstructionFormat::UnaryIeee32 => InstructionData::UnaryIeee32 { 2464 opcode, 2465 imm: self.match_ieee32("expected immediate 32-bit float operand")?, 2466 }, 2467 InstructionFormat::UnaryIeee64 => InstructionData::UnaryIeee64 { 2468 opcode, 2469 imm: self.match_ieee64("expected immediate 64-bit float operand")?, 2470 }, 2471 InstructionFormat::UnaryConst => { 2472 let constant_handle = if let Some(Token::Constant(_)) = self.token() { 2473 // If handed a `const?`, use that. 2474 let c = self.match_constant()?; 2475 ctx.check_constant(c, self.loc)?; 2476 c 2477 } else if let Some(controlling_type) = explicit_control_type { 2478 // If an explicit control type is present, we expect a sized value and insert 2479 // it in the constant pool. 2480 let uimm128 = self.match_uimm128(controlling_type)?; 2481 ctx.function.dfg.constants.insert(uimm128) 2482 } else { 2483 return err!( 2484 self.loc, 2485 "Expected either a const entity or a typed value, e.g. inst.i32x4 [...]" 2486 ); 2487 }; 2488 InstructionData::UnaryConst { 2489 opcode, 2490 constant_handle, 2491 } 2492 } 2493 InstructionFormat::UnaryGlobalValue => { 2494 let gv = self.match_gv("expected global value")?; 2495 ctx.check_gv(gv, self.loc)?; 2496 InstructionData::UnaryGlobalValue { 2497 opcode, 2498 global_value: gv, 2499 } 2500 } 2501 InstructionFormat::Binary => { 2502 let lhs = self.match_value("expected SSA value first operand")?; 2503 self.match_token(Token::Comma, "expected ',' between operands")?; 2504 let rhs = self.match_value("expected SSA value second operand")?; 2505 InstructionData::Binary { 2506 opcode, 2507 args: [lhs, rhs], 2508 } 2509 } 2510 InstructionFormat::BinaryImm8 => { 2511 let arg = self.match_value("expected SSA value first operand")?; 2512 self.match_token(Token::Comma, "expected ',' between operands")?; 2513 let imm = self.match_uimm8("expected unsigned 8-bit immediate")?; 2514 InstructionData::BinaryImm8 { opcode, arg, imm } 2515 } 2516 InstructionFormat::BinaryImm64 => { 2517 let lhs = self.match_value("expected SSA value first operand")?; 2518 self.match_token(Token::Comma, "expected ',' between operands")?; 2519 let rhs = self.match_imm64("expected immediate integer second operand")?; 2520 InstructionData::BinaryImm64 { 2521 opcode, 2522 arg: lhs, 2523 imm: rhs, 2524 } 2525 } 2526 InstructionFormat::Ternary => { 2527 // Names here refer to the `select` instruction. 2528 // This format is also use by `fma`. 2529 let ctrl_arg = self.match_value("expected SSA value control operand")?; 2530 self.match_token(Token::Comma, "expected ',' between operands")?; 2531 let true_arg = self.match_value("expected SSA value true operand")?; 2532 self.match_token(Token::Comma, "expected ',' between operands")?; 2533 let false_arg = self.match_value("expected SSA value false operand")?; 2534 InstructionData::Ternary { 2535 opcode, 2536 args: [ctrl_arg, true_arg, false_arg], 2537 } 2538 } 2539 InstructionFormat::MultiAry => { 2540 let args = self.parse_value_list()?; 2541 InstructionData::MultiAry { 2542 opcode, 2543 args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists), 2544 } 2545 } 2546 InstructionFormat::NullAry => InstructionData::NullAry { opcode }, 2547 InstructionFormat::Jump => { 2548 // Parse the destination block number. 2549 let block_num = self.match_block("expected jump destination block")?; 2550 let args = self.parse_opt_value_list()?; 2551 let destination = ctx.function.dfg.block_call(block_num, &args); 2552 InstructionData::Jump { 2553 opcode, 2554 destination, 2555 } 2556 } 2557 InstructionFormat::Brif => { 2558 let arg = self.match_value("expected SSA value control operand")?; 2559 self.match_token(Token::Comma, "expected ',' between operands")?; 2560 let block_then = { 2561 let block_num = self.match_block("expected branch then block")?; 2562 let args = self.parse_opt_value_list()?; 2563 ctx.function.dfg.block_call(block_num, &args) 2564 }; 2565 self.match_token(Token::Comma, "expected ',' between operands")?; 2566 let block_else = { 2567 let block_num = self.match_block("expected branch else block")?; 2568 let args = self.parse_opt_value_list()?; 2569 ctx.function.dfg.block_call(block_num, &args) 2570 }; 2571 InstructionData::Brif { 2572 opcode, 2573 arg, 2574 blocks: [block_then, block_else], 2575 } 2576 } 2577 InstructionFormat::BranchTable => { 2578 let arg = self.match_value("expected SSA value operand")?; 2579 self.match_token(Token::Comma, "expected ',' between operands")?; 2580 let block_num = self.match_block("expected branch destination block")?; 2581 let args = self.parse_opt_value_list()?; 2582 let destination = ctx.function.dfg.block_call(block_num, &args); 2583 self.match_token(Token::Comma, "expected ',' between operands")?; 2584 let table = self.parse_jump_table(ctx, destination)?; 2585 InstructionData::BranchTable { opcode, arg, table } 2586 } 2587 InstructionFormat::TernaryImm8 => { 2588 let lhs = self.match_value("expected SSA value first operand")?; 2589 self.match_token(Token::Comma, "expected ',' between operands")?; 2590 let rhs = self.match_value("expected SSA value last operand")?; 2591 self.match_token(Token::Comma, "expected ',' between operands")?; 2592 let imm = self.match_uimm8("expected 8-bit immediate")?; 2593 InstructionData::TernaryImm8 { 2594 opcode, 2595 imm, 2596 args: [lhs, rhs], 2597 } 2598 } 2599 InstructionFormat::Shuffle => { 2600 let a = self.match_value("expected SSA value first operand")?; 2601 self.match_token(Token::Comma, "expected ',' between operands")?; 2602 let b = self.match_value("expected SSA value second operand")?; 2603 self.match_token(Token::Comma, "expected ',' between operands")?; 2604 let uimm128 = self.match_uimm128(I8X16)?; 2605 let imm = ctx.function.dfg.immediates.push(uimm128); 2606 InstructionData::Shuffle { 2607 opcode, 2608 imm, 2609 args: [a, b], 2610 } 2611 } 2612 InstructionFormat::IntCompare => { 2613 let cond = self.match_enum("expected intcc condition code")?; 2614 let lhs = self.match_value("expected SSA value first operand")?; 2615 self.match_token(Token::Comma, "expected ',' between operands")?; 2616 let rhs = self.match_value("expected SSA value second operand")?; 2617 InstructionData::IntCompare { 2618 opcode, 2619 cond, 2620 args: [lhs, rhs], 2621 } 2622 } 2623 InstructionFormat::IntCompareImm => { 2624 let cond = self.match_enum("expected intcc condition code")?; 2625 let lhs = self.match_value("expected SSA value first operand")?; 2626 self.match_token(Token::Comma, "expected ',' between operands")?; 2627 let rhs = self.match_imm64("expected immediate second operand")?; 2628 InstructionData::IntCompareImm { 2629 opcode, 2630 cond, 2631 arg: lhs, 2632 imm: rhs, 2633 } 2634 } 2635 InstructionFormat::FloatCompare => { 2636 let cond = self.match_enum("expected floatcc condition code")?; 2637 let lhs = self.match_value("expected SSA value first operand")?; 2638 self.match_token(Token::Comma, "expected ',' between operands")?; 2639 let rhs = self.match_value("expected SSA value second operand")?; 2640 InstructionData::FloatCompare { 2641 opcode, 2642 cond, 2643 args: [lhs, rhs], 2644 } 2645 } 2646 InstructionFormat::Call => { 2647 let func_ref = self.match_fn("expected function reference")?; 2648 ctx.check_fn(func_ref, self.loc)?; 2649 self.match_token(Token::LPar, "expected '(' before arguments")?; 2650 let args = self.parse_value_list()?; 2651 self.match_token(Token::RPar, "expected ')' after arguments")?; 2652 InstructionData::Call { 2653 opcode, 2654 func_ref, 2655 args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists), 2656 } 2657 } 2658 InstructionFormat::CallIndirect => { 2659 let sig_ref = self.match_sig("expected signature reference")?; 2660 ctx.check_sig(sig_ref, self.loc)?; 2661 self.match_token(Token::Comma, "expected ',' between operands")?; 2662 let callee = self.match_value("expected SSA value callee operand")?; 2663 self.match_token(Token::LPar, "expected '(' before arguments")?; 2664 let args = self.parse_value_list()?; 2665 self.match_token(Token::RPar, "expected ')' after arguments")?; 2666 InstructionData::CallIndirect { 2667 opcode, 2668 sig_ref, 2669 args: args.into_value_list(&[callee], &mut ctx.function.dfg.value_lists), 2670 } 2671 } 2672 InstructionFormat::FuncAddr => { 2673 let func_ref = self.match_fn("expected function reference")?; 2674 ctx.check_fn(func_ref, self.loc)?; 2675 InstructionData::FuncAddr { opcode, func_ref } 2676 } 2677 InstructionFormat::StackLoad => { 2678 let ss = self.match_ss("expected stack slot number: ss«n»")?; 2679 ctx.check_ss(ss, self.loc)?; 2680 let offset = self.optional_offset32()?; 2681 InstructionData::StackLoad { 2682 opcode, 2683 stack_slot: ss, 2684 offset, 2685 } 2686 } 2687 InstructionFormat::StackStore => { 2688 let arg = self.match_value("expected SSA value operand")?; 2689 self.match_token(Token::Comma, "expected ',' between operands")?; 2690 let ss = self.match_ss("expected stack slot number: ss«n»")?; 2691 ctx.check_ss(ss, self.loc)?; 2692 let offset = self.optional_offset32()?; 2693 InstructionData::StackStore { 2694 opcode, 2695 arg, 2696 stack_slot: ss, 2697 offset, 2698 } 2699 } 2700 InstructionFormat::DynamicStackLoad => { 2701 let dss = self.match_dss("expected dynamic stack slot number: dss«n»")?; 2702 ctx.check_dss(dss, self.loc)?; 2703 InstructionData::DynamicStackLoad { 2704 opcode, 2705 dynamic_stack_slot: dss, 2706 } 2707 } 2708 InstructionFormat::DynamicStackStore => { 2709 let arg = self.match_value("expected SSA value operand")?; 2710 self.match_token(Token::Comma, "expected ',' between operands")?; 2711 let dss = self.match_dss("expected dynamic stack slot number: dss«n»")?; 2712 ctx.check_dss(dss, self.loc)?; 2713 InstructionData::DynamicStackStore { 2714 opcode, 2715 arg, 2716 dynamic_stack_slot: dss, 2717 } 2718 } 2719 InstructionFormat::TableAddr => { 2720 let table = self.match_table("expected table identifier")?; 2721 ctx.check_table(table, self.loc)?; 2722 self.match_token(Token::Comma, "expected ',' between operands")?; 2723 let arg = self.match_value("expected SSA value table address")?; 2724 let offset = self.optional_offset32()?; 2725 InstructionData::TableAddr { 2726 opcode, 2727 table, 2728 arg, 2729 offset, 2730 } 2731 } 2732 InstructionFormat::Load => { 2733 let flags = self.optional_memflags(); 2734 let addr = self.match_value("expected SSA value address")?; 2735 let offset = self.optional_offset32()?; 2736 InstructionData::Load { 2737 opcode, 2738 flags, 2739 arg: addr, 2740 offset, 2741 } 2742 } 2743 InstructionFormat::Store => { 2744 let flags = self.optional_memflags(); 2745 let arg = self.match_value("expected SSA value operand")?; 2746 self.match_token(Token::Comma, "expected ',' between operands")?; 2747 let addr = self.match_value("expected SSA value address")?; 2748 let offset = self.optional_offset32()?; 2749 InstructionData::Store { 2750 opcode, 2751 flags, 2752 args: [arg, addr], 2753 offset, 2754 } 2755 } 2756 InstructionFormat::Trap => { 2757 let code = self.match_enum("expected trap code")?; 2758 InstructionData::Trap { opcode, code } 2759 } 2760 InstructionFormat::CondTrap => { 2761 let arg = self.match_value("expected SSA value operand")?; 2762 self.match_token(Token::Comma, "expected ',' between operands")?; 2763 let code = self.match_enum("expected trap code")?; 2764 InstructionData::CondTrap { opcode, arg, code } 2765 } 2766 InstructionFormat::AtomicCas => { 2767 let flags = self.optional_memflags(); 2768 let addr = self.match_value("expected SSA value address")?; 2769 self.match_token(Token::Comma, "expected ',' between operands")?; 2770 let expected = self.match_value("expected SSA value address")?; 2771 self.match_token(Token::Comma, "expected ',' between operands")?; 2772 let replacement = self.match_value("expected SSA value address")?; 2773 InstructionData::AtomicCas { 2774 opcode, 2775 flags, 2776 args: [addr, expected, replacement], 2777 } 2778 } 2779 InstructionFormat::AtomicRmw => { 2780 let flags = self.optional_memflags(); 2781 let op = self.match_enum("expected AtomicRmwOp")?; 2782 let addr = self.match_value("expected SSA value address")?; 2783 self.match_token(Token::Comma, "expected ',' between operands")?; 2784 let arg2 = self.match_value("expected SSA value address")?; 2785 InstructionData::AtomicRmw { 2786 opcode, 2787 flags, 2788 op, 2789 args: [addr, arg2], 2790 } 2791 } 2792 InstructionFormat::LoadNoOffset => { 2793 let flags = self.optional_memflags(); 2794 let addr = self.match_value("expected SSA value address")?; 2795 InstructionData::LoadNoOffset { 2796 opcode, 2797 flags, 2798 arg: addr, 2799 } 2800 } 2801 InstructionFormat::StoreNoOffset => { 2802 let flags = self.optional_memflags(); 2803 let arg = self.match_value("expected SSA value operand")?; 2804 self.match_token(Token::Comma, "expected ',' between operands")?; 2805 let addr = self.match_value("expected SSA value address")?; 2806 InstructionData::StoreNoOffset { 2807 opcode, 2808 flags, 2809 args: [arg, addr], 2810 } 2811 } 2812 InstructionFormat::IntAddTrap => { 2813 let a = self.match_value("expected SSA value operand")?; 2814 self.match_token(Token::Comma, "expected ',' between operands")?; 2815 let b = self.match_value("expected SSA value operand")?; 2816 self.match_token(Token::Comma, "expected ',' between operands")?; 2817 let code = self.match_enum("expected trap code")?; 2818 InstructionData::IntAddTrap { 2819 opcode, 2820 args: [a, b], 2821 code, 2822 } 2823 } 2824 }; 2825 Ok(idata) 2826 } 2827 } 2828 2829 #[cfg(test)] 2830 mod tests { 2831 use super::*; 2832 use crate::error::ParseError; 2833 use crate::isaspec::IsaSpec; 2834 use crate::testfile::{Comment, Details}; 2835 use cranelift_codegen::ir::entities::AnyEntity; 2836 use cranelift_codegen::ir::types; 2837 use cranelift_codegen::ir::StackSlotKind; 2838 use cranelift_codegen::ir::{ArgumentExtension, ArgumentPurpose}; 2839 use cranelift_codegen::isa::CallConv; 2840 2841 #[test] 2842 fn argument_type() { 2843 let mut p = Parser::new("i32 sext"); 2844 let arg = p.parse_abi_param().unwrap(); 2845 assert_eq!(arg.value_type, types::I32); 2846 assert_eq!(arg.extension, ArgumentExtension::Sext); 2847 assert_eq!(arg.purpose, ArgumentPurpose::Normal); 2848 let ParseError { 2849 location, 2850 message, 2851 is_warning, 2852 } = p.parse_abi_param().unwrap_err(); 2853 assert_eq!(location.line_number, 1); 2854 assert_eq!(message, "expected parameter type"); 2855 assert!(!is_warning); 2856 } 2857 2858 #[test] 2859 fn aliases() { 2860 let (func, details) = Parser::new( 2861 "function %qux() system_v { 2862 block0: 2863 v4 = iconst.i8 6 2864 v3 -> v4 2865 v1 = iadd_imm v3, 17 2866 }", 2867 ) 2868 .parse_function() 2869 .unwrap(); 2870 assert_eq!(func.name.to_string(), "%qux"); 2871 let v4 = details.map.lookup_str("v4").unwrap(); 2872 assert_eq!(v4.to_string(), "v4"); 2873 let v3 = details.map.lookup_str("v3").unwrap(); 2874 assert_eq!(v3.to_string(), "v3"); 2875 match v3 { 2876 AnyEntity::Value(v3) => { 2877 let aliased_to = func.dfg.resolve_aliases(v3); 2878 assert_eq!(aliased_to.to_string(), "v4"); 2879 } 2880 _ => panic!("expected value: {}", v3), 2881 } 2882 } 2883 2884 #[test] 2885 fn signature() { 2886 let sig = Parser::new("()system_v").parse_signature().unwrap(); 2887 assert_eq!(sig.params.len(), 0); 2888 assert_eq!(sig.returns.len(), 0); 2889 assert_eq!(sig.call_conv, CallConv::SystemV); 2890 2891 let sig2 = Parser::new("(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 system_v") 2892 .parse_signature() 2893 .unwrap(); 2894 assert_eq!( 2895 sig2.to_string(), 2896 "(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 system_v" 2897 ); 2898 assert_eq!(sig2.call_conv, CallConv::SystemV); 2899 2900 // Old-style signature without a calling convention. 2901 assert_eq!( 2902 Parser::new("()").parse_signature().unwrap().to_string(), 2903 "() fast" 2904 ); 2905 assert_eq!( 2906 Parser::new("() notacc") 2907 .parse_signature() 2908 .unwrap_err() 2909 .to_string(), 2910 "1: unknown calling convention: notacc" 2911 ); 2912 2913 // `void` is not recognized as a type by the lexer. It should not appear in files. 2914 assert_eq!( 2915 Parser::new("() -> void") 2916 .parse_signature() 2917 .unwrap_err() 2918 .to_string(), 2919 "1: expected parameter type" 2920 ); 2921 assert_eq!( 2922 Parser::new("i8 -> i8") 2923 .parse_signature() 2924 .unwrap_err() 2925 .to_string(), 2926 "1: expected function signature: ( args... )" 2927 ); 2928 assert_eq!( 2929 Parser::new("(i8 -> i8") 2930 .parse_signature() 2931 .unwrap_err() 2932 .to_string(), 2933 "1: expected ')' after function arguments" 2934 ); 2935 } 2936 2937 #[test] 2938 fn stack_slot_decl() { 2939 let (func, _) = Parser::new( 2940 "function %foo() system_v { 2941 ss3 = explicit_slot 13 2942 ss1 = explicit_slot 1 2943 }", 2944 ) 2945 .parse_function() 2946 .unwrap(); 2947 assert_eq!(func.name.to_string(), "%foo"); 2948 let mut iter = func.sized_stack_slots.keys(); 2949 let _ss0 = iter.next().unwrap(); 2950 let ss1 = iter.next().unwrap(); 2951 assert_eq!(ss1.to_string(), "ss1"); 2952 assert_eq!( 2953 func.sized_stack_slots[ss1].kind, 2954 StackSlotKind::ExplicitSlot 2955 ); 2956 assert_eq!(func.sized_stack_slots[ss1].size, 1); 2957 let _ss2 = iter.next().unwrap(); 2958 let ss3 = iter.next().unwrap(); 2959 assert_eq!(ss3.to_string(), "ss3"); 2960 assert_eq!( 2961 func.sized_stack_slots[ss3].kind, 2962 StackSlotKind::ExplicitSlot 2963 ); 2964 assert_eq!(func.sized_stack_slots[ss3].size, 13); 2965 assert_eq!(iter.next(), None); 2966 2967 // Catch duplicate definitions. 2968 assert_eq!( 2969 Parser::new( 2970 "function %bar() system_v { 2971 ss1 = explicit_slot 13 2972 ss1 = explicit_slot 1 2973 }", 2974 ) 2975 .parse_function() 2976 .unwrap_err() 2977 .to_string(), 2978 "3: duplicate entity: ss1" 2979 ); 2980 } 2981 2982 #[test] 2983 fn block_header() { 2984 let (func, _) = Parser::new( 2985 "function %blocks() system_v { 2986 block0: 2987 block4(v3: i32): 2988 }", 2989 ) 2990 .parse_function() 2991 .unwrap(); 2992 assert_eq!(func.name.to_string(), "%blocks"); 2993 2994 let mut blocks = func.layout.blocks(); 2995 2996 let block0 = blocks.next().unwrap(); 2997 assert_eq!(func.dfg.block_params(block0), &[]); 2998 2999 let block4 = blocks.next().unwrap(); 3000 let block4_args = func.dfg.block_params(block4); 3001 assert_eq!(block4_args.len(), 1); 3002 assert_eq!(func.dfg.value_type(block4_args[0]), types::I32); 3003 } 3004 3005 #[test] 3006 fn duplicate_block() { 3007 let ParseError { 3008 location, 3009 message, 3010 is_warning, 3011 } = Parser::new( 3012 "function %blocks() system_v { 3013 block0: 3014 block0: 3015 return 2", 3016 ) 3017 .parse_function() 3018 .unwrap_err(); 3019 3020 assert_eq!(location.line_number, 3); 3021 assert_eq!(message, "duplicate entity: block0"); 3022 assert!(!is_warning); 3023 } 3024 3025 #[test] 3026 fn number_of_blocks() { 3027 let ParseError { 3028 location, 3029 message, 3030 is_warning, 3031 } = Parser::new( 3032 "function %a() { 3033 block100000:", 3034 ) 3035 .parse_function() 3036 .unwrap_err(); 3037 3038 assert_eq!(location.line_number, 2); 3039 assert_eq!(message, "too many blocks"); 3040 assert!(!is_warning); 3041 } 3042 3043 #[test] 3044 fn duplicate_ss() { 3045 let ParseError { 3046 location, 3047 message, 3048 is_warning, 3049 } = Parser::new( 3050 "function %blocks() system_v { 3051 ss0 = explicit_slot 8 3052 ss0 = explicit_slot 8", 3053 ) 3054 .parse_function() 3055 .unwrap_err(); 3056 3057 assert_eq!(location.line_number, 3); 3058 assert_eq!(message, "duplicate entity: ss0"); 3059 assert!(!is_warning); 3060 } 3061 3062 #[test] 3063 fn duplicate_gv() { 3064 let ParseError { 3065 location, 3066 message, 3067 is_warning, 3068 } = Parser::new( 3069 "function %blocks() system_v { 3070 gv0 = vmctx 3071 gv0 = vmctx", 3072 ) 3073 .parse_function() 3074 .unwrap_err(); 3075 3076 assert_eq!(location.line_number, 3); 3077 assert_eq!(message, "duplicate entity: gv0"); 3078 assert!(!is_warning); 3079 } 3080 3081 #[test] 3082 fn duplicate_sig() { 3083 let ParseError { 3084 location, 3085 message, 3086 is_warning, 3087 } = Parser::new( 3088 "function %blocks() system_v { 3089 sig0 = () 3090 sig0 = ()", 3091 ) 3092 .parse_function() 3093 .unwrap_err(); 3094 3095 assert_eq!(location.line_number, 3); 3096 assert_eq!(message, "duplicate entity: sig0"); 3097 assert!(!is_warning); 3098 } 3099 3100 #[test] 3101 fn duplicate_fn() { 3102 let ParseError { 3103 location, 3104 message, 3105 is_warning, 3106 } = Parser::new( 3107 "function %blocks() system_v { 3108 sig0 = () 3109 fn0 = %foo sig0 3110 fn0 = %foo sig0", 3111 ) 3112 .parse_function() 3113 .unwrap_err(); 3114 3115 assert_eq!(location.line_number, 4); 3116 assert_eq!(message, "duplicate entity: fn0"); 3117 assert!(!is_warning); 3118 } 3119 3120 #[test] 3121 fn comments() { 3122 let (func, Details { comments, .. }) = Parser::new( 3123 "; before 3124 function %comment() system_v { ; decl 3125 ss10 = explicit_slot 13 ; stackslot. 3126 ; Still stackslot. 3127 block0: ; Basic block 3128 trap user42; Instruction 3129 } ; Trailing. 3130 ; More trailing.", 3131 ) 3132 .parse_function() 3133 .unwrap(); 3134 assert_eq!(func.name.to_string(), "%comment"); 3135 assert_eq!(comments.len(), 7); // no 'before' comment. 3136 assert_eq!( 3137 comments[0], 3138 Comment { 3139 entity: AnyEntity::Function, 3140 text: "; decl", 3141 } 3142 ); 3143 assert_eq!(comments[1].entity.to_string(), "ss10"); 3144 assert_eq!(comments[2].entity.to_string(), "ss10"); 3145 assert_eq!(comments[2].text, "; Still stackslot."); 3146 assert_eq!(comments[3].entity.to_string(), "block0"); 3147 assert_eq!(comments[3].text, "; Basic block"); 3148 3149 assert_eq!(comments[4].entity.to_string(), "inst0"); 3150 assert_eq!(comments[4].text, "; Instruction"); 3151 3152 assert_eq!(comments[5].entity, AnyEntity::Function); 3153 assert_eq!(comments[6].entity, AnyEntity::Function); 3154 } 3155 3156 #[test] 3157 fn test_file() { 3158 let tf = parse_test( 3159 r#"; before 3160 test cfg option=5 3161 test verify 3162 set enable_float=false 3163 feature "foo" 3164 feature !"bar" 3165 ; still preamble 3166 function %comment() system_v {}"#, 3167 ParseOptions::default(), 3168 ) 3169 .unwrap(); 3170 assert_eq!(tf.commands.len(), 2); 3171 assert_eq!(tf.commands[0].command, "cfg"); 3172 assert_eq!(tf.commands[1].command, "verify"); 3173 match tf.isa_spec { 3174 IsaSpec::None(s) => { 3175 assert!(s.enable_verifier()); 3176 assert!(!s.enable_float()); 3177 } 3178 _ => panic!("unexpected ISAs"), 3179 } 3180 assert_eq!(tf.features[0], Feature::With(&"foo")); 3181 assert_eq!(tf.features[1], Feature::Without(&"bar")); 3182 assert_eq!(tf.preamble_comments.len(), 2); 3183 assert_eq!(tf.preamble_comments[0].text, "; before"); 3184 assert_eq!(tf.preamble_comments[1].text, "; still preamble"); 3185 assert_eq!(tf.functions.len(), 1); 3186 assert_eq!(tf.functions[0].0.name.to_string(), "%comment"); 3187 } 3188 3189 #[test] 3190 fn isa_spec() { 3191 assert!(parse_test( 3192 "target 3193 function %foo() system_v {}", 3194 ParseOptions::default() 3195 ) 3196 .is_err()); 3197 3198 assert!(parse_test( 3199 "target x86_64 3200 set enable_float=false 3201 function %foo() system_v {}", 3202 ParseOptions::default() 3203 ) 3204 .is_err()); 3205 3206 match parse_test( 3207 "set enable_float=false 3208 target x86_64 3209 function %foo() system_v {}", 3210 ParseOptions::default(), 3211 ) 3212 .unwrap() 3213 .isa_spec 3214 { 3215 IsaSpec::None(_) => panic!("Expected some ISA"), 3216 IsaSpec::Some(v) => { 3217 assert_eq!(v.len(), 1); 3218 assert!(v[0].name() == "x64" || v[0].name() == "x86"); 3219 } 3220 } 3221 } 3222 3223 #[test] 3224 fn user_function_name() { 3225 // Valid characters in the name: 3226 let func = Parser::new( 3227 "function u1:2() system_v { 3228 block0: 3229 trap int_divz 3230 }", 3231 ) 3232 .parse_function() 3233 .unwrap() 3234 .0; 3235 assert_eq!(func.name.to_string(), "u1:2"); 3236 3237 // Invalid characters in the name: 3238 let mut parser = Parser::new( 3239 "function u123:abc() system_v { 3240 block0: 3241 trap stk_ovf 3242 }", 3243 ); 3244 assert!(parser.parse_function().is_err()); 3245 3246 // Incomplete function names should not be valid: 3247 let mut parser = Parser::new( 3248 "function u() system_v { 3249 block0: 3250 trap int_ovf 3251 }", 3252 ); 3253 assert!(parser.parse_function().is_err()); 3254 3255 let mut parser = Parser::new( 3256 "function u0() system_v { 3257 block0: 3258 trap int_ovf 3259 }", 3260 ); 3261 assert!(parser.parse_function().is_err()); 3262 3263 let mut parser = Parser::new( 3264 "function u0:() system_v { 3265 block0: 3266 trap int_ovf 3267 }", 3268 ); 3269 assert!(parser.parse_function().is_err()); 3270 } 3271 3272 #[test] 3273 fn change_default_calling_convention() { 3274 let code = "function %test() { 3275 block0: 3276 return 3277 }"; 3278 3279 // By default the parser will use the fast calling convention if none is specified. 3280 let mut parser = Parser::new(code); 3281 assert_eq!( 3282 parser.parse_function().unwrap().0.signature.call_conv, 3283 CallConv::Fast 3284 ); 3285 3286 // However, we can specify a different calling convention to be the default. 3287 let mut parser = Parser::new(code).with_default_calling_convention(CallConv::Cold); 3288 assert_eq!( 3289 parser.parse_function().unwrap().0.signature.call_conv, 3290 CallConv::Cold 3291 ); 3292 } 3293 3294 #[test] 3295 fn u8_as_hex() { 3296 fn parse_as_uimm8(text: &str) -> ParseResult<u8> { 3297 Parser::new(text).match_uimm8("unable to parse u8") 3298 } 3299 3300 assert_eq!(parse_as_uimm8("0").unwrap(), 0); 3301 assert_eq!(parse_as_uimm8("0xff").unwrap(), 255); 3302 assert!(parse_as_uimm8("-1").is_err()); 3303 assert!(parse_as_uimm8("0xffa").is_err()); 3304 } 3305 3306 #[test] 3307 fn i16_as_hex() { 3308 fn parse_as_imm16(text: &str) -> ParseResult<i16> { 3309 Parser::new(text).match_imm16("unable to parse i16") 3310 } 3311 3312 assert_eq!(parse_as_imm16("0x8000").unwrap(), -32768); 3313 assert_eq!(parse_as_imm16("0xffff").unwrap(), -1); 3314 assert_eq!(parse_as_imm16("0").unwrap(), 0); 3315 assert_eq!(parse_as_imm16("0x7fff").unwrap(), 32767); 3316 assert_eq!( 3317 parse_as_imm16("-0x0001").unwrap(), 3318 parse_as_imm16("0xffff").unwrap() 3319 ); 3320 assert_eq!( 3321 parse_as_imm16("-0x7fff").unwrap(), 3322 parse_as_imm16("0x8001").unwrap() 3323 ); 3324 assert!(parse_as_imm16("0xffffa").is_err()); 3325 } 3326 3327 #[test] 3328 fn i32_as_hex() { 3329 fn parse_as_imm32(text: &str) -> ParseResult<i32> { 3330 Parser::new(text).match_imm32("unable to parse i32") 3331 } 3332 3333 assert_eq!(parse_as_imm32("0x80000000").unwrap(), -2147483648); 3334 assert_eq!(parse_as_imm32("0xffffffff").unwrap(), -1); 3335 assert_eq!(parse_as_imm32("0").unwrap(), 0); 3336 assert_eq!(parse_as_imm32("0x7fffffff").unwrap(), 2147483647); 3337 assert_eq!( 3338 parse_as_imm32("-0x00000001").unwrap(), 3339 parse_as_imm32("0xffffffff").unwrap() 3340 ); 3341 assert_eq!( 3342 parse_as_imm32("-0x7fffffff").unwrap(), 3343 parse_as_imm32("0x80000001").unwrap() 3344 ); 3345 assert!(parse_as_imm32("0xffffffffa").is_err()); 3346 } 3347 3348 #[test] 3349 fn i64_as_hex() { 3350 fn parse_as_imm64(text: &str) -> ParseResult<Imm64> { 3351 Parser::new(text).match_imm64("unable to parse Imm64") 3352 } 3353 3354 assert_eq!( 3355 parse_as_imm64("0x8000000000000000").unwrap(), 3356 Imm64::new(-9223372036854775808) 3357 ); 3358 assert_eq!( 3359 parse_as_imm64("0xffffffffffffffff").unwrap(), 3360 Imm64::new(-1) 3361 ); 3362 assert_eq!(parse_as_imm64("0").unwrap(), Imm64::new(0)); 3363 assert_eq!( 3364 parse_as_imm64("0x7fffffffffffffff").unwrap(), 3365 Imm64::new(9223372036854775807) 3366 ); 3367 assert_eq!( 3368 parse_as_imm64("-0x0000000000000001").unwrap(), 3369 parse_as_imm64("0xffffffffffffffff").unwrap() 3370 ); 3371 assert_eq!( 3372 parse_as_imm64("-0x7fffffffffffffff").unwrap(), 3373 parse_as_imm64("0x8000000000000001").unwrap() 3374 ); 3375 assert!(parse_as_imm64("0xffffffffffffffffa").is_err()); 3376 } 3377 3378 #[test] 3379 fn uimm128() { 3380 macro_rules! parse_as_constant_data { 3381 ($text:expr, $type:expr) => {{ 3382 Parser::new($text).parse_literals_to_constant_data($type) 3383 }}; 3384 } 3385 macro_rules! can_parse_as_constant_data { 3386 ($text:expr, $type:expr) => {{ 3387 assert!(parse_as_constant_data!($text, $type).is_ok()) 3388 }}; 3389 } 3390 macro_rules! cannot_parse_as_constant_data { 3391 ($text:expr, $type:expr) => {{ 3392 assert!(parse_as_constant_data!($text, $type).is_err()) 3393 }}; 3394 } 3395 3396 can_parse_as_constant_data!("1 2 3 4", I32X4); 3397 can_parse_as_constant_data!("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16", I8X16); 3398 can_parse_as_constant_data!("0x1.1 0x2.2 0x3.3 0x4.4", F32X4); 3399 can_parse_as_constant_data!("0x0 0x1 0x2 0x3", I32X4); 3400 can_parse_as_constant_data!("-1 0 -1 0 -1 0 -1 0", I16X8); 3401 can_parse_as_constant_data!("0 -1", I64X2); 3402 can_parse_as_constant_data!("-1 0", I64X2); 3403 can_parse_as_constant_data!("-1 -1 -1 -1 -1", I32X4); // note that parse_literals_to_constant_data will leave extra tokens unconsumed 3404 3405 cannot_parse_as_constant_data!("1 2 3", I32X4); 3406 cannot_parse_as_constant_data!(" ", F32X4); 3407 } 3408 3409 #[test] 3410 fn parse_constant_from_booleans() { 3411 let c = Parser::new("-1 0 -1 0") 3412 .parse_literals_to_constant_data(I32X4) 3413 .unwrap(); 3414 assert_eq!( 3415 c.into_vec(), 3416 [0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0] 3417 ) 3418 } 3419 3420 #[test] 3421 fn parse_unbounded_constants() { 3422 // Unlike match_uimm128, match_hexadecimal_constant can parse byte sequences of any size: 3423 assert_eq!( 3424 Parser::new("0x0100") 3425 .match_hexadecimal_constant("err message") 3426 .unwrap(), 3427 vec![0, 1].into() 3428 ); 3429 3430 // Only parse hexadecimal constants: 3431 assert!(Parser::new("228") 3432 .match_hexadecimal_constant("err message") 3433 .is_err()); 3434 } 3435 3436 #[test] 3437 fn parse_run_commands() { 3438 // Helper for creating signatures. 3439 fn sig(ins: &[Type], outs: &[Type]) -> Signature { 3440 let mut sig = Signature::new(CallConv::Fast); 3441 for i in ins { 3442 sig.params.push(AbiParam::new(*i)); 3443 } 3444 for o in outs { 3445 sig.returns.push(AbiParam::new(*o)); 3446 } 3447 sig 3448 } 3449 3450 // Helper for parsing run commands. 3451 fn parse(text: &str, sig: &Signature) -> ParseResult<RunCommand> { 3452 Parser::new(text).parse_run_command(sig) 3453 } 3454 3455 // Check that we can parse and display the same set of run commands. 3456 fn assert_roundtrip(text: &str, sig: &Signature) { 3457 assert_eq!(parse(text, sig).unwrap().to_string(), text); 3458 } 3459 assert_roundtrip("run: %fn0() == 42", &sig(&[], &[I32])); 3460 assert_roundtrip( 3461 "run: %fn0(8, 16, 32, 64) == 1", 3462 &sig(&[I8, I16, I32, I64], &[I8]), 3463 ); 3464 assert_roundtrip( 3465 "run: %my_func(1) == 0x0f0e0d0c0b0a09080706050403020100", 3466 &sig(&[I32], &[I8X16]), 3467 ); 3468 3469 // Verify that default invocations are created when not specified. 3470 assert_eq!( 3471 parse("run", &sig(&[], &[I32])).unwrap().to_string(), 3472 "run: %default() != 0" 3473 ); 3474 assert_eq!( 3475 parse("print", &sig(&[], &[F32X4, I16X8])) 3476 .unwrap() 3477 .to_string(), 3478 "print: %default()" 3479 ); 3480 3481 // Demonstrate some unparseable cases. 3482 assert!(parse("print", &sig(&[I32], &[I32])).is_err()); 3483 assert!(parse("print:", &sig(&[], &[])).is_err()); 3484 assert!(parse("run: ", &sig(&[], &[])).is_err()); 3485 } 3486 3487 #[test] 3488 fn parse_data_values() { 3489 fn parse(text: &str, ty: Type) -> DataValue { 3490 Parser::new(text).parse_data_value(ty).unwrap() 3491 } 3492 3493 assert_eq!(parse("8", I8).to_string(), "8"); 3494 assert_eq!(parse("16", I16).to_string(), "16"); 3495 assert_eq!(parse("32", I32).to_string(), "32"); 3496 assert_eq!(parse("64", I64).to_string(), "64"); 3497 assert_eq!( 3498 parse("0x01234567_01234567_01234567_01234567", I128).to_string(), 3499 "1512366032949150931280199141537564007" 3500 ); 3501 assert_eq!(parse("1234567", I128).to_string(), "1234567"); 3502 assert_eq!(parse("0x32.32", F32).to_string(), "0x1.919000p5"); 3503 assert_eq!(parse("0x64.64", F64).to_string(), "0x1.9190000000000p6"); 3504 assert_eq!( 3505 parse("[0 1 2 3]", I32X4).to_string(), 3506 "0x00000003000000020000000100000000" 3507 ); 3508 } 3509 3510 #[test] 3511 fn parse_cold_blocks() { 3512 let code = "function %test() { 3513 block0 cold: 3514 return 3515 block1(v0: i32) cold: 3516 return 3517 block2(v1: i32): 3518 return 3519 }"; 3520 3521 let mut parser = Parser::new(code); 3522 let func = parser.parse_function().unwrap().0; 3523 assert_eq!(func.layout.blocks().count(), 3); 3524 assert!(func.layout.is_cold(Block::from_u32(0))); 3525 assert!(func.layout.is_cold(Block::from_u32(1))); 3526 assert!(!func.layout.is_cold(Block::from_u32(2))); 3527 } 3528 } 3529