1use crate::error::{Location, ParseError, ParseResult};
4use crate::isaspec;
5use crate::lexer::{LexError, Lexer, LocatedError, LocatedToken, Token};
6use crate::run_command::{Comparison, Invocation, RunCommand};
7use crate::sourcemap::SourceMap;
8use crate::testcommand::TestCommand;
9use crate::testfile::{Comment, Details, Feature, TestFile};
10use cranelift_codegen::data_value::DataValue;
11use cranelift_codegen::entity::{EntityRef, PrimaryMap};
12use cranelift_codegen::ir::entities::{AnyEntity, DynamicType, MemoryType};
13use cranelift_codegen::ir::immediates::{
14 Ieee128, Ieee16, Ieee32, Ieee64, Imm64, Offset32, Uimm32, Uimm64,
15};
16use cranelift_codegen::ir::instructions::{InstructionData, InstructionFormat, VariableArgs};
17use cranelift_codegen::ir::pcc::{BaseExpr, Expr, Fact};
18use cranelift_codegen::ir::types;
19use cranelift_codegen::ir::types::*;
20use cranelift_codegen::ir::{self, UserExternalNameRef};
21use cranelift_codegen::ir::{
22 AbiParam, ArgumentExtension, ArgumentPurpose, Block, Constant, ConstantData, DynamicStackSlot,
23 DynamicStackSlotData, DynamicTypeData, ExtFuncData, ExternalName, FuncRef, Function,
24 GlobalValue, GlobalValueData, JumpTableData, MemFlags, MemoryTypeData, MemoryTypeField, Opcode,
25 SigRef, Signature, StackSlot, StackSlotData, StackSlotKind, UserFuncName, Value,
26};
27use cranelift_codegen::isa::{self, CallConv};
28use cranelift_codegen::packed_option::ReservedValue;
29use cranelift_codegen::{settings, settings::Configurable, timing};
30use smallvec::SmallVec;
31use std::mem;
32use std::str::FromStr;
33use std::{u16, u32};
34use target_lexicon::Triple;
35
36macro_rules! match_imm {
37 ($signed:ty, $unsigned:ty, $parser:expr, $err_msg:expr) => {{
38 if let Some(Token::Integer(text)) = $parser.token() {
39 $parser.consume();
40 let negative = text.starts_with('-');
41 let positive = text.starts_with('+');
42 let text = if negative || positive {
43 &text[1..]
45 } else {
46 text
47 };
48
49 let value = if text.starts_with("0x") {
51 let text = text.replace("_", "");
53 <$unsigned>::from_str_radix(&text[2..], 16).map_err(|_| {
55 $parser.error(&format!(
56 "unable to parse '{}' value as a hexadecimal {} immediate",
57 &text[2..],
58 stringify!($unsigned),
59 ))
60 })?
61 } else {
62 text.parse()
64 .map_err(|_| $parser.error("expected decimal immediate"))?
65 };
66
67 let signed = if negative {
69 let value = value.wrapping_neg() as $signed;
70 if value > 0 {
71 return Err($parser.error("negative number too small"));
72 }
73 value
74 } else {
75 value as $signed
76 };
77
78 Ok(signed)
79 } else {
80 err!($parser.loc, $err_msg)
81 }
82 }};
83}
84
85const MAX_BLOCKS_IN_A_FUNCTION: u32 = 100_000;
87
88pub fn parse_functions(text: &str) -> ParseResult<Vec<Function>> {
92 let _tt = timing::parse_text();
93 parse_test(text, ParseOptions::default())
94 .map(|file| file.functions.into_iter().map(|(func, _)| func).collect())
95}
96
97pub struct ParseOptions<'a> {
99 pub passes: Option<&'a [String]>,
101 pub target: Option<&'a str>,
103 pub default_calling_convention: CallConv,
105 pub unwind_info: bool,
107 pub machine_code_cfg_info: bool,
109}
110
111impl Default for ParseOptions<'_> {
112 fn default() -> Self {
113 Self {
114 passes: None,
115 target: None,
116 default_calling_convention: CallConv::Fast,
117 unwind_info: false,
118 machine_code_cfg_info: false,
119 }
120 }
121}
122
123pub fn parse_test<'a>(text: &'a str, options: ParseOptions<'a>) -> ParseResult<TestFile<'a>> {
127 let _tt = timing::parse_text();
128 let mut parser = Parser::new(text);
129
130 parser.start_gathering_comments();
132
133 let isa_spec: isaspec::IsaSpec;
134 let commands: Vec<TestCommand<'a>>;
135
136 match options.passes {
139 Some(pass_vec) => {
140 parser.parse_test_commands();
141 commands = parser.parse_cmdline_passes(pass_vec);
142 parser.parse_target_specs(&options)?;
143 isa_spec = parser.parse_cmdline_target(options.target)?;
144 }
145 None => {
146 commands = parser.parse_test_commands();
147 isa_spec = parser.parse_target_specs(&options)?;
148 }
149 };
150 let features = parser.parse_cranelift_features()?;
151
152 parser = if commands.iter().any(|tc| tc.command == "run") {
156 let host_default_calling_convention = CallConv::triple_default(&Triple::host());
157 parser.with_default_calling_convention(host_default_calling_convention)
158 } else {
159 parser.with_default_calling_convention(options.default_calling_convention)
160 };
161
162 parser.token();
163 parser.claim_gathered_comments(AnyEntity::Function);
164
165 let preamble_comments = parser.take_comments();
166 let functions = parser.parse_function_list()?;
167
168 Ok(TestFile {
169 commands,
170 isa_spec,
171 features,
172 preamble_comments,
173 functions,
174 })
175}
176
177pub fn parse_run_command(text: &str, signature: &Signature) -> ParseResult<Option<RunCommand>> {
185 let _tt = timing::parse_text();
186 let trimmed_text = text.trim_start_matches(|c| c == ' ' || c == ';');
189 let mut parser = Parser::new(trimmed_text);
190 match parser.token() {
191 Some(Token::Identifier("run")) | Some(Token::Identifier("print")) => {
192 parser.parse_run_command(signature).map(|c| Some(c))
193 }
194 Some(_) | None => Ok(None),
195 }
196}
197
198pub struct Parser<'a> {
199 lex: Lexer<'a>,
200
201 lex_error: Option<LexError>,
202
203 lookahead: Option<Token<'a>>,
205
206 loc: Location,
208
209 gathering_comments: bool,
211
212 gathered_comments: Vec<&'a str>,
214
215 comments: Vec<Comment<'a>>,
217
218 predeclared_external_names: PrimaryMap<UserExternalNameRef, ir::UserExternalName>,
223
224 default_calling_convention: CallConv,
226}
227
228struct Context {
230 function: Function,
231 map: SourceMap,
232
233 aliases: Vec<Value>,
235}
236
237impl Context {
238 fn new(f: Function) -> Self {
239 Self {
240 function: f,
241 map: SourceMap::new(),
242 aliases: Vec::new(),
243 }
244 }
245
246 fn add_ss(&mut self, ss: StackSlot, data: StackSlotData, loc: Location) -> ParseResult<()> {
248 self.map.def_ss(ss, loc)?;
249 while self.function.sized_stack_slots.next_key().index() <= ss.index() {
250 self.function.create_sized_stack_slot(StackSlotData::new(
251 StackSlotKind::ExplicitSlot,
252 0,
253 0,
254 ));
255 }
256 self.function.sized_stack_slots[ss] = data;
257 Ok(())
258 }
259
260 fn check_ss(&self, ss: StackSlot, loc: Location) -> ParseResult<()> {
262 if !self.map.contains_ss(ss) {
263 err!(loc, "undefined stack slot {}", ss)
264 } else {
265 Ok(())
266 }
267 }
268
269 fn add_dss(
271 &mut self,
272 ss: DynamicStackSlot,
273 data: DynamicStackSlotData,
274 loc: Location,
275 ) -> ParseResult<()> {
276 self.map.def_dss(ss, loc)?;
277 while self.function.dynamic_stack_slots.next_key().index() <= ss.index() {
278 self.function
279 .create_dynamic_stack_slot(DynamicStackSlotData::new(
280 StackSlotKind::ExplicitDynamicSlot,
281 data.dyn_ty,
282 ));
283 }
284 self.function.dynamic_stack_slots[ss] = data;
285 Ok(())
286 }
287
288 fn check_dss(&self, dss: DynamicStackSlot, loc: Location) -> ParseResult<()> {
290 if !self.map.contains_dss(dss) {
291 err!(loc, "undefined dynamic stack slot {}", dss)
292 } else {
293 Ok(())
294 }
295 }
296
297 fn add_dt(&mut self, dt: DynamicType, data: DynamicTypeData, loc: Location) -> ParseResult<()> {
299 self.map.def_dt(dt, loc)?;
300 while self.function.dfg.dynamic_types.next_key().index() <= dt.index() {
301 self.function.dfg.make_dynamic_ty(DynamicTypeData::new(
302 data.base_vector_ty,
303 data.dynamic_scale,
304 ));
305 }
306 self.function.dfg.dynamic_types[dt] = data;
307 Ok(())
308 }
309
310 fn add_gv(
312 &mut self,
313 gv: GlobalValue,
314 data: GlobalValueData,
315 maybe_fact: Option<Fact>,
316 loc: Location,
317 ) -> ParseResult<()> {
318 self.map.def_gv(gv, loc)?;
319 while self.function.global_values.next_key().index() <= gv.index() {
320 self.function.create_global_value(GlobalValueData::Symbol {
321 name: ExternalName::testcase(""),
322 offset: Imm64::new(0),
323 colocated: false,
324 tls: false,
325 });
326 }
327 self.function.global_values[gv] = data;
328 if let Some(fact) = maybe_fact {
329 self.function.global_value_facts[gv] = Some(fact);
330 }
331 Ok(())
332 }
333
334 fn add_mt(&mut self, mt: MemoryType, data: MemoryTypeData, loc: Location) -> ParseResult<()> {
336 self.map.def_mt(mt, loc)?;
337 while self.function.memory_types.next_key().index() <= mt.index() {
338 self.function.create_memory_type(MemoryTypeData::default());
339 }
340 self.function.memory_types[mt] = data;
341 Ok(())
342 }
343
344 fn check_gv(&self, gv: GlobalValue, loc: Location) -> ParseResult<()> {
346 if !self.map.contains_gv(gv) {
347 err!(loc, "undefined global value {}", gv)
348 } else {
349 Ok(())
350 }
351 }
352
353 fn add_sig(
355 &mut self,
356 sig: SigRef,
357 data: Signature,
358 loc: Location,
359 defaultcc: CallConv,
360 ) -> ParseResult<()> {
361 self.map.def_sig(sig, loc)?;
362 while self.function.dfg.signatures.next_key().index() <= sig.index() {
363 self.function.import_signature(Signature::new(defaultcc));
364 }
365 self.function.dfg.signatures[sig] = data;
366 Ok(())
367 }
368
369 fn check_sig(&self, sig: SigRef, loc: Location) -> ParseResult<()> {
371 if !self.map.contains_sig(sig) {
372 err!(loc, "undefined signature {}", sig)
373 } else {
374 Ok(())
375 }
376 }
377
378 fn add_fn(&mut self, fn_: FuncRef, data: ExtFuncData, loc: Location) -> ParseResult<()> {
380 self.map.def_fn(fn_, loc)?;
381 while self.function.dfg.ext_funcs.next_key().index() <= fn_.index() {
382 self.function.import_function(ExtFuncData {
383 name: ExternalName::testcase(""),
384 signature: SigRef::reserved_value(),
385 colocated: false,
386 });
387 }
388 self.function.dfg.ext_funcs[fn_] = data;
389 Ok(())
390 }
391
392 fn check_fn(&self, fn_: FuncRef, loc: Location) -> ParseResult<()> {
394 if !self.map.contains_fn(fn_) {
395 err!(loc, "undefined function {}", fn_)
396 } else {
397 Ok(())
398 }
399 }
400
401 fn add_constant(
403 &mut self,
404 constant: Constant,
405 data: ConstantData,
406 loc: Location,
407 ) -> ParseResult<()> {
408 self.map.def_constant(constant, loc)?;
409 self.function.dfg.constants.set(constant, data);
410 Ok(())
411 }
412
413 fn add_stack_limit(&mut self, limit: GlobalValue, loc: Location) -> ParseResult<()> {
415 if self.function.stack_limit.is_some() {
416 return err!(loc, "stack limit defined twice");
417 }
418 self.function.stack_limit = Some(limit);
419 Ok(())
420 }
421
422 fn check_constant(&self, c: Constant, loc: Location) -> ParseResult<()> {
424 if !self.map.contains_constant(c) {
425 err!(loc, "undefined constant {}", c)
426 } else {
427 Ok(())
428 }
429 }
430
431 fn add_block(&mut self, block: Block, loc: Location) -> ParseResult<Block> {
433 self.map.def_block(block, loc)?;
434 while self.function.dfg.num_blocks() <= block.index() {
435 self.function.dfg.make_block();
436 }
437 self.function.layout.append_block(block);
438 Ok(block)
439 }
440
441 fn set_cold_block(&mut self, block: Block) {
443 self.function.layout.set_cold(block);
444 }
445}
446
447impl<'a> Parser<'a> {
448 pub fn new(text: &'a str) -> Self {
450 Self {
451 lex: Lexer::new(text),
452 lex_error: None,
453 lookahead: None,
454 loc: Location { line_number: 0 },
455 gathering_comments: false,
456 gathered_comments: Vec::new(),
457 comments: Vec::new(),
458 default_calling_convention: CallConv::Fast,
459 predeclared_external_names: Default::default(),
460 }
461 }
462
463 pub fn with_default_calling_convention(self, default_calling_convention: CallConv) -> Self {
466 Self {
467 default_calling_convention,
468 ..self
469 }
470 }
471
472 fn consume(&mut self) -> Token<'a> {
474 self.lookahead.take().expect("No token to consume")
475 }
476
477 fn consume_line(&mut self) -> &'a str {
480 let rest = self.lex.rest_of_line();
481 self.consume();
482 rest
483 }
484
485 fn token(&mut self) -> Option<Token<'a>> {
487 while self.lookahead.is_none() {
488 match self.lex.next() {
489 Some(Ok(LocatedToken { token, location })) => {
490 match token {
491 Token::Comment(text) => {
492 if self.gathering_comments {
493 self.gathered_comments.push(text);
494 }
495 }
496 _ => self.lookahead = Some(token),
497 }
498 self.loc = location;
499 }
500 Some(Err(LocatedError { error, location })) => {
501 self.lex_error = Some(error);
502 self.loc = location;
503 break;
504 }
505 None => break,
506 }
507 }
508 self.lookahead
509 }
510
511 fn start_gathering_comments(&mut self) {
513 debug_assert!(!self.gathering_comments);
514 self.gathering_comments = true;
515 debug_assert!(self.gathered_comments.is_empty());
516 }
517
518 fn claim_gathered_comments<E: Into<AnyEntity>>(&mut self, entity: E) {
521 debug_assert!(self.gathering_comments);
522 let entity = entity.into();
523 self.comments.extend(
524 self.gathered_comments
525 .drain(..)
526 .map(|text| Comment { entity, text }),
527 );
528 self.gathering_comments = false;
529 }
530
531 fn take_comments(&mut self) -> Vec<Comment<'a>> {
533 debug_assert!(!self.gathering_comments);
534 mem::replace(&mut self.comments, Vec::new())
535 }
536
537 fn match_token(&mut self, want: Token<'a>, err_msg: &str) -> ParseResult<Token<'a>> {
539 if self.token() == Some(want) {
540 Ok(self.consume())
541 } else {
542 err!(self.loc, err_msg)
543 }
544 }
545
546 fn optional(&mut self, want: Token<'a>) -> bool {
548 if self.token() == Some(want) {
549 self.consume();
550 true
551 } else {
552 false
553 }
554 }
555
556 fn match_identifier(&mut self, want: &'static str, err_msg: &str) -> ParseResult<Token<'a>> {
559 if self.token() == Some(Token::Identifier(want)) {
560 Ok(self.consume())
561 } else {
562 err!(self.loc, err_msg)
563 }
564 }
565
566 fn match_type(&mut self, err_msg: &str) -> ParseResult<Type> {
568 if let Some(Token::Type(t)) = self.token() {
569 self.consume();
570 Ok(t)
571 } else {
572 err!(self.loc, err_msg)
573 }
574 }
575
576 fn match_ss(&mut self, err_msg: &str) -> ParseResult<StackSlot> {
578 if let Some(Token::StackSlot(ss)) = self.token() {
579 self.consume();
580 if let Some(ss) = StackSlot::with_number(ss) {
581 return Ok(ss);
582 }
583 }
584 err!(self.loc, err_msg)
585 }
586
587 fn match_dss(&mut self, err_msg: &str) -> ParseResult<DynamicStackSlot> {
589 if let Some(Token::DynamicStackSlot(ss)) = self.token() {
590 self.consume();
591 if let Some(ss) = DynamicStackSlot::with_number(ss) {
592 return Ok(ss);
593 }
594 }
595 err!(self.loc, err_msg)
596 }
597
598 fn match_dt(&mut self, err_msg: &str) -> ParseResult<DynamicType> {
600 if let Some(Token::DynamicType(dt)) = self.token() {
601 self.consume();
602 if let Some(dt) = DynamicType::with_number(dt) {
603 return Ok(dt);
604 }
605 }
606 err!(self.loc, err_msg)
607 }
608
609 fn concrete_from_dt(&mut self, dt: DynamicType, ctx: &mut Context) -> Option<Type> {
611 ctx.function.get_concrete_dynamic_ty(dt)
612 }
613
614 fn match_gv(&mut self, err_msg: &str) -> ParseResult<GlobalValue> {
616 if let Some(Token::GlobalValue(gv)) = self.token() {
617 self.consume();
618 if let Some(gv) = GlobalValue::with_number(gv) {
619 return Ok(gv);
620 }
621 }
622 err!(self.loc, err_msg)
623 }
624
625 fn match_fn(&mut self, err_msg: &str) -> ParseResult<FuncRef> {
627 if let Some(Token::FuncRef(fnref)) = self.token() {
628 self.consume();
629 if let Some(fnref) = FuncRef::with_number(fnref) {
630 return Ok(fnref);
631 }
632 }
633 err!(self.loc, err_msg)
634 }
635
636 fn match_sig(&mut self, err_msg: &str) -> ParseResult<SigRef> {
638 if let Some(Token::SigRef(sigref)) = self.token() {
639 self.consume();
640 if let Some(sigref) = SigRef::with_number(sigref) {
641 return Ok(sigref);
642 }
643 }
644 err!(self.loc, err_msg)
645 }
646
647 fn match_mt(&mut self, err_msg: &str) -> ParseResult<MemoryType> {
649 if let Some(Token::MemoryType(mt)) = self.token() {
650 self.consume();
651 if let Some(mt) = MemoryType::with_number(mt) {
652 return Ok(mt);
653 }
654 }
655 err!(self.loc, err_msg)
656 }
657
658 fn match_constant(&mut self) -> ParseResult<Constant> {
660 if let Some(Token::Constant(c)) = self.token() {
661 self.consume();
662 if let Some(c) = Constant::with_number(c) {
663 return Ok(c);
664 }
665 }
666 err!(self.loc, "expected constant number: const«n»")
667 }
668
669 fn match_stack_limit(&mut self) -> ParseResult<()> {
671 if let Some(Token::Identifier("stack_limit")) = self.token() {
672 self.consume();
673 return Ok(());
674 }
675 err!(self.loc, "expected identifier: stack_limit")
676 }
677
678 fn match_block(&mut self, err_msg: &str) -> ParseResult<Block> {
680 if let Some(Token::Block(block)) = self.token() {
681 self.consume();
682 Ok(block)
683 } else {
684 err!(self.loc, err_msg)
685 }
686 }
687
688 fn match_value(&mut self, err_msg: &str) -> ParseResult<Value> {
690 if let Some(Token::Value(v)) = self.token() {
691 self.consume();
692 Ok(v)
693 } else {
694 err!(self.loc, err_msg)
695 }
696 }
697
698 fn error(&self, message: &str) -> ParseError {
699 ParseError {
700 location: self.loc,
701 message: message.to_string(),
702 is_warning: false,
703 }
704 }
705
706 fn match_imm64(&mut self, err_msg: &str) -> ParseResult<Imm64> {
708 if let Some(Token::Integer(text)) = self.token() {
709 self.consume();
710 text.parse().map_err(|e| self.error(e))
713 } else {
714 err!(self.loc, err_msg)
715 }
716 }
717
718 fn match_hexadecimal_constant(&mut self, err_msg: &str) -> ParseResult<ConstantData> {
720 if let Some(Token::Integer(text)) = self.token() {
721 self.consume();
722 text.parse().map_err(|e| {
723 self.error(&format!(
724 "expected hexadecimal immediate, failed to parse: {e}"
725 ))
726 })
727 } else {
728 err!(self.loc, err_msg)
729 }
730 }
731
732 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 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 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 {expected_size} bytes"
754 )))
755 }
756 }
757
758 fn match_uimm64(&mut self, err_msg: &str) -> ParseResult<Uimm64> {
760 if let Some(Token::Integer(text)) = self.token() {
761 self.consume();
762 text.parse()
765 .map_err(|_| self.error("expected u64 decimal immediate"))
766 } else {
767 err!(self.loc, err_msg)
768 }
769 }
770
771 fn match_uimm32(&mut self, err_msg: &str) -> ParseResult<Uimm32> {
773 if let Some(Token::Integer(text)) = self.token() {
774 self.consume();
775 text.parse().map_err(|e| self.error(e))
778 } else {
779 err!(self.loc, err_msg)
780 }
781 }
782
783 fn match_uimm8(&mut self, err_msg: &str) -> ParseResult<u8> {
786 if let Some(Token::Integer(text)) = self.token() {
787 self.consume();
788 if let Some(num) = text.strip_prefix("0x") {
790 u8::from_str_radix(num, 16)
792 .map_err(|_| self.error("unable to parse u8 as a hexadecimal immediate"))
793 } else {
794 text.parse()
796 .map_err(|_| self.error("expected u8 decimal immediate"))
797 }
798 } else {
799 err!(self.loc, err_msg)
800 }
801 }
802
803 fn match_imm8(&mut self, err_msg: &str) -> ParseResult<i8> {
805 match_imm!(i8, u8, self, err_msg)
806 }
807
808 fn match_imm16(&mut self, err_msg: &str) -> ParseResult<i16> {
810 match_imm!(i16, u16, self, err_msg)
811 }
812
813 fn match_imm32(&mut self, err_msg: &str) -> ParseResult<i32> {
816 match_imm!(i32, u32, self, err_msg)
817 }
818
819 fn match_imm128(&mut self, err_msg: &str) -> ParseResult<i128> {
821 match_imm!(i128, u128, self, err_msg)
822 }
823
824 fn optional_offset32(&mut self) -> ParseResult<Offset32> {
829 if let Some(Token::Integer(text)) = self.token() {
830 if text.starts_with('+') || text.starts_with('-') {
831 self.consume();
832 return text.parse().map_err(|e| self.error(e));
835 }
836 }
837 Ok(Offset32::new(0))
839 }
840
841 fn optional_offset_imm64(&mut self) -> ParseResult<Imm64> {
846 if let Some(Token::Integer(text)) = self.token() {
847 if text.starts_with('+') || text.starts_with('-') {
848 self.consume();
849 return text.parse().map_err(|e| self.error(e));
852 }
853 }
854 Ok(Imm64::new(0))
856 }
857
858 fn match_ieee16(&mut self, err_msg: &str) -> ParseResult<Ieee16> {
860 if let Some(Token::Float(text)) = self.token() {
861 self.consume();
862 text.parse().map_err(|e| self.error(e))
865 } else {
866 err!(self.loc, err_msg)
867 }
868 }
869
870 fn match_ieee32(&mut self, err_msg: &str) -> ParseResult<Ieee32> {
872 if let Some(Token::Float(text)) = self.token() {
873 self.consume();
874 text.parse().map_err(|e| self.error(e))
877 } else {
878 err!(self.loc, err_msg)
879 }
880 }
881
882 fn match_ieee64(&mut self, err_msg: &str) -> ParseResult<Ieee64> {
884 if let Some(Token::Float(text)) = self.token() {
885 self.consume();
886 text.parse().map_err(|e| self.error(e))
889 } else {
890 err!(self.loc, err_msg)
891 }
892 }
893
894 fn match_ieee128(&mut self, err_msg: &str) -> ParseResult<Ieee128> {
896 if let Some(Token::Float(text)) = self.token() {
897 self.consume();
898 text.parse().map_err(|e| self.error(e))
901 } else {
902 err!(self.loc, err_msg)
903 }
904 }
905
906 fn match_enum<T: FromStr>(&mut self, err_msg: &str) -> ParseResult<T> {
908 if let Some(Token::Identifier(text)) = self.token() {
909 self.consume();
910 text.parse().map_err(|_| self.error(err_msg))
911 } else {
912 err!(self.loc, err_msg)
913 }
914 }
915
916 fn optional_memflags(&mut self) -> ParseResult<MemFlags> {
918 let mut flags = MemFlags::new();
919 while let Some(Token::Identifier(text)) = self.token() {
920 match flags.set_by_name(text) {
921 Ok(true) => {
922 self.consume();
923 }
924 Ok(false) => break,
925 Err(msg) => return err!(self.loc, msg),
926 }
927 }
928 Ok(flags)
929 }
930
931 fn match_any_identifier(&mut self, err_msg: &str) -> ParseResult<&'a str> {
933 if let Some(Token::Identifier(text)) = self.token() {
934 self.consume();
935 Ok(text)
936 } else {
937 err!(self.loc, err_msg)
938 }
939 }
940
941 fn optional_srcloc(&mut self) -> ParseResult<ir::SourceLoc> {
945 if let Some(Token::SourceLoc(text)) = self.token() {
946 match u32::from_str_radix(text, 16) {
947 Ok(num) => {
948 self.consume();
949 Ok(ir::SourceLoc::new(num))
950 }
951 Err(_) => return err!(self.loc, "invalid source location: {}", text),
952 }
953 } else {
954 Ok(Default::default())
955 }
956 }
957
958 fn parse_literals_to_constant_data(&mut self, ty: Type) -> ParseResult<ConstantData> {
961 macro_rules! consume {
962 ( $ty:ident, $match_fn:expr ) => {{
963 assert!($ty.is_vector());
964 let mut data = ConstantData::default();
965 for _ in 0..$ty.lane_count() {
966 data = data.append($match_fn);
967 }
968 data
969 }};
970 }
971
972 if !ty.is_vector() && !ty.is_dynamic_vector() {
973 err!(self.loc, "Expected a controlling vector type, not {}", ty)
974 } else {
975 let constant_data = match ty.lane_type() {
976 I8 => consume!(ty, self.match_imm8("Expected an 8-bit integer")?),
977 I16 => consume!(ty, self.match_imm16("Expected a 16-bit integer")?),
978 I32 => consume!(ty, self.match_imm32("Expected a 32-bit integer")?),
979 I64 => consume!(ty, self.match_imm64("Expected a 64-bit integer")?),
980 F32 => consume!(ty, self.match_ieee32("Expected a 32-bit float")?),
981 F64 => consume!(ty, self.match_ieee64("Expected a 64-bit float")?),
982 _ => return err!(self.loc, "Expected a type of: float, int, bool"),
983 };
984 Ok(constant_data)
985 }
986 }
987
988 pub fn parse_cmdline_passes(&mut self, passes: &'a [String]) -> Vec<TestCommand<'a>> {
990 let mut list = Vec::new();
991 for pass in passes {
992 list.push(TestCommand::new(pass));
993 }
994 list
995 }
996
997 pub fn parse_test_commands(&mut self) -> Vec<TestCommand<'a>> {
999 let mut list = Vec::new();
1000 while self.token() == Some(Token::Identifier("test")) {
1001 list.push(TestCommand::new(self.consume_line()));
1002 }
1003 list
1004 }
1005
1006 fn parse_cmdline_target(&mut self, target_pass: Option<&str>) -> ParseResult<isaspec::IsaSpec> {
1011 let mut specified_target = false;
1013
1014 let mut targets = Vec::new();
1015 let flag_builder = settings::builder();
1016
1017 if let Some(targ) = target_pass {
1018 let loc = self.loc;
1019 let triple = match Triple::from_str(targ) {
1020 Ok(triple) => triple,
1021 Err(err) => return err!(loc, err),
1022 };
1023 let isa_builder = match isa::lookup(triple) {
1024 Err(isa::LookupError::SupportDisabled) => {
1025 return err!(loc, "support disabled target '{}'", targ);
1026 }
1027 Err(isa::LookupError::Unsupported) => {
1028 return warn!(loc, "unsupported target '{}'", targ);
1029 }
1030 Ok(b) => b,
1031 };
1032 specified_target = true;
1033
1034 targets.push(
1036 isa_builder
1037 .finish(settings::Flags::new(flag_builder.clone()))
1038 .map_err(|e| ParseError {
1039 location: loc,
1040 message: format!("invalid ISA flags for '{targ}': {e:?}"),
1041 is_warning: false,
1042 })?,
1043 );
1044 }
1045
1046 if !specified_target {
1047 Ok(isaspec::IsaSpec::None(settings::Flags::new(flag_builder)))
1049 } else {
1050 Ok(isaspec::IsaSpec::Some(targets))
1051 }
1052 }
1053
1054 fn parse_target_specs(&mut self, options: &ParseOptions) -> ParseResult<isaspec::IsaSpec> {
1059 let mut seen_target = false;
1061 let mut last_set_loc = None;
1063
1064 let mut targets = Vec::new();
1065 let mut flag_builder = settings::builder();
1066
1067 let bool_to_str = |val: bool| {
1068 if val {
1069 "true"
1070 } else {
1071 "false"
1072 }
1073 };
1074
1075 flag_builder
1077 .set(
1078 "machine_code_cfg_info",
1079 bool_to_str(options.machine_code_cfg_info),
1080 )
1081 .expect("machine_code_cfg_info option should be present");
1082
1083 flag_builder
1084 .set("unwind_info", bool_to_str(options.unwind_info))
1085 .expect("unwind_info option should be present");
1086
1087 while let Some(Token::Identifier(command)) = self.token() {
1088 match command {
1089 "set" => {
1090 last_set_loc = Some(self.loc);
1091 isaspec::parse_options(
1092 self.consume_line().trim().split_whitespace(),
1093 &mut flag_builder,
1094 self.loc,
1095 )
1096 .map_err(|err| ParseError::from(err))?;
1097 }
1098 "target" => {
1099 let loc = self.loc;
1100 let mut words = self.consume_line().trim().split_whitespace().peekable();
1103 let target_name = match words.next() {
1105 Some(w) => w,
1106 None => return err!(loc, "expected target triple"),
1107 };
1108 let triple = match Triple::from_str(target_name) {
1109 Ok(triple) => triple,
1110 Err(err) => return err!(loc, err),
1111 };
1112 let mut isa_builder = match isa::lookup(triple) {
1113 Err(isa::LookupError::SupportDisabled) => {
1114 continue;
1115 }
1116 Err(isa::LookupError::Unsupported) => {
1117 return warn!(loc, "unsupported target '{}'", target_name);
1118 }
1119 Ok(b) => b,
1120 };
1121 last_set_loc = None;
1122 seen_target = true;
1123 isaspec::parse_options(words, &mut isa_builder, self.loc)?;
1125
1126 targets.push(
1128 isa_builder
1129 .finish(settings::Flags::new(flag_builder.clone()))
1130 .map_err(|e| ParseError {
1131 location: loc,
1132 message: format!("invalid ISA flags for '{target_name}': {e:?}"),
1133 is_warning: false,
1134 })?,
1135 );
1136 }
1137 _ => break,
1138 }
1139 }
1140
1141 if !seen_target {
1142 Ok(isaspec::IsaSpec::None(settings::Flags::new(flag_builder)))
1144 } else if let Some(loc) = last_set_loc {
1145 err!(
1146 loc,
1147 "dangling 'set' command after ISA specification has no effect."
1148 )
1149 } else {
1150 Ok(isaspec::IsaSpec::Some(targets))
1151 }
1152 }
1153
1154 pub fn parse_cranelift_features(&mut self) -> ParseResult<Vec<Feature<'a>>> {
1156 let mut list = Vec::new();
1157 while self.token() == Some(Token::Identifier("feature")) {
1158 self.consume();
1159 let has = !self.optional(Token::Bang);
1160 match (self.token(), has) {
1161 (Some(Token::String(flag)), true) => list.push(Feature::With(flag)),
1162 (Some(Token::String(flag)), false) => list.push(Feature::Without(flag)),
1163 (tok, _) => {
1164 return err!(
1165 self.loc,
1166 format!("Expected feature flag string, got {:?}", tok)
1167 )
1168 }
1169 }
1170 self.consume();
1171 }
1172 Ok(list)
1173 }
1174
1175 pub fn parse_function_list(&mut self) -> ParseResult<Vec<(Function, Details<'a>)>> {
1179 let mut list = Vec::new();
1180 while self.token().is_some() {
1181 list.push(self.parse_function()?);
1182 }
1183 if let Some(err) = self.lex_error {
1184 return match err {
1185 LexError::InvalidChar => err!(self.loc, "invalid character"),
1186 };
1187 }
1188 Ok(list)
1189 }
1190
1191 fn parse_function(&mut self) -> ParseResult<(Function, Details<'a>)> {
1196 self.token();
1199 debug_assert!(self.comments.is_empty());
1200 self.start_gathering_comments();
1201
1202 self.match_identifier("function", "expected 'function'")?;
1203
1204 let location = self.loc;
1205
1206 let name = self.parse_user_func_name()?;
1208
1209 let sig = self.parse_signature()?;
1211
1212 let mut ctx = Context::new(Function::with_name_signature(name, sig));
1213
1214 self.match_token(Token::LBrace, "expected '{' before function body")?;
1216
1217 self.token();
1218 self.claim_gathered_comments(AnyEntity::Function);
1219
1220 self.parse_preamble(&mut ctx)?;
1222 self.parse_function_body(&mut ctx)?;
1224 self.match_token(Token::RBrace, "expected '}' after function body")?;
1226
1227 self.start_gathering_comments();
1229 self.token();
1230 self.claim_gathered_comments(AnyEntity::Function);
1231
1232 for (user_func_ref, user_external_name) in
1234 std::mem::take(&mut self.predeclared_external_names)
1235 {
1236 let actual_ref = ctx
1237 .function
1238 .declare_imported_user_function(user_external_name);
1239 assert_eq!(user_func_ref, actual_ref);
1240 }
1241
1242 let details = Details {
1243 location,
1244 comments: self.take_comments(),
1245 map: ctx.map,
1246 };
1247
1248 Ok((ctx.function, details))
1249 }
1250
1251 fn parse_user_func_name(&mut self) -> ParseResult<UserFuncName> {
1258 match self.token() {
1259 Some(Token::Name(s)) => {
1260 self.consume();
1261 Ok(UserFuncName::testcase(s))
1262 }
1263 Some(Token::UserRef(namespace)) => {
1264 self.consume();
1265 match self.token() {
1266 Some(Token::Colon) => {
1267 self.consume();
1268 match self.token() {
1269 Some(Token::Integer(index_str)) => {
1270 self.consume();
1271 let index: u32 =
1272 u32::from_str_radix(index_str, 10).map_err(|_| {
1273 self.error("the integer given overflows the u32 type")
1274 })?;
1275 Ok(UserFuncName::user(namespace, index))
1276 }
1277 _ => err!(self.loc, "expected integer"),
1278 }
1279 }
1280 _ => {
1281 err!(self.loc, "expected user function name in the form uX:Y")
1282 }
1283 }
1284 }
1285 _ => err!(self.loc, "expected external name"),
1286 }
1287 }
1288
1289 fn parse_external_name(&mut self) -> ParseResult<ExternalName> {
1296 match self.token() {
1297 Some(Token::Name(s)) => {
1298 self.consume();
1299 s.parse()
1300 .map_err(|_| self.error("invalid test case or libcall name"))
1301 }
1302
1303 Some(Token::UserNameRef(name_ref)) => {
1304 self.consume();
1305 Ok(ExternalName::user(UserExternalNameRef::new(
1306 name_ref as usize,
1307 )))
1308 }
1309
1310 Some(Token::UserRef(namespace)) => {
1311 self.consume();
1312 if let Some(Token::Colon) = self.token() {
1313 self.consume();
1314 match self.token() {
1315 Some(Token::Integer(index_str)) => {
1316 let index: u32 = u32::from_str_radix(index_str, 10).map_err(|_| {
1317 self.error("the integer given overflows the u32 type")
1318 })?;
1319 self.consume();
1320
1321 let name_ref = self
1325 .predeclared_external_names
1326 .iter()
1327 .find_map(|(reff, name)| {
1328 if name.index == index && name.namespace == namespace {
1329 Some(reff)
1330 } else {
1331 None
1332 }
1333 })
1334 .unwrap_or_else(|| {
1335 self.predeclared_external_names
1336 .push(ir::UserExternalName { namespace, index })
1337 });
1338
1339 Ok(ExternalName::user(name_ref))
1340 }
1341 _ => err!(self.loc, "expected integer"),
1342 }
1343 } else {
1344 err!(self.loc, "expected colon")
1345 }
1346 }
1347
1348 _ => err!(self.loc, "expected external name"),
1349 }
1350 }
1351
1352 fn parse_signature(&mut self) -> ParseResult<Signature> {
1357 let mut sig = Signature::new(self.default_calling_convention);
1359
1360 self.match_token(Token::LPar, "expected function signature: ( args... )")?;
1361 if self.token() != Some(Token::RPar) {
1363 sig.params = self.parse_abi_param_list()?;
1364 }
1365 self.match_token(Token::RPar, "expected ')' after function arguments")?;
1366 if self.optional(Token::Arrow) {
1367 sig.returns = self.parse_abi_param_list()?;
1368 }
1369
1370 match self.token() {
1372 Some(Token::Identifier(text)) => match text.parse() {
1373 Ok(cc) => {
1374 self.consume();
1375 sig.call_conv = cc;
1376 }
1377 _ => return err!(self.loc, "unknown calling convention: {}", text),
1378 },
1379
1380 Some(Token::Cold) => {
1381 self.consume();
1382 sig.call_conv = CallConv::Cold;
1383 }
1384 _ => {}
1385 }
1386
1387 Ok(sig)
1388 }
1389
1390 fn parse_abi_param_list(&mut self) -> ParseResult<Vec<AbiParam>> {
1395 let mut list = Vec::new();
1396
1397 list.push(self.parse_abi_param()?);
1399
1400 while self.optional(Token::Comma) {
1402 list.push(self.parse_abi_param()?);
1404 }
1405
1406 Ok(list)
1407 }
1408
1409 fn parse_abi_param(&mut self) -> ParseResult<AbiParam> {
1411 let mut arg = AbiParam::new(self.match_type("expected parameter type")?);
1413
1414 while let Some(Token::Identifier(s)) = self.token() {
1416 match s {
1417 "uext" => arg.extension = ArgumentExtension::Uext,
1418 "sext" => arg.extension = ArgumentExtension::Sext,
1419 "sarg" => {
1420 self.consume();
1421 self.match_token(Token::LPar, "expected '(' to begin sarg size")?;
1422 let size = self.match_uimm32("expected byte-size in sarg decl")?;
1423 self.match_token(Token::RPar, "expected ')' to end sarg size")?;
1424 arg.purpose = ArgumentPurpose::StructArgument(size.into());
1425 continue;
1426 }
1427 _ => {
1428 if let Ok(purpose) = s.parse() {
1429 arg.purpose = purpose;
1430 } else {
1431 break;
1432 }
1433 }
1434 }
1435 self.consume();
1436 }
1437
1438 Ok(arg)
1439 }
1440
1441 fn parse_preamble(&mut self, ctx: &mut Context) -> ParseResult<()> {
1452 loop {
1453 match self.token() {
1454 Some(Token::StackSlot(..)) => {
1455 self.start_gathering_comments();
1456 let loc = self.loc;
1457 self.parse_stack_slot_decl()
1458 .and_then(|(ss, dat)| ctx.add_ss(ss, dat, loc))
1459 }
1460 Some(Token::DynamicStackSlot(..)) => {
1461 self.start_gathering_comments();
1462 let loc = self.loc;
1463 self.parse_dynamic_stack_slot_decl()
1464 .and_then(|(dss, dat)| ctx.add_dss(dss, dat, loc))
1465 }
1466 Some(Token::DynamicType(..)) => {
1467 self.start_gathering_comments();
1468 let loc = self.loc;
1469 self.parse_dynamic_type_decl()
1470 .and_then(|(dt, dat)| ctx.add_dt(dt, dat, loc))
1471 }
1472 Some(Token::GlobalValue(..)) => {
1473 self.start_gathering_comments();
1474 self.parse_global_value_decl()
1475 .and_then(|(gv, dat, maybe_fact)| ctx.add_gv(gv, dat, maybe_fact, self.loc))
1476 }
1477 Some(Token::MemoryType(..)) => {
1478 self.start_gathering_comments();
1479 self.parse_memory_type_decl()
1480 .and_then(|(mt, dat)| ctx.add_mt(mt, dat, self.loc))
1481 }
1482 Some(Token::SigRef(..)) => {
1483 self.start_gathering_comments();
1484 self.parse_signature_decl().and_then(|(sig, dat)| {
1485 ctx.add_sig(sig, dat, self.loc, self.default_calling_convention)
1486 })
1487 }
1488 Some(Token::FuncRef(..)) => {
1489 self.start_gathering_comments();
1490 self.parse_function_decl(ctx)
1491 .and_then(|(fn_, dat)| ctx.add_fn(fn_, dat, self.loc))
1492 }
1493 Some(Token::Constant(..)) => {
1494 self.start_gathering_comments();
1495 self.parse_constant_decl()
1496 .and_then(|(c, v)| ctx.add_constant(c, v, self.loc))
1497 }
1498 Some(Token::Identifier("stack_limit")) => {
1499 self.start_gathering_comments();
1500 self.parse_stack_limit_decl()
1501 .and_then(|gv| ctx.add_stack_limit(gv, self.loc))
1502 }
1503 _ => return Ok(()),
1505 }?;
1506 }
1507 }
1508
1509 fn parse_stack_slot_decl(&mut self) -> ParseResult<(StackSlot, StackSlotData)> {
1518 let ss = self.match_ss("expected stack slot number: ss«n»")?;
1519 self.match_token(Token::Equal, "expected '=' in stack slot declaration")?;
1520 let kind = self.match_enum("expected stack slot kind")?;
1521
1522 let bytes: i64 = self
1524 .match_imm64("expected byte-size in stack_slot decl")?
1525 .into();
1526 if bytes < 0 {
1527 return err!(self.loc, "negative stack slot size");
1528 }
1529 if bytes > i64::from(u32::MAX) {
1530 return err!(self.loc, "stack slot too large");
1531 }
1532
1533 let align = if self.token() == Some(Token::Comma) {
1535 self.consume();
1536 self.match_token(
1537 Token::Identifier("align"),
1538 "expected a valid stack-slot flag (currently only `align`)",
1539 )?;
1540 self.match_token(Token::Equal, "expected `=` after flag")?;
1541 let align: i64 = self
1542 .match_imm64("expected alignment-size after `align` flag")?
1543 .into();
1544 u32::try_from(align)
1545 .map_err(|_| self.error("alignment must be a 32-bit unsigned integer"))?
1546 } else {
1547 1
1548 };
1549
1550 if !align.is_power_of_two() {
1551 return err!(self.loc, "stack slot alignment is not a power of two");
1552 }
1553 let align_shift = u8::try_from(align.ilog2()).unwrap(); let data = StackSlotData::new(kind, bytes as u32, align_shift);
1556
1557 self.token();
1559 self.claim_gathered_comments(ss);
1560
1561 Ok((ss, data))
1563 }
1564
1565 fn parse_dynamic_stack_slot_decl(
1566 &mut self,
1567 ) -> ParseResult<(DynamicStackSlot, DynamicStackSlotData)> {
1568 let dss = self.match_dss("expected stack slot number: dss«n»")?;
1569 self.match_token(Token::Equal, "expected '=' in stack slot declaration")?;
1570 let kind = self.match_enum("expected stack slot kind")?;
1571 let dt = self.match_dt("expected dynamic type")?;
1572 let data = DynamicStackSlotData::new(kind, dt);
1573 self.token();
1575 self.claim_gathered_comments(dss);
1576
1577 Ok((dss, data))
1579 }
1580
1581 fn parse_dynamic_type_decl(&mut self) -> ParseResult<(DynamicType, DynamicTypeData)> {
1582 let dt = self.match_dt("expected dynamic type number: dt«n»")?;
1583 self.match_token(Token::Equal, "expected '=' in stack slot declaration")?;
1584 let vector_base_ty = self.match_type("expected base type")?;
1585 assert!(vector_base_ty.is_vector(), "expected vector type");
1586 self.match_token(
1587 Token::Multiply,
1588 "expected '*' followed by a dynamic scale value",
1589 )?;
1590 let dyn_scale = self.match_gv("expected dynamic scale global value")?;
1591 let data = DynamicTypeData::new(vector_base_ty, dyn_scale);
1592 self.token();
1594 self.claim_gathered_comments(dt);
1595 Ok((dt, data))
1596 }
1597
1598 fn parse_global_value_decl(
1608 &mut self,
1609 ) -> ParseResult<(GlobalValue, GlobalValueData, Option<Fact>)> {
1610 let gv = self.match_gv("expected global value number: gv«n»")?;
1611
1612 let fact = if self.token() == Some(Token::Bang) {
1613 self.consume();
1614 Some(self.parse_fact()?)
1615 } else {
1616 None
1617 };
1618
1619 self.match_token(Token::Equal, "expected '=' in global value declaration")?;
1620
1621 let data = match self.match_any_identifier("expected global value kind")? {
1622 "vmctx" => GlobalValueData::VMContext,
1623 "load" => {
1624 self.match_token(
1625 Token::Dot,
1626 "expected '.' followed by type in load global value decl",
1627 )?;
1628 let global_type = self.match_type("expected load type")?;
1629 let flags = self.optional_memflags()?;
1630 let base = self.match_gv("expected global value: gv«n»")?;
1631 let offset = self.optional_offset32()?;
1632
1633 if !(flags.notrap() && flags.aligned()) {
1634 return err!(self.loc, "global-value load must be notrap and aligned");
1635 }
1636 GlobalValueData::Load {
1637 base,
1638 offset,
1639 global_type,
1640 flags,
1641 }
1642 }
1643 "iadd_imm" => {
1644 self.match_token(
1645 Token::Dot,
1646 "expected '.' followed by type in iadd_imm global value decl",
1647 )?;
1648 let global_type = self.match_type("expected iadd type")?;
1649 let base = self.match_gv("expected global value: gv«n»")?;
1650 self.match_token(
1651 Token::Comma,
1652 "expected ',' followed by rhs in iadd_imm global value decl",
1653 )?;
1654 let offset = self.match_imm64("expected iadd_imm immediate")?;
1655 GlobalValueData::IAddImm {
1656 base,
1657 offset,
1658 global_type,
1659 }
1660 }
1661 "symbol" => {
1662 let colocated = self.optional(Token::Identifier("colocated"));
1663 let tls = self.optional(Token::Identifier("tls"));
1664 let name = self.parse_external_name()?;
1665 let offset = self.optional_offset_imm64()?;
1666 GlobalValueData::Symbol {
1667 name,
1668 offset,
1669 colocated,
1670 tls,
1671 }
1672 }
1673 "dyn_scale_target_const" => {
1674 self.match_token(
1675 Token::Dot,
1676 "expected '.' followed by type in dynamic scale global value decl",
1677 )?;
1678 let vector_type = self.match_type("expected load type")?;
1679 assert!(vector_type.is_vector(), "Expected vector type");
1680 GlobalValueData::DynScaleTargetConst { vector_type }
1681 }
1682 other => return err!(self.loc, "Unknown global value kind '{}'", other),
1683 };
1684
1685 self.token();
1687 self.claim_gathered_comments(gv);
1688
1689 Ok((gv, data, fact))
1690 }
1691
1692 fn parse_memory_type_field(&mut self) -> ParseResult<MemoryTypeField> {
1697 let offset: u64 = self
1698 .match_uimm64(
1699 "expected u64 constant value for field offset in struct memory-type declaration",
1700 )?
1701 .into();
1702 self.match_token(
1703 Token::Colon,
1704 "expected colon after field offset in struct memory-type declaration",
1705 )?;
1706 let ty = self.match_type("expected type for field in struct memory-type declaration")?;
1707 let readonly = if self.token() == Some(Token::Identifier("readonly")) {
1708 self.consume();
1709 true
1710 } else {
1711 false
1712 };
1713 let fact = if self.token() == Some(Token::Bang) {
1714 self.consume();
1715 let fact = self.parse_fact()?;
1716 Some(fact)
1717 } else {
1718 None
1719 };
1720 Ok(MemoryTypeField {
1721 offset,
1722 ty,
1723 readonly,
1724 fact,
1725 })
1726 }
1727
1728 fn parse_memory_type_decl(&mut self) -> ParseResult<(MemoryType, MemoryTypeData)> {
1738 let mt = self.match_mt("expected memory type number: mt«n»")?;
1739 self.match_token(Token::Equal, "expected '=' in memory type declaration")?;
1740
1741 let data = match self.token() {
1742 Some(Token::Identifier("struct")) => {
1743 self.consume();
1744 let size: u64 = self.match_uimm64("expected u64 constant value for struct size in struct memory-type declaration")?.into();
1745 self.match_token(Token::LBrace, "expected opening brace to start struct fields in struct memory-type declaration")?;
1746 let mut fields = vec![];
1747 while self.token() != Some(Token::RBrace) {
1748 let field = self.parse_memory_type_field()?;
1749 fields.push(field);
1750 if self.token() == Some(Token::Comma) {
1751 self.consume();
1752 } else {
1753 break;
1754 }
1755 }
1756 self.match_token(
1757 Token::RBrace,
1758 "expected closing brace after struct fields in struct memory-type declaration",
1759 )?;
1760 MemoryTypeData::Struct { size, fields }
1761 }
1762 Some(Token::Identifier("memory")) => {
1763 self.consume();
1764 let size: u64 = self.match_uimm64("expected u64 constant value for size in static-memory memory-type declaration")?.into();
1765 MemoryTypeData::Memory { size }
1766 }
1767 Some(Token::Identifier("dynamic_memory")) => {
1768 self.consume();
1769 let gv = self.match_gv(
1770 "expected a global value for `dynamic_memory` memory-type declaration",
1771 )?;
1772 self.match_token(
1773 Token::Plus,
1774 "expected `+` after global value in `dynamic_memory` memory-type declaration",
1775 )?;
1776 let size: u64 = self.match_uimm64("expected u64 constant value for size offset in `dynamic_memory` memory-type declaration")?.into();
1777 MemoryTypeData::DynamicMemory { gv, size }
1778 }
1779 Some(Token::Identifier("empty")) => {
1780 self.consume();
1781 MemoryTypeData::Empty
1782 }
1783 other => {
1784 return err!(
1785 self.loc,
1786 "Unknown memory type declaration kind '{:?}'",
1787 other
1788 )
1789 }
1790 };
1791
1792 self.token();
1794 self.claim_gathered_comments(mt);
1795
1796 Ok((mt, data))
1797 }
1798
1799 fn parse_signature_decl(&mut self) -> ParseResult<(SigRef, Signature)> {
1804 let sig = self.match_sig("expected signature number: sig«n»")?;
1805 self.match_token(Token::Equal, "expected '=' in signature decl")?;
1806 let data = self.parse_signature()?;
1807
1808 self.token();
1810 self.claim_gathered_comments(sig);
1811
1812 Ok((sig, data))
1813 }
1814
1815 fn parse_function_decl(&mut self, ctx: &mut Context) -> ParseResult<(FuncRef, ExtFuncData)> {
1826 let fn_ = self.match_fn("expected function number: fn«n»")?;
1827 self.match_token(Token::Equal, "expected '=' in function decl")?;
1828
1829 let loc = self.loc;
1830
1831 let colocated = self.optional(Token::Identifier("colocated"));
1833
1834 let name = self.parse_external_name()?;
1836
1837 let data = match self.token() {
1839 Some(Token::LPar) => {
1840 let sig = self.parse_signature()?;
1842 let sigref = ctx.function.import_signature(sig);
1843 ctx.map
1844 .def_entity(sigref.into(), loc)
1845 .expect("duplicate SigRef entities created");
1846 ExtFuncData {
1847 name,
1848 signature: sigref,
1849 colocated,
1850 }
1851 }
1852 Some(Token::SigRef(sig_src)) => {
1853 let sig = match SigRef::with_number(sig_src) {
1854 None => {
1855 return err!(self.loc, "attempted to use invalid signature ss{}", sig_src);
1856 }
1857 Some(sig) => sig,
1858 };
1859 ctx.check_sig(sig, self.loc)?;
1860 self.consume();
1861 ExtFuncData {
1862 name,
1863 signature: sig,
1864 colocated,
1865 }
1866 }
1867 _ => return err!(self.loc, "expected 'function' or sig«n» in function decl"),
1868 };
1869
1870 self.token();
1872 self.claim_gathered_comments(fn_);
1873
1874 Ok((fn_, data))
1875 }
1876
1877 fn parse_jump_table(
1882 &mut self,
1883 ctx: &mut Context,
1884 def: ir::BlockCall,
1885 ) -> ParseResult<ir::JumpTable> {
1886 self.match_token(Token::LBracket, "expected '[' before jump table contents")?;
1887
1888 let mut data = Vec::new();
1889
1890 match self.token() {
1891 Some(Token::Block(dest)) => {
1892 self.consume();
1893 let args = self.parse_opt_value_list()?;
1894 data.push(ctx.function.dfg.block_call(dest, &args));
1895
1896 loop {
1897 match self.token() {
1898 Some(Token::Comma) => {
1899 self.consume();
1900 if let Some(Token::Block(dest)) = self.token() {
1901 self.consume();
1902 let args = self.parse_opt_value_list()?;
1903 data.push(ctx.function.dfg.block_call(dest, &args));
1904 } else {
1905 return err!(self.loc, "expected jump_table entry");
1906 }
1907 }
1908 Some(Token::RBracket) => break,
1909 _ => return err!(self.loc, "expected ']' after jump table contents"),
1910 }
1911 }
1912 }
1913 Some(Token::RBracket) => (),
1914 _ => return err!(self.loc, "expected jump_table entry"),
1915 }
1916
1917 self.consume();
1918
1919 Ok(ctx
1920 .function
1921 .dfg
1922 .jump_tables
1923 .push(JumpTableData::new(def, &data)))
1924 }
1925
1926 fn parse_constant_decl(&mut self) -> ParseResult<(Constant, ConstantData)> {
1930 let name = self.match_constant()?;
1931 self.match_token(Token::Equal, "expected '=' in constant decl")?;
1932 let data = if let Some(Token::Type(_)) = self.token() {
1933 let ty = self.match_type("expected type of constant")?;
1934 self.match_uimm128(ty)
1935 } else {
1936 self.match_hexadecimal_constant("expected an immediate hexadecimal operand")
1937 }?;
1938
1939 self.token();
1941 self.claim_gathered_comments(name);
1942
1943 Ok((name, data))
1944 }
1945
1946 fn parse_stack_limit_decl(&mut self) -> ParseResult<GlobalValue> {
1950 self.match_stack_limit()?;
1951 self.match_token(Token::Equal, "expected '=' in stack limit decl")?;
1952 let limit = match self.token() {
1953 Some(Token::GlobalValue(base_num)) => match GlobalValue::with_number(base_num) {
1954 Some(gv) => gv,
1955 None => return err!(self.loc, "invalid global value number for stack limit"),
1956 },
1957 _ => return err!(self.loc, "expected global value"),
1958 };
1959 self.consume();
1960
1961 self.token();
1963 self.claim_gathered_comments(AnyEntity::StackLimit);
1964
1965 Ok(limit)
1966 }
1967
1968 fn parse_function_body(&mut self, ctx: &mut Context) -> ParseResult<()> {
1973 while self.token() != Some(Token::RBrace) {
1974 self.parse_basic_block(ctx)?;
1975 }
1976
1977 for block in &ctx.function.layout {
1980 for inst in ctx.function.layout.block_insts(block) {
1981 for value in ctx.function.dfg.inst_values(inst) {
1982 if !ctx.map.contains_value(value) {
1983 return err!(
1984 ctx.map.location(AnyEntity::Inst(inst)).unwrap(),
1985 "undefined operand value {}",
1986 value
1987 );
1988 }
1989 }
1990 }
1991 }
1992
1993 for alias in &ctx.aliases {
1994 if !ctx.function.dfg.set_alias_type_for_parser(*alias) {
1995 let loc = ctx.map.location(AnyEntity::Value(*alias)).unwrap();
1996 return err!(loc, "alias cycle involving {}", alias);
1997 }
1998 }
1999
2000 Ok(())
2001 }
2002
2003 fn parse_basic_block(&mut self, ctx: &mut Context) -> ParseResult<()> {
2010 self.start_gathering_comments();
2012
2013 let block_num = self.match_block("expected block header")?;
2014 let block = ctx.add_block(block_num, self.loc)?;
2015
2016 if block_num.as_u32() >= MAX_BLOCKS_IN_A_FUNCTION {
2017 return Err(self.error("too many blocks"));
2018 }
2019
2020 if self.token() == Some(Token::LPar) {
2021 self.parse_block_params(ctx, block)?;
2022 }
2023
2024 if self.optional(Token::Cold) {
2025 ctx.set_cold_block(block);
2026 }
2027
2028 self.match_token(Token::Colon, "expected ':' after block parameters")?;
2029
2030 self.token();
2032 self.claim_gathered_comments(block);
2033
2034 while match self.token() {
2036 Some(Token::Value(_))
2037 | Some(Token::Identifier(_))
2038 | Some(Token::LBracket)
2039 | Some(Token::SourceLoc(_)) => true,
2040 _ => false,
2041 } {
2042 let srcloc = self.optional_srcloc()?;
2043
2044 let results = self.parse_inst_results(ctx)?;
2049
2050 for result in &results {
2051 while ctx.function.dfg.num_values() <= result.index() {
2052 ctx.function.dfg.make_invalid_value_for_parser();
2053 }
2054 }
2055
2056 match self.token() {
2057 Some(Token::Arrow) => {
2058 self.consume();
2059 self.parse_value_alias(&results, ctx)?;
2060 }
2061 Some(Token::Equal) => {
2062 self.consume();
2063 self.parse_instruction(&results, srcloc, ctx, block)?;
2064 }
2065 _ if !results.is_empty() => return err!(self.loc, "expected -> or ="),
2066 _ => self.parse_instruction(&results, srcloc, ctx, block)?,
2067 }
2068 }
2069
2070 Ok(())
2071 }
2072
2073 fn parse_block_params(&mut self, ctx: &mut Context, block: Block) -> ParseResult<()> {
2077 self.match_token(Token::LPar, "expected '(' before block parameters")?;
2079
2080 if self.token() == Some(Token::RPar) {
2082 self.consume();
2083 return Ok(());
2084 }
2085
2086 self.parse_block_param(ctx, block)?;
2088
2089 while self.optional(Token::Comma) {
2091 self.parse_block_param(ctx, block)?;
2093 }
2094
2095 self.match_token(Token::RPar, "expected ')' after block parameters")?;
2097
2098 Ok(())
2099 }
2100
2101 fn parse_block_param(&mut self, ctx: &mut Context, block: Block) -> ParseResult<()> {
2107 let v = self.match_value("block argument must be a value")?;
2109 let v_location = self.loc;
2110 let fact = if self.token() == Some(Token::Bang) {
2112 self.consume();
2113 Some(self.parse_fact()?)
2115 } else {
2116 None
2117 };
2118 self.match_token(Token::Colon, "expected ':' after block argument")?;
2119 while ctx.function.dfg.num_values() <= v.index() {
2122 ctx.function.dfg.make_invalid_value_for_parser();
2123 }
2124
2125 let t = self.match_type("expected block argument type")?;
2126 ctx.function.dfg.append_block_param_for_parser(block, t, v);
2128 ctx.map.def_value(v, v_location)?;
2129 ctx.function.dfg.facts[v] = fact;
2130
2131 Ok(())
2132 }
2133
2134 fn parse_fact(&mut self) -> ParseResult<Fact> {
2147 match self.token() {
2148 Some(Token::Identifier("range")) => {
2149 self.consume();
2150 self.match_token(Token::LPar, "`range` fact needs an opening `(`")?;
2151 let bit_width: u64 = self
2152 .match_uimm64("expected a bit-width value for `range` fact")?
2153 .into();
2154 self.match_token(Token::Comma, "expected a comma")?;
2155 let min: u64 = self
2156 .match_uimm64("expected a min value for `range` fact")?
2157 .into();
2158 self.match_token(Token::Comma, "expected a comma")?;
2159 let max: u64 = self
2160 .match_uimm64("expected a max value for `range` fact")?
2161 .into();
2162 self.match_token(Token::RPar, "`range` fact needs a closing `)`")?;
2163 let bit_width_max = match bit_width {
2164 x if x > 64 => {
2165 return Err(self.error("bitwidth must be <= 64 bits on a `range` fact"));
2166 }
2167 64 => u64::MAX,
2168 x => (1u64 << x) - 1,
2169 };
2170 if min > max {
2171 return Err(self.error(
2172 "min value must be less than or equal to max value on a `range` fact",
2173 ));
2174 }
2175 if max > bit_width_max {
2176 return Err(
2177 self.error("max value is out of range for bitwidth on a `range` fact")
2178 );
2179 }
2180 Ok(Fact::Range {
2181 bit_width: u16::try_from(bit_width).unwrap(),
2182 min: min.into(),
2183 max: max.into(),
2184 })
2185 }
2186 Some(Token::Identifier("dynamic_range")) => {
2187 self.consume();
2188 self.match_token(Token::LPar, "`dynamic_range` fact needs an opening `(`")?;
2189 let bit_width: u64 = self
2190 .match_uimm64("expected a bit-width value for `dynamic_range` fact")?
2191 .into();
2192 self.match_token(Token::Comma, "expected a comma")?;
2193 let min = self.parse_expr()?;
2194 self.match_token(Token::Comma, "expected a comma")?;
2195 let max = self.parse_expr()?;
2196 self.match_token(Token::RPar, "`dynamic_range` fact needs a closing `)`")?;
2197 Ok(Fact::DynamicRange {
2198 bit_width: u16::try_from(bit_width).unwrap(),
2199 min,
2200 max,
2201 })
2202 }
2203 Some(Token::Identifier("mem")) => {
2204 self.consume();
2205 self.match_token(Token::LPar, "expected a `(`")?;
2206 let ty = self.match_mt("expected a memory type for `mem` fact")?;
2207 self.match_token(
2208 Token::Comma,
2209 "expected a comma after memory type in `mem` fact",
2210 )?;
2211 let min_offset: u64 = self
2212 .match_uimm64("expected a uimm64 minimum pointer offset for `mem` fact")?
2213 .into();
2214 self.match_token(Token::Comma, "expected a comma after offset in `mem` fact")?;
2215 let max_offset: u64 = self
2216 .match_uimm64("expected a uimm64 maximum pointer offset for `mem` fact")?
2217 .into();
2218 let nullable = if self.token() == Some(Token::Comma) {
2219 self.consume();
2220 self.match_token(
2221 Token::Identifier("nullable"),
2222 "expected `nullable` in last optional field of `dynamic_mem`",
2223 )?;
2224 true
2225 } else {
2226 false
2227 };
2228 self.match_token(Token::RPar, "expected a `)`")?;
2229 Ok(Fact::Mem {
2230 ty,
2231 min_offset,
2232 max_offset,
2233 nullable,
2234 })
2235 }
2236 Some(Token::Identifier("dynamic_mem")) => {
2237 self.consume();
2238 self.match_token(Token::LPar, "expected a `(`")?;
2239 let ty = self.match_mt("expected a memory type for `dynamic_mem` fact")?;
2240 self.match_token(
2241 Token::Comma,
2242 "expected a comma after memory type in `dynamic_mem` fact",
2243 )?;
2244 let min = self.parse_expr()?;
2245 self.match_token(
2246 Token::Comma,
2247 "expected a comma after offset in `dynamic_mem` fact",
2248 )?;
2249 let max = self.parse_expr()?;
2250 let nullable = if self.token() == Some(Token::Comma) {
2251 self.consume();
2252 self.match_token(
2253 Token::Identifier("nullable"),
2254 "expected `nullable` in last optional field of `dynamic_mem`",
2255 )?;
2256 true
2257 } else {
2258 false
2259 };
2260 self.match_token(Token::RPar, "expected a `)`")?;
2261 Ok(Fact::DynamicMem {
2262 ty,
2263 min,
2264 max,
2265 nullable,
2266 })
2267 }
2268 Some(Token::Identifier("def")) => {
2269 self.consume();
2270 self.match_token(Token::LPar, "expected a `(`")?;
2271 let value = self.match_value("expected a value number in `def` fact")?;
2272 self.match_token(Token::RPar, "expected a `)`")?;
2273 Ok(Fact::Def { value })
2274 }
2275 Some(Token::Identifier("compare")) => {
2276 self.consume();
2277 self.match_token(Token::LPar, "expected a `(`")?;
2278 let kind = self.match_enum("expected intcc condition code in `compare` fact")?;
2279 self.match_token(
2280 Token::Comma,
2281 "expected comma in `compare` fact after condition code",
2282 )?;
2283 let lhs = self.parse_expr()?;
2284 self.match_token(Token::Comma, "expected comma in `compare` fact after LHS")?;
2285 let rhs = self.parse_expr()?;
2286 self.match_token(Token::RPar, "expected a `)`")?;
2287 Ok(Fact::Compare { kind, lhs, rhs })
2288 }
2289 Some(Token::Identifier("conflict")) => {
2290 self.consume();
2291 Ok(Fact::Conflict)
2292 }
2293 _ => Err(self.error(
2294 "expected a `range`, 'dynamic_range', `mem`, `dynamic_mem`, `def`, `compare` or `conflict` fact",
2295 )),
2296 }
2297 }
2298
2299 fn parse_expr(&mut self) -> ParseResult<Expr> {
2306 if let Some(Token::Integer(_)) = self.token() {
2307 let offset: i64 = self
2308 .match_imm64("expected imm64 for dynamic expression")?
2309 .into();
2310 Ok(Expr {
2311 base: BaseExpr::None,
2312 offset,
2313 })
2314 } else {
2315 let base = self.parse_base_expr()?;
2316 match self.token() {
2317 Some(Token::Plus) => {
2318 self.consume();
2319 let offset: u64 = self
2320 .match_uimm64(
2321 "expected uimm64 in imm64 range for offset in dynamic expression",
2322 )?
2323 .into();
2324 let offset: i64 = i64::try_from(offset).map_err(|_| {
2325 self.error("integer offset in dynamic expression is out of range")
2326 })?;
2327 Ok(Expr { base, offset })
2328 }
2329 Some(Token::Integer(x)) if x.starts_with("-") => {
2330 let offset: i64 = self
2331 .match_imm64("expected an imm64 range for offset in dynamic expression")?
2332 .into();
2333 Ok(Expr { base, offset })
2334 }
2335 _ => Ok(Expr { base, offset: 0 }),
2336 }
2337 }
2338 }
2339
2340 fn parse_base_expr(&mut self) -> ParseResult<BaseExpr> {
2347 match self.token() {
2348 Some(Token::Identifier("max")) => {
2349 self.consume();
2350 Ok(BaseExpr::Max)
2351 }
2352 Some(Token::GlobalValue(..)) => {
2353 let gv = self.match_gv("expected global value")?;
2354 Ok(BaseExpr::GlobalValue(gv))
2355 }
2356 Some(Token::Value(..)) => {
2357 let value = self.match_value("expected value")?;
2358 Ok(BaseExpr::Value(value))
2359 }
2360 _ => Ok(BaseExpr::None),
2361 }
2362 }
2363
2364 fn parse_inst_results(&mut self, ctx: &mut Context) -> ParseResult<SmallVec<[Value; 1]>> {
2369 let mut results = SmallVec::new();
2371
2372 if let Some(Token::Value(v)) = self.token() {
2375 self.consume();
2376
2377 results.push(v);
2378
2379 let fact = if self.token() == Some(Token::Bang) {
2380 self.consume();
2381 Some(self.parse_fact()?)
2383 } else {
2384 None
2385 };
2386 ctx.function.dfg.facts[v] = fact;
2387
2388 while self.optional(Token::Comma) {
2390 let v = self.match_value("expected result value")?;
2392 results.push(v);
2393
2394 let fact = if self.token() == Some(Token::Bang) {
2395 self.consume();
2396 Some(self.parse_fact()?)
2398 } else {
2399 None
2400 };
2401 ctx.function.dfg.facts[v] = fact;
2402 }
2403 }
2404
2405 Ok(results)
2406 }
2407
2408 fn parse_value_alias(&mut self, results: &[Value], ctx: &mut Context) -> ParseResult<()> {
2413 if results.len() != 1 {
2414 return err!(self.loc, "wrong number of aliases");
2415 }
2416 let result = results[0];
2417 let dest = self.match_value("expected value alias")?;
2418
2419 if ctx.map.contains_value(result) {
2421 if let Some(old) = ctx.function.dfg.value_alias_dest_for_serialization(result) {
2422 if old != dest {
2423 return err!(
2424 self.loc,
2425 "value {} is already defined as an alias with destination {}",
2426 result,
2427 old
2428 );
2429 }
2430 } else {
2431 return err!(self.loc, "value {} is already defined");
2432 }
2433 } else {
2434 ctx.map.def_value(result, self.loc)?;
2435 }
2436
2437 if !ctx.map.contains_value(dest) {
2438 return err!(self.loc, "value {} is not yet defined", dest);
2439 }
2440
2441 ctx.function
2442 .dfg
2443 .make_value_alias_for_serialization(dest, result);
2444
2445 ctx.aliases.push(result);
2446 Ok(())
2447 }
2448
2449 fn parse_instruction(
2454 &mut self,
2455 results: &[Value],
2456 srcloc: ir::SourceLoc,
2457 ctx: &mut Context,
2458 block: Block,
2459 ) -> ParseResult<()> {
2460 for val in results {
2462 ctx.map.def_value(*val, self.loc)?;
2463 }
2464
2465 self.start_gathering_comments();
2467
2468 let opcode = if let Some(Token::Identifier(text)) = self.token() {
2470 match text.parse() {
2471 Ok(opc) => opc,
2472 Err(msg) => return err!(self.loc, "{}: '{}'", msg, text),
2473 }
2474 } else {
2475 return err!(self.loc, "expected instruction opcode");
2476 };
2477 let opcode_loc = self.loc;
2478 self.consume();
2479
2480 let explicit_ctrl_type = if self.optional(Token::Dot) {
2483 if let Some(Token::Type(_t)) = self.token() {
2484 Some(self.match_type("expected type after 'opcode.'")?)
2485 } else {
2486 let dt = self.match_dt("expected dynamic type")?;
2487 self.concrete_from_dt(dt, ctx)
2488 }
2489 } else {
2490 None
2491 };
2492
2493 let inst_data = self.parse_inst_operands(ctx, opcode, explicit_ctrl_type)?;
2495
2496 let ctrl_typevar = self.infer_typevar(ctx, opcode, explicit_ctrl_type, &inst_data)?;
2503 let inst = ctx.function.dfg.make_inst(inst_data);
2504 if opcode.is_call() && !opcode.is_return() && self.optional(Token::Comma) {
2505 self.match_identifier("stack_map", "expected `stack_map = [...]`")?;
2506 self.match_token(Token::Equal, "expected `= [...]`")?;
2507 self.match_token(Token::LBracket, "expected `[...]`")?;
2508 while !self.optional(Token::RBracket) {
2509 let ty = self.match_type("expected `<type> @ <slot> + <offset>`")?;
2510 self.match_token(Token::At, "expected `@ <slot> + <offset>`")?;
2511 let slot = self.match_ss("expected `<slot> + <offset>`")?;
2512 let offset: u32 = match self.token() {
2513 Some(Token::Integer(s)) if s.starts_with('+') => {
2514 self.match_uimm32("expected a u32 offset")?.into()
2515 }
2516 _ => {
2517 self.match_token(Token::Plus, "expected `+ <offset>`")?;
2518 self.match_uimm32("expected a u32 offset")?.into()
2519 }
2520 };
2521 ctx.function
2522 .dfg
2523 .append_user_stack_map_entry(inst, ir::UserStackMapEntry { ty, slot, offset });
2524 if !self.optional(Token::Comma) {
2525 self.match_token(Token::RBracket, "expected `,` or `]`")?;
2526 break;
2527 }
2528 }
2529 }
2530 let num_results =
2531 ctx.function
2532 .dfg
2533 .make_inst_results_for_parser(inst, ctrl_typevar, results);
2534 ctx.function.layout.append_inst(inst, block);
2535 ctx.map
2536 .def_entity(inst.into(), opcode_loc)
2537 .expect("duplicate inst references created");
2538
2539 if !srcloc.is_default() {
2540 ctx.function.set_srcloc(inst, srcloc);
2541 }
2542
2543 if results.len() != num_results {
2544 return err!(
2545 self.loc,
2546 "instruction produces {} result values, {} given",
2547 num_results,
2548 results.len()
2549 );
2550 }
2551
2552 self.token();
2554 self.claim_gathered_comments(inst);
2555
2556 Ok(())
2557 }
2558
2559 fn infer_typevar(
2567 &self,
2568 ctx: &Context,
2569 opcode: Opcode,
2570 explicit_ctrl_type: Option<Type>,
2571 inst_data: &InstructionData,
2572 ) -> ParseResult<Type> {
2573 let constraints = opcode.constraints();
2574 let ctrl_type = match explicit_ctrl_type {
2575 Some(t) => t,
2576 None => {
2577 if constraints.use_typevar_operand() {
2578 let ctrl_src_value = inst_data
2585 .typevar_operand(&ctx.function.dfg.value_lists)
2586 .expect("Constraints <-> Format inconsistency");
2587 if !ctx.map.contains_value(ctrl_src_value) {
2588 return err!(
2589 self.loc,
2590 "type variable required for polymorphic opcode, e.g. '{}.{}'; \
2591 can't infer from {} which is not yet defined",
2592 opcode,
2593 constraints.ctrl_typeset().unwrap().example(),
2594 ctrl_src_value
2595 );
2596 }
2597 if !ctx.function.dfg.value_is_valid_for_parser(ctrl_src_value) {
2598 return err!(
2599 self.loc,
2600 "type variable required for polymorphic opcode, e.g. '{}.{}'; \
2601 can't infer from {} which is not yet resolved",
2602 opcode,
2603 constraints.ctrl_typeset().unwrap().example(),
2604 ctrl_src_value
2605 );
2606 }
2607 ctx.function.dfg.value_type(ctrl_src_value)
2608 } else if constraints.is_polymorphic() {
2609 return err!(
2612 self.loc,
2613 "type variable required for polymorphic opcode, e.g. '{}.{}'",
2614 opcode,
2615 constraints.ctrl_typeset().unwrap().example()
2616 );
2617 } else {
2618 INVALID
2620 }
2621 }
2622 };
2623
2624 if let Some(typeset) = constraints.ctrl_typeset() {
2628 if !typeset.contains(ctrl_type) {
2630 return err!(
2631 self.loc,
2632 "{} is not a valid typevar for {}",
2633 ctrl_type,
2634 opcode
2635 );
2636 }
2637 } else if ctrl_type != INVALID {
2639 return err!(self.loc, "{} does not take a typevar", opcode);
2640 }
2641
2642 Ok(ctrl_type)
2643 }
2644
2645 fn parse_value_list(&mut self) -> ParseResult<VariableArgs> {
2650 let mut args = VariableArgs::new();
2651
2652 if let Some(Token::Value(v)) = self.token() {
2653 args.push(v);
2654 self.consume();
2655 } else {
2656 return Ok(args);
2657 }
2658
2659 while self.optional(Token::Comma) {
2660 args.push(self.match_value("expected value in argument list")?);
2661 }
2662
2663 Ok(args)
2664 }
2665
2666 fn parse_opt_value_list(&mut self) -> ParseResult<VariableArgs> {
2668 if !self.optional(Token::LPar) {
2669 return Ok(VariableArgs::new());
2670 }
2671
2672 let args = self.parse_value_list()?;
2673
2674 self.match_token(Token::RPar, "expected ')' after arguments")?;
2675
2676 Ok(args)
2677 }
2678
2679 fn parse_run_command(&mut self, sig: &Signature) -> ParseResult<RunCommand> {
2684 match self.token() {
2686 Some(Token::Identifier("run")) => {
2687 self.consume();
2688 if self.optional(Token::Colon) {
2689 let invocation = self.parse_run_invocation(sig)?;
2690 let comparison = self.parse_run_comparison()?;
2691 let expected = self.parse_run_returns(sig)?;
2692 Ok(RunCommand::Run(invocation, comparison, expected))
2693 } else if sig.params.is_empty()
2694 && sig.returns.len() == 1
2695 && sig.returns[0].value_type.is_int()
2696 {
2697 let invocation = Invocation::new("default", vec![]);
2701 let expected = vec![DataValue::I8(0)];
2702 let comparison = Comparison::NotEquals;
2703 Ok(RunCommand::Run(invocation, comparison, expected))
2704 } else {
2705 Err(self.error("unable to parse the run command"))
2706 }
2707 }
2708 Some(Token::Identifier("print")) => {
2709 self.consume();
2710 if self.optional(Token::Colon) {
2711 Ok(RunCommand::Print(self.parse_run_invocation(sig)?))
2712 } else if sig.params.is_empty() {
2713 let invocation = Invocation::new("default", vec![]);
2715 Ok(RunCommand::Print(invocation))
2716 } else {
2717 Err(self.error("unable to parse the print command"))
2718 }
2719 }
2720 _ => Err(self.error("expected a 'run:' or 'print:' command")),
2721 }
2722 }
2723
2724 fn parse_run_invocation(&mut self, sig: &Signature) -> ParseResult<Invocation> {
2731 if let Some(Token::Name(name)) = self.token() {
2732 self.consume();
2733 self.match_token(
2734 Token::LPar,
2735 "expected invocation parentheses, e.g. %fn(...)",
2736 )?;
2737
2738 let arg_types = sig
2739 .params
2740 .iter()
2741 .map(|abi| abi.value_type)
2742 .collect::<Vec<_>>();
2743 let args = self.parse_data_value_list(&arg_types)?;
2744
2745 self.match_token(
2746 Token::RPar,
2747 "expected invocation parentheses, e.g. %fn(...)",
2748 )?;
2749 Ok(Invocation::new(name, args))
2750 } else {
2751 Err(self.error("expected a function name, e.g. %my_fn"))
2752 }
2753 }
2754
2755 fn parse_run_comparison(&mut self) -> ParseResult<Comparison> {
2759 if self.optional(Token::Equal) {
2760 self.match_token(Token::Equal, "expected another =")?;
2761 Ok(Comparison::Equals)
2762 } else if self.optional(Token::Bang) {
2763 self.match_token(Token::Equal, "expected a =")?;
2764 Ok(Comparison::NotEquals)
2765 } else {
2766 Err(self.error("unable to parse a valid comparison operator"))
2767 }
2768 }
2769
2770 fn parse_run_returns(&mut self, sig: &Signature) -> ParseResult<Vec<DataValue>> {
2776 if sig.returns.len() != 1 {
2777 self.match_token(Token::LBracket, "expected a left bracket [")?;
2778 }
2779
2780 let returns = self
2781 .parse_data_value_list(&sig.returns.iter().map(|a| a.value_type).collect::<Vec<_>>())?;
2782
2783 if sig.returns.len() != 1 {
2784 self.match_token(Token::RBracket, "expected a right bracket ]")?;
2785 }
2786 Ok(returns)
2787 }
2788
2789 fn parse_data_value_list(&mut self, types: &[Type]) -> ParseResult<Vec<DataValue>> {
2793 let mut values = vec![];
2794 for ty in types.iter().take(1) {
2795 values.push(self.parse_data_value(*ty)?);
2796 }
2797 for ty in types.iter().skip(1) {
2798 self.match_token(
2799 Token::Comma,
2800 "expected a comma between invocation arguments",
2801 )?;
2802 values.push(self.parse_data_value(*ty)?);
2803 }
2804 Ok(values)
2805 }
2806
2807 fn parse_data_value(&mut self, ty: Type) -> ParseResult<DataValue> {
2811 let dv = match ty {
2812 I8 => DataValue::from(self.match_imm8("expected a i8")?),
2813 I16 => DataValue::from(self.match_imm16("expected an i16")?),
2814 I32 => DataValue::from(self.match_imm32("expected an i32")?),
2815 I64 => DataValue::from(Into::<i64>::into(self.match_imm64("expected an i64")?)),
2816 I128 => DataValue::from(self.match_imm128("expected an i128")?),
2817 F16 => DataValue::from(self.match_ieee16("expected an f16")?),
2818 F32 => DataValue::from(self.match_ieee32("expected an f32")?),
2819 F64 => DataValue::from(self.match_ieee64("expected an f64")?),
2820 F128 => DataValue::from(self.match_ieee128("expected an f128")?),
2821 _ if (ty.is_vector() || ty.is_dynamic_vector()) => {
2822 let as_vec = self.match_uimm128(ty)?.into_vec();
2823 if as_vec.len() == 16 {
2824 let mut as_array = [0; 16];
2825 as_array.copy_from_slice(&as_vec[..]);
2826 DataValue::from(as_array)
2827 } else if as_vec.len() == 8 {
2828 let mut as_array = [0; 8];
2829 as_array.copy_from_slice(&as_vec[..]);
2830 DataValue::from(as_array)
2831 } else {
2832 return Err(self.error("only 128-bit vectors are currently supported"));
2833 }
2834 }
2835 _ => return Err(self.error(&format!("don't know how to parse data values of: {ty}"))),
2836 };
2837 Ok(dv)
2838 }
2839
2840 fn parse_inst_operands(
2843 &mut self,
2844 ctx: &mut Context,
2845 opcode: Opcode,
2846 explicit_control_type: Option<Type>,
2847 ) -> ParseResult<InstructionData> {
2848 let idata = match opcode.format() {
2849 InstructionFormat::Unary => InstructionData::Unary {
2850 opcode,
2851 arg: self.match_value("expected SSA value operand")?,
2852 },
2853 InstructionFormat::UnaryImm => {
2854 let msg = |bits| format!("expected immediate {bits}-bit integer operand");
2855 let unsigned = match explicit_control_type {
2856 Some(types::I8) => self.match_imm8(&msg(8))? as u8 as i64,
2857 Some(types::I16) => self.match_imm16(&msg(16))? as u16 as i64,
2858 Some(types::I32) => self.match_imm32(&msg(32))? as u32 as i64,
2859 Some(types::I64) => self.match_imm64(&msg(64))?.bits(),
2860 _ => {
2861 return err!(
2862 self.loc,
2863 "expected one of the following type: i8, i16, i32 or i64"
2864 )
2865 }
2866 };
2867 InstructionData::UnaryImm {
2868 opcode,
2869 imm: Imm64::new(unsigned),
2870 }
2871 }
2872 InstructionFormat::UnaryIeee16 => InstructionData::UnaryIeee16 {
2873 opcode,
2874 imm: self.match_ieee16("expected immediate 16-bit float operand")?,
2875 },
2876 InstructionFormat::UnaryIeee32 => InstructionData::UnaryIeee32 {
2877 opcode,
2878 imm: self.match_ieee32("expected immediate 32-bit float operand")?,
2879 },
2880 InstructionFormat::UnaryIeee64 => InstructionData::UnaryIeee64 {
2881 opcode,
2882 imm: self.match_ieee64("expected immediate 64-bit float operand")?,
2883 },
2884 InstructionFormat::UnaryConst => {
2885 let constant_handle = if let Some(Token::Constant(_)) = self.token() {
2886 let c = self.match_constant()?;
2888 ctx.check_constant(c, self.loc)?;
2889 c
2890 } else if opcode == Opcode::F128const {
2891 let ieee128 = self.match_ieee128("expected immediate 128-bit float operand")?;
2892 ctx.function.dfg.constants.insert(ieee128.into())
2893 } else if let Some(controlling_type) = explicit_control_type {
2894 let uimm128 = self.match_uimm128(controlling_type)?;
2897 ctx.function.dfg.constants.insert(uimm128)
2898 } else {
2899 return err!(
2900 self.loc,
2901 "Expected either a const entity or a typed value, e.g. inst.i32x4 [...]"
2902 );
2903 };
2904 InstructionData::UnaryConst {
2905 opcode,
2906 constant_handle,
2907 }
2908 }
2909 InstructionFormat::UnaryGlobalValue => {
2910 let gv = self.match_gv("expected global value")?;
2911 ctx.check_gv(gv, self.loc)?;
2912 InstructionData::UnaryGlobalValue {
2913 opcode,
2914 global_value: gv,
2915 }
2916 }
2917 InstructionFormat::Binary => {
2918 let lhs = self.match_value("expected SSA value first operand")?;
2919 self.match_token(Token::Comma, "expected ',' between operands")?;
2920 let rhs = self.match_value("expected SSA value second operand")?;
2921 InstructionData::Binary {
2922 opcode,
2923 args: [lhs, rhs],
2924 }
2925 }
2926 InstructionFormat::BinaryImm8 => {
2927 let arg = self.match_value("expected SSA value first operand")?;
2928 self.match_token(Token::Comma, "expected ',' between operands")?;
2929 let imm = self.match_uimm8("expected unsigned 8-bit immediate")?;
2930 InstructionData::BinaryImm8 { opcode, arg, imm }
2931 }
2932 InstructionFormat::BinaryImm64 => {
2933 let lhs = self.match_value("expected SSA value first operand")?;
2934 self.match_token(Token::Comma, "expected ',' between operands")?;
2935 let rhs = self.match_imm64("expected immediate integer second operand")?;
2936 InstructionData::BinaryImm64 {
2937 opcode,
2938 arg: lhs,
2939 imm: rhs,
2940 }
2941 }
2942 InstructionFormat::Ternary => {
2943 let ctrl_arg = self.match_value("expected SSA value control operand")?;
2946 self.match_token(Token::Comma, "expected ',' between operands")?;
2947 let true_arg = self.match_value("expected SSA value true operand")?;
2948 self.match_token(Token::Comma, "expected ',' between operands")?;
2949 let false_arg = self.match_value("expected SSA value false operand")?;
2950 InstructionData::Ternary {
2951 opcode,
2952 args: [ctrl_arg, true_arg, false_arg],
2953 }
2954 }
2955 InstructionFormat::MultiAry => {
2956 let args = self.parse_value_list()?;
2957 InstructionData::MultiAry {
2958 opcode,
2959 args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists),
2960 }
2961 }
2962 InstructionFormat::NullAry => InstructionData::NullAry { opcode },
2963 InstructionFormat::Jump => {
2964 let block_num = self.match_block("expected jump destination block")?;
2966 let args = self.parse_opt_value_list()?;
2967 let destination = ctx.function.dfg.block_call(block_num, &args);
2968 InstructionData::Jump {
2969 opcode,
2970 destination,
2971 }
2972 }
2973 InstructionFormat::Brif => {
2974 let arg = self.match_value("expected SSA value control operand")?;
2975 self.match_token(Token::Comma, "expected ',' between operands")?;
2976 let block_then = {
2977 let block_num = self.match_block("expected branch then block")?;
2978 let args = self.parse_opt_value_list()?;
2979 ctx.function.dfg.block_call(block_num, &args)
2980 };
2981 self.match_token(Token::Comma, "expected ',' between operands")?;
2982 let block_else = {
2983 let block_num = self.match_block("expected branch else block")?;
2984 let args = self.parse_opt_value_list()?;
2985 ctx.function.dfg.block_call(block_num, &args)
2986 };
2987 InstructionData::Brif {
2988 opcode,
2989 arg,
2990 blocks: [block_then, block_else],
2991 }
2992 }
2993 InstructionFormat::BranchTable => {
2994 let arg = self.match_value("expected SSA value operand")?;
2995 self.match_token(Token::Comma, "expected ',' between operands")?;
2996 let block_num = self.match_block("expected branch destination block")?;
2997 let args = self.parse_opt_value_list()?;
2998 let destination = ctx.function.dfg.block_call(block_num, &args);
2999 self.match_token(Token::Comma, "expected ',' between operands")?;
3000 let table = self.parse_jump_table(ctx, destination)?;
3001 InstructionData::BranchTable { opcode, arg, table }
3002 }
3003 InstructionFormat::TernaryImm8 => {
3004 let lhs = self.match_value("expected SSA value first operand")?;
3005 self.match_token(Token::Comma, "expected ',' between operands")?;
3006 let rhs = self.match_value("expected SSA value last operand")?;
3007 self.match_token(Token::Comma, "expected ',' between operands")?;
3008 let imm = self.match_uimm8("expected 8-bit immediate")?;
3009 InstructionData::TernaryImm8 {
3010 opcode,
3011 imm,
3012 args: [lhs, rhs],
3013 }
3014 }
3015 InstructionFormat::Shuffle => {
3016 let a = self.match_value("expected SSA value first operand")?;
3017 self.match_token(Token::Comma, "expected ',' between operands")?;
3018 let b = self.match_value("expected SSA value second operand")?;
3019 self.match_token(Token::Comma, "expected ',' between operands")?;
3020 let uimm128 = self.match_uimm128(I8X16)?;
3021 let imm = ctx.function.dfg.immediates.push(uimm128);
3022 InstructionData::Shuffle {
3023 opcode,
3024 imm,
3025 args: [a, b],
3026 }
3027 }
3028 InstructionFormat::IntCompare => {
3029 let cond = self.match_enum("expected intcc condition code")?;
3030 let lhs = self.match_value("expected SSA value first operand")?;
3031 self.match_token(Token::Comma, "expected ',' between operands")?;
3032 let rhs = self.match_value("expected SSA value second operand")?;
3033 InstructionData::IntCompare {
3034 opcode,
3035 cond,
3036 args: [lhs, rhs],
3037 }
3038 }
3039 InstructionFormat::IntCompareImm => {
3040 let cond = self.match_enum("expected intcc condition code")?;
3041 let lhs = self.match_value("expected SSA value first operand")?;
3042 self.match_token(Token::Comma, "expected ',' between operands")?;
3043 let rhs = self.match_imm64("expected immediate second operand")?;
3044 InstructionData::IntCompareImm {
3045 opcode,
3046 cond,
3047 arg: lhs,
3048 imm: rhs,
3049 }
3050 }
3051 InstructionFormat::FloatCompare => {
3052 let cond = self.match_enum("expected floatcc condition code")?;
3053 let lhs = self.match_value("expected SSA value first operand")?;
3054 self.match_token(Token::Comma, "expected ',' between operands")?;
3055 let rhs = self.match_value("expected SSA value second operand")?;
3056 InstructionData::FloatCompare {
3057 opcode,
3058 cond,
3059 args: [lhs, rhs],
3060 }
3061 }
3062 InstructionFormat::Call => {
3063 let func_ref = self.match_fn("expected function reference")?;
3064 ctx.check_fn(func_ref, self.loc)?;
3065 self.match_token(Token::LPar, "expected '(' before arguments")?;
3066 let args = self.parse_value_list()?;
3067 self.match_token(Token::RPar, "expected ')' after arguments")?;
3068 InstructionData::Call {
3069 opcode,
3070 func_ref,
3071 args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists),
3072 }
3073 }
3074 InstructionFormat::CallIndirect => {
3075 let sig_ref = self.match_sig("expected signature reference")?;
3076 ctx.check_sig(sig_ref, self.loc)?;
3077 self.match_token(Token::Comma, "expected ',' between operands")?;
3078 let callee = self.match_value("expected SSA value callee operand")?;
3079 self.match_token(Token::LPar, "expected '(' before arguments")?;
3080 let args = self.parse_value_list()?;
3081 self.match_token(Token::RPar, "expected ')' after arguments")?;
3082 InstructionData::CallIndirect {
3083 opcode,
3084 sig_ref,
3085 args: args.into_value_list(&[callee], &mut ctx.function.dfg.value_lists),
3086 }
3087 }
3088 InstructionFormat::FuncAddr => {
3089 let func_ref = self.match_fn("expected function reference")?;
3090 ctx.check_fn(func_ref, self.loc)?;
3091 InstructionData::FuncAddr { opcode, func_ref }
3092 }
3093 InstructionFormat::StackLoad => {
3094 let ss = self.match_ss("expected stack slot number: ss«n»")?;
3095 ctx.check_ss(ss, self.loc)?;
3096 let offset = self.optional_offset32()?;
3097 InstructionData::StackLoad {
3098 opcode,
3099 stack_slot: ss,
3100 offset,
3101 }
3102 }
3103 InstructionFormat::StackStore => {
3104 let arg = self.match_value("expected SSA value operand")?;
3105 self.match_token(Token::Comma, "expected ',' between operands")?;
3106 let ss = self.match_ss("expected stack slot number: ss«n»")?;
3107 ctx.check_ss(ss, self.loc)?;
3108 let offset = self.optional_offset32()?;
3109 InstructionData::StackStore {
3110 opcode,
3111 arg,
3112 stack_slot: ss,
3113 offset,
3114 }
3115 }
3116 InstructionFormat::DynamicStackLoad => {
3117 let dss = self.match_dss("expected dynamic stack slot number: dss«n»")?;
3118 ctx.check_dss(dss, self.loc)?;
3119 InstructionData::DynamicStackLoad {
3120 opcode,
3121 dynamic_stack_slot: dss,
3122 }
3123 }
3124 InstructionFormat::DynamicStackStore => {
3125 let arg = self.match_value("expected SSA value operand")?;
3126 self.match_token(Token::Comma, "expected ',' between operands")?;
3127 let dss = self.match_dss("expected dynamic stack slot number: dss«n»")?;
3128 ctx.check_dss(dss, self.loc)?;
3129 InstructionData::DynamicStackStore {
3130 opcode,
3131 arg,
3132 dynamic_stack_slot: dss,
3133 }
3134 }
3135 InstructionFormat::Load => {
3136 let flags = self.optional_memflags()?;
3137 let addr = self.match_value("expected SSA value address")?;
3138 let offset = self.optional_offset32()?;
3139 InstructionData::Load {
3140 opcode,
3141 flags,
3142 arg: addr,
3143 offset,
3144 }
3145 }
3146 InstructionFormat::Store => {
3147 let flags = self.optional_memflags()?;
3148 let arg = self.match_value("expected SSA value operand")?;
3149 self.match_token(Token::Comma, "expected ',' between operands")?;
3150 let addr = self.match_value("expected SSA value address")?;
3151 let offset = self.optional_offset32()?;
3152 InstructionData::Store {
3153 opcode,
3154 flags,
3155 args: [arg, addr],
3156 offset,
3157 }
3158 }
3159 InstructionFormat::Trap => {
3160 let code = self.match_enum("expected trap code")?;
3161 InstructionData::Trap { opcode, code }
3162 }
3163 InstructionFormat::CondTrap => {
3164 let arg = self.match_value("expected SSA value operand")?;
3165 self.match_token(Token::Comma, "expected ',' between operands")?;
3166 let code = self.match_enum("expected trap code")?;
3167 InstructionData::CondTrap { opcode, arg, code }
3168 }
3169 InstructionFormat::AtomicCas => {
3170 let flags = self.optional_memflags()?;
3171 let addr = self.match_value("expected SSA value address")?;
3172 self.match_token(Token::Comma, "expected ',' between operands")?;
3173 let expected = self.match_value("expected SSA value address")?;
3174 self.match_token(Token::Comma, "expected ',' between operands")?;
3175 let replacement = self.match_value("expected SSA value address")?;
3176 InstructionData::AtomicCas {
3177 opcode,
3178 flags,
3179 args: [addr, expected, replacement],
3180 }
3181 }
3182 InstructionFormat::AtomicRmw => {
3183 let flags = self.optional_memflags()?;
3184 let op = self.match_enum("expected AtomicRmwOp")?;
3185 let addr = self.match_value("expected SSA value address")?;
3186 self.match_token(Token::Comma, "expected ',' between operands")?;
3187 let arg2 = self.match_value("expected SSA value address")?;
3188 InstructionData::AtomicRmw {
3189 opcode,
3190 flags,
3191 op,
3192 args: [addr, arg2],
3193 }
3194 }
3195 InstructionFormat::LoadNoOffset => {
3196 let flags = self.optional_memflags()?;
3197 let addr = self.match_value("expected SSA value address")?;
3198 InstructionData::LoadNoOffset {
3199 opcode,
3200 flags,
3201 arg: addr,
3202 }
3203 }
3204 InstructionFormat::StoreNoOffset => {
3205 let flags = self.optional_memflags()?;
3206 let arg = self.match_value("expected SSA value operand")?;
3207 self.match_token(Token::Comma, "expected ',' between operands")?;
3208 let addr = self.match_value("expected SSA value address")?;
3209 InstructionData::StoreNoOffset {
3210 opcode,
3211 flags,
3212 args: [arg, addr],
3213 }
3214 }
3215 InstructionFormat::IntAddTrap => {
3216 let a = self.match_value("expected SSA value operand")?;
3217 self.match_token(Token::Comma, "expected ',' between operands")?;
3218 let b = self.match_value("expected SSA value operand")?;
3219 self.match_token(Token::Comma, "expected ',' between operands")?;
3220 let code = self.match_enum("expected trap code")?;
3221 InstructionData::IntAddTrap {
3222 opcode,
3223 args: [a, b],
3224 code,
3225 }
3226 }
3227 };
3228 Ok(idata)
3229 }
3230}
3231
3232#[cfg(test)]
3233mod tests {
3234 use super::*;
3235 use crate::isaspec::IsaSpec;
3236
3237 #[test]
3238 fn argument_type() {
3239 let mut p = Parser::new("i32 sext");
3240 let arg = p.parse_abi_param().unwrap();
3241 assert_eq!(arg.value_type, types::I32);
3242 assert_eq!(arg.extension, ArgumentExtension::Sext);
3243 assert_eq!(arg.purpose, ArgumentPurpose::Normal);
3244 let ParseError {
3245 location,
3246 message,
3247 is_warning,
3248 } = p.parse_abi_param().unwrap_err();
3249 assert_eq!(location.line_number, 1);
3250 assert_eq!(message, "expected parameter type");
3251 assert!(!is_warning);
3252 }
3253
3254 #[test]
3255 fn aliases() {
3256 let (func, details) = Parser::new(
3257 "function %qux() system_v {
3258 block0:
3259 v4 = iconst.i8 6
3260 v3 -> v4
3261 v1 = iadd_imm v3, 17
3262 }",
3263 )
3264 .parse_function()
3265 .unwrap();
3266 assert_eq!(func.name.to_string(), "%qux");
3267 let v4 = details.map.lookup_str("v4").unwrap();
3268 assert_eq!(v4.to_string(), "v4");
3269 let v3 = details.map.lookup_str("v3").unwrap();
3270 assert_eq!(v3.to_string(), "v3");
3271 match v3 {
3272 AnyEntity::Value(v3) => {
3273 let aliased_to = func.dfg.resolve_aliases(v3);
3274 assert_eq!(aliased_to.to_string(), "v4");
3275 }
3276 _ => panic!("expected value: {v3}"),
3277 }
3278 }
3279
3280 #[test]
3281 fn signature() {
3282 let sig = Parser::new("()system_v").parse_signature().unwrap();
3283 assert_eq!(sig.params.len(), 0);
3284 assert_eq!(sig.returns.len(), 0);
3285 assert_eq!(sig.call_conv, CallConv::SystemV);
3286
3287 let sig2 =
3288 Parser::new("(i8 uext, f16, f32, f64, f128, i32 sret) -> i32 sext, f64 system_v")
3289 .parse_signature()
3290 .unwrap();
3291 assert_eq!(
3292 sig2.to_string(),
3293 "(i8 uext, f16, f32, f64, f128, i32 sret) -> i32 sext, f64 system_v"
3294 );
3295 assert_eq!(sig2.call_conv, CallConv::SystemV);
3296
3297 assert_eq!(
3299 Parser::new("()").parse_signature().unwrap().to_string(),
3300 "() fast"
3301 );
3302 assert_eq!(
3303 Parser::new("() notacc")
3304 .parse_signature()
3305 .unwrap_err()
3306 .to_string(),
3307 "1: unknown calling convention: notacc"
3308 );
3309
3310 assert_eq!(
3312 Parser::new("() -> void")
3313 .parse_signature()
3314 .unwrap_err()
3315 .to_string(),
3316 "1: expected parameter type"
3317 );
3318 assert_eq!(
3319 Parser::new("i8 -> i8")
3320 .parse_signature()
3321 .unwrap_err()
3322 .to_string(),
3323 "1: expected function signature: ( args... )"
3324 );
3325 assert_eq!(
3326 Parser::new("(i8 -> i8")
3327 .parse_signature()
3328 .unwrap_err()
3329 .to_string(),
3330 "1: expected ')' after function arguments"
3331 );
3332 }
3333
3334 #[test]
3335 fn stack_slot_decl() {
3336 let (func, _) = Parser::new(
3337 "function %foo() system_v {
3338 ss3 = explicit_slot 13
3339 ss1 = explicit_slot 1
3340 }",
3341 )
3342 .parse_function()
3343 .unwrap();
3344 assert_eq!(func.name.to_string(), "%foo");
3345 let mut iter = func.sized_stack_slots.keys();
3346 let _ss0 = iter.next().unwrap();
3347 let ss1 = iter.next().unwrap();
3348 assert_eq!(ss1.to_string(), "ss1");
3349 assert_eq!(
3350 func.sized_stack_slots[ss1].kind,
3351 StackSlotKind::ExplicitSlot
3352 );
3353 assert_eq!(func.sized_stack_slots[ss1].size, 1);
3354 let _ss2 = iter.next().unwrap();
3355 let ss3 = iter.next().unwrap();
3356 assert_eq!(ss3.to_string(), "ss3");
3357 assert_eq!(
3358 func.sized_stack_slots[ss3].kind,
3359 StackSlotKind::ExplicitSlot
3360 );
3361 assert_eq!(func.sized_stack_slots[ss3].size, 13);
3362 assert_eq!(iter.next(), None);
3363
3364 assert_eq!(
3366 Parser::new(
3367 "function %bar() system_v {
3368 ss1 = explicit_slot 13
3369 ss1 = explicit_slot 1
3370 }",
3371 )
3372 .parse_function()
3373 .unwrap_err()
3374 .to_string(),
3375 "3: duplicate entity: ss1"
3376 );
3377 }
3378
3379 #[test]
3380 fn block_header() {
3381 let (func, _) = Parser::new(
3382 "function %blocks() system_v {
3383 block0:
3384 block4(v3: i32):
3385 }",
3386 )
3387 .parse_function()
3388 .unwrap();
3389 assert_eq!(func.name.to_string(), "%blocks");
3390
3391 let mut blocks = func.layout.blocks();
3392
3393 let block0 = blocks.next().unwrap();
3394 assert_eq!(func.dfg.block_params(block0), &[]);
3395
3396 let block4 = blocks.next().unwrap();
3397 let block4_args = func.dfg.block_params(block4);
3398 assert_eq!(block4_args.len(), 1);
3399 assert_eq!(func.dfg.value_type(block4_args[0]), types::I32);
3400 }
3401
3402 #[test]
3403 fn duplicate_block() {
3404 let ParseError {
3405 location,
3406 message,
3407 is_warning,
3408 } = Parser::new(
3409 "function %blocks() system_v {
3410 block0:
3411 block0:
3412 return 2",
3413 )
3414 .parse_function()
3415 .unwrap_err();
3416
3417 assert_eq!(location.line_number, 3);
3418 assert_eq!(message, "duplicate entity: block0");
3419 assert!(!is_warning);
3420 }
3421
3422 #[test]
3423 fn number_of_blocks() {
3424 let ParseError {
3425 location,
3426 message,
3427 is_warning,
3428 } = Parser::new(
3429 "function %a() {
3430 block100000:",
3431 )
3432 .parse_function()
3433 .unwrap_err();
3434
3435 assert_eq!(location.line_number, 2);
3436 assert_eq!(message, "too many blocks");
3437 assert!(!is_warning);
3438 }
3439
3440 #[test]
3441 fn duplicate_ss() {
3442 let ParseError {
3443 location,
3444 message,
3445 is_warning,
3446 } = Parser::new(
3447 "function %blocks() system_v {
3448 ss0 = explicit_slot 8
3449 ss0 = explicit_slot 8",
3450 )
3451 .parse_function()
3452 .unwrap_err();
3453
3454 assert_eq!(location.line_number, 3);
3455 assert_eq!(message, "duplicate entity: ss0");
3456 assert!(!is_warning);
3457 }
3458
3459 #[test]
3460 fn duplicate_gv() {
3461 let ParseError {
3462 location,
3463 message,
3464 is_warning,
3465 } = Parser::new(
3466 "function %blocks() system_v {
3467 gv0 = vmctx
3468 gv0 = vmctx",
3469 )
3470 .parse_function()
3471 .unwrap_err();
3472
3473 assert_eq!(location.line_number, 3);
3474 assert_eq!(message, "duplicate entity: gv0");
3475 assert!(!is_warning);
3476 }
3477
3478 #[test]
3479 fn duplicate_sig() {
3480 let ParseError {
3481 location,
3482 message,
3483 is_warning,
3484 } = Parser::new(
3485 "function %blocks() system_v {
3486 sig0 = ()
3487 sig0 = ()",
3488 )
3489 .parse_function()
3490 .unwrap_err();
3491
3492 assert_eq!(location.line_number, 3);
3493 assert_eq!(message, "duplicate entity: sig0");
3494 assert!(!is_warning);
3495 }
3496
3497 #[test]
3498 fn duplicate_fn() {
3499 let ParseError {
3500 location,
3501 message,
3502 is_warning,
3503 } = Parser::new(
3504 "function %blocks() system_v {
3505 sig0 = ()
3506 fn0 = %foo sig0
3507 fn0 = %foo sig0",
3508 )
3509 .parse_function()
3510 .unwrap_err();
3511
3512 assert_eq!(location.line_number, 4);
3513 assert_eq!(message, "duplicate entity: fn0");
3514 assert!(!is_warning);
3515 }
3516
3517 #[test]
3518 fn comments() {
3519 let (func, Details { comments, .. }) = Parser::new(
3520 "; before
3521 function %comment() system_v { ; decl
3522 ss10 = explicit_slot 13 ; stackslot.
3523 ; Still stackslot.
3524 block0: ; Basic block
3525 trap user42; Instruction
3526 } ; Trailing.
3527 ; More trailing.",
3528 )
3529 .parse_function()
3530 .unwrap();
3531 assert_eq!(func.name.to_string(), "%comment");
3532 assert_eq!(comments.len(), 7); assert_eq!(
3534 comments[0],
3535 Comment {
3536 entity: AnyEntity::Function,
3537 text: "; decl",
3538 }
3539 );
3540 assert_eq!(comments[1].entity.to_string(), "ss10");
3541 assert_eq!(comments[2].entity.to_string(), "ss10");
3542 assert_eq!(comments[2].text, "; Still stackslot.");
3543 assert_eq!(comments[3].entity.to_string(), "block0");
3544 assert_eq!(comments[3].text, "; Basic block");
3545
3546 assert_eq!(comments[4].entity.to_string(), "inst0");
3547 assert_eq!(comments[4].text, "; Instruction");
3548
3549 assert_eq!(comments[5].entity, AnyEntity::Function);
3550 assert_eq!(comments[6].entity, AnyEntity::Function);
3551 }
3552
3553 #[test]
3554 fn test_file() {
3555 let tf = parse_test(
3556 r#"; before
3557 test cfg option=5
3558 test verify
3559 set enable_float=false
3560 feature "foo"
3561 feature !"bar"
3562 ; still preamble
3563 function %comment() system_v {}"#,
3564 ParseOptions::default(),
3565 )
3566 .unwrap();
3567 assert_eq!(tf.commands.len(), 2);
3568 assert_eq!(tf.commands[0].command, "cfg");
3569 assert_eq!(tf.commands[1].command, "verify");
3570 match tf.isa_spec {
3571 IsaSpec::None(s) => {
3572 assert!(s.enable_verifier());
3573 assert!(!s.enable_float());
3574 }
3575 _ => panic!("unexpected ISAs"),
3576 }
3577 assert_eq!(tf.features[0], Feature::With(&"foo"));
3578 assert_eq!(tf.features[1], Feature::Without(&"bar"));
3579 assert_eq!(tf.preamble_comments.len(), 2);
3580 assert_eq!(tf.preamble_comments[0].text, "; before");
3581 assert_eq!(tf.preamble_comments[1].text, "; still preamble");
3582 assert_eq!(tf.functions.len(), 1);
3583 assert_eq!(tf.functions[0].0.name.to_string(), "%comment");
3584 }
3585
3586 #[test]
3587 fn isa_spec() {
3588 assert!(parse_test(
3589 "target
3590 function %foo() system_v {}",
3591 ParseOptions::default()
3592 )
3593 .is_err());
3594
3595 assert!(parse_test(
3596 "target x86_64
3597 set enable_float=false
3598 function %foo() system_v {}",
3599 ParseOptions::default()
3600 )
3601 .is_err());
3602
3603 match parse_test(
3604 "set enable_float=false
3605 target x86_64
3606 function %foo() system_v {}",
3607 ParseOptions::default(),
3608 )
3609 .unwrap()
3610 .isa_spec
3611 {
3612 IsaSpec::None(_) => panic!("Expected some ISA"),
3613 IsaSpec::Some(v) => {
3614 assert_eq!(v.len(), 1);
3615 assert!(v[0].name() == "x64" || v[0].name() == "x86");
3616 }
3617 }
3618 }
3619
3620 #[test]
3621 fn user_function_name() {
3622 let func = Parser::new(
3624 "function u1:2() system_v {
3625 block0:
3626 trap int_divz
3627 }",
3628 )
3629 .parse_function()
3630 .unwrap()
3631 .0;
3632 assert_eq!(func.name.to_string(), "u1:2");
3633
3634 let mut parser = Parser::new(
3636 "function u123:abc() system_v {
3637 block0:
3638 trap stk_ovf
3639 }",
3640 );
3641 assert!(parser.parse_function().is_err());
3642
3643 let mut parser = Parser::new(
3645 "function u() system_v {
3646 block0:
3647 trap int_ovf
3648 }",
3649 );
3650 assert!(parser.parse_function().is_err());
3651
3652 let mut parser = Parser::new(
3653 "function u0() system_v {
3654 block0:
3655 trap int_ovf
3656 }",
3657 );
3658 assert!(parser.parse_function().is_err());
3659
3660 let mut parser = Parser::new(
3661 "function u0:() system_v {
3662 block0:
3663 trap int_ovf
3664 }",
3665 );
3666 assert!(parser.parse_function().is_err());
3667 }
3668
3669 #[test]
3670 fn change_default_calling_convention() {
3671 let code = "function %test() {
3672 block0:
3673 return
3674 }";
3675
3676 let mut parser = Parser::new(code);
3678 assert_eq!(
3679 parser.parse_function().unwrap().0.signature.call_conv,
3680 CallConv::Fast
3681 );
3682
3683 let mut parser = Parser::new(code).with_default_calling_convention(CallConv::Cold);
3685 assert_eq!(
3686 parser.parse_function().unwrap().0.signature.call_conv,
3687 CallConv::Cold
3688 );
3689 }
3690
3691 #[test]
3692 fn u8_as_hex() {
3693 fn parse_as_uimm8(text: &str) -> ParseResult<u8> {
3694 Parser::new(text).match_uimm8("unable to parse u8")
3695 }
3696
3697 assert_eq!(parse_as_uimm8("0").unwrap(), 0);
3698 assert_eq!(parse_as_uimm8("0xff").unwrap(), 255);
3699 assert!(parse_as_uimm8("-1").is_err());
3700 assert!(parse_as_uimm8("0xffa").is_err());
3701 }
3702
3703 #[test]
3704 fn i16_as_hex() {
3705 fn parse_as_imm16(text: &str) -> ParseResult<i16> {
3706 Parser::new(text).match_imm16("unable to parse i16")
3707 }
3708
3709 assert_eq!(parse_as_imm16("0x8000").unwrap(), -32768);
3710 assert_eq!(parse_as_imm16("0xffff").unwrap(), -1);
3711 assert_eq!(parse_as_imm16("0").unwrap(), 0);
3712 assert_eq!(parse_as_imm16("0x7fff").unwrap(), 32767);
3713 assert_eq!(
3714 parse_as_imm16("-0x0001").unwrap(),
3715 parse_as_imm16("0xffff").unwrap()
3716 );
3717 assert_eq!(
3718 parse_as_imm16("-0x7fff").unwrap(),
3719 parse_as_imm16("0x8001").unwrap()
3720 );
3721 assert!(parse_as_imm16("0xffffa").is_err());
3722 }
3723
3724 #[test]
3725 fn i32_as_hex() {
3726 fn parse_as_imm32(text: &str) -> ParseResult<i32> {
3727 Parser::new(text).match_imm32("unable to parse i32")
3728 }
3729
3730 assert_eq!(parse_as_imm32("0x80000000").unwrap(), -2147483648);
3731 assert_eq!(parse_as_imm32("0xffffffff").unwrap(), -1);
3732 assert_eq!(parse_as_imm32("0").unwrap(), 0);
3733 assert_eq!(parse_as_imm32("0x7fffffff").unwrap(), 2147483647);
3734 assert_eq!(
3735 parse_as_imm32("-0x00000001").unwrap(),
3736 parse_as_imm32("0xffffffff").unwrap()
3737 );
3738 assert_eq!(
3739 parse_as_imm32("-0x7fffffff").unwrap(),
3740 parse_as_imm32("0x80000001").unwrap()
3741 );
3742 assert!(parse_as_imm32("0xffffffffa").is_err());
3743 }
3744
3745 #[test]
3746 fn i64_as_hex() {
3747 fn parse_as_imm64(text: &str) -> ParseResult<Imm64> {
3748 Parser::new(text).match_imm64("unable to parse Imm64")
3749 }
3750
3751 assert_eq!(
3752 parse_as_imm64("0x8000000000000000").unwrap(),
3753 Imm64::new(-9223372036854775808)
3754 );
3755 assert_eq!(
3756 parse_as_imm64("0xffffffffffffffff").unwrap(),
3757 Imm64::new(-1)
3758 );
3759 assert_eq!(parse_as_imm64("0").unwrap(), Imm64::new(0));
3760 assert_eq!(
3761 parse_as_imm64("0x7fffffffffffffff").unwrap(),
3762 Imm64::new(9223372036854775807)
3763 );
3764 assert_eq!(
3765 parse_as_imm64("-0x0000000000000001").unwrap(),
3766 parse_as_imm64("0xffffffffffffffff").unwrap()
3767 );
3768 assert_eq!(
3769 parse_as_imm64("-0x7fffffffffffffff").unwrap(),
3770 parse_as_imm64("0x8000000000000001").unwrap()
3771 );
3772 assert!(parse_as_imm64("0xffffffffffffffffa").is_err());
3773 }
3774
3775 #[test]
3776 fn uimm128() {
3777 macro_rules! parse_as_constant_data {
3778 ($text:expr, $type:expr) => {{
3779 Parser::new($text).parse_literals_to_constant_data($type)
3780 }};
3781 }
3782 macro_rules! can_parse_as_constant_data {
3783 ($text:expr, $type:expr) => {{
3784 assert!(parse_as_constant_data!($text, $type).is_ok())
3785 }};
3786 }
3787 macro_rules! cannot_parse_as_constant_data {
3788 ($text:expr, $type:expr) => {{
3789 assert!(parse_as_constant_data!($text, $type).is_err())
3790 }};
3791 }
3792
3793 can_parse_as_constant_data!("1 2 3 4", I32X4);
3794 can_parse_as_constant_data!("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16", I8X16);
3795 can_parse_as_constant_data!("0x1.1 0x2.2 0x3.3 0x4.4", F32X4);
3796 can_parse_as_constant_data!("0x0 0x1 0x2 0x3", I32X4);
3797 can_parse_as_constant_data!("-1 0 -1 0 -1 0 -1 0", I16X8);
3798 can_parse_as_constant_data!("0 -1", I64X2);
3799 can_parse_as_constant_data!("-1 0", I64X2);
3800 can_parse_as_constant_data!("-1 -1 -1 -1 -1", I32X4); cannot_parse_as_constant_data!("1 2 3", I32X4);
3803 cannot_parse_as_constant_data!(" ", F32X4);
3804 }
3805
3806 #[test]
3807 fn parse_constant_from_booleans() {
3808 let c = Parser::new("-1 0 -1 0")
3809 .parse_literals_to_constant_data(I32X4)
3810 .unwrap();
3811 assert_eq!(
3812 c.into_vec(),
3813 [0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0]
3814 )
3815 }
3816
3817 #[test]
3818 fn parse_unbounded_constants() {
3819 assert_eq!(
3821 Parser::new("0x0100")
3822 .match_hexadecimal_constant("err message")
3823 .unwrap(),
3824 vec![0, 1].into()
3825 );
3826
3827 assert!(Parser::new("228")
3829 .match_hexadecimal_constant("err message")
3830 .is_err());
3831 }
3832
3833 #[test]
3834 fn parse_run_commands() {
3835 fn sig(ins: &[Type], outs: &[Type]) -> Signature {
3837 let mut sig = Signature::new(CallConv::Fast);
3838 for i in ins {
3839 sig.params.push(AbiParam::new(*i));
3840 }
3841 for o in outs {
3842 sig.returns.push(AbiParam::new(*o));
3843 }
3844 sig
3845 }
3846
3847 fn parse(text: &str, sig: &Signature) -> ParseResult<RunCommand> {
3849 Parser::new(text).parse_run_command(sig)
3850 }
3851
3852 fn assert_roundtrip(text: &str, sig: &Signature) {
3854 assert_eq!(parse(text, sig).unwrap().to_string(), text);
3855 }
3856 assert_roundtrip("run: %fn0() == 42", &sig(&[], &[I32]));
3857 assert_roundtrip(
3858 "run: %fn0(8, 16, 32, 64) == 1",
3859 &sig(&[I8, I16, I32, I64], &[I8]),
3860 );
3861 assert_roundtrip(
3862 "run: %my_func(1) == 0x0f0e0d0c0b0a09080706050403020100",
3863 &sig(&[I32], &[I8X16]),
3864 );
3865
3866 assert_eq!(
3868 parse("run", &sig(&[], &[I32])).unwrap().to_string(),
3869 "run: %default() != 0"
3870 );
3871 assert_eq!(
3872 parse("print", &sig(&[], &[F32X4, I16X8]))
3873 .unwrap()
3874 .to_string(),
3875 "print: %default()"
3876 );
3877
3878 assert!(parse("print", &sig(&[I32], &[I32])).is_err());
3880 assert!(parse("print:", &sig(&[], &[])).is_err());
3881 assert!(parse("run: ", &sig(&[], &[])).is_err());
3882 }
3883
3884 #[test]
3885 fn parse_data_values() {
3886 fn parse(text: &str, ty: Type) -> DataValue {
3887 Parser::new(text).parse_data_value(ty).unwrap()
3888 }
3889
3890 assert_eq!(parse("8", I8).to_string(), "8");
3891 assert_eq!(parse("16", I16).to_string(), "16");
3892 assert_eq!(parse("32", I32).to_string(), "32");
3893 assert_eq!(parse("64", I64).to_string(), "64");
3894 assert_eq!(
3895 parse("0x01234567_01234567_01234567_01234567", I128).to_string(),
3896 "1512366032949150931280199141537564007"
3897 );
3898 assert_eq!(parse("1234567", I128).to_string(), "1234567");
3899 assert_eq!(parse("0x16.1", F16).to_string(), "0x1.610p4");
3900 assert_eq!(parse("0x32.32", F32).to_string(), "0x1.919000p5");
3901 assert_eq!(parse("0x64.64", F64).to_string(), "0x1.9190000000000p6");
3902 assert_eq!(
3903 parse("0x128.128", F128).to_string(),
3904 "0x1.2812800000000000000000000000p8"
3905 );
3906 assert_eq!(
3907 parse("[0 1 2 3]", I32X4).to_string(),
3908 "0x00000003000000020000000100000000"
3909 );
3910 }
3911
3912 #[test]
3913 fn parse_cold_blocks() {
3914 let code = "function %test() {
3915 block0 cold:
3916 return
3917 block1(v0: i32) cold:
3918 return
3919 block2(v1: i32):
3920 return
3921 }";
3922
3923 let mut parser = Parser::new(code);
3924 let func = parser.parse_function().unwrap().0;
3925 assert_eq!(func.layout.blocks().count(), 3);
3926 assert!(func.layout.is_cold(Block::from_u32(0)));
3927 assert!(func.layout.is_cold(Block::from_u32(1)));
3928 assert!(!func.layout.is_cold(Block::from_u32(2)));
3929 }
3930}