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};
13use cranelift_codegen::ir::immediates::{
14 Ieee16, Ieee32, Ieee64, Ieee128, Imm64, Offset32, Uimm32, Uimm64,
15};
16use cranelift_codegen::ir::instructions::{InstructionData, InstructionFormat, VariableArgs};
17use cranelift_codegen::ir::{self, StackSlotKey, UserExternalNameRef};
18use cranelift_codegen::ir::{DebugTag, types::*};
19
20use cranelift_codegen::ir::{
21 AbiParam, ArgumentExtension, ArgumentPurpose, Block, BlockArg, Constant, ConstantData,
22 DynamicStackSlot, DynamicStackSlotData, DynamicTypeData, ExtFuncData, ExternalName, FuncRef,
23 Function, GlobalValue, GlobalValueData, JumpTableData, MemFlags, Opcode, SigRef, Signature,
24 StackSlot, StackSlotData, StackSlotKind, UserFuncName, Value, types,
25};
26use cranelift_codegen::isa::{self, CallConv};
27use cranelift_codegen::packed_option::ReservedValue;
28use cranelift_codegen::{settings, settings::Configurable, timing};
29use smallvec::SmallVec;
30use std::mem;
31use std::str::FromStr;
32use std::{u16, u32};
33use target_lexicon::Triple;
34
35macro_rules! match_imm {
36 ($signed:ty, $unsigned:ty, $parser:expr, $err_msg:expr) => {{
37 if let Some(Token::Integer(text)) = $parser.token() {
38 $parser.consume();
39 let negative = text.starts_with('-');
40 let positive = text.starts_with('+');
41 let text = if negative || positive {
42 &text[1..]
44 } else {
45 text
46 };
47
48 let value = if text.starts_with("0x") {
50 let text = text.replace("_", "");
52 <$unsigned>::from_str_radix(&text[2..], 16).map_err(|_| {
54 $parser.error(&format!(
55 "unable to parse '{}' value as a hexadecimal {} immediate",
56 &text[2..],
57 stringify!($unsigned),
58 ))
59 })?
60 } else {
61 text.parse()
63 .map_err(|_| $parser.error("expected decimal immediate"))?
64 };
65
66 let signed = if negative {
68 let value = value.wrapping_neg() as $signed;
69 if value > 0 {
70 return Err($parser.error("negative number too small"));
71 }
72 value
73 } else {
74 value as $signed
75 };
76
77 Ok(signed)
78 } else {
79 err!($parser.loc, $err_msg)
80 }
81 }};
82}
83
84const MAX_BLOCKS_IN_A_FUNCTION: u32 = 100_000;
86
87pub fn parse_functions(text: &str) -> ParseResult<Vec<Function>> {
91 let _tt = timing::parse_text();
92 parse_test(text, ParseOptions::default())
93 .map(|file| file.functions.into_iter().map(|(func, _)| func).collect())
94}
95
96pub struct ParseOptions<'a> {
98 pub passes: Option<&'a [String]>,
100 pub target: Option<&'a str>,
102 pub default_calling_convention: CallConv,
104 pub unwind_info: bool,
106 pub machine_code_cfg_info: bool,
108}
109
110impl Default for ParseOptions<'_> {
111 fn default() -> Self {
112 Self {
113 passes: None,
114 target: None,
115 default_calling_convention: CallConv::Fast,
116 unwind_info: false,
117 machine_code_cfg_info: false,
118 }
119 }
120}
121
122pub fn parse_test<'a>(text: &'a str, options: ParseOptions<'a>) -> ParseResult<TestFile<'a>> {
126 let _tt = timing::parse_text();
127 let mut parser = Parser::new(text);
128
129 parser.start_gathering_comments();
131
132 let isa_spec: isaspec::IsaSpec;
133 let commands: Vec<TestCommand<'a>>;
134
135 match options.passes {
138 Some(pass_vec) => {
139 parser.parse_test_commands();
140 commands = parser.parse_cmdline_passes(pass_vec);
141 parser.parse_target_specs(&options)?;
142 isa_spec = parser.parse_cmdline_target(options.target)?;
143 }
144 None => {
145 commands = parser.parse_test_commands();
146 isa_spec = parser.parse_target_specs(&options)?;
147 }
148 };
149 let features = parser.parse_cranelift_features()?;
150
151 parser = if commands.iter().any(|tc| tc.command == "run") {
155 let host_default_calling_convention = CallConv::triple_default(&Triple::host());
156 parser.with_default_calling_convention(host_default_calling_convention)
157 } else {
158 parser.with_default_calling_convention(options.default_calling_convention)
159 };
160
161 parser.token();
162 parser.claim_gathered_comments(AnyEntity::Function);
163
164 let preamble_comments = parser.take_comments();
165 let functions = parser.parse_function_list()?;
166
167 Ok(TestFile {
168 commands,
169 isa_spec,
170 features,
171 preamble_comments,
172 functions,
173 })
174}
175
176pub fn parse_run_command(text: &str, signature: &Signature) -> ParseResult<Option<RunCommand>> {
184 let _tt = timing::parse_text();
185 let trimmed_text = text.trim_start_matches(|c| c == ' ' || c == ';');
188 let mut parser = Parser::new(trimmed_text);
189 match parser.token() {
190 Some(Token::Identifier("run")) | Some(Token::Identifier("print")) => {
191 parser.parse_run_command(signature).map(|c| Some(c))
192 }
193 Some(_) | None => Ok(None),
194 }
195}
196
197pub struct Parser<'a> {
198 lex: Lexer<'a>,
199
200 lex_error: Option<LexError>,
201
202 lookahead: Option<Token<'a>>,
204
205 loc: Location,
207
208 gathering_comments: bool,
210
211 gathered_comments: Vec<&'a str>,
213
214 comments: Vec<Comment<'a>>,
216
217 predeclared_external_names: PrimaryMap<UserExternalNameRef, ir::UserExternalName>,
222
223 default_calling_convention: CallConv,
225}
226
227struct Context {
229 function: Function,
230 map: SourceMap,
231
232 aliases: Vec<Value>,
234}
235
236impl Context {
237 fn new(f: Function) -> Self {
238 Self {
239 function: f,
240 map: SourceMap::new(),
241 aliases: Vec::new(),
242 }
243 }
244
245 fn add_ss(&mut self, ss: StackSlot, data: StackSlotData, loc: Location) -> ParseResult<()> {
247 self.map.def_ss(ss, loc)?;
248 while self.function.sized_stack_slots.next_key().index() <= ss.index() {
249 self.function.create_sized_stack_slot(StackSlotData::new(
250 StackSlotKind::ExplicitSlot,
251 0,
252 0,
253 ));
254 }
255 self.function.sized_stack_slots[ss] = data;
256 Ok(())
257 }
258
259 fn check_ss(&self, ss: StackSlot, loc: Location) -> ParseResult<()> {
261 if !self.map.contains_ss(ss) {
262 err!(loc, "undefined stack slot {}", ss)
263 } else {
264 Ok(())
265 }
266 }
267
268 fn add_dss(
270 &mut self,
271 ss: DynamicStackSlot,
272 data: DynamicStackSlotData,
273 loc: Location,
274 ) -> ParseResult<()> {
275 self.map.def_dss(ss, loc)?;
276 while self.function.dynamic_stack_slots.next_key().index() <= ss.index() {
277 self.function
278 .create_dynamic_stack_slot(DynamicStackSlotData::new(
279 StackSlotKind::ExplicitDynamicSlot,
280 data.dyn_ty,
281 ));
282 }
283 self.function.dynamic_stack_slots[ss] = data;
284 Ok(())
285 }
286
287 fn check_dss(&self, dss: DynamicStackSlot, loc: Location) -> ParseResult<()> {
289 if !self.map.contains_dss(dss) {
290 err!(loc, "undefined dynamic stack slot {}", dss)
291 } else {
292 Ok(())
293 }
294 }
295
296 fn add_dt(&mut self, dt: DynamicType, data: DynamicTypeData, loc: Location) -> ParseResult<()> {
298 self.map.def_dt(dt, loc)?;
299 while self.function.dfg.dynamic_types.next_key().index() <= dt.index() {
300 self.function.dfg.make_dynamic_ty(DynamicTypeData::new(
301 data.base_vector_ty,
302 data.dynamic_scale,
303 ));
304 }
305 self.function.dfg.dynamic_types[dt] = data;
306 Ok(())
307 }
308
309 fn add_gv(&mut self, gv: GlobalValue, data: GlobalValueData, loc: Location) -> ParseResult<()> {
311 self.map.def_gv(gv, loc)?;
312 while self.function.global_values.next_key().index() <= gv.index() {
313 self.function.create_global_value(GlobalValueData::Symbol {
314 name: ExternalName::testcase(""),
315 offset: Imm64::new(0),
316 colocated: false,
317 tls: false,
318 });
319 }
320 self.function.global_values[gv] = data;
321 Ok(())
322 }
323
324 fn check_gv(&self, gv: GlobalValue, loc: Location) -> ParseResult<()> {
326 if !self.map.contains_gv(gv) {
327 err!(loc, "undefined global value {}", gv)
328 } else {
329 Ok(())
330 }
331 }
332
333 fn add_sig(
335 &mut self,
336 sig: SigRef,
337 data: Signature,
338 loc: Location,
339 defaultcc: CallConv,
340 ) -> ParseResult<()> {
341 self.map.def_sig(sig, loc)?;
342 while self.function.dfg.signatures.next_key().index() <= sig.index() {
343 self.function.import_signature(Signature::new(defaultcc));
344 }
345 self.function.dfg.signatures[sig] = data;
346 Ok(())
347 }
348
349 fn check_sig(&self, sig: SigRef, loc: Location) -> ParseResult<()> {
351 if !self.map.contains_sig(sig) {
352 err!(loc, "undefined signature {}", sig)
353 } else {
354 Ok(())
355 }
356 }
357
358 fn add_fn(&mut self, fn_: FuncRef, data: ExtFuncData, loc: Location) -> ParseResult<()> {
360 self.map.def_fn(fn_, loc)?;
361 while self.function.dfg.ext_funcs.next_key().index() <= fn_.index() {
362 self.function.import_function(ExtFuncData {
363 name: ExternalName::testcase(""),
364 signature: SigRef::reserved_value(),
365 colocated: false,
366 patchable: false,
367 });
368 }
369 self.function.dfg.ext_funcs[fn_] = data;
370 Ok(())
371 }
372
373 fn check_fn(&self, fn_: FuncRef, loc: Location) -> ParseResult<()> {
375 if !self.map.contains_fn(fn_) {
376 err!(loc, "undefined function {}", fn_)
377 } else {
378 Ok(())
379 }
380 }
381
382 fn add_constant(
384 &mut self,
385 constant: Constant,
386 data: ConstantData,
387 loc: Location,
388 ) -> ParseResult<()> {
389 self.map.def_constant(constant, loc)?;
390 self.function.dfg.constants.set(constant, data);
391 Ok(())
392 }
393
394 fn add_stack_limit(&mut self, limit: GlobalValue, loc: Location) -> ParseResult<()> {
396 if self.function.stack_limit.is_some() {
397 return err!(loc, "stack limit defined twice");
398 }
399 self.function.stack_limit = Some(limit);
400 Ok(())
401 }
402
403 fn check_constant(&self, c: Constant, loc: Location) -> ParseResult<()> {
405 if !self.map.contains_constant(c) {
406 err!(loc, "undefined constant {}", c)
407 } else {
408 Ok(())
409 }
410 }
411
412 fn add_block(&mut self, block: Block, loc: Location) -> ParseResult<Block> {
414 self.map.def_block(block, loc)?;
415 while self.function.dfg.num_blocks() <= block.index() {
416 self.function.dfg.make_block();
417 }
418 self.function.layout.append_block(block);
419 Ok(block)
420 }
421
422 fn set_cold_block(&mut self, block: Block) {
424 self.function.layout.set_cold(block);
425 }
426}
427
428impl<'a> Parser<'a> {
429 pub fn new(text: &'a str) -> Self {
431 Self {
432 lex: Lexer::new(text),
433 lex_error: None,
434 lookahead: None,
435 loc: Location { line_number: 0 },
436 gathering_comments: false,
437 gathered_comments: Vec::new(),
438 comments: Vec::new(),
439 default_calling_convention: CallConv::Fast,
440 predeclared_external_names: Default::default(),
441 }
442 }
443
444 pub fn with_default_calling_convention(self, default_calling_convention: CallConv) -> Self {
447 Self {
448 default_calling_convention,
449 ..self
450 }
451 }
452
453 fn consume(&mut self) -> Token<'a> {
455 self.lookahead.take().expect("No token to consume")
456 }
457
458 fn consume_line(&mut self) -> &'a str {
461 let rest = self.lex.rest_of_line();
462 self.consume();
463 rest
464 }
465
466 fn token(&mut self) -> Option<Token<'a>> {
468 while self.lookahead.is_none() {
469 match self.lex.next() {
470 Some(Ok(LocatedToken { token, location })) => {
471 match token {
472 Token::Comment(text) => {
473 if self.gathering_comments {
474 self.gathered_comments.push(text);
475 }
476 }
477 _ => self.lookahead = Some(token),
478 }
479 self.loc = location;
480 }
481 Some(Err(LocatedError { error, location })) => {
482 self.lex_error = Some(error);
483 self.loc = location;
484 break;
485 }
486 None => break,
487 }
488 }
489 self.lookahead
490 }
491
492 fn start_gathering_comments(&mut self) {
494 debug_assert!(!self.gathering_comments);
495 self.gathering_comments = true;
496 debug_assert!(self.gathered_comments.is_empty());
497 }
498
499 fn claim_gathered_comments<E: Into<AnyEntity>>(&mut self, entity: E) {
502 debug_assert!(self.gathering_comments);
503 let entity = entity.into();
504 self.comments.extend(
505 self.gathered_comments
506 .drain(..)
507 .map(|text| Comment { entity, text }),
508 );
509 self.gathering_comments = false;
510 }
511
512 fn take_comments(&mut self) -> Vec<Comment<'a>> {
514 debug_assert!(!self.gathering_comments);
515 mem::replace(&mut self.comments, Vec::new())
516 }
517
518 fn match_token(&mut self, want: Token<'a>, err_msg: &str) -> ParseResult<Token<'a>> {
520 if self.token() == Some(want) {
521 Ok(self.consume())
522 } else {
523 err!(self.loc, err_msg)
524 }
525 }
526
527 fn optional(&mut self, want: Token<'a>) -> bool {
529 if self.token() == Some(want) {
530 self.consume();
531 true
532 } else {
533 false
534 }
535 }
536
537 fn match_identifier(&mut self, want: &'static str, err_msg: &str) -> ParseResult<Token<'a>> {
540 if self.token() == Some(Token::Identifier(want)) {
541 Ok(self.consume())
542 } else {
543 err!(self.loc, err_msg)
544 }
545 }
546
547 fn match_type(&mut self, err_msg: &str) -> ParseResult<Type> {
549 if let Some(Token::Type(t)) = self.token() {
550 self.consume();
551 Ok(t)
552 } else {
553 err!(self.loc, err_msg)
554 }
555 }
556
557 fn match_ss(&mut self, err_msg: &str) -> ParseResult<StackSlot> {
559 if let Some(Token::StackSlot(ss)) = self.token() {
560 self.consume();
561 if let Some(ss) = StackSlot::with_number(ss) {
562 return Ok(ss);
563 }
564 }
565 err!(self.loc, err_msg)
566 }
567
568 fn match_dss(&mut self, err_msg: &str) -> ParseResult<DynamicStackSlot> {
570 if let Some(Token::DynamicStackSlot(ss)) = self.token() {
571 self.consume();
572 if let Some(ss) = DynamicStackSlot::with_number(ss) {
573 return Ok(ss);
574 }
575 }
576 err!(self.loc, err_msg)
577 }
578
579 fn match_dt(&mut self, err_msg: &str) -> ParseResult<DynamicType> {
581 if let Some(Token::DynamicType(dt)) = self.token() {
582 self.consume();
583 if let Some(dt) = DynamicType::with_number(dt) {
584 return Ok(dt);
585 }
586 }
587 err!(self.loc, err_msg)
588 }
589
590 fn concrete_from_dt(&mut self, dt: DynamicType, ctx: &mut Context) -> Option<Type> {
592 ctx.function.get_concrete_dynamic_ty(dt)
593 }
594
595 fn match_gv(&mut self, err_msg: &str) -> ParseResult<GlobalValue> {
597 if let Some(Token::GlobalValue(gv)) = self.token() {
598 self.consume();
599 if let Some(gv) = GlobalValue::with_number(gv) {
600 return Ok(gv);
601 }
602 }
603 err!(self.loc, err_msg)
604 }
605
606 fn match_fn(&mut self, err_msg: &str) -> ParseResult<FuncRef> {
608 if let Some(Token::FuncRef(fnref)) = self.token() {
609 self.consume();
610 if let Some(fnref) = FuncRef::with_number(fnref) {
611 return Ok(fnref);
612 }
613 }
614 err!(self.loc, err_msg)
615 }
616
617 fn match_sig(&mut self, err_msg: &str) -> ParseResult<SigRef> {
619 if let Some(Token::SigRef(sigref)) = self.token() {
620 self.consume();
621 if let Some(sigref) = SigRef::with_number(sigref) {
622 return Ok(sigref);
623 }
624 }
625 err!(self.loc, err_msg)
626 }
627
628 fn match_constant(&mut self) -> ParseResult<Constant> {
630 if let Some(Token::Constant(c)) = self.token() {
631 self.consume();
632 if let Some(c) = Constant::with_number(c) {
633 return Ok(c);
634 }
635 }
636 err!(self.loc, "expected constant number: const«n»")
637 }
638
639 fn match_stack_limit(&mut self) -> ParseResult<()> {
641 if let Some(Token::Identifier("stack_limit")) = self.token() {
642 self.consume();
643 return Ok(());
644 }
645 err!(self.loc, "expected identifier: stack_limit")
646 }
647
648 fn match_block(&mut self, err_msg: &str) -> ParseResult<Block> {
650 if let Some(Token::Block(block)) = self.token() {
651 self.consume();
652 Ok(block)
653 } else {
654 err!(self.loc, err_msg)
655 }
656 }
657
658 fn match_value(&mut self, err_msg: &str) -> ParseResult<Value> {
660 if let Some(Token::Value(v)) = self.token() {
661 self.consume();
662 Ok(v)
663 } else {
664 err!(self.loc, err_msg)
665 }
666 }
667
668 fn error(&self, message: &str) -> ParseError {
669 ParseError {
670 location: self.loc,
671 message: message.to_string(),
672 is_warning: false,
673 }
674 }
675
676 fn match_imm64(&mut self, err_msg: &str) -> ParseResult<Imm64> {
678 if let Some(Token::Integer(text)) = self.token() {
679 self.consume();
680 text.parse().map_err(|e| self.error(e))
683 } else {
684 err!(self.loc, err_msg)
685 }
686 }
687
688 fn match_hexadecimal_constant(&mut self, err_msg: &str) -> ParseResult<ConstantData> {
690 if let Some(Token::Integer(text)) = self.token() {
691 self.consume();
692 text.parse().map_err(|e| {
693 self.error(&format!(
694 "expected hexadecimal immediate, failed to parse: {e}"
695 ))
696 })
697 } else {
698 err!(self.loc, err_msg)
699 }
700 }
701
702 fn match_uimm128(&mut self, controlling_type: Type) -> ParseResult<ConstantData> {
706 let expected_size = controlling_type.bytes() as usize;
707 let constant_data = if self.optional(Token::LBracket) {
708 let uimm128 = self.parse_literals_to_constant_data(controlling_type)?;
710 self.match_token(Token::RBracket, "expected a terminating right bracket")?;
711 uimm128
712 } else {
713 let uimm128 =
715 self.match_hexadecimal_constant("expected an immediate hexadecimal operand")?;
716 uimm128.expand_to(expected_size)
717 };
718
719 if constant_data.len() == expected_size {
720 Ok(constant_data)
721 } else {
722 Err(self.error(&format!(
723 "expected parsed constant to have {expected_size} bytes"
724 )))
725 }
726 }
727
728 fn match_uimm64(&mut self, err_msg: &str) -> ParseResult<Uimm64> {
730 if let Some(Token::Integer(text)) = self.token() {
731 self.consume();
732 text.parse()
735 .map_err(|_| self.error("expected u64 decimal immediate"))
736 } else {
737 err!(self.loc, err_msg)
738 }
739 }
740
741 fn match_uimm32(&mut self, err_msg: &str) -> ParseResult<Uimm32> {
743 if let Some(Token::Integer(text)) = self.token() {
744 self.consume();
745 text.parse().map_err(|e| self.error(e))
748 } else {
749 err!(self.loc, err_msg)
750 }
751 }
752
753 fn match_uimm8(&mut self, err_msg: &str) -> ParseResult<u8> {
756 if let Some(Token::Integer(text)) = self.token() {
757 self.consume();
758 if let Some(num) = text.strip_prefix("0x") {
760 u8::from_str_radix(num, 16)
762 .map_err(|_| self.error("unable to parse u8 as a hexadecimal immediate"))
763 } else {
764 text.parse()
766 .map_err(|_| self.error("expected u8 decimal immediate"))
767 }
768 } else {
769 err!(self.loc, err_msg)
770 }
771 }
772
773 fn match_imm8(&mut self, err_msg: &str) -> ParseResult<i8> {
775 match_imm!(i8, u8, self, err_msg)
776 }
777
778 fn match_imm16(&mut self, err_msg: &str) -> ParseResult<i16> {
780 match_imm!(i16, u16, self, err_msg)
781 }
782
783 fn match_imm32(&mut self, err_msg: &str) -> ParseResult<i32> {
786 match_imm!(i32, u32, self, err_msg)
787 }
788
789 fn match_imm128(&mut self, err_msg: &str) -> ParseResult<i128> {
791 match_imm!(i128, u128, self, err_msg)
792 }
793
794 fn optional_offset32(&mut self) -> ParseResult<Offset32> {
799 if let Some(Token::Integer(text)) = self.token() {
800 if text.starts_with('+') || text.starts_with('-') {
801 self.consume();
802 return text.parse().map_err(|e| self.error(e));
805 }
806 }
807 Ok(Offset32::new(0))
809 }
810
811 fn optional_offset_imm64(&mut self) -> ParseResult<Imm64> {
816 if let Some(Token::Integer(text)) = self.token() {
817 if text.starts_with('+') || text.starts_with('-') {
818 self.consume();
819 return text.parse().map_err(|e| self.error(e));
822 }
823 }
824 Ok(Imm64::new(0))
826 }
827
828 fn match_ieee16(&mut self, err_msg: &str) -> ParseResult<Ieee16> {
830 if let Some(Token::Float(text)) = self.token() {
831 self.consume();
832 text.parse().map_err(|e| self.error(e))
835 } else {
836 err!(self.loc, err_msg)
837 }
838 }
839
840 fn match_ieee32(&mut self, err_msg: &str) -> ParseResult<Ieee32> {
842 if let Some(Token::Float(text)) = self.token() {
843 self.consume();
844 text.parse().map_err(|e| self.error(e))
847 } else {
848 err!(self.loc, err_msg)
849 }
850 }
851
852 fn match_ieee64(&mut self, err_msg: &str) -> ParseResult<Ieee64> {
854 if let Some(Token::Float(text)) = self.token() {
855 self.consume();
856 text.parse().map_err(|e| self.error(e))
859 } else {
860 err!(self.loc, err_msg)
861 }
862 }
863
864 fn match_ieee128(&mut self, err_msg: &str) -> ParseResult<Ieee128> {
866 if let Some(Token::Float(text)) = self.token() {
867 self.consume();
868 text.parse().map_err(|e| self.error(e))
871 } else {
872 err!(self.loc, err_msg)
873 }
874 }
875
876 fn match_enum<T: FromStr>(&mut self, err_msg: &str) -> ParseResult<T> {
878 if let Some(Token::Identifier(text)) = self.token() {
879 self.consume();
880 text.parse().map_err(|_| self.error(err_msg))
881 } else {
882 err!(self.loc, err_msg)
883 }
884 }
885
886 fn optional_memflags(&mut self) -> ParseResult<MemFlags> {
888 let mut flags = MemFlags::new();
889 while let Some(Token::Identifier(text)) = self.token() {
890 match flags.set_by_name(text) {
891 Ok(true) => {
892 self.consume();
893 }
894 Ok(false) => break,
895 Err(msg) => return err!(self.loc, msg),
896 }
897 }
898 Ok(flags)
899 }
900
901 fn match_any_identifier(&mut self, err_msg: &str) -> ParseResult<&'a str> {
903 if let Some(Token::Identifier(text)) = self.token() {
904 self.consume();
905 Ok(text)
906 } else {
907 err!(self.loc, err_msg)
908 }
909 }
910
911 fn optional_srcloc(&mut self) -> ParseResult<ir::SourceLoc> {
915 if let Some(Token::SourceLoc(text)) = self.token() {
916 match u32::from_str_radix(text, 16) {
917 Ok(num) => {
918 self.consume();
919 Ok(ir::SourceLoc::new(num))
920 }
921 Err(_) => return err!(self.loc, "invalid source location: {}", text),
922 }
923 } else {
924 Ok(Default::default())
925 }
926 }
927
928 fn optional_debug_tags(&mut self) -> ParseResult<Vec<DebugTag>> {
930 if self.optional(Token::LAngle) {
931 let mut tags = vec![];
932 while !self.optional(Token::RAngle) {
933 match self.token() {
934 Some(Token::Integer(_)) => {
935 let value: u32 = self.match_uimm32("expected a u32 value")?.into();
936 tags.push(DebugTag::User(value));
937 }
938 Some(Token::StackSlot(slot)) => {
939 self.consume();
940 tags.push(DebugTag::StackSlot(StackSlot::from_u32(slot)));
941 }
942 _ => {
943 return err!(
944 self.loc,
945 "expected integer user value or stack slot in debug tags"
946 );
947 }
948 }
949 if !self.optional(Token::Comma) {
950 self.match_token(Token::RAngle, "expected `,` or `>`")?;
951 break;
952 }
953 }
954 Ok(tags)
955 } else {
956 Ok(vec![])
957 }
958 }
959
960 fn parse_literals_to_constant_data(&mut self, ty: Type) -> ParseResult<ConstantData> {
963 macro_rules! consume {
964 ( $ty:ident, $match_fn:expr ) => {{
965 assert!($ty.is_vector());
966 let mut data = ConstantData::default();
967 for _ in 0..$ty.lane_count() {
968 data = data.append($match_fn);
969 }
970 data
971 }};
972 }
973
974 if !ty.is_vector() && !ty.is_dynamic_vector() {
975 err!(self.loc, "Expected a controlling vector type, not {}", ty)
976 } else {
977 let constant_data = match ty.lane_type() {
978 I8 => consume!(ty, self.match_imm8("Expected an 8-bit integer")?),
979 I16 => consume!(ty, self.match_imm16("Expected a 16-bit integer")?),
980 I32 => consume!(ty, self.match_imm32("Expected a 32-bit integer")?),
981 I64 => consume!(ty, self.match_imm64("Expected a 64-bit integer")?),
982 F32 => consume!(ty, self.match_ieee32("Expected a 32-bit float")?),
983 F64 => consume!(ty, self.match_ieee64("Expected a 64-bit float")?),
984 _ => return err!(self.loc, "Expected a type of: float, int, bool"),
985 };
986 Ok(constant_data)
987 }
988 }
989
990 pub fn parse_cmdline_passes(&mut self, passes: &'a [String]) -> Vec<TestCommand<'a>> {
992 let mut list = Vec::new();
993 for pass in passes {
994 list.push(TestCommand::new(pass));
995 }
996 list
997 }
998
999 pub fn parse_test_commands(&mut self) -> Vec<TestCommand<'a>> {
1001 let mut list = Vec::new();
1002 while self.token() == Some(Token::Identifier("test")) {
1003 list.push(TestCommand::new(self.consume_line()));
1004 }
1005 list
1006 }
1007
1008 fn parse_cmdline_target(&mut self, target_pass: Option<&str>) -> ParseResult<isaspec::IsaSpec> {
1013 let mut specified_target = false;
1015
1016 let mut targets = Vec::new();
1017 let flag_builder = settings::builder();
1018
1019 if let Some(targ) = target_pass {
1020 let loc = self.loc;
1021 let triple = match Triple::from_str(targ) {
1022 Ok(triple) => triple,
1023 Err(err) => return err!(loc, err),
1024 };
1025 let isa_builder = match isa::lookup(triple) {
1026 Err(isa::LookupError::SupportDisabled) => {
1027 return err!(loc, "support disabled target '{}'", targ);
1028 }
1029 Err(isa::LookupError::Unsupported) => {
1030 return warn!(loc, "unsupported target '{}'", targ);
1031 }
1032 Ok(b) => b,
1033 };
1034 specified_target = true;
1035
1036 targets.push(
1038 isa_builder
1039 .finish(settings::Flags::new(flag_builder.clone()))
1040 .map_err(|e| ParseError {
1041 location: loc,
1042 message: format!("invalid ISA flags for '{targ}': {e:?}"),
1043 is_warning: false,
1044 })?,
1045 );
1046 }
1047
1048 if !specified_target {
1049 Ok(isaspec::IsaSpec::None(settings::Flags::new(flag_builder)))
1051 } else {
1052 Ok(isaspec::IsaSpec::Some(targets))
1053 }
1054 }
1055
1056 fn parse_target_specs(&mut self, options: &ParseOptions) -> ParseResult<isaspec::IsaSpec> {
1061 let mut seen_target = false;
1063 let mut last_set_loc = None;
1065
1066 let mut targets = Vec::new();
1067 let mut flag_builder = settings::builder();
1068
1069 let bool_to_str = |val: bool| {
1070 if val { "true" } else { "false" }
1071 };
1072
1073 flag_builder
1075 .set(
1076 "machine_code_cfg_info",
1077 bool_to_str(options.machine_code_cfg_info),
1078 )
1079 .expect("machine_code_cfg_info option should be present");
1080
1081 flag_builder
1082 .set("unwind_info", bool_to_str(options.unwind_info))
1083 .expect("unwind_info option should be present");
1084
1085 while let Some(Token::Identifier(command)) = self.token() {
1086 match command {
1087 "set" => {
1088 last_set_loc = Some(self.loc);
1089 isaspec::parse_options(
1090 self.consume_line().trim().split_whitespace(),
1091 &mut flag_builder,
1092 self.loc,
1093 )
1094 .map_err(|err| ParseError::from(err))?;
1095 }
1096 "target" => {
1097 let loc = self.loc;
1098 let mut words = self.consume_line().trim().split_whitespace().peekable();
1101 let target_name = match words.next() {
1103 Some(w) => w,
1104 None => return err!(loc, "expected target triple"),
1105 };
1106 let triple = match Triple::from_str(target_name) {
1107 Ok(triple) => triple,
1108 Err(err) => return err!(loc, err),
1109 };
1110 let mut isa_builder = match isa::lookup(triple) {
1111 Err(isa::LookupError::SupportDisabled) => {
1112 continue;
1113 }
1114 Err(isa::LookupError::Unsupported) => {
1115 return warn!(loc, "unsupported target '{}'", target_name);
1116 }
1117 Ok(b) => b,
1118 };
1119 last_set_loc = None;
1120 seen_target = true;
1121 isaspec::parse_options(words, &mut isa_builder, self.loc)?;
1123
1124 targets.push(
1126 isa_builder
1127 .finish(settings::Flags::new(flag_builder.clone()))
1128 .map_err(|e| ParseError {
1129 location: loc,
1130 message: format!("invalid ISA flags for '{target_name}': {e:?}"),
1131 is_warning: false,
1132 })?,
1133 );
1134 }
1135 _ => break,
1136 }
1137 }
1138
1139 if !seen_target {
1140 Ok(isaspec::IsaSpec::None(settings::Flags::new(flag_builder)))
1142 } else if let Some(loc) = last_set_loc {
1143 err!(
1144 loc,
1145 "dangling 'set' command after ISA specification has no effect."
1146 )
1147 } else {
1148 Ok(isaspec::IsaSpec::Some(targets))
1149 }
1150 }
1151
1152 pub fn parse_cranelift_features(&mut self) -> ParseResult<Vec<Feature<'a>>> {
1154 let mut list = Vec::new();
1155 while self.token() == Some(Token::Identifier("feature")) {
1156 self.consume();
1157 let has = !self.optional(Token::Bang);
1158 match (self.token(), has) {
1159 (Some(Token::String(flag)), true) => list.push(Feature::With(flag)),
1160 (Some(Token::String(flag)), false) => list.push(Feature::Without(flag)),
1161 (tok, _) => {
1162 return err!(
1163 self.loc,
1164 format!("Expected feature flag string, got {:?}", tok)
1165 );
1166 }
1167 }
1168 self.consume();
1169 }
1170 Ok(list)
1171 }
1172
1173 pub fn parse_function_list(&mut self) -> ParseResult<Vec<(Function, Details<'a>)>> {
1177 let mut list = Vec::new();
1178 while self.token().is_some() {
1179 list.push(self.parse_function()?);
1180 }
1181 if let Some(err) = self.lex_error {
1182 return match err {
1183 LexError::InvalidChar => err!(self.loc, "invalid character"),
1184 };
1185 }
1186 Ok(list)
1187 }
1188
1189 fn parse_function(&mut self) -> ParseResult<(Function, Details<'a>)> {
1194 self.token();
1197 debug_assert!(self.comments.is_empty());
1198 self.start_gathering_comments();
1199
1200 self.match_identifier("function", "expected 'function'")?;
1201
1202 let location = self.loc;
1203
1204 let name = self.parse_user_func_name()?;
1206
1207 let sig = self.parse_signature()?;
1209
1210 let mut ctx = Context::new(Function::with_name_signature(name, sig));
1211
1212 self.match_token(Token::LBrace, "expected '{' before function body")?;
1214
1215 self.token();
1216 self.claim_gathered_comments(AnyEntity::Function);
1217
1218 self.parse_preamble(&mut ctx)?;
1220 self.parse_function_body(&mut ctx)?;
1222 self.match_token(Token::RBrace, "expected '}' after function body")?;
1224
1225 self.start_gathering_comments();
1227 self.token();
1228 self.claim_gathered_comments(AnyEntity::Function);
1229
1230 for (user_func_ref, user_external_name) in
1232 std::mem::take(&mut self.predeclared_external_names)
1233 {
1234 let actual_ref = ctx
1235 .function
1236 .declare_imported_user_function(user_external_name);
1237 assert_eq!(user_func_ref, actual_ref);
1238 }
1239
1240 let details = Details {
1241 location,
1242 comments: self.take_comments(),
1243 map: ctx.map,
1244 };
1245
1246 Ok((ctx.function, details))
1247 }
1248
1249 fn parse_user_func_name(&mut self) -> ParseResult<UserFuncName> {
1256 match self.token() {
1257 Some(Token::Name(s)) => {
1258 self.consume();
1259 Ok(UserFuncName::testcase(s))
1260 }
1261 Some(Token::UserRef(namespace)) => {
1262 self.consume();
1263 match self.token() {
1264 Some(Token::Colon) => {
1265 self.consume();
1266 match self.token() {
1267 Some(Token::Integer(index_str)) => {
1268 self.consume();
1269 let index: u32 =
1270 u32::from_str_radix(index_str, 10).map_err(|_| {
1271 self.error("the integer given overflows the u32 type")
1272 })?;
1273 Ok(UserFuncName::user(namespace, index))
1274 }
1275 _ => err!(self.loc, "expected integer"),
1276 }
1277 }
1278 _ => {
1279 err!(self.loc, "expected user function name in the form uX:Y")
1280 }
1281 }
1282 }
1283 _ => err!(self.loc, "expected external name"),
1284 }
1285 }
1286
1287 fn parse_external_name(&mut self) -> ParseResult<ExternalName> {
1294 match self.token() {
1295 Some(Token::Name(s)) => {
1296 self.consume();
1297 s.parse()
1298 .map_err(|_| self.error("invalid test case or libcall name"))
1299 }
1300
1301 Some(Token::UserNameRef(name_ref)) => {
1302 self.consume();
1303 Ok(ExternalName::user(UserExternalNameRef::new(
1304 name_ref as usize,
1305 )))
1306 }
1307
1308 Some(Token::UserRef(namespace)) => {
1309 self.consume();
1310 if let Some(Token::Colon) = self.token() {
1311 self.consume();
1312 match self.token() {
1313 Some(Token::Integer(index_str)) => {
1314 let index: u32 = u32::from_str_radix(index_str, 10).map_err(|_| {
1315 self.error("the integer given overflows the u32 type")
1316 })?;
1317 self.consume();
1318
1319 let name_ref = self
1323 .predeclared_external_names
1324 .iter()
1325 .find_map(|(reff, name)| {
1326 if name.index == index && name.namespace == namespace {
1327 Some(reff)
1328 } else {
1329 None
1330 }
1331 })
1332 .unwrap_or_else(|| {
1333 self.predeclared_external_names
1334 .push(ir::UserExternalName { namespace, index })
1335 });
1336
1337 Ok(ExternalName::user(name_ref))
1338 }
1339 _ => err!(self.loc, "expected integer"),
1340 }
1341 } else {
1342 err!(self.loc, "expected colon")
1343 }
1344 }
1345
1346 _ => err!(self.loc, "expected external name"),
1347 }
1348 }
1349
1350 fn parse_signature(&mut self) -> ParseResult<Signature> {
1355 let mut sig = Signature::new(self.default_calling_convention);
1357
1358 self.match_token(Token::LPar, "expected function signature: ( args... )")?;
1359 if self.token() != Some(Token::RPar) {
1361 sig.params = self.parse_abi_param_list()?;
1362 }
1363 self.match_token(Token::RPar, "expected ')' after function arguments")?;
1364 if self.optional(Token::Arrow) {
1365 sig.returns = self.parse_abi_param_list()?;
1366 }
1367
1368 match self.token() {
1370 Some(Token::Identifier(text)) => match text.parse() {
1371 Ok(cc) => {
1372 self.consume();
1373 sig.call_conv = cc;
1374 }
1375 _ => return err!(self.loc, "unknown calling convention: {}", text),
1376 },
1377 _ => {}
1378 }
1379
1380 Ok(sig)
1381 }
1382
1383 fn parse_abi_param_list(&mut self) -> ParseResult<Vec<AbiParam>> {
1388 let mut list = Vec::new();
1389
1390 list.push(self.parse_abi_param()?);
1392
1393 while self.optional(Token::Comma) {
1395 list.push(self.parse_abi_param()?);
1397 }
1398
1399 Ok(list)
1400 }
1401
1402 fn parse_abi_param(&mut self) -> ParseResult<AbiParam> {
1404 let mut arg = AbiParam::new(self.match_type("expected parameter type")?);
1406
1407 while let Some(Token::Identifier(s)) = self.token() {
1409 match s {
1410 "uext" => arg.extension = ArgumentExtension::Uext,
1411 "sext" => arg.extension = ArgumentExtension::Sext,
1412 "sarg" => {
1413 self.consume();
1414 self.match_token(Token::LPar, "expected '(' to begin sarg size")?;
1415 let size = self.match_uimm32("expected byte-size in sarg decl")?;
1416 self.match_token(Token::RPar, "expected ')' to end sarg size")?;
1417 arg.purpose = ArgumentPurpose::StructArgument(size.into());
1418 continue;
1419 }
1420 _ => {
1421 if let Ok(purpose) = s.parse() {
1422 arg.purpose = purpose;
1423 } else {
1424 break;
1425 }
1426 }
1427 }
1428 self.consume();
1429 }
1430
1431 Ok(arg)
1432 }
1433
1434 fn parse_preamble(&mut self, ctx: &mut Context) -> ParseResult<()> {
1445 loop {
1446 match self.token() {
1447 Some(Token::StackSlot(..)) => {
1448 self.start_gathering_comments();
1449 let loc = self.loc;
1450 self.parse_stack_slot_decl()
1451 .and_then(|(ss, dat)| ctx.add_ss(ss, dat, loc))
1452 }
1453 Some(Token::DynamicStackSlot(..)) => {
1454 self.start_gathering_comments();
1455 let loc = self.loc;
1456 self.parse_dynamic_stack_slot_decl()
1457 .and_then(|(dss, dat)| ctx.add_dss(dss, dat, loc))
1458 }
1459 Some(Token::DynamicType(..)) => {
1460 self.start_gathering_comments();
1461 let loc = self.loc;
1462 self.parse_dynamic_type_decl()
1463 .and_then(|(dt, dat)| ctx.add_dt(dt, dat, loc))
1464 }
1465 Some(Token::GlobalValue(..)) => {
1466 self.start_gathering_comments();
1467 self.parse_global_value_decl()
1468 .and_then(|(gv, dat)| ctx.add_gv(gv, dat, self.loc))
1469 }
1470 Some(Token::SigRef(..)) => {
1471 self.start_gathering_comments();
1472 self.parse_signature_decl().and_then(|(sig, dat)| {
1473 ctx.add_sig(sig, dat, self.loc, self.default_calling_convention)
1474 })
1475 }
1476 Some(Token::FuncRef(..)) => {
1477 self.start_gathering_comments();
1478 self.parse_function_decl(ctx)
1479 .and_then(|(fn_, dat)| ctx.add_fn(fn_, dat, self.loc))
1480 }
1481 Some(Token::Constant(..)) => {
1482 self.start_gathering_comments();
1483 self.parse_constant_decl()
1484 .and_then(|(c, v)| ctx.add_constant(c, v, self.loc))
1485 }
1486 Some(Token::Identifier("stack_limit")) => {
1487 self.start_gathering_comments();
1488 self.parse_stack_limit_decl()
1489 .and_then(|gv| ctx.add_stack_limit(gv, self.loc))
1490 }
1491 _ => return Ok(()),
1493 }?;
1494 }
1495 }
1496
1497 fn parse_stack_slot_decl(&mut self) -> ParseResult<(StackSlot, StackSlotData)> {
1506 let ss = self.match_ss("expected stack slot number: ss«n»")?;
1507 self.match_token(Token::Equal, "expected '=' in stack slot declaration")?;
1508 let kind = self.match_enum("expected stack slot kind")?;
1509
1510 let bytes: i64 = self
1512 .match_imm64("expected byte-size in stack_slot decl")?
1513 .into();
1514 if bytes < 0 {
1515 return err!(self.loc, "negative stack slot size");
1516 }
1517 if bytes > i64::from(u32::MAX) {
1518 return err!(self.loc, "stack slot too large");
1519 }
1520
1521 let mut align = 1;
1522 let mut key = None;
1523
1524 while self.token() == Some(Token::Comma) {
1525 self.consume();
1526 match self.token() {
1527 Some(Token::Identifier("align")) => {
1528 self.consume();
1529 self.match_token(Token::Equal, "expected `=` after flag")?;
1530 let align64: i64 = self
1531 .match_imm64("expected alignment-size after `align` flag")?
1532 .into();
1533 align = u32::try_from(align64)
1534 .map_err(|_| self.error("alignment must be a 32-bit unsigned integer"))?;
1535 }
1536 Some(Token::Identifier("key")) => {
1537 self.consume();
1538 self.match_token(Token::Equal, "expected `=` after flag")?;
1539 let value = self.match_uimm64("expected `u64` value for `key` flag")?;
1540 key = Some(StackSlotKey::new(value.into()));
1541 }
1542 _ => {
1543 return Err(self.error("invalid flag for stack slot"));
1544 }
1545 }
1546 }
1547
1548 if !align.is_power_of_two() {
1549 return err!(self.loc, "stack slot alignment is not a power of two");
1550 }
1551 let align_shift = u8::try_from(align.ilog2()).unwrap(); let data = match key {
1554 Some(key) => StackSlotData::new_with_key(kind, bytes as u32, align_shift, key),
1555 None => StackSlotData::new(kind, bytes as u32, align_shift),
1556 };
1557
1558 self.token();
1560 self.claim_gathered_comments(ss);
1561
1562 Ok((ss, data))
1564 }
1565
1566 fn parse_dynamic_stack_slot_decl(
1567 &mut self,
1568 ) -> ParseResult<(DynamicStackSlot, DynamicStackSlotData)> {
1569 let dss = self.match_dss("expected stack slot number: dss«n»")?;
1570 self.match_token(Token::Equal, "expected '=' in stack slot declaration")?;
1571 let kind = self.match_enum("expected stack slot kind")?;
1572 let dt = self.match_dt("expected dynamic type")?;
1573 let data = DynamicStackSlotData::new(kind, dt);
1574 self.token();
1576 self.claim_gathered_comments(dss);
1577
1578 Ok((dss, data))
1580 }
1581
1582 fn parse_dynamic_type_decl(&mut self) -> ParseResult<(DynamicType, DynamicTypeData)> {
1583 let dt = self.match_dt("expected dynamic type number: dt«n»")?;
1584 self.match_token(Token::Equal, "expected '=' in stack slot declaration")?;
1585 let vector_base_ty = self.match_type("expected base type")?;
1586 assert!(vector_base_ty.is_vector(), "expected vector type");
1587 self.match_token(
1588 Token::Multiply,
1589 "expected '*' followed by a dynamic scale value",
1590 )?;
1591 let dyn_scale = self.match_gv("expected dynamic scale global value")?;
1592 let data = DynamicTypeData::new(vector_base_ty, dyn_scale);
1593 self.token();
1595 self.claim_gathered_comments(dt);
1596 Ok((dt, data))
1597 }
1598
1599 fn parse_global_value_decl(&mut self) -> ParseResult<(GlobalValue, GlobalValueData)> {
1609 let gv = self.match_gv("expected global value number: gv«n»")?;
1610
1611 self.match_token(Token::Equal, "expected '=' in global value declaration")?;
1612
1613 let data = match self.match_any_identifier("expected global value kind")? {
1614 "vmctx" => GlobalValueData::VMContext,
1615 "load" => {
1616 self.match_token(
1617 Token::Dot,
1618 "expected '.' followed by type in load global value decl",
1619 )?;
1620 let global_type = self.match_type("expected load type")?;
1621 let flags = self.optional_memflags()?;
1622 let base = self.match_gv("expected global value: gv«n»")?;
1623 let offset = self.optional_offset32()?;
1624
1625 if !(flags.notrap() && flags.aligned()) {
1626 return err!(self.loc, "global-value load must be notrap and aligned");
1627 }
1628 GlobalValueData::Load {
1629 base,
1630 offset,
1631 global_type,
1632 flags,
1633 }
1634 }
1635 "iadd_imm" => {
1636 self.match_token(
1637 Token::Dot,
1638 "expected '.' followed by type in iadd_imm global value decl",
1639 )?;
1640 let global_type = self.match_type("expected iadd type")?;
1641 let base = self.match_gv("expected global value: gv«n»")?;
1642 self.match_token(
1643 Token::Comma,
1644 "expected ',' followed by rhs in iadd_imm global value decl",
1645 )?;
1646 let offset = self.match_imm64("expected iadd_imm immediate")?;
1647 GlobalValueData::IAddImm {
1648 base,
1649 offset,
1650 global_type,
1651 }
1652 }
1653 "symbol" => {
1654 let colocated = self.optional(Token::Identifier("colocated"));
1655 let tls = self.optional(Token::Identifier("tls"));
1656 let name = self.parse_external_name()?;
1657 let offset = self.optional_offset_imm64()?;
1658 GlobalValueData::Symbol {
1659 name,
1660 offset,
1661 colocated,
1662 tls,
1663 }
1664 }
1665 "dyn_scale_target_const" => {
1666 self.match_token(
1667 Token::Dot,
1668 "expected '.' followed by type in dynamic scale global value decl",
1669 )?;
1670 let vector_type = self.match_type("expected load type")?;
1671 assert!(vector_type.is_vector(), "Expected vector type");
1672 GlobalValueData::DynScaleTargetConst { vector_type }
1673 }
1674 other => return err!(self.loc, "Unknown global value kind '{}'", other),
1675 };
1676
1677 self.token();
1679 self.claim_gathered_comments(gv);
1680
1681 Ok((gv, data))
1682 }
1683
1684 fn parse_signature_decl(&mut self) -> ParseResult<(SigRef, Signature)> {
1689 let sig = self.match_sig("expected signature number: sig«n»")?;
1690 self.match_token(Token::Equal, "expected '=' in signature decl")?;
1691 let data = self.parse_signature()?;
1692
1693 self.token();
1695 self.claim_gathered_comments(sig);
1696
1697 Ok((sig, data))
1698 }
1699
1700 fn parse_function_decl(&mut self, ctx: &mut Context) -> ParseResult<(FuncRef, ExtFuncData)> {
1711 let fn_ = self.match_fn("expected function number: fn«n»")?;
1712 self.match_token(Token::Equal, "expected '=' in function decl")?;
1713
1714 let loc = self.loc;
1715
1716 let colocated = self.optional(Token::Identifier("colocated"));
1718 let patchable = self.optional(Token::Identifier("patchable"));
1720
1721 let name = self.parse_external_name()?;
1723
1724 let data = match self.token() {
1726 Some(Token::LPar) => {
1727 let sig = self.parse_signature()?;
1729 let sigref = ctx.function.import_signature(sig);
1730 ctx.map
1731 .def_entity(sigref.into(), loc)
1732 .expect("duplicate SigRef entities created");
1733 ExtFuncData {
1734 name,
1735 signature: sigref,
1736 colocated,
1737 patchable,
1738 }
1739 }
1740 Some(Token::SigRef(sig_src)) => {
1741 let sig = match SigRef::with_number(sig_src) {
1742 None => {
1743 return err!(self.loc, "attempted to use invalid signature ss{}", sig_src);
1744 }
1745 Some(sig) => sig,
1746 };
1747 ctx.check_sig(sig, self.loc)?;
1748 self.consume();
1749 ExtFuncData {
1750 name,
1751 signature: sig,
1752 colocated,
1753 patchable,
1754 }
1755 }
1756 _ => return err!(self.loc, "expected 'function' or sig«n» in function decl"),
1757 };
1758
1759 self.token();
1761 self.claim_gathered_comments(fn_);
1762
1763 Ok((fn_, data))
1764 }
1765
1766 fn parse_jump_table(
1771 &mut self,
1772 ctx: &mut Context,
1773 def: ir::BlockCall,
1774 ) -> ParseResult<ir::JumpTable> {
1775 self.match_token(Token::LBracket, "expected '[' before jump table contents")?;
1776
1777 let mut data = Vec::new();
1778
1779 match self.token() {
1780 Some(Token::Block(dest)) => {
1781 self.consume();
1782 let args = self.parse_opt_block_call_args()?;
1783 data.push(ctx.function.dfg.block_call(dest, &args));
1784
1785 loop {
1786 match self.token() {
1787 Some(Token::Comma) => {
1788 self.consume();
1789 if let Some(Token::Block(dest)) = self.token() {
1790 self.consume();
1791 let args = self.parse_opt_block_call_args()?;
1792 data.push(ctx.function.dfg.block_call(dest, &args));
1793 } else {
1794 return err!(self.loc, "expected jump_table entry");
1795 }
1796 }
1797 Some(Token::RBracket) => break,
1798 _ => return err!(self.loc, "expected ']' after jump table contents"),
1799 }
1800 }
1801 }
1802 Some(Token::RBracket) => (),
1803 _ => return err!(self.loc, "expected jump_table entry"),
1804 }
1805
1806 self.consume();
1807
1808 Ok(ctx
1809 .function
1810 .dfg
1811 .jump_tables
1812 .push(JumpTableData::new(def, &data)))
1813 }
1814
1815 fn parse_exception_table(&mut self, ctx: &mut Context) -> ParseResult<ir::ExceptionTable> {
1822 let sig = self.match_sig("expected signature of called function")?;
1823 self.match_token(Token::Comma, "expected comma after signature argument")?;
1824
1825 let mut handlers = vec![];
1826
1827 let block_num = self.match_block("expected branch destination block")?;
1828 let args = self.parse_opt_block_call_args()?;
1829 let normal_return = ctx.function.dfg.block_call(block_num, &args);
1830
1831 self.match_token(
1832 Token::Comma,
1833 "expected comma after normal-return destination",
1834 )?;
1835
1836 self.match_token(
1837 Token::LBracket,
1838 "expected an open-bracket for exception table list",
1839 )?;
1840 loop {
1841 match self.token() {
1842 Some(Token::RBracket) => {
1843 break;
1844 }
1845 Some(Token::ExceptionTag(tag)) => {
1846 self.consume();
1847 self.match_token(Token::Colon, "expected ':' after exception tag")?;
1848 let tag = ir::ExceptionTag::from_u32(tag);
1849 let block_num = self.match_block("expected branch destination block")?;
1850 let args = self.parse_opt_block_call_args()?;
1851 let block_call = ctx.function.dfg.block_call(block_num, &args);
1852 handlers.push(ir::ExceptionTableItem::Tag(tag, block_call));
1853 }
1854 Some(Token::Identifier("default")) => {
1855 self.consume();
1856 self.match_token(Token::Colon, "expected ':' after 'default'")?;
1857 let block_num = self.match_block("expected branch destination block")?;
1858 let args = self.parse_opt_block_call_args()?;
1859 let block_call = ctx.function.dfg.block_call(block_num, &args);
1860 handlers.push(ir::ExceptionTableItem::Default(block_call));
1861 }
1862 Some(Token::Identifier("context")) => {
1863 self.consume();
1864 let val = self.match_value("expected value for exception-handler context")?;
1865 handlers.push(ir::ExceptionTableItem::Context(val));
1866 }
1867 _ => return err!(self.loc, "invalid token"),
1868 }
1869
1870 if let Some(Token::Comma) = self.token() {
1871 self.consume();
1872 } else {
1873 break;
1874 }
1875 }
1876 self.match_token(Token::RBracket, "expected closing bracket")?;
1877
1878 Ok(ctx
1879 .function
1880 .dfg
1881 .exception_tables
1882 .push(ir::ExceptionTableData::new(sig, normal_return, handlers)))
1883 }
1884
1885 fn parse_constant_decl(&mut self) -> ParseResult<(Constant, ConstantData)> {
1889 let name = self.match_constant()?;
1890 self.match_token(Token::Equal, "expected '=' in constant decl")?;
1891 let data = if let Some(Token::Type(_)) = self.token() {
1892 let ty = self.match_type("expected type of constant")?;
1893 self.match_uimm128(ty)
1894 } else {
1895 self.match_hexadecimal_constant("expected an immediate hexadecimal operand")
1896 }?;
1897
1898 self.token();
1900 self.claim_gathered_comments(name);
1901
1902 Ok((name, data))
1903 }
1904
1905 fn parse_stack_limit_decl(&mut self) -> ParseResult<GlobalValue> {
1909 self.match_stack_limit()?;
1910 self.match_token(Token::Equal, "expected '=' in stack limit decl")?;
1911 let limit = match self.token() {
1912 Some(Token::GlobalValue(base_num)) => match GlobalValue::with_number(base_num) {
1913 Some(gv) => gv,
1914 None => return err!(self.loc, "invalid global value number for stack limit"),
1915 },
1916 _ => return err!(self.loc, "expected global value"),
1917 };
1918 self.consume();
1919
1920 self.token();
1922 self.claim_gathered_comments(AnyEntity::StackLimit);
1923
1924 Ok(limit)
1925 }
1926
1927 fn parse_function_body(&mut self, ctx: &mut Context) -> ParseResult<()> {
1932 while self.token() != Some(Token::RBrace) {
1933 self.parse_basic_block(ctx)?;
1934 }
1935
1936 for block in &ctx.function.layout {
1939 for inst in ctx.function.layout.block_insts(block) {
1940 for value in ctx.function.dfg.inst_values(inst) {
1941 if !ctx.map.contains_value(value) {
1942 return err!(
1943 ctx.map.location(AnyEntity::Inst(inst)).unwrap(),
1944 "undefined operand value {}",
1945 value
1946 );
1947 }
1948 }
1949 }
1950 }
1951
1952 for alias in &ctx.aliases {
1953 if !ctx.function.dfg.set_alias_type_for_parser(*alias) {
1954 let loc = ctx.map.location(AnyEntity::Value(*alias)).unwrap();
1955 return err!(loc, "alias cycle involving {}", alias);
1956 }
1957 }
1958
1959 Ok(())
1960 }
1961
1962 fn parse_basic_block(&mut self, ctx: &mut Context) -> ParseResult<()> {
1969 self.start_gathering_comments();
1971
1972 let block_num = self.match_block("expected block header")?;
1973 let block = ctx.add_block(block_num, self.loc)?;
1974
1975 if block_num.as_u32() >= MAX_BLOCKS_IN_A_FUNCTION {
1976 return Err(self.error("too many blocks"));
1977 }
1978
1979 if self.token() == Some(Token::LPar) {
1980 self.parse_block_params(ctx, block)?;
1981 }
1982
1983 if self.optional(Token::Cold) {
1984 ctx.set_cold_block(block);
1985 }
1986
1987 self.match_token(Token::Colon, "expected ':' after block parameters")?;
1988
1989 self.token();
1991 self.claim_gathered_comments(block);
1992
1993 while match self.token() {
1995 Some(Token::Value(_))
1996 | Some(Token::Identifier(_))
1997 | Some(Token::LBracket)
1998 | Some(Token::SourceLoc(_))
1999 | Some(Token::LAngle) => true,
2000 _ => false,
2001 } {
2002 let srcloc = self.optional_srcloc()?;
2003
2004 let debug_tags = self.optional_debug_tags()?;
2005
2006 let results = self.parse_inst_results()?;
2011
2012 for result in &results {
2013 while ctx.function.dfg.num_values() <= result.index() {
2014 ctx.function.dfg.make_invalid_value_for_parser();
2015 }
2016 }
2017
2018 match self.token() {
2019 Some(Token::Arrow) => {
2020 self.consume();
2021 self.parse_value_alias(&results, ctx)?;
2022 }
2023 Some(Token::Equal) => {
2024 self.consume();
2025 self.parse_instruction(&results, srcloc, debug_tags, ctx, block)?;
2026 }
2027 _ if !results.is_empty() => return err!(self.loc, "expected -> or ="),
2028 _ => self.parse_instruction(&results, srcloc, debug_tags, ctx, block)?,
2029 }
2030 }
2031
2032 Ok(())
2033 }
2034
2035 fn parse_block_params(&mut self, ctx: &mut Context, block: Block) -> ParseResult<()> {
2039 self.match_token(Token::LPar, "expected '(' before block parameters")?;
2041
2042 if self.token() == Some(Token::RPar) {
2044 self.consume();
2045 return Ok(());
2046 }
2047
2048 self.parse_block_param(ctx, block)?;
2050
2051 while self.optional(Token::Comma) {
2053 self.parse_block_param(ctx, block)?;
2055 }
2056
2057 self.match_token(Token::RPar, "expected ')' after block parameters")?;
2059
2060 Ok(())
2061 }
2062
2063 fn parse_block_param(&mut self, ctx: &mut Context, block: Block) -> ParseResult<()> {
2069 let v = self.match_value("block argument must be a value")?;
2071 let v_location = self.loc;
2072 self.match_token(Token::Colon, "expected ':' after block argument")?;
2073 while ctx.function.dfg.num_values() <= v.index() {
2075 ctx.function.dfg.make_invalid_value_for_parser();
2076 }
2077
2078 let t = self.match_type("expected block argument type")?;
2079 ctx.function.dfg.append_block_param_for_parser(block, t, v);
2081 ctx.map.def_value(v, v_location)?;
2082
2083 Ok(())
2084 }
2085
2086 fn parse_inst_results(&mut self) -> ParseResult<SmallVec<[Value; 1]>> {
2091 let mut results = SmallVec::new();
2093
2094 if let Some(Token::Value(v)) = self.token() {
2097 self.consume();
2098
2099 results.push(v);
2100
2101 while self.optional(Token::Comma) {
2103 let v = self.match_value("expected result value")?;
2105 results.push(v);
2106 }
2107 }
2108
2109 Ok(results)
2110 }
2111
2112 fn parse_value_alias(&mut self, results: &[Value], ctx: &mut Context) -> ParseResult<()> {
2117 if results.len() != 1 {
2118 return err!(self.loc, "wrong number of aliases");
2119 }
2120 let result = results[0];
2121 let dest = self.match_value("expected value alias")?;
2122
2123 if ctx.map.contains_value(result) {
2125 if let Some(old) = ctx.function.dfg.value_alias_dest_for_serialization(result) {
2126 if old != dest {
2127 return err!(
2128 self.loc,
2129 "value {} is already defined as an alias with destination {}",
2130 result,
2131 old
2132 );
2133 }
2134 } else {
2135 return err!(self.loc, "value {} is already defined");
2136 }
2137 } else {
2138 ctx.map.def_value(result, self.loc)?;
2139 }
2140
2141 if !ctx.map.contains_value(dest) {
2142 return err!(self.loc, "value {} is not yet defined", dest);
2143 }
2144
2145 ctx.function
2146 .dfg
2147 .make_value_alias_for_serialization(dest, result);
2148
2149 ctx.aliases.push(result);
2150 Ok(())
2151 }
2152
2153 fn parse_instruction(
2158 &mut self,
2159 results: &[Value],
2160 srcloc: ir::SourceLoc,
2161 debug_tags: Vec<DebugTag>,
2162 ctx: &mut Context,
2163 block: Block,
2164 ) -> ParseResult<()> {
2165 for val in results {
2167 ctx.map.def_value(*val, self.loc)?;
2168 }
2169
2170 self.start_gathering_comments();
2172
2173 let opcode = if let Some(Token::Identifier(text)) = self.token() {
2175 match text.parse() {
2176 Ok(opc) => opc,
2177 Err(msg) => return err!(self.loc, "{}: '{}'", msg, text),
2178 }
2179 } else {
2180 return err!(self.loc, "expected instruction opcode");
2181 };
2182 let opcode_loc = self.loc;
2183 self.consume();
2184
2185 let explicit_ctrl_type = if self.optional(Token::Dot) {
2188 if let Some(Token::Type(_t)) = self.token() {
2189 Some(self.match_type("expected type after 'opcode.'")?)
2190 } else {
2191 let dt = self.match_dt("expected dynamic type")?;
2192 self.concrete_from_dt(dt, ctx)
2193 }
2194 } else {
2195 None
2196 };
2197
2198 let inst_data = self.parse_inst_operands(ctx, opcode, explicit_ctrl_type)?;
2200
2201 let ctrl_typevar = self.infer_typevar(ctx, opcode, explicit_ctrl_type, &inst_data)?;
2202 let inst = ctx.function.dfg.make_inst(inst_data);
2203
2204 if self.optional(Token::Comma) {
2206 self.match_token(
2207 Token::Identifier("stack_map"),
2208 "expected `stack_map = [...]`",
2209 )?;
2210 if !opcode.is_call() || opcode.is_return() {
2211 return err!(
2212 self.loc,
2213 "stack map can only be attached to a (non-tail) call"
2214 );
2215 }
2216
2217 self.match_token(Token::Equal, "expected `= [...]`")?;
2218 self.match_token(Token::LBracket, "expected `[...]`")?;
2219 while !self.optional(Token::RBracket) {
2220 let ty = self.match_type("expected `<type> @ <slot> + <offset>`")?;
2221 self.match_token(Token::At, "expected `@ <slot> + <offset>`")?;
2222 let slot = self.match_ss("expected `<slot> + <offset>`")?;
2223 let offset: u32 = match self.token() {
2224 Some(Token::Integer(s)) if s.starts_with('+') => {
2225 self.match_uimm32("expected a u32 offset")?.into()
2226 }
2227 _ => {
2228 self.match_token(Token::Plus, "expected `+ <offset>`")?;
2229 self.match_uimm32("expected a u32 offset")?.into()
2230 }
2231 };
2232 ctx.function
2233 .dfg
2234 .append_user_stack_map_entry(inst, ir::UserStackMapEntry { ty, slot, offset });
2235 if !self.optional(Token::Comma) {
2236 self.match_token(Token::RBracket, "expected `,` or `]`")?;
2237 break;
2238 }
2239 }
2240 }
2241
2242 let num_results =
2249 ctx.function
2250 .dfg
2251 .make_inst_results_for_parser(inst, ctrl_typevar, results);
2252 ctx.function.layout.append_inst(inst, block);
2253 ctx.map
2254 .def_entity(inst.into(), opcode_loc)
2255 .expect("duplicate inst references created");
2256
2257 if !srcloc.is_default() {
2258 ctx.function.set_srcloc(inst, srcloc);
2259 }
2260 if !debug_tags.is_empty() {
2261 ctx.function.debug_tags.set(inst, debug_tags);
2262 }
2263
2264 if results.len() != num_results {
2265 return err!(
2266 self.loc,
2267 "instruction produces {} result values, {} given",
2268 num_results,
2269 results.len()
2270 );
2271 }
2272
2273 self.token();
2275 self.claim_gathered_comments(inst);
2276
2277 Ok(())
2278 }
2279
2280 fn infer_typevar(
2288 &self,
2289 ctx: &Context,
2290 opcode: Opcode,
2291 explicit_ctrl_type: Option<Type>,
2292 inst_data: &InstructionData,
2293 ) -> ParseResult<Type> {
2294 let constraints = opcode.constraints();
2295 let ctrl_type = match explicit_ctrl_type {
2296 Some(t) => t,
2297 None => {
2298 if constraints.use_typevar_operand() {
2299 let ctrl_src_value = inst_data
2306 .typevar_operand(&ctx.function.dfg.value_lists)
2307 .expect("Constraints <-> Format inconsistency");
2308 if !ctx.map.contains_value(ctrl_src_value) {
2309 return err!(
2310 self.loc,
2311 "type variable required for polymorphic opcode, e.g. '{}.{}'; \
2312 can't infer from {} which is not yet defined",
2313 opcode,
2314 constraints.ctrl_typeset().unwrap().example(),
2315 ctrl_src_value
2316 );
2317 }
2318 if !ctx.function.dfg.value_is_valid_for_parser(ctrl_src_value) {
2319 return err!(
2320 self.loc,
2321 "type variable required for polymorphic opcode, e.g. '{}.{}'; \
2322 can't infer from {} which is not yet resolved",
2323 opcode,
2324 constraints.ctrl_typeset().unwrap().example(),
2325 ctrl_src_value
2326 );
2327 }
2328 ctx.function.dfg.value_type(ctrl_src_value)
2329 } else if constraints.is_polymorphic() {
2330 return err!(
2333 self.loc,
2334 "type variable required for polymorphic opcode, e.g. '{}.{}'",
2335 opcode,
2336 constraints.ctrl_typeset().unwrap().example()
2337 );
2338 } else {
2339 INVALID
2341 }
2342 }
2343 };
2344
2345 if let Some(typeset) = constraints.ctrl_typeset() {
2349 if !typeset.contains(ctrl_type) {
2351 return err!(
2352 self.loc,
2353 "{} is not a valid typevar for {}",
2354 ctrl_type,
2355 opcode
2356 );
2357 }
2358 } else if ctrl_type != INVALID {
2360 return err!(self.loc, "{} does not take a typevar", opcode);
2361 }
2362
2363 Ok(ctrl_type)
2364 }
2365
2366 fn parse_value_list(&mut self) -> ParseResult<VariableArgs> {
2371 let mut args = VariableArgs::new();
2372
2373 if let Some(Token::Value(v)) = self.token() {
2374 args.push(v);
2375 self.consume();
2376 } else {
2377 return Ok(args);
2378 }
2379
2380 while self.optional(Token::Comma) {
2381 args.push(self.match_value("expected value in argument list")?);
2382 }
2383
2384 Ok(args)
2385 }
2386
2387 fn parse_opt_block_call_args(&mut self) -> ParseResult<Vec<BlockArg>> {
2390 if !self.optional(Token::LPar) {
2391 return Ok(vec![]);
2392 }
2393
2394 let mut args = vec![];
2395 while self.token() != Some(Token::RPar) {
2396 args.push(self.parse_block_call_arg()?);
2397 if self.token() == Some(Token::Comma) {
2398 self.consume();
2399 } else {
2400 break;
2401 }
2402 }
2403
2404 self.match_token(Token::RPar, "expected ')' after arguments")?;
2405
2406 Ok(args)
2407 }
2408
2409 fn parse_block_call_arg(&mut self) -> ParseResult<BlockArg> {
2410 match self.token() {
2411 Some(Token::Value(v)) => {
2412 self.consume();
2413 Ok(BlockArg::Value(v))
2414 }
2415 Some(Token::TryCallRet(i)) => {
2416 self.consume();
2417 Ok(BlockArg::TryCallRet(i))
2418 }
2419 Some(Token::TryCallExn(i)) => {
2420 self.consume();
2421 Ok(BlockArg::TryCallExn(i))
2422 }
2423 tok => Err(self.error(&format!("unexpected token: {tok:?}"))),
2424 }
2425 }
2426
2427 fn parse_run_command(&mut self, sig: &Signature) -> ParseResult<RunCommand> {
2432 match self.token() {
2434 Some(Token::Identifier("run")) => {
2435 self.consume();
2436 if self.optional(Token::Colon) {
2437 let invocation = self.parse_run_invocation(sig)?;
2438 let comparison = self.parse_run_comparison()?;
2439 let expected = self.parse_run_returns(sig)?;
2440 Ok(RunCommand::Run(invocation, comparison, expected))
2441 } else if sig.params.is_empty()
2442 && sig.returns.len() == 1
2443 && sig.returns[0].value_type.is_int()
2444 {
2445 let invocation = Invocation::new("default", vec![]);
2449 let expected = vec![DataValue::I8(0)];
2450 let comparison = Comparison::NotEquals;
2451 Ok(RunCommand::Run(invocation, comparison, expected))
2452 } else {
2453 Err(self.error("unable to parse the run command"))
2454 }
2455 }
2456 Some(Token::Identifier("print")) => {
2457 self.consume();
2458 if self.optional(Token::Colon) {
2459 Ok(RunCommand::Print(self.parse_run_invocation(sig)?))
2460 } else if sig.params.is_empty() {
2461 let invocation = Invocation::new("default", vec![]);
2463 Ok(RunCommand::Print(invocation))
2464 } else {
2465 Err(self.error("unable to parse the print command"))
2466 }
2467 }
2468 _ => Err(self.error("expected a 'run:' or 'print:' command")),
2469 }
2470 }
2471
2472 fn parse_run_invocation(&mut self, sig: &Signature) -> ParseResult<Invocation> {
2479 if let Some(Token::Name(name)) = self.token() {
2480 self.consume();
2481 self.match_token(
2482 Token::LPar,
2483 "expected invocation parentheses, e.g. %fn(...)",
2484 )?;
2485
2486 let arg_types = sig
2487 .params
2488 .iter()
2489 .map(|abi| abi.value_type)
2490 .collect::<Vec<_>>();
2491 let args = self.parse_data_value_list(&arg_types)?;
2492
2493 self.match_token(
2494 Token::RPar,
2495 "expected invocation parentheses, e.g. %fn(...)",
2496 )?;
2497 Ok(Invocation::new(name, args))
2498 } else {
2499 Err(self.error("expected a function name, e.g. %my_fn"))
2500 }
2501 }
2502
2503 fn parse_run_comparison(&mut self) -> ParseResult<Comparison> {
2507 if self.optional(Token::Equal) {
2508 self.match_token(Token::Equal, "expected another =")?;
2509 Ok(Comparison::Equals)
2510 } else if self.optional(Token::Bang) {
2511 self.match_token(Token::Equal, "expected a =")?;
2512 Ok(Comparison::NotEquals)
2513 } else {
2514 Err(self.error("unable to parse a valid comparison operator"))
2515 }
2516 }
2517
2518 fn parse_run_returns(&mut self, sig: &Signature) -> ParseResult<Vec<DataValue>> {
2524 if sig.returns.len() != 1 {
2525 self.match_token(Token::LBracket, "expected a left bracket [")?;
2526 }
2527
2528 let returns = self
2529 .parse_data_value_list(&sig.returns.iter().map(|a| a.value_type).collect::<Vec<_>>())?;
2530
2531 if sig.returns.len() != 1 {
2532 self.match_token(Token::RBracket, "expected a right bracket ]")?;
2533 }
2534 Ok(returns)
2535 }
2536
2537 fn parse_data_value_list(&mut self, types: &[Type]) -> ParseResult<Vec<DataValue>> {
2541 let mut values = vec![];
2542 for ty in types.iter().take(1) {
2543 values.push(self.parse_data_value(*ty)?);
2544 }
2545 for ty in types.iter().skip(1) {
2546 self.match_token(
2547 Token::Comma,
2548 "expected a comma between invocation arguments",
2549 )?;
2550 values.push(self.parse_data_value(*ty)?);
2551 }
2552 Ok(values)
2553 }
2554
2555 fn parse_data_value(&mut self, ty: Type) -> ParseResult<DataValue> {
2559 let dv = match ty {
2560 I8 => DataValue::from(self.match_imm8("expected a i8")?),
2561 I16 => DataValue::from(self.match_imm16("expected an i16")?),
2562 I32 => DataValue::from(self.match_imm32("expected an i32")?),
2563 I64 => DataValue::from(Into::<i64>::into(self.match_imm64("expected an i64")?)),
2564 I128 => DataValue::from(self.match_imm128("expected an i128")?),
2565 F16 => DataValue::from(self.match_ieee16("expected an f16")?),
2566 F32 => DataValue::from(self.match_ieee32("expected an f32")?),
2567 F64 => DataValue::from(self.match_ieee64("expected an f64")?),
2568 F128 => DataValue::from(self.match_ieee128("expected an f128")?),
2569 _ if (ty.is_vector() || ty.is_dynamic_vector()) => {
2570 let as_vec = self.match_uimm128(ty)?.into_vec();
2571 let slice = as_vec.as_slice();
2572 match slice.len() {
2573 16 => DataValue::V128(slice.try_into().unwrap()),
2574 8 => DataValue::V64(slice.try_into().unwrap()),
2575 4 => DataValue::V32(slice.try_into().unwrap()),
2576 2 => DataValue::V16(slice.try_into().unwrap()),
2577 _ => {
2578 return Err(
2579 self.error("vectors larger than 128 bits are not currently supported")
2580 );
2581 }
2582 }
2583 }
2584 _ => return Err(self.error(&format!("don't know how to parse data values of: {ty}"))),
2585 };
2586 Ok(dv)
2587 }
2588
2589 fn parse_inst_operands(
2592 &mut self,
2593 ctx: &mut Context,
2594 opcode: Opcode,
2595 explicit_control_type: Option<Type>,
2596 ) -> ParseResult<InstructionData> {
2597 let idata = match opcode.format() {
2598 InstructionFormat::Unary => InstructionData::Unary {
2599 opcode,
2600 arg: self.match_value("expected SSA value operand")?,
2601 },
2602 InstructionFormat::UnaryImm => {
2603 let msg = |bits| format!("expected immediate {bits}-bit integer operand");
2604 let unsigned = match explicit_control_type {
2605 Some(types::I8) => self.match_imm8(&msg(8))? as u8 as i64,
2606 Some(types::I16) => self.match_imm16(&msg(16))? as u16 as i64,
2607 Some(types::I32) => self.match_imm32(&msg(32))? as u32 as i64,
2608 Some(types::I64) => self.match_imm64(&msg(64))?.bits(),
2609 _ => {
2610 return err!(
2611 self.loc,
2612 "expected one of the following type: i8, i16, i32 or i64"
2613 );
2614 }
2615 };
2616 InstructionData::UnaryImm {
2617 opcode,
2618 imm: Imm64::new(unsigned),
2619 }
2620 }
2621 InstructionFormat::UnaryIeee16 => InstructionData::UnaryIeee16 {
2622 opcode,
2623 imm: self.match_ieee16("expected immediate 16-bit float operand")?,
2624 },
2625 InstructionFormat::UnaryIeee32 => InstructionData::UnaryIeee32 {
2626 opcode,
2627 imm: self.match_ieee32("expected immediate 32-bit float operand")?,
2628 },
2629 InstructionFormat::UnaryIeee64 => InstructionData::UnaryIeee64 {
2630 opcode,
2631 imm: self.match_ieee64("expected immediate 64-bit float operand")?,
2632 },
2633 InstructionFormat::UnaryConst => {
2634 let constant_handle = if let Some(Token::Constant(_)) = self.token() {
2635 let c = self.match_constant()?;
2637 ctx.check_constant(c, self.loc)?;
2638 c
2639 } else if opcode == Opcode::F128const {
2640 let ieee128 = self.match_ieee128("expected immediate 128-bit float operand")?;
2641 ctx.function.dfg.constants.insert(ieee128.into())
2642 } else if let Some(controlling_type) = explicit_control_type {
2643 let uimm128 = self.match_uimm128(controlling_type)?;
2646 ctx.function.dfg.constants.insert(uimm128)
2647 } else {
2648 return err!(
2649 self.loc,
2650 "Expected either a const entity or a typed value, e.g. inst.i32x4 [...]"
2651 );
2652 };
2653 InstructionData::UnaryConst {
2654 opcode,
2655 constant_handle,
2656 }
2657 }
2658 InstructionFormat::UnaryGlobalValue => {
2659 let gv = self.match_gv("expected global value")?;
2660 ctx.check_gv(gv, self.loc)?;
2661 InstructionData::UnaryGlobalValue {
2662 opcode,
2663 global_value: gv,
2664 }
2665 }
2666 InstructionFormat::Binary => {
2667 let lhs = self.match_value("expected SSA value first operand")?;
2668 self.match_token(Token::Comma, "expected ',' between operands")?;
2669 let rhs = self.match_value("expected SSA value second operand")?;
2670 InstructionData::Binary {
2671 opcode,
2672 args: [lhs, rhs],
2673 }
2674 }
2675 InstructionFormat::BinaryImm8 => {
2676 let arg = self.match_value("expected SSA value first operand")?;
2677 self.match_token(Token::Comma, "expected ',' between operands")?;
2678 let imm = self.match_uimm8("expected unsigned 8-bit immediate")?;
2679 InstructionData::BinaryImm8 { opcode, arg, imm }
2680 }
2681 InstructionFormat::BinaryImm64 => {
2682 let lhs = self.match_value("expected SSA value first operand")?;
2683 self.match_token(Token::Comma, "expected ',' between operands")?;
2684 let rhs = self.match_imm64("expected immediate integer second operand")?;
2685 InstructionData::BinaryImm64 {
2686 opcode,
2687 arg: lhs,
2688 imm: rhs,
2689 }
2690 }
2691 InstructionFormat::Ternary => {
2692 let ctrl_arg = self.match_value("expected SSA value control operand")?;
2695 self.match_token(Token::Comma, "expected ',' between operands")?;
2696 let true_arg = self.match_value("expected SSA value true operand")?;
2697 self.match_token(Token::Comma, "expected ',' between operands")?;
2698 let false_arg = self.match_value("expected SSA value false operand")?;
2699 InstructionData::Ternary {
2700 opcode,
2701 args: [ctrl_arg, true_arg, false_arg],
2702 }
2703 }
2704 InstructionFormat::MultiAry => {
2705 let args = self.parse_value_list()?;
2706 InstructionData::MultiAry {
2707 opcode,
2708 args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists),
2709 }
2710 }
2711 InstructionFormat::NullAry => InstructionData::NullAry { opcode },
2712 InstructionFormat::Jump => {
2713 let block_num = self.match_block("expected jump destination block")?;
2715 let args = self.parse_opt_block_call_args()?;
2716 let destination = ctx.function.dfg.block_call(block_num, &args);
2717 InstructionData::Jump {
2718 opcode,
2719 destination,
2720 }
2721 }
2722 InstructionFormat::Brif => {
2723 let arg = self.match_value("expected SSA value control operand")?;
2724 self.match_token(Token::Comma, "expected ',' between operands")?;
2725 let block_then = {
2726 let block_num = self.match_block("expected branch then block")?;
2727 let args = self.parse_opt_block_call_args()?;
2728 ctx.function.dfg.block_call(block_num, &args)
2729 };
2730 self.match_token(Token::Comma, "expected ',' between operands")?;
2731 let block_else = {
2732 let block_num = self.match_block("expected branch else block")?;
2733 let args = self.parse_opt_block_call_args()?;
2734 ctx.function.dfg.block_call(block_num, &args)
2735 };
2736 InstructionData::Brif {
2737 opcode,
2738 arg,
2739 blocks: [block_then, block_else],
2740 }
2741 }
2742 InstructionFormat::BranchTable => {
2743 let arg = self.match_value("expected SSA value operand")?;
2744 self.match_token(Token::Comma, "expected ',' between operands")?;
2745 let block_num = self.match_block("expected branch destination block")?;
2746 let args = self.parse_opt_block_call_args()?;
2747 let destination = ctx.function.dfg.block_call(block_num, &args);
2748 self.match_token(Token::Comma, "expected ',' between operands")?;
2749 let table = self.parse_jump_table(ctx, destination)?;
2750 InstructionData::BranchTable { opcode, arg, table }
2751 }
2752 InstructionFormat::TernaryImm8 => {
2753 let lhs = self.match_value("expected SSA value first operand")?;
2754 self.match_token(Token::Comma, "expected ',' between operands")?;
2755 let rhs = self.match_value("expected SSA value last operand")?;
2756 self.match_token(Token::Comma, "expected ',' between operands")?;
2757 let imm = self.match_uimm8("expected 8-bit immediate")?;
2758 InstructionData::TernaryImm8 {
2759 opcode,
2760 imm,
2761 args: [lhs, rhs],
2762 }
2763 }
2764 InstructionFormat::Shuffle => {
2765 let a = self.match_value("expected SSA value first operand")?;
2766 self.match_token(Token::Comma, "expected ',' between operands")?;
2767 let b = self.match_value("expected SSA value second operand")?;
2768 self.match_token(Token::Comma, "expected ',' between operands")?;
2769 let uimm128 = self.match_uimm128(I8X16)?;
2770 let imm = ctx.function.dfg.immediates.push(uimm128);
2771 InstructionData::Shuffle {
2772 opcode,
2773 imm,
2774 args: [a, b],
2775 }
2776 }
2777 InstructionFormat::IntCompare => {
2778 let cond = self.match_enum("expected intcc condition code")?;
2779 let lhs = self.match_value("expected SSA value first operand")?;
2780 self.match_token(Token::Comma, "expected ',' between operands")?;
2781 let rhs = self.match_value("expected SSA value second operand")?;
2782 InstructionData::IntCompare {
2783 opcode,
2784 cond,
2785 args: [lhs, rhs],
2786 }
2787 }
2788 InstructionFormat::IntCompareImm => {
2789 let cond = self.match_enum("expected intcc condition code")?;
2790 let lhs = self.match_value("expected SSA value first operand")?;
2791 self.match_token(Token::Comma, "expected ',' between operands")?;
2792 let rhs = self.match_imm64("expected immediate second operand")?;
2793 InstructionData::IntCompareImm {
2794 opcode,
2795 cond,
2796 arg: lhs,
2797 imm: rhs,
2798 }
2799 }
2800 InstructionFormat::FloatCompare => {
2801 let cond = self.match_enum("expected floatcc condition code")?;
2802 let lhs = self.match_value("expected SSA value first operand")?;
2803 self.match_token(Token::Comma, "expected ',' between operands")?;
2804 let rhs = self.match_value("expected SSA value second operand")?;
2805 InstructionData::FloatCompare {
2806 opcode,
2807 cond,
2808 args: [lhs, rhs],
2809 }
2810 }
2811 InstructionFormat::Call => {
2812 let func_ref = self.match_fn("expected function reference")?;
2813 ctx.check_fn(func_ref, self.loc)?;
2814 self.match_token(Token::LPar, "expected '(' before arguments")?;
2815 let args = self.parse_value_list()?;
2816 self.match_token(Token::RPar, "expected ')' after arguments")?;
2817 InstructionData::Call {
2818 opcode,
2819 func_ref,
2820 args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists),
2821 }
2822 }
2823 InstructionFormat::CallIndirect => {
2824 let sig_ref = self.match_sig("expected signature reference")?;
2825 ctx.check_sig(sig_ref, self.loc)?;
2826 self.match_token(Token::Comma, "expected ',' between operands")?;
2827 let callee = self.match_value("expected SSA value callee operand")?;
2828 self.match_token(Token::LPar, "expected '(' before arguments")?;
2829 let args = self.parse_value_list()?;
2830 self.match_token(Token::RPar, "expected ')' after arguments")?;
2831 InstructionData::CallIndirect {
2832 opcode,
2833 sig_ref,
2834 args: args.into_value_list(&[callee], &mut ctx.function.dfg.value_lists),
2835 }
2836 }
2837 InstructionFormat::TryCall => {
2838 let func_ref = self.match_fn("expected function reference")?;
2839 ctx.check_fn(func_ref, self.loc)?;
2840 self.match_token(Token::LPar, "expected '(' before arguments")?;
2841 let args = self.parse_value_list()?;
2842 self.match_token(Token::RPar, "expected ')' after arguments")?;
2843 self.match_token(Token::Comma, "expected ',' after argument list")?;
2844 let exception = self.parse_exception_table(ctx)?;
2845 InstructionData::TryCall {
2846 opcode,
2847 func_ref,
2848 args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists),
2849 exception,
2850 }
2851 }
2852 InstructionFormat::TryCallIndirect => {
2853 let callee = self.match_value("expected SSA value callee operand")?;
2854 self.match_token(Token::LPar, "expected '(' before arguments")?;
2855 let args = self.parse_value_list()?;
2856 self.match_token(Token::RPar, "expected ')' after arguments")?;
2857 self.match_token(Token::Comma, "expected ',' after argument list")?;
2858 let exception = self.parse_exception_table(ctx)?;
2859 InstructionData::TryCallIndirect {
2860 opcode,
2861 args: args.into_value_list(&[callee], &mut ctx.function.dfg.value_lists),
2862 exception,
2863 }
2864 }
2865 InstructionFormat::FuncAddr => {
2866 let func_ref = self.match_fn("expected function reference")?;
2867 ctx.check_fn(func_ref, self.loc)?;
2868 InstructionData::FuncAddr { opcode, func_ref }
2869 }
2870 InstructionFormat::StackLoad => {
2871 let ss = self.match_ss("expected stack slot number: ss«n»")?;
2872 ctx.check_ss(ss, self.loc)?;
2873 let offset = self.optional_offset32()?;
2874 InstructionData::StackLoad {
2875 opcode,
2876 stack_slot: ss,
2877 offset,
2878 }
2879 }
2880 InstructionFormat::StackStore => {
2881 let arg = self.match_value("expected SSA value operand")?;
2882 self.match_token(Token::Comma, "expected ',' between operands")?;
2883 let ss = self.match_ss("expected stack slot number: ss«n»")?;
2884 ctx.check_ss(ss, self.loc)?;
2885 let offset = self.optional_offset32()?;
2886 InstructionData::StackStore {
2887 opcode,
2888 arg,
2889 stack_slot: ss,
2890 offset,
2891 }
2892 }
2893 InstructionFormat::DynamicStackLoad => {
2894 let dss = self.match_dss("expected dynamic stack slot number: dss«n»")?;
2895 ctx.check_dss(dss, self.loc)?;
2896 InstructionData::DynamicStackLoad {
2897 opcode,
2898 dynamic_stack_slot: dss,
2899 }
2900 }
2901 InstructionFormat::DynamicStackStore => {
2902 let arg = self.match_value("expected SSA value operand")?;
2903 self.match_token(Token::Comma, "expected ',' between operands")?;
2904 let dss = self.match_dss("expected dynamic stack slot number: dss«n»")?;
2905 ctx.check_dss(dss, self.loc)?;
2906 InstructionData::DynamicStackStore {
2907 opcode,
2908 arg,
2909 dynamic_stack_slot: dss,
2910 }
2911 }
2912 InstructionFormat::Load => {
2913 let flags = self.optional_memflags()?;
2914 let addr = self.match_value("expected SSA value address")?;
2915 let offset = self.optional_offset32()?;
2916 InstructionData::Load {
2917 opcode,
2918 flags,
2919 arg: addr,
2920 offset,
2921 }
2922 }
2923 InstructionFormat::Store => {
2924 let flags = self.optional_memflags()?;
2925 let arg = self.match_value("expected SSA value operand")?;
2926 self.match_token(Token::Comma, "expected ',' between operands")?;
2927 let addr = self.match_value("expected SSA value address")?;
2928 let offset = self.optional_offset32()?;
2929 InstructionData::Store {
2930 opcode,
2931 flags,
2932 args: [arg, addr],
2933 offset,
2934 }
2935 }
2936 InstructionFormat::Trap => {
2937 let code = self.match_enum("expected trap code")?;
2938 InstructionData::Trap { opcode, code }
2939 }
2940 InstructionFormat::CondTrap => {
2941 let arg = self.match_value("expected SSA value operand")?;
2942 self.match_token(Token::Comma, "expected ',' between operands")?;
2943 let code = self.match_enum("expected trap code")?;
2944 InstructionData::CondTrap { opcode, arg, code }
2945 }
2946 InstructionFormat::AtomicCas => {
2947 let flags = self.optional_memflags()?;
2948 let addr = self.match_value("expected SSA value address")?;
2949 self.match_token(Token::Comma, "expected ',' between operands")?;
2950 let expected = self.match_value("expected SSA value address")?;
2951 self.match_token(Token::Comma, "expected ',' between operands")?;
2952 let replacement = self.match_value("expected SSA value address")?;
2953 InstructionData::AtomicCas {
2954 opcode,
2955 flags,
2956 args: [addr, expected, replacement],
2957 }
2958 }
2959 InstructionFormat::AtomicRmw => {
2960 let flags = self.optional_memflags()?;
2961 let op = self.match_enum("expected AtomicRmwOp")?;
2962 let addr = self.match_value("expected SSA value address")?;
2963 self.match_token(Token::Comma, "expected ',' between operands")?;
2964 let arg2 = self.match_value("expected SSA value address")?;
2965 InstructionData::AtomicRmw {
2966 opcode,
2967 flags,
2968 op,
2969 args: [addr, arg2],
2970 }
2971 }
2972 InstructionFormat::LoadNoOffset => {
2973 let flags = self.optional_memflags()?;
2974 let addr = self.match_value("expected SSA value address")?;
2975 InstructionData::LoadNoOffset {
2976 opcode,
2977 flags,
2978 arg: addr,
2979 }
2980 }
2981 InstructionFormat::StoreNoOffset => {
2982 let flags = self.optional_memflags()?;
2983 let arg = self.match_value("expected SSA value operand")?;
2984 self.match_token(Token::Comma, "expected ',' between operands")?;
2985 let addr = self.match_value("expected SSA value address")?;
2986 InstructionData::StoreNoOffset {
2987 opcode,
2988 flags,
2989 args: [arg, addr],
2990 }
2991 }
2992 InstructionFormat::IntAddTrap => {
2993 let a = self.match_value("expected SSA value operand")?;
2994 self.match_token(Token::Comma, "expected ',' between operands")?;
2995 let b = self.match_value("expected SSA value operand")?;
2996 self.match_token(Token::Comma, "expected ',' between operands")?;
2997 let code = self.match_enum("expected trap code")?;
2998 InstructionData::IntAddTrap {
2999 opcode,
3000 args: [a, b],
3001 code,
3002 }
3003 }
3004 InstructionFormat::ExceptionHandlerAddress => {
3005 let block = self.match_block("expected block")?;
3006 self.match_token(Token::Comma, "expected ',' between operands")?;
3007 let imm = self.match_imm64("expected immediate handler index")?;
3008 InstructionData::ExceptionHandlerAddress { opcode, block, imm }
3009 }
3010 };
3011 Ok(idata)
3012 }
3013}
3014
3015#[cfg(test)]
3016mod tests {
3017 use super::*;
3018 use crate::isaspec::IsaSpec;
3019
3020 #[test]
3021 fn argument_type() {
3022 let mut p = Parser::new("i32 sext");
3023 let arg = p.parse_abi_param().unwrap();
3024 assert_eq!(arg.value_type, types::I32);
3025 assert_eq!(arg.extension, ArgumentExtension::Sext);
3026 assert_eq!(arg.purpose, ArgumentPurpose::Normal);
3027 let ParseError {
3028 location,
3029 message,
3030 is_warning,
3031 } = p.parse_abi_param().unwrap_err();
3032 assert_eq!(location.line_number, 1);
3033 assert_eq!(message, "expected parameter type");
3034 assert!(!is_warning);
3035 }
3036
3037 #[test]
3038 fn aliases() {
3039 let (func, details) = Parser::new(
3040 "function %qux() system_v {
3041 block0:
3042 v4 = iconst.i8 6
3043 v3 -> v4
3044 v1 = iadd_imm v3, 17
3045 }",
3046 )
3047 .parse_function()
3048 .unwrap();
3049 assert_eq!(func.name.to_string(), "%qux");
3050 let v4 = details.map.lookup_str("v4").unwrap();
3051 assert_eq!(v4.to_string(), "v4");
3052 let v3 = details.map.lookup_str("v3").unwrap();
3053 assert_eq!(v3.to_string(), "v3");
3054 match v3 {
3055 AnyEntity::Value(v3) => {
3056 let aliased_to = func.dfg.resolve_aliases(v3);
3057 assert_eq!(aliased_to.to_string(), "v4");
3058 }
3059 _ => panic!("expected value: {v3}"),
3060 }
3061 }
3062
3063 #[test]
3064 fn signature() {
3065 let sig = Parser::new("()system_v").parse_signature().unwrap();
3066 assert_eq!(sig.params.len(), 0);
3067 assert_eq!(sig.returns.len(), 0);
3068 assert_eq!(sig.call_conv, CallConv::SystemV);
3069
3070 let sig2 =
3071 Parser::new("(i8 uext, f16, f32, f64, f128, i32 sret) -> i32 sext, f64 system_v")
3072 .parse_signature()
3073 .unwrap();
3074 assert_eq!(
3075 sig2.to_string(),
3076 "(i8 uext, f16, f32, f64, f128, i32 sret) -> i32 sext, f64 system_v"
3077 );
3078 assert_eq!(sig2.call_conv, CallConv::SystemV);
3079
3080 assert_eq!(
3082 Parser::new("()").parse_signature().unwrap().to_string(),
3083 "() fast"
3084 );
3085 assert_eq!(
3086 Parser::new("() notacc")
3087 .parse_signature()
3088 .unwrap_err()
3089 .to_string(),
3090 "1: unknown calling convention: notacc"
3091 );
3092
3093 assert_eq!(
3095 Parser::new("() -> void")
3096 .parse_signature()
3097 .unwrap_err()
3098 .to_string(),
3099 "1: expected parameter type"
3100 );
3101 assert_eq!(
3102 Parser::new("i8 -> i8")
3103 .parse_signature()
3104 .unwrap_err()
3105 .to_string(),
3106 "1: expected function signature: ( args... )"
3107 );
3108 assert_eq!(
3109 Parser::new("(i8 -> i8")
3110 .parse_signature()
3111 .unwrap_err()
3112 .to_string(),
3113 "1: expected ')' after function arguments"
3114 );
3115 }
3116
3117 #[test]
3118 fn stack_slot_decl() {
3119 let (func, _) = Parser::new(
3120 "function %foo() system_v {
3121 ss3 = explicit_slot 13
3122 ss1 = explicit_slot 1
3123 }",
3124 )
3125 .parse_function()
3126 .unwrap();
3127 assert_eq!(func.name.to_string(), "%foo");
3128 let mut iter = func.sized_stack_slots.keys();
3129 let _ss0 = iter.next().unwrap();
3130 let ss1 = iter.next().unwrap();
3131 assert_eq!(ss1.to_string(), "ss1");
3132 assert_eq!(
3133 func.sized_stack_slots[ss1].kind,
3134 StackSlotKind::ExplicitSlot
3135 );
3136 assert_eq!(func.sized_stack_slots[ss1].size, 1);
3137 let _ss2 = iter.next().unwrap();
3138 let ss3 = iter.next().unwrap();
3139 assert_eq!(ss3.to_string(), "ss3");
3140 assert_eq!(
3141 func.sized_stack_slots[ss3].kind,
3142 StackSlotKind::ExplicitSlot
3143 );
3144 assert_eq!(func.sized_stack_slots[ss3].size, 13);
3145 assert_eq!(iter.next(), None);
3146
3147 assert_eq!(
3149 Parser::new(
3150 "function %bar() system_v {
3151 ss1 = explicit_slot 13
3152 ss1 = explicit_slot 1
3153 }",
3154 )
3155 .parse_function()
3156 .unwrap_err()
3157 .to_string(),
3158 "3: duplicate entity: ss1"
3159 );
3160 }
3161
3162 #[test]
3163 fn block_header() {
3164 let (func, _) = Parser::new(
3165 "function %blocks() system_v {
3166 block0:
3167 block4(v3: i32):
3168 }",
3169 )
3170 .parse_function()
3171 .unwrap();
3172 assert_eq!(func.name.to_string(), "%blocks");
3173
3174 let mut blocks = func.layout.blocks();
3175
3176 let block0 = blocks.next().unwrap();
3177 assert_eq!(func.dfg.block_params(block0), &[]);
3178
3179 let block4 = blocks.next().unwrap();
3180 let block4_args = func.dfg.block_params(block4);
3181 assert_eq!(block4_args.len(), 1);
3182 assert_eq!(func.dfg.value_type(block4_args[0]), types::I32);
3183 }
3184
3185 #[test]
3186 fn duplicate_block() {
3187 let ParseError {
3188 location,
3189 message,
3190 is_warning,
3191 } = Parser::new(
3192 "function %blocks() system_v {
3193 block0:
3194 block0:
3195 return 2",
3196 )
3197 .parse_function()
3198 .unwrap_err();
3199
3200 assert_eq!(location.line_number, 3);
3201 assert_eq!(message, "duplicate entity: block0");
3202 assert!(!is_warning);
3203 }
3204
3205 #[test]
3206 fn number_of_blocks() {
3207 let ParseError {
3208 location,
3209 message,
3210 is_warning,
3211 } = Parser::new(
3212 "function %a() {
3213 block100000:",
3214 )
3215 .parse_function()
3216 .unwrap_err();
3217
3218 assert_eq!(location.line_number, 2);
3219 assert_eq!(message, "too many blocks");
3220 assert!(!is_warning);
3221 }
3222
3223 #[test]
3224 fn duplicate_ss() {
3225 let ParseError {
3226 location,
3227 message,
3228 is_warning,
3229 } = Parser::new(
3230 "function %blocks() system_v {
3231 ss0 = explicit_slot 8
3232 ss0 = explicit_slot 8",
3233 )
3234 .parse_function()
3235 .unwrap_err();
3236
3237 assert_eq!(location.line_number, 3);
3238 assert_eq!(message, "duplicate entity: ss0");
3239 assert!(!is_warning);
3240 }
3241
3242 #[test]
3243 fn duplicate_gv() {
3244 let ParseError {
3245 location,
3246 message,
3247 is_warning,
3248 } = Parser::new(
3249 "function %blocks() system_v {
3250 gv0 = vmctx
3251 gv0 = vmctx",
3252 )
3253 .parse_function()
3254 .unwrap_err();
3255
3256 assert_eq!(location.line_number, 3);
3257 assert_eq!(message, "duplicate entity: gv0");
3258 assert!(!is_warning);
3259 }
3260
3261 #[test]
3262 fn duplicate_sig() {
3263 let ParseError {
3264 location,
3265 message,
3266 is_warning,
3267 } = Parser::new(
3268 "function %blocks() system_v {
3269 sig0 = ()
3270 sig0 = ()",
3271 )
3272 .parse_function()
3273 .unwrap_err();
3274
3275 assert_eq!(location.line_number, 3);
3276 assert_eq!(message, "duplicate entity: sig0");
3277 assert!(!is_warning);
3278 }
3279
3280 #[test]
3281 fn duplicate_fn() {
3282 let ParseError {
3283 location,
3284 message,
3285 is_warning,
3286 } = Parser::new(
3287 "function %blocks() system_v {
3288 sig0 = ()
3289 fn0 = %foo sig0
3290 fn0 = %foo sig0",
3291 )
3292 .parse_function()
3293 .unwrap_err();
3294
3295 assert_eq!(location.line_number, 4);
3296 assert_eq!(message, "duplicate entity: fn0");
3297 assert!(!is_warning);
3298 }
3299
3300 #[test]
3301 fn comments() {
3302 let (func, Details { comments, .. }) = Parser::new(
3303 "; before
3304 function %comment() system_v { ; decl
3305 ss10 = explicit_slot 13 ; stackslot.
3306 ; Still stackslot.
3307 block0: ; Basic block
3308 trap user42; Instruction
3309 } ; Trailing.
3310 ; More trailing.",
3311 )
3312 .parse_function()
3313 .unwrap();
3314 assert_eq!(func.name.to_string(), "%comment");
3315 assert_eq!(comments.len(), 7); assert_eq!(
3317 comments[0],
3318 Comment {
3319 entity: AnyEntity::Function,
3320 text: "; decl",
3321 }
3322 );
3323 assert_eq!(comments[1].entity.to_string(), "ss10");
3324 assert_eq!(comments[2].entity.to_string(), "ss10");
3325 assert_eq!(comments[2].text, "; Still stackslot.");
3326 assert_eq!(comments[3].entity.to_string(), "block0");
3327 assert_eq!(comments[3].text, "; Basic block");
3328
3329 assert_eq!(comments[4].entity.to_string(), "inst0");
3330 assert_eq!(comments[4].text, "; Instruction");
3331
3332 assert_eq!(comments[5].entity, AnyEntity::Function);
3333 assert_eq!(comments[6].entity, AnyEntity::Function);
3334 }
3335
3336 #[test]
3337 fn test_file() {
3338 let tf = parse_test(
3339 r#"; before
3340 test cfg option=5
3341 test verify
3342 set unwind_info=false
3343 feature "foo"
3344 feature !"bar"
3345 ; still preamble
3346 function %comment() system_v {}"#,
3347 ParseOptions::default(),
3348 )
3349 .unwrap();
3350 assert_eq!(tf.commands.len(), 2);
3351 assert_eq!(tf.commands[0].command, "cfg");
3352 assert_eq!(tf.commands[1].command, "verify");
3353 match tf.isa_spec {
3354 IsaSpec::None(s) => {
3355 assert!(s.enable_verifier());
3356 assert!(!s.unwind_info());
3357 }
3358 _ => panic!("unexpected ISAs"),
3359 }
3360 assert_eq!(tf.features[0], Feature::With(&"foo"));
3361 assert_eq!(tf.features[1], Feature::Without(&"bar"));
3362 assert_eq!(tf.preamble_comments.len(), 2);
3363 assert_eq!(tf.preamble_comments[0].text, "; before");
3364 assert_eq!(tf.preamble_comments[1].text, "; still preamble");
3365 assert_eq!(tf.functions.len(), 1);
3366 assert_eq!(tf.functions[0].0.name.to_string(), "%comment");
3367 }
3368
3369 #[test]
3370 fn isa_spec() {
3371 assert!(
3372 parse_test(
3373 "target
3374 function %foo() system_v {}",
3375 ParseOptions::default()
3376 )
3377 .is_err()
3378 );
3379
3380 assert!(
3381 parse_test(
3382 "target x86_64
3383 set unwind_info=false
3384 function %foo() system_v {}",
3385 ParseOptions::default()
3386 )
3387 .is_err()
3388 );
3389
3390 match parse_test(
3391 "set unwind_info=false
3392 target x86_64
3393 function %foo() system_v {}",
3394 ParseOptions::default(),
3395 )
3396 .unwrap()
3397 .isa_spec
3398 {
3399 IsaSpec::None(_) => panic!("Expected some ISA"),
3400 IsaSpec::Some(v) => {
3401 assert_eq!(v.len(), 1);
3402 assert!(v[0].name() == "x64" || v[0].name() == "x86");
3403 }
3404 }
3405 }
3406
3407 #[test]
3408 fn user_function_name() {
3409 let func = Parser::new(
3411 "function u1:2() system_v {
3412 block0:
3413 trap int_divz
3414 }",
3415 )
3416 .parse_function()
3417 .unwrap()
3418 .0;
3419 assert_eq!(func.name.to_string(), "u1:2");
3420
3421 let mut parser = Parser::new(
3423 "function u123:abc() system_v {
3424 block0:
3425 trap stk_ovf
3426 }",
3427 );
3428 assert!(parser.parse_function().is_err());
3429
3430 let mut parser = Parser::new(
3432 "function u() system_v {
3433 block0:
3434 trap int_ovf
3435 }",
3436 );
3437 assert!(parser.parse_function().is_err());
3438
3439 let mut parser = Parser::new(
3440 "function u0() system_v {
3441 block0:
3442 trap int_ovf
3443 }",
3444 );
3445 assert!(parser.parse_function().is_err());
3446
3447 let mut parser = Parser::new(
3448 "function u0:() system_v {
3449 block0:
3450 trap int_ovf
3451 }",
3452 );
3453 assert!(parser.parse_function().is_err());
3454 }
3455
3456 #[test]
3457 fn change_default_calling_convention() {
3458 let code = "function %test() {
3459 block0:
3460 return
3461 }";
3462
3463 let mut parser = Parser::new(code);
3465 assert_eq!(
3466 parser.parse_function().unwrap().0.signature.call_conv,
3467 CallConv::Fast
3468 );
3469
3470 let mut parser = Parser::new(code).with_default_calling_convention(CallConv::PreserveAll);
3472 assert_eq!(
3473 parser.parse_function().unwrap().0.signature.call_conv,
3474 CallConv::PreserveAll
3475 );
3476 }
3477
3478 #[test]
3479 fn u8_as_hex() {
3480 fn parse_as_uimm8(text: &str) -> ParseResult<u8> {
3481 Parser::new(text).match_uimm8("unable to parse u8")
3482 }
3483
3484 assert_eq!(parse_as_uimm8("0").unwrap(), 0);
3485 assert_eq!(parse_as_uimm8("0xff").unwrap(), 255);
3486 assert!(parse_as_uimm8("-1").is_err());
3487 assert!(parse_as_uimm8("0xffa").is_err());
3488 }
3489
3490 #[test]
3491 fn i16_as_hex() {
3492 fn parse_as_imm16(text: &str) -> ParseResult<i16> {
3493 Parser::new(text).match_imm16("unable to parse i16")
3494 }
3495
3496 assert_eq!(parse_as_imm16("0x8000").unwrap(), -32768);
3497 assert_eq!(parse_as_imm16("0xffff").unwrap(), -1);
3498 assert_eq!(parse_as_imm16("0").unwrap(), 0);
3499 assert_eq!(parse_as_imm16("0x7fff").unwrap(), 32767);
3500 assert_eq!(
3501 parse_as_imm16("-0x0001").unwrap(),
3502 parse_as_imm16("0xffff").unwrap()
3503 );
3504 assert_eq!(
3505 parse_as_imm16("-0x7fff").unwrap(),
3506 parse_as_imm16("0x8001").unwrap()
3507 );
3508 assert!(parse_as_imm16("0xffffa").is_err());
3509 }
3510
3511 #[test]
3512 fn i32_as_hex() {
3513 fn parse_as_imm32(text: &str) -> ParseResult<i32> {
3514 Parser::new(text).match_imm32("unable to parse i32")
3515 }
3516
3517 assert_eq!(parse_as_imm32("0x80000000").unwrap(), -2147483648);
3518 assert_eq!(parse_as_imm32("0xffffffff").unwrap(), -1);
3519 assert_eq!(parse_as_imm32("0").unwrap(), 0);
3520 assert_eq!(parse_as_imm32("0x7fffffff").unwrap(), 2147483647);
3521 assert_eq!(
3522 parse_as_imm32("-0x00000001").unwrap(),
3523 parse_as_imm32("0xffffffff").unwrap()
3524 );
3525 assert_eq!(
3526 parse_as_imm32("-0x7fffffff").unwrap(),
3527 parse_as_imm32("0x80000001").unwrap()
3528 );
3529 assert!(parse_as_imm32("0xffffffffa").is_err());
3530 }
3531
3532 #[test]
3533 fn i64_as_hex() {
3534 fn parse_as_imm64(text: &str) -> ParseResult<Imm64> {
3535 Parser::new(text).match_imm64("unable to parse Imm64")
3536 }
3537
3538 assert_eq!(
3539 parse_as_imm64("0x8000000000000000").unwrap(),
3540 Imm64::new(-9223372036854775808)
3541 );
3542 assert_eq!(
3543 parse_as_imm64("0xffffffffffffffff").unwrap(),
3544 Imm64::new(-1)
3545 );
3546 assert_eq!(parse_as_imm64("0").unwrap(), Imm64::new(0));
3547 assert_eq!(
3548 parse_as_imm64("0x7fffffffffffffff").unwrap(),
3549 Imm64::new(9223372036854775807)
3550 );
3551 assert_eq!(
3552 parse_as_imm64("-0x0000000000000001").unwrap(),
3553 parse_as_imm64("0xffffffffffffffff").unwrap()
3554 );
3555 assert_eq!(
3556 parse_as_imm64("-0x7fffffffffffffff").unwrap(),
3557 parse_as_imm64("0x8000000000000001").unwrap()
3558 );
3559 assert!(parse_as_imm64("0xffffffffffffffffa").is_err());
3560 }
3561
3562 #[test]
3563 fn uimm128() {
3564 macro_rules! parse_as_constant_data {
3565 ($text:expr, $type:expr) => {{ Parser::new($text).parse_literals_to_constant_data($type) }};
3566 }
3567 macro_rules! can_parse_as_constant_data {
3568 ($text:expr, $type:expr) => {{ assert!(parse_as_constant_data!($text, $type).is_ok()) }};
3569 }
3570 macro_rules! cannot_parse_as_constant_data {
3571 ($text:expr, $type:expr) => {{ assert!(parse_as_constant_data!($text, $type).is_err()) }};
3572 }
3573
3574 can_parse_as_constant_data!("1 2 3 4", I32X4);
3575 can_parse_as_constant_data!("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16", I8X16);
3576 can_parse_as_constant_data!("0x1.1 0x2.2 0x3.3 0x4.4", F32X4);
3577 can_parse_as_constant_data!("0x0 0x1 0x2 0x3", I32X4);
3578 can_parse_as_constant_data!("-1 0 -1 0 -1 0 -1 0", I16X8);
3579 can_parse_as_constant_data!("0 -1", I64X2);
3580 can_parse_as_constant_data!("-1 0", I64X2);
3581 can_parse_as_constant_data!("-1 -1 -1 -1 -1", I32X4); cannot_parse_as_constant_data!("1 2 3", I32X4);
3584 cannot_parse_as_constant_data!(" ", F32X4);
3585 }
3586
3587 #[test]
3588 fn parse_constant_from_booleans() {
3589 let c = Parser::new("-1 0 -1 0")
3590 .parse_literals_to_constant_data(I32X4)
3591 .unwrap();
3592 assert_eq!(
3593 c.into_vec(),
3594 [
3595 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0
3596 ]
3597 )
3598 }
3599
3600 #[test]
3601 fn parse_unbounded_constants() {
3602 assert_eq!(
3604 Parser::new("0x0100")
3605 .match_hexadecimal_constant("err message")
3606 .unwrap(),
3607 vec![0, 1].into()
3608 );
3609
3610 assert!(
3612 Parser::new("228")
3613 .match_hexadecimal_constant("err message")
3614 .is_err()
3615 );
3616 }
3617
3618 #[test]
3619 fn parse_run_commands() {
3620 fn sig(ins: &[Type], outs: &[Type]) -> Signature {
3622 let mut sig = Signature::new(CallConv::Fast);
3623 for i in ins {
3624 sig.params.push(AbiParam::new(*i));
3625 }
3626 for o in outs {
3627 sig.returns.push(AbiParam::new(*o));
3628 }
3629 sig
3630 }
3631
3632 fn parse(text: &str, sig: &Signature) -> ParseResult<RunCommand> {
3634 Parser::new(text).parse_run_command(sig)
3635 }
3636
3637 fn assert_roundtrip(text: &str, sig: &Signature) {
3639 assert_eq!(parse(text, sig).unwrap().to_string(), text);
3640 }
3641 assert_roundtrip("run: %fn0() == 42", &sig(&[], &[I32]));
3642 assert_roundtrip(
3643 "run: %fn0(8, 16, 32, 64) == 1",
3644 &sig(&[I8, I16, I32, I64], &[I8]),
3645 );
3646 assert_roundtrip(
3647 "run: %my_func(1) == 0x0f0e0d0c0b0a09080706050403020100",
3648 &sig(&[I32], &[I8X16]),
3649 );
3650
3651 assert_eq!(
3653 parse("run", &sig(&[], &[I32])).unwrap().to_string(),
3654 "run: %default() != 0"
3655 );
3656 assert_eq!(
3657 parse("print", &sig(&[], &[F32X4, I16X8]))
3658 .unwrap()
3659 .to_string(),
3660 "print: %default()"
3661 );
3662
3663 assert!(parse("print", &sig(&[I32], &[I32])).is_err());
3665 assert!(parse("print:", &sig(&[], &[])).is_err());
3666 assert!(parse("run: ", &sig(&[], &[])).is_err());
3667 }
3668
3669 #[test]
3670 fn parse_data_values() {
3671 fn parse(text: &str, ty: Type) -> DataValue {
3672 Parser::new(text).parse_data_value(ty).unwrap()
3673 }
3674
3675 assert_eq!(parse("8", I8).to_string(), "8");
3676 assert_eq!(parse("16", I16).to_string(), "16");
3677 assert_eq!(parse("32", I32).to_string(), "32");
3678 assert_eq!(parse("64", I64).to_string(), "64");
3679 assert_eq!(
3680 parse("0x01234567_01234567_01234567_01234567", I128).to_string(),
3681 "1512366032949150931280199141537564007"
3682 );
3683 assert_eq!(parse("1234567", I128).to_string(), "1234567");
3684 assert_eq!(parse("0x16.1", F16).to_string(), "0x1.610p4");
3685 assert_eq!(parse("0x32.32", F32).to_string(), "0x1.919000p5");
3686 assert_eq!(parse("0x64.64", F64).to_string(), "0x1.9190000000000p6");
3687 assert_eq!(
3688 parse("0x128.128", F128).to_string(),
3689 "0x1.2812800000000000000000000000p8"
3690 );
3691 assert_eq!(
3692 parse("[0 1 2 3]", I32X4).to_string(),
3693 "0x00000003000000020000000100000000"
3694 );
3695 assert_eq!(parse("[1 2]", I32X2).to_string(), "0x0000000200000001");
3696 assert_eq!(parse("[1 2 3 4]", I8X4).to_string(), "0x04030201");
3697 assert_eq!(parse("[1 2]", I8X2).to_string(), "0x0201");
3698 }
3699
3700 #[test]
3701 fn parse_cold_blocks() {
3702 let code = "function %test() {
3703 block0 cold:
3704 return
3705 block1(v0: i32) cold:
3706 return
3707 block2(v1: i32):
3708 return
3709 }";
3710
3711 let mut parser = Parser::new(code);
3712 let func = parser.parse_function().unwrap().0;
3713 assert_eq!(func.layout.blocks().count(), 3);
3714 assert!(func.layout.is_cold(Block::from_u32(0)));
3715 assert!(func.layout.is_cold(Block::from_u32(1)));
3716 assert!(!func.layout.is_cold(Block::from_u32(2)));
3717 }
3718}