1use std::fmt;
34
35use rucc_base::float::Format;
36use rucc_base::{Idx, Interner, Symbol};
37use rucc_diag::Span;
38use rucc_target::{Slot, TargetInfo};
39use rucc_tuple::TargetTuple;
40
41use crate::attrs::{AttrSet, Attrs, FpContract};
42use crate::func::Func;
43use crate::inst::{
44 Abi, AsmInfo, Block, BlockCall, CallInfo, Imm, Inst, InstData, MemInfo, Meta, MetaNode, Param,
45 PlaneNode, Restrict, Signature, SwitchInfo, TbaaNode, VaInfo, Value,
46};
47use crate::module::{
48 Alias, AliasKind, DataLayout, Datum, Global, Linkage, Module, Reloc, TlsModel, Visibility,
49};
50use crate::{
51 Bounds, Extra, ExtraKind, FORMAT_VERSION, Facts, Flags, FloatPred, IntPred, MemOrder, Opcode,
52 Owner, RmwOp, StorageClass, Type,
53};
54
55#[derive(Clone, Debug, PartialEq, Eq)]
61pub struct ParseError {
62 pub line: u32,
64 pub message: String,
66}
67
68impl fmt::Display for ParseError {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(f, "line {}: {}", self.line, self.message)
71 }
72}
73
74impl std::error::Error for ParseError {}
75
76pub fn parse(text: &str, names: &mut Interner) -> Result<Module, ParseError> {
85 Parser::new(text, names).module()
86}
87
88struct Parser<'a, 'n> {
90 text: &'a str,
91 pos: usize,
92 line: u32,
93 names: &'n mut Interner,
94 meta_used: Option<(u32, u32)>,
97}
98
99struct PendingBlock<'a> {
101 params: Vec<(u32, Type)>,
102 insts: Vec<PendingInst<'a>>,
103}
104
105struct PendingFacts {
107 line: u32,
108 value: u32,
109 bounds: Option<(u32, u32)>,
110 init: Option<u64>,
111 align: Option<u32>,
112 live: bool,
113}
114
115impl PendingFacts {
116 fn new(line: u32, value: u32) -> Self {
117 Self { line, value, bounds: None, init: None, align: None, live: false }
118 }
119}
120
121struct PendingInst<'a> {
123 opcode: Opcode,
124 flags: Flags,
125 results: Vec<u32>,
126 written: Vec<Type>,
128 args: Vec<u32>,
129 mem: Option<u32>,
133 extra: PendingExtra<'a>,
134 line: u32,
135}
136
137struct PendingCall {
139 block: u32,
140 args: Vec<u32>,
141}
142
143enum PendingExtra<'a> {
145 None,
146 Imm(&'a str),
148 Symbol(Symbol),
149 IntPred(IntPred),
150 FloatPred(FloatPred),
151 Mem(MemInfo),
152 VaObject(MemInfo, Vec<Slot>),
155 Rmw(RmwOp, MemInfo),
156 Order(MemOrder),
157 Class(StorageClass),
158 Owner(Owner),
159 Node(Meta),
160 Reason(Symbol),
161 Targets(Vec<PendingCall>),
162 Call {
163 callee: Option<Symbol>,
164 signature: Signature,
165 abis: Vec<Abi>,
168 },
169 Switch {
170 targets: Vec<PendingCall>,
171 cases: Vec<&'a str>,
172 },
173 Asm {
174 template: Symbol,
175 constraints: Symbol,
176 clobbers: Symbol,
177 targets: Vec<PendingCall>,
178 },
179}
180
181impl<'a, 'n> Parser<'a, 'n> {
182 fn new(text: &'a str, names: &'n mut Interner) -> Self {
183 Parser { text, pos: 0, line: 1, names, meta_used: None }
184 }
185
186 fn module(mut self) -> Result<Module, ParseError> {
189 let name = self.header_name()?;
190 self.expect("; format ")?;
191 let version = self.u32()?;
192 if version != FORMAT_VERSION {
193 return self.fail(format!(
194 "this build reads format {FORMAT_VERSION} and the text says format {version}"
195 ));
196 }
197 self.end_of_line()?;
198
199 self.expect("target triple = ")?;
200 let triple = self.quoted_str()?;
201 let Ok(tuple) = triple.parse::<TargetTuple>() else {
202 return self.fail(format!("`{triple}` is not a target triple"));
203 };
204 self.end_of_line()?;
205
206 self.expect("target datalayout = ")?;
207 let layout = self.quoted_str()?;
208 let Some(datalayout) = DataLayout::parse(&layout) else {
209 return self.fail(format!("`{layout}` is not a data layout"));
210 };
211 self.end_of_line()?;
212
213 let name = self.names.intern(&name);
214 let mut module = Module::new(name, &TargetInfo::for_tuple(tuple));
215 module.datalayout = datalayout;
216
217 loop {
218 self.skip_blank_lines();
219 if self.at_end() {
220 break;
221 }
222 match self.peek_word() {
223 "global" => self.global(&mut module)?,
224 "alias" | "ifunc" => self.alias(&mut module)?,
225 "func" => self.func(&mut module)?,
226 _ if self.at("!") => self.meta(&mut module)?,
227 other => return self.fail(format!("`{other}` does not start anything")),
228 }
229 }
230
231 if let Some((used, line)) = self.meta_used {
232 let count = module.counts().metadata as u32;
233 if used >= count {
234 self.line = line;
235 return self.fail(format!("!{used} is used and never defined"));
236 }
237 }
238 Ok(module)
239 }
240
241 fn header_name(&mut self) -> Result<String, ParseError> {
243 self.expect("; ModuleID = '")?;
244 let start = self.pos;
245 let Some(end) = self.text[start..].find('\'') else {
246 return self.fail("the module name is not closed");
247 };
248 let name = self.text[start..start + end].to_string();
249 self.pos = start + end + 1;
250 self.end_of_line()?;
251 Ok(name)
252 }
253
254 fn global(&mut self, module: &mut Module) -> Result<(), ParseError> {
257 self.expect("global")?;
258 let name = self.symbol()?;
259 self.expect(":")?;
260
261 let mut global = Global::new(name, 0, 1);
262 if self.eat_word("bytes") {
263 global.size = self.u64()?;
264 if self.eat("=") {
265 self.expect("{")?;
266 let mut data = Vec::new();
267 if !self.eat("}") {
271 loop {
272 data.push(self.datum(module)?);
273 if !self.eat(",") {
274 break;
275 }
276 }
277 self.expect("}")?;
278 }
279 global.init = Some(module.push_data(&data));
280 }
281 } else {
282 let ty = self.ty()?;
283 self.expect("=")?;
284 let text = self.imm_text()?;
285 let value = self.imm(text, ty)?;
286 let datum = Datum::Scalar { ty, value: module.add_imm(value) };
287 global.size = datum.size(module);
288 global.init = Some(module.push_data(&[datum]));
289 }
290
291 while self.eat(",") {
292 match self.word() {
293 "align" => global.align = self.u32()?,
294 "linkage" => {
295 global.linkage = self.parenthesised(Linkage::from_name, "a linkage")?
296 }
297 "visibility" => {
298 global.visibility =
299 self.parenthesised(Visibility::from_name, "a visibility")?;
300 }
301 "tls" => {
302 global.tls =
303 Some(self.parenthesised(TlsModel::from_name, "a thread-local model")?);
304 }
305 "constant" => global.constant = true,
306 "section" => global.section = Some(self.symbol_from_string()?),
307 other => return self.fail(format!("a global has no `{other}`")),
308 }
309 }
310 self.end_of_line()?;
311 module.add_global(global);
312 Ok(())
313 }
314
315 fn datum(&mut self, module: &mut Module) -> Result<Datum, ParseError> {
317 match self.peek_word() {
318 "zero" => {
319 self.expect("zero")?;
320 Ok(Datum::Zero(self.u64()?))
321 }
322 "bytes" => {
323 self.expect("bytes")?;
324 let bytes = self.string()?;
325 Ok(Datum::Bytes(module.push_bytes(&bytes)))
326 }
327 "addr" => {
328 self.expect("addr")?;
329 self.expect(".")?;
330 let size = self.u32()?;
331 let symbol = self.symbol()?;
332 let addend = if self.eat("+") {
333 self.i64()?
334 } else if self.eat("-") {
335 let amount = self.i64()?;
336 match amount.checked_neg() {
337 Some(negated) => negated,
338 None => return self.fail("that offset has no negative"),
339 }
340 } else {
341 0
342 };
343 Ok(Datum::Addr(module.add_reloc(Reloc { symbol, addend, size })))
344 }
345 _ => {
346 let ty = self.ty()?;
347 let text = self.imm_text()?;
348 let value = self.imm(text, ty)?;
349 Ok(Datum::Scalar { ty, value: module.add_imm(value) })
350 }
351 }
352 }
353
354 fn alias(&mut self, module: &mut Module) -> Result<(), ParseError> {
355 let word = self.word();
356 let Some(kind) = AliasKind::from_name(word) else {
357 return self.fail(format!("`{word}` is not a kind of alias"));
358 };
359 let name = self.symbol()?;
360 self.expect("=")?;
361 let target = self.symbol()?;
362 let mut alias = Alias::new(name, target);
363 alias.kind = kind;
364 while self.eat(",") {
365 match self.word() {
366 "linkage" => alias.linkage = self.parenthesised(Linkage::from_name, "a linkage")?,
367 "visibility" => {
368 alias.visibility = self.parenthesised(Visibility::from_name, "a visibility")?;
369 }
370 other => return self.fail(format!("an alias has no `{other}`")),
371 }
372 }
373 self.end_of_line()?;
374 module.add_alias(alias);
375 Ok(())
376 }
377
378 fn meta(&mut self, module: &mut Module) -> Result<(), ParseError> {
379 let index = self.meta_ref()?;
380 let expected = module.counts().metadata as u32;
381 if index.raw() != expected {
382 return self.fail(format!("metadata is numbered in order and !{expected} comes next"));
383 }
384 self.expect("=")?;
385 let node = match self.word() {
386 "tbaa" => {
387 let name = self.symbol_from_string()?;
388 let mut node = TbaaNode { name, parent: None, offset: 0 };
389 while self.eat(",") {
390 match self.word() {
391 "parent" => node.parent = Some(self.meta_ref()?),
392 "offset" => node.offset = self.u64()?,
393 other => return self.fail(format!("a metadata node has no `{other}`")),
394 }
395 }
396 MetaNode::Tbaa(node)
397 }
398 "plane" => MetaNode::Plane(if self.peek_is("!") {
402 PlaneNode::Type(self.meta_ref()?)
403 } else {
404 match self.word() {
405 "no_type" => PlaneNode::NoType,
406 "character" => PlaneNode::Character,
407 "pointer_slot" => {
408 let k = self.u32()?;
409 match u8::try_from(k) {
410 Ok(k) => PlaneNode::PointerSlot(k),
411 Err(_) => return self.fail(format!("no pointer has a byte {k}")),
412 }
413 }
414 other => return self.fail(format!("`{other}` is not a plane entry")),
415 }
416 }),
417 other => return self.fail(format!("`{other}` is not a kind of metadata node")),
418 };
419 if node.points_at().is_some_and(|at| at.raw() >= index.raw()) {
420 return self.fail("a metadata node names one that comes before it");
421 }
422 self.end_of_line()?;
423 module.add_meta(node);
424 Ok(())
425 }
426
427 fn func(&mut self, module: &mut Module) -> Result<(), ParseError> {
430 self.expect("func")?;
431 let name = self.symbol()?;
432 let signature = self.signature()?;
433 let mut func = Func::new(name, signature);
434 while self.eat(",") {
435 match self.word() {
436 "linkage" => func.linkage = self.parenthesised(Linkage::from_name, "a linkage")?,
437 "visibility" => {
438 func.visibility = self.parenthesised(Visibility::from_name, "a visibility")?;
439 }
440 "attrs" => func.attrs = self.attrs()?,
441 "section" => func.section = Some(self.symbol_from_string()?),
442 other => return self.fail(format!("a function has no `{other}`")),
443 }
444 }
445 if self.eat(";") {
446 self.end_of_line()?;
447 module.add_func(func);
448 return Ok(());
449 }
450 self.expect("{")?;
451 self.end_of_line()?;
452 let (blocks, facts) = self.body()?;
453 self.build(&mut func, &blocks, &facts)?;
454 module.add_func(func);
455 Ok(())
456 }
457
458 fn signature(&mut self) -> Result<Signature, ParseError> {
460 self.expect("(")?;
461 let mut signature = Signature::new();
462 if !self.eat(")") {
463 loop {
464 if self.eat("...") {
465 signature.variadic = true;
466 break;
467 }
468 signature.params.push(self.param()?);
469 if !self.eat(",") {
470 break;
471 }
472 }
473 self.expect(")")?;
474 }
475 if self.eat("->") {
476 if self.eat("(") {
477 loop {
478 signature.returns.push(self.param()?);
479 if !self.eat(",") {
480 break;
481 }
482 }
483 self.expect(")")?;
484 } else {
485 signature.returns.push(self.param()?);
486 }
487 }
488 Ok(signature)
489 }
490
491 fn param(&mut self) -> Result<Param, ParseError> {
493 let ty = self.ty()?;
494 let abi = self.abi()?;
495 Ok(Param { ty, abi })
496 }
497
498 fn abi(&mut self) -> Result<Abi, ParseError> {
500 let abi = match self.peek_word() {
501 "sext" => {
502 self.word();
503 Abi::Sext
504 }
505 "zext" => {
506 self.word();
507 Abi::Zext
508 }
509 word @ ("byval" | "sret") => {
510 let indirect = word == "byval";
511 self.word();
512 self.expect("(")?;
513 let size = self.u64()?;
514 self.expect(",")?;
515 self.expect("align")?;
516 let align = self.u32()?;
517 self.expect(")")?;
518 if indirect { Abi::ByVal { size, align } } else { Abi::Sret { size, align } }
519 }
520 _ => Abi::Plain,
521 };
522 Ok(abi)
523 }
524
525 fn attrs(&mut self) -> Result<Attrs, ParseError> {
526 self.expect("(")?;
527 let mut attrs = Attrs::NONE;
528 loop {
529 let word = self.word();
530 if self.eat("=") {
531 let value = self.word();
532 match word {
533 "fp_contract" => match FpContract::from_name(value) {
534 Some(contract) => attrs.fp_contract = contract,
535 None => return self.fail(format!("`{value}` is not a contraction")),
536 },
537 other => return self.fail(format!("`{other}` takes no value")),
538 }
539 } else {
540 match AttrSet::from_name(word) {
541 Some(attr) => attrs.set |= attr,
542 None => return self.fail(format!("`{word}` is not an attribute")),
543 }
544 }
545 if !self.eat(",") {
546 break;
547 }
548 }
549 self.expect(")")?;
550 Ok(attrs)
551 }
552
553 fn body(&mut self) -> Result<(Vec<PendingBlock<'a>>, Vec<PendingFacts>), ParseError> {
555 let mut blocks: Vec<PendingBlock<'a>> = Vec::new();
556 let mut facts: Vec<PendingFacts> = Vec::new();
557 loop {
558 self.skip_blank_lines();
559 if self.eat("}") {
560 self.end_of_line()?;
561 return Ok((blocks, facts));
562 }
563 if self.at_end() {
564 return self.fail("the function is not closed");
565 }
566 if self.peek_word() == "facts" {
567 self.word();
570 self.expect(":")?;
571 self.end_of_line()?;
572 loop {
573 self.skip_blank_lines();
574 if !self.peek_is("%") {
575 break;
576 }
577 facts.push(self.fact_line()?);
578 }
579 continue;
580 }
581 if self.peek_word().starts_with("block") {
582 let number = self.block_ref()?;
583 if number as usize != blocks.len() {
584 return self.fail(format!(
585 "blocks are numbered in order and block{} comes next",
586 blocks.len()
587 ));
588 }
589 let mut params = Vec::new();
590 if self.eat("(") {
591 loop {
592 let value = self.value_ref()?;
593 self.expect(":")?;
594 params.push((value, self.ty()?));
595 if !self.eat(",") {
596 break;
597 }
598 }
599 self.expect(")")?;
600 }
601 self.expect(":")?;
602 self.end_of_line()?;
603 blocks.push(PendingBlock { params, insts: Vec::new() });
604 continue;
605 }
606 let inst = self.inst()?;
607 match blocks.last_mut() {
608 Some(block) => block.insts.push(inst),
609 None => return self.fail("an instruction before any block"),
610 }
611 }
612 }
613
614 fn fact_line(&mut self) -> Result<PendingFacts, ParseError> {
616 let line = self.line;
617 let value = self.value_ref()?;
618 self.expect("=")?;
619 let mut facts = PendingFacts::new(line, value);
620 loop {
621 self.expect("!")?;
622 let word = self.word();
623 match word {
624 "bounds" => {
625 self.expect("(")?;
626 let lo = self.value_ref()?;
627 self.expect(",")?;
628 let ext = self.value_ref()?;
629 self.expect(")")?;
630 facts.bounds = Some((lo, ext));
631 }
632 "live" => facts.live = true,
633 "init" => {
634 self.expect("(")?;
635 facts.init = Some(self.u64()?);
636 self.expect(")")?;
637 }
638 "aligned" => {
639 self.expect("(")?;
640 facts.align = Some(self.u32()?);
641 self.expect(")")?;
642 }
643 other => return self.fail(format!("`{other}` is not a fact")),
644 }
645 if !self.eat(",") {
646 break;
647 }
648 }
649 self.end_of_line()?;
650 Ok(facts)
651 }
652
653 fn inst(&mut self) -> Result<PendingInst<'a>, ParseError> {
655 let line = self.line;
656 let mut results = Vec::new();
657 if self.peek_is("%") {
658 results = self.value_list()?;
659 self.expect("=")?;
660 }
661
662 let word = self.word();
663 let Some(opcode) = Opcode::from_name(word) else {
664 return self.fail(format!("`{word}` is not an opcode"));
665 };
666 let (written, flags) = self.suffixes()?;
667
668 let mut args = Vec::new();
669 let extra = match opcode.extra_kind() {
670 ExtraKind::None => {
671 args = self.value_list()?;
672 PendingExtra::None
673 }
674 ExtraKind::Imm => PendingExtra::Imm(self.imm_text()?),
675 ExtraKind::Symbol => {
676 let symbol = self.symbol()?;
677 if self.eat("(") {
678 args = self.value_list()?;
679 self.expect(")")?;
680 }
681 PendingExtra::Symbol(symbol)
682 }
683 ExtraKind::IntPred => {
684 let word = self.word();
685 let Some(pred) = IntPred::from_name(word) else {
686 return self.fail(format!("`{word}` is not an integer comparison"));
687 };
688 args = self.value_list()?;
689 PendingExtra::IntPred(pred)
690 }
691 ExtraKind::FloatPred => {
692 let word = self.word();
693 let Some(pred) = FloatPred::from_name(word) else {
694 return self.fail(format!("`{word}` is not a floating point comparison"));
695 };
696 args = self.value_list()?;
697 PendingExtra::FloatPred(pred)
698 }
699 ExtraKind::Mem => {
700 if matches!(opcode, Opcode::Store | Opcode::AtomicStore) {
701 let value = self.value_ref()?;
703 self.expect("->")?;
704 args = vec![value, self.value_ref()?];
705 } else {
706 args = self.value_list()?;
707 }
708 PendingExtra::Mem(self.mem()?)
709 }
710 ExtraKind::VaObject => {
711 args = self.value_list()?;
712 let (info, slots) = self.va()?;
713 PendingExtra::VaObject(info, slots)
714 }
715 ExtraKind::Rmw => {
716 let word = self.word();
717 let Some(op) = RmwOp::from_name(word) else {
718 return self.fail(format!("`{word}` is not a read-modify-write"));
719 };
720 args = self.value_list()?;
721 PendingExtra::Rmw(op, self.mem()?)
722 }
723 ExtraKind::Order => {
724 let word = self.word();
725 let Some(order) = MemOrder::from_name(word) else {
726 return self.fail(format!("`{word}` is not an ordering"));
727 };
728 PendingExtra::Order(order)
729 }
730 ExtraKind::Class => {
733 args = self.value_list()?;
734 self.expect(",")?;
735 self.expect("class")?;
736 let word = self.word();
737 let Some(class) = StorageClass::from_name(word) else {
738 return self.fail(format!("`{word}` is not a storage class"));
739 };
740 PendingExtra::Class(class)
741 }
742 ExtraKind::Owner => {
743 args = self.value_list()?;
744 self.expect(",")?;
745 self.expect("to")?;
746 let word = self.word();
747 let Some(owner) = Owner::from_name(word) else {
748 return self.fail(format!("`{word}` is not somewhere a range can go"));
749 };
750 PendingExtra::Owner(owner)
751 }
752 ExtraKind::Node => {
753 args = self.value_list()?;
754 self.expect(",")?;
755 self.expect("tbaa")?;
756 PendingExtra::Node(self.meta_ref()?)
757 }
758 ExtraKind::Reason => PendingExtra::Reason(self.symbol_from_string()?),
759 ExtraKind::Targets => {
760 args = self.value_list()?;
761 if !args.is_empty() {
762 self.expect(",")?;
763 }
764 let mut targets = Vec::new();
765 loop {
766 targets.push(self.block_call()?);
767 if !self.eat(",") {
768 break;
769 }
770 }
771 PendingExtra::Targets(targets)
772 }
773 ExtraKind::Call => {
774 let callee = if self.peek_is("@") {
775 Some(self.symbol()?)
776 } else {
777 args.push(self.value_ref()?);
778 None
779 };
780 self.expect("(")?;
781 let (values, abis) = self.call_args()?;
782 args.extend(values);
783 self.expect(")")?;
784 self.expect(":")?;
785 PendingExtra::Call { callee, signature: self.signature()?, abis }
786 }
787 ExtraKind::Switch => {
788 args = self.value_list()?;
789 let mut targets = Vec::new();
790 let mut cases = Vec::new();
791 if self.eat(",") {
792 targets.push(self.block_call()?);
793 self.expect(",")?;
794 self.expect("[")?;
795 if !self.eat("]") {
796 loop {
797 cases.push(self.imm_text()?);
798 self.expect("=>")?;
799 targets.push(self.block_call()?);
800 if !self.eat(",") {
801 break;
802 }
803 }
804 self.expect("]")?;
805 }
806 }
807 PendingExtra::Switch { targets, cases }
808 }
809 ExtraKind::Asm => {
810 let template = self.symbol_from_string()?;
811 self.expect(",")?;
812 let constraints = self.symbol_from_string()?;
813 self.expect(",")?;
814 let clobbers = self.symbol_from_string()?;
815 self.expect("(")?;
816 args = self.value_list()?;
817 self.expect(")")?;
818 let mut targets = Vec::new();
819 if self.eat(",") {
820 self.expect("labels")?;
821 self.expect("[")?;
822 loop {
823 targets.push(self.block_call()?);
824 if !self.eat(",") {
825 break;
826 }
827 }
828 self.expect("]")?;
829 }
830 PendingExtra::Asm { template, constraints, clobbers, targets }
831 }
832 };
833 let mut mem = None;
836 if self.eat("[") {
837 self.expect("mem")?;
838 let value = self.value_ref()?;
839 self.expect("]")?;
840 args.push(value);
841 mem = Some(value);
842 }
843 self.end_of_line()?;
844 Ok(PendingInst { opcode, flags, results, written, args, mem, extra, line })
845 }
846
847 fn suffixes(&mut self) -> Result<(Vec<Type>, Flags), ParseError> {
849 let mut written = Vec::new();
850 let mut flags = Flags::NONE;
851 while self.at(".") {
852 self.pos += 1;
853 if self.at("(") {
854 self.pos += 1;
855 loop {
856 written.push(self.ty()?);
857 if !self.eat(",") {
858 break;
859 }
860 }
861 self.expect(")")?;
862 continue;
863 }
864 let word = self.glued_word();
865 if let Some(flag) = Flags::from_name(word) {
866 flags |= flag;
867 } else if let Some(ty) = Type::parse(word) {
868 written.push(ty);
869 } else {
870 return self.fail(format!("`{word}` is neither a type nor a flag"));
871 }
872 }
873 Ok((written, flags))
874 }
875
876 fn mem(&mut self) -> Result<MemInfo, ParseError> {
878 let mut info = MemInfo {
879 size: 0,
880 align: 1,
881 order: MemOrder::NotAtomic,
882 tbaa: None,
883 owns: 0,
884 restrict: Restrict::NONE,
885 };
886 while self.eat(",") {
887 let word = self.word();
888 if !self.mem_field(&mut info, word)? {
889 return self.fail(format!("an access has no `{word}`"));
890 }
891 }
892 Ok(info)
893 }
894
895 fn mem_field(&mut self, info: &mut MemInfo, word: &str) -> Result<bool, ParseError> {
897 match word {
898 "size" => info.size = self.u64()?,
899 "align" => info.align = self.u32()?,
900 "tbaa" => info.tbaa = Some(self.meta_ref()?),
901 "owns" => info.owns = self.u32()?,
902 "restrict" => info.restrict = self.restrict()?,
903 _ => match MemOrder::from_name(word) {
904 Some(order) => info.order = order,
905 None => return Ok(false),
906 },
907 }
908 Ok(true)
909 }
910
911 fn restrict(&mut self) -> Result<Restrict, ParseError> {
913 self.expect("(")?;
914 let clique = self.u16()?;
915 self.expect(",")?;
916 let base = self.u16()?;
917 self.expect(")")?;
918 Ok(Restrict { clique, base })
919 }
920
921 fn va(&mut self) -> Result<(MemInfo, Vec<Slot>), ParseError> {
924 let mut info = MemInfo {
925 size: 0,
926 align: 1,
927 order: MemOrder::NotAtomic,
928 tbaa: None,
929 owns: 0,
930 restrict: Restrict::NONE,
931 };
932 let mut slots = Vec::new();
933 while self.eat(",") {
934 let word = self.word();
935 if word == "in" {
936 self.expect("(")?;
937 loop {
938 slots.push(self.slot()?);
939 if !self.eat(",") {
940 break;
941 }
942 }
943 self.expect(")")?;
944 } else if !self.mem_field(&mut info, word)? {
945 return self
946 .fail(format!("an object off a variable argument list has no `{word}`"));
947 }
948 }
949 Ok((info, slots))
950 }
951
952 fn slot(&mut self) -> Result<Slot, ParseError> {
954 let word = self.word();
955 let slot = match word {
956 "int" => {
957 let size = self.u32()?;
958 self.expect("at")?;
959 Slot::Integer { offset: self.u64()?, size }
960 }
961 "float" => {
962 let name = self.word();
963 let Some(format) = Format::from_name(name) else {
964 return self.fail(format!("`{name}` is not a floating point format"));
965 };
966 self.expect("at")?;
967 Slot::Float { offset: self.u64()?, format }
968 }
969 _ => return self.fail(format!("`{word}` is not how a slot is written")),
970 };
971 Ok(slot)
972 }
973
974 fn block_call(&mut self) -> Result<PendingCall, ParseError> {
976 let block = self.block_ref()?;
977 let mut args = Vec::new();
978 if self.eat("(") {
979 args = self.value_list()?;
980 self.expect(")")?;
981 }
982 Ok(PendingCall { block, args })
983 }
984
985 fn build(
989 &mut self,
990 func: &mut Func,
991 blocks: &[PendingBlock<'a>],
992 facts: &[PendingFacts],
993 ) -> Result<(), ParseError> {
994 let count = self.check_numbering(blocks)?;
995 let types = self.value_types(blocks, count)?;
996
997 let mut next = 0;
998 for pending in blocks {
999 let block = func.create_block();
1000 for &(number, ty) in &pending.params {
1001 if number != next {
1002 self.line = self.line_of(blocks, number);
1003 return self
1004 .fail(format!("values are numbered in order and %{next} comes next"));
1005 }
1006 func.append_param(block, ty);
1007 next += 1;
1008 }
1009 for inst in &pending.insts {
1010 if inst.results.first().is_some_and(|&first| first != next) {
1011 self.line = inst.line;
1012 return self
1013 .fail(format!("values are numbered in order and %{next} comes next"));
1014 }
1015 let built = self.build_inst(func, inst, &types)?;
1016 func.append_inst(block, built);
1017 next += inst.results.len() as u32;
1018 }
1019 }
1020 self.build_facts(func, facts, next)?;
1021 Ok(())
1022 }
1023
1024 fn build_facts(
1030 &mut self,
1031 func: &mut Func,
1032 facts: &[PendingFacts],
1033 count: u32,
1034 ) -> Result<(), ParseError> {
1035 for pending in facts {
1036 self.line = pending.line;
1037 for number in [
1038 Some(pending.value),
1039 pending.bounds.map(|(lo, _)| lo),
1040 pending.bounds.map(|(_, ext)| ext),
1041 ]
1042 .into_iter()
1043 .flatten()
1044 {
1045 if number >= count {
1046 return self.fail(format!("%{number} is used and never defined"));
1047 }
1048 }
1049 let value = Value::from_usize(pending.value as usize);
1050 if !func.facts(value).is_empty() {
1051 return self.fail(format!("%{} is said twice", pending.value));
1052 }
1053 func.set_facts(
1054 value,
1055 Facts {
1056 bounds: pending.bounds.map(|(lo, ext)| Bounds {
1057 lo: Value::from_usize(lo as usize),
1058 ext: Value::from_usize(ext as usize),
1059 }),
1060 init: pending.init,
1061 align: pending.align,
1062 live: pending.live,
1063 },
1064 );
1065 }
1066 Ok(())
1067 }
1068
1069 fn check_numbering(&mut self, blocks: &[PendingBlock<'a>]) -> Result<u32, ParseError> {
1073 let mut count = 0;
1074 for pending in blocks {
1075 count += pending.params.len();
1076 for inst in &pending.insts {
1077 count += inst.results.len();
1078 }
1079 }
1080 let count = count as u32;
1081 let total = blocks.len() as u32;
1082 for pending in blocks {
1083 for inst in &pending.insts {
1084 self.line = inst.line;
1085 for &arg in &inst.args {
1086 if arg >= count {
1087 return self.fail(format!("%{arg} is used and never defined"));
1088 }
1089 }
1090 for call in inst_calls(inst) {
1091 if call.block >= total {
1092 return self.fail(format!("block{} is used and never defined", call.block));
1093 }
1094 for &arg in &call.args {
1095 if arg >= count {
1096 return self.fail(format!("%{arg} is used and never defined"));
1097 }
1098 }
1099 }
1100 }
1101 }
1102 Ok(count)
1103 }
1104
1105 fn value_types(
1112 &mut self,
1113 blocks: &[PendingBlock<'a>],
1114 count: u32,
1115 ) -> Result<Vec<Option<Type>>, ParseError> {
1116 let mut types = vec![None; count as usize];
1117 for pending in blocks {
1118 for &(number, ty) in &pending.params {
1119 types[number as usize] = Some(ty);
1120 }
1121 }
1122 loop {
1123 let mut progress = false;
1124 for pending in blocks {
1125 for inst in &pending.insts {
1126 let Some(&first) = inst.results.first() else { continue };
1127 if types[first as usize].is_some() {
1128 continue;
1129 }
1130 let Some(resolved) = result_types(inst, &types) else { continue };
1131 if resolved.len() != inst.results.len() {
1132 self.line = inst.line;
1133 return self.fail(format!(
1134 "{} produces {} values and the text names {}",
1135 inst.opcode.name(),
1136 resolved.len(),
1137 inst.results.len()
1138 ));
1139 }
1140 for (&number, ty) in inst.results.iter().zip(resolved) {
1141 types[number as usize] = Some(ty);
1142 }
1143 progress = true;
1144 }
1145 }
1146 if !progress {
1147 break;
1148 }
1149 }
1150 for pending in blocks {
1151 for inst in &pending.insts {
1152 if inst.results.first().is_some_and(|&first| types[first as usize].is_none()) {
1153 self.line = inst.line;
1154 return self.fail(format!(
1155 "nothing in the text says what {} produces",
1156 inst.opcode.name()
1157 ));
1158 }
1159 }
1160 }
1161 Ok(types)
1162 }
1163
1164 fn build_inst(
1165 &mut self,
1166 func: &mut Func,
1167 pending: &PendingInst<'a>,
1168 types: &[Option<Type>],
1169 ) -> Result<Inst, ParseError> {
1170 let results: Vec<Type> = pending
1171 .results
1172 .iter()
1173 .map(|&number| types[number as usize].unwrap_or(Type::VOID))
1174 .collect();
1175 let args: Vec<Value> =
1176 pending.args.iter().map(|&number| Value::from_usize(number as usize)).collect();
1177 let arg_list = func.push_values(&args);
1178
1179 let extra = match &pending.extra {
1180 PendingExtra::None => Extra::None,
1181 PendingExtra::Imm(text) => {
1182 let ty = results.first().copied().unwrap_or(Type::VOID);
1183 self.line = pending.line;
1184 let imm = self.imm(text, ty)?;
1185 Extra::Imm(func.add_imm(imm))
1186 }
1187 PendingExtra::Symbol(symbol) => Extra::Symbol(*symbol),
1188 PendingExtra::IntPred(pred) => Extra::IntPred(*pred),
1189 PendingExtra::FloatPred(pred) => Extra::FloatPred(*pred),
1190 PendingExtra::Mem(info) => Extra::Mem(func.add_mem(*info)),
1191 PendingExtra::VaObject(info, slots) => {
1192 let mem = func.add_mem(*info);
1193 let slots = func.push_slots(slots);
1194 Extra::VaObject(func.add_va_object(VaInfo { mem, slots }))
1195 }
1196 PendingExtra::Rmw(op, info) => Extra::Rmw(*op, func.add_mem(*info)),
1197 PendingExtra::Order(order) => Extra::Order(*order),
1198 PendingExtra::Class(class) => Extra::Class(*class),
1199 PendingExtra::Owner(owner) => Extra::Owner(*owner),
1200 PendingExtra::Node(node) => Extra::Node(*node),
1201 PendingExtra::Reason(reason) => Extra::Reason(*reason),
1202 PendingExtra::Targets(targets) => {
1203 let calls = build_calls(func, targets);
1204 Extra::Targets(func.push_block_calls(&calls))
1205 }
1206 PendingExtra::Call { callee, signature, abis } => {
1207 let named = signature.params.len();
1208 if abis.iter().take(named).any(|&abi| abi != Abi::Plain) {
1209 self.line = pending.line;
1210 return self.fail(
1211 "the signature is what says how an argument it names travels".to_string(),
1212 );
1213 }
1214 let varargs = match abis.get(named.min(abis.len())..) {
1215 Some(rest) if rest.iter().any(|&abi| abi != Abi::Plain) => rest,
1216 _ => &[],
1217 };
1218 let varargs = func.push_abis(varargs);
1219 let sig = func.add_signature(signature.clone());
1220 Extra::Call(func.add_call(CallInfo { callee: *callee, signature: sig, varargs }))
1221 }
1222 PendingExtra::Switch { targets, cases } => {
1223 let ty = pending
1224 .args
1225 .first()
1226 .and_then(|&number| types[number as usize])
1227 .unwrap_or(Type::VOID);
1228 self.line = pending.line;
1229 let mut imms = Vec::with_capacity(cases.len());
1230 for case in cases {
1231 imms.push(self.imm(case, ty)?);
1232 }
1233 let calls = build_calls(func, targets);
1234 let targets = func.push_block_calls(&calls);
1235 let cases = func.push_imms(&imms);
1236 Extra::Switch(func.add_switch(SwitchInfo { targets, cases }))
1237 }
1238 PendingExtra::Asm { template, constraints, clobbers, targets } => {
1239 let calls = build_calls(func, targets);
1240 let targets = func.push_block_calls(&calls);
1241 Extra::Asm(func.add_asm(AsmInfo {
1242 template: *template,
1243 constraints: *constraints,
1244 clobbers: *clobbers,
1245 targets,
1246 }))
1247 }
1248 };
1249
1250 let data = InstData {
1251 opcode: pending.opcode,
1252 flags: pending.flags,
1253 args: arg_list,
1254 extra,
1255 ..InstData::new(pending.opcode)
1256 };
1257 Ok(func.create_inst(data, &results, Span::DUMMY))
1258 }
1259
1260 fn line_of(&self, blocks: &[PendingBlock<'a>], number: u32) -> u32 {
1262 for pending in blocks {
1263 for inst in &pending.insts {
1264 if inst.results.contains(&number) {
1265 return inst.line;
1266 }
1267 }
1268 }
1269 self.line
1270 }
1271
1272 fn imm(&mut self, text: &str, ty: Type) -> Result<Imm, ParseError> {
1276 let scalar = if ty.is_vector() { ty.lane() } else { ty };
1277 if scalar.is_int() {
1278 match parse_i128(text) {
1279 Some(value) => Ok(Imm::int(value, scalar)),
1280 None => self.fail(format!("`{text}` is not an {scalar}")),
1281 }
1282 } else {
1283 match text.strip_prefix("0x").and_then(|rest| u128::from_str_radix(rest, 16).ok()) {
1284 Some(bits) => Ok(Imm::from_bits(bits)),
1285 None => self.fail(format!("`{text}` is not the bits of a {scalar}")),
1286 }
1287 }
1288 }
1289
1290 fn imm_text(&mut self) -> Result<&'a str, ParseError> {
1292 self.spaces();
1293 let start = self.pos;
1294 if self.at("-") {
1295 self.pos += 1;
1296 }
1297 while self.peek().is_some_and(|byte| byte.is_ascii_alphanumeric()) {
1298 self.pos += 1;
1299 }
1300 if self.pos == start {
1301 return self.fail("a constant was expected");
1302 }
1303 Ok(&self.text[start..self.pos])
1304 }
1305
1306 fn ty(&mut self) -> Result<Type, ParseError> {
1307 let word = self.word();
1308 match Type::parse(word) {
1309 Some(ty) => Ok(ty),
1310 None => self.fail(format!("`{word}` is not a type")),
1311 }
1312 }
1313
1314 fn value_ref(&mut self) -> Result<u32, ParseError> {
1316 self.expect("%")?;
1317 self.u32()
1318 }
1319
1320 fn value_list(&mut self) -> Result<Vec<u32>, ParseError> {
1322 let mut values = Vec::new();
1323 if !self.peek_is("%") {
1324 return Ok(values);
1325 }
1326 loop {
1327 values.push(self.value_ref()?);
1328 let save = self.pos;
1329 if !self.eat(",") {
1330 return Ok(values);
1331 }
1332 if !self.peek_is("%") {
1333 self.pos = save;
1334 return Ok(values);
1335 }
1336 }
1337 }
1338
1339 fn call_args(&mut self) -> Result<(Vec<u32>, Vec<Abi>), ParseError> {
1342 let mut values = Vec::new();
1343 let mut abis = Vec::new();
1344 if !self.peek_is("%") {
1345 return Ok((values, abis));
1346 }
1347 loop {
1348 values.push(self.value_ref()?);
1349 abis.push(self.abi()?);
1350 let save = self.pos;
1351 if !self.eat(",") {
1352 return Ok((values, abis));
1353 }
1354 if !self.peek_is("%") {
1355 self.pos = save;
1356 return Ok((values, abis));
1357 }
1358 }
1359 }
1360
1361 fn block_ref(&mut self) -> Result<u32, ParseError> {
1363 let word = self.word();
1364 match word.strip_prefix("block").and_then(parse_u32) {
1365 Some(number) => Ok(number),
1366 None => self.fail(format!("`{word}` is not a block")),
1367 }
1368 }
1369
1370 fn meta_ref(&mut self) -> Result<Meta, ParseError> {
1372 self.expect("!")?;
1373 let index = self.u32()?;
1374 let seen = self.meta_used.is_none_or(|(used, _)| index > used);
1375 if seen {
1376 self.meta_used = Some((index, self.line));
1377 }
1378 Ok(Idx::from_usize(index as usize))
1379 }
1380
1381 fn symbol(&mut self) -> Result<Symbol, ParseError> {
1383 self.expect("@")?;
1384 let start = self.pos;
1385 while self.peek().is_some_and(is_name_byte) {
1386 self.pos += 1;
1387 }
1388 if self.pos == start {
1389 return self.fail("a name was expected");
1390 }
1391 let name = &self.text[start..self.pos];
1392 Ok(self.names.intern(name))
1393 }
1394
1395 fn symbol_from_string(&mut self) -> Result<Symbol, ParseError> {
1397 let text = self.quoted_str()?;
1398 Ok(self.names.intern(&text))
1399 }
1400
1401 fn quoted_str(&mut self) -> Result<String, ParseError> {
1403 let bytes = self.string()?;
1404 match String::from_utf8(bytes) {
1405 Ok(text) => Ok(text),
1406 Err(_) => self.fail("that string is not text"),
1407 }
1408 }
1409
1410 fn string(&mut self) -> Result<Vec<u8>, ParseError> {
1412 self.expect("\"")?;
1413 let mut bytes = Vec::new();
1414 loop {
1415 let Some(byte) = self.peek() else {
1416 return self.fail("that string is not closed");
1417 };
1418 self.pos += 1;
1419 match byte {
1420 b'"' => return Ok(bytes),
1421 b'\n' => return self.fail("that string is not closed"),
1422 b'\\' => {
1423 let escape = match self.peek() {
1424 Some(b'"') => b'"',
1425 Some(b'\\') => b'\\',
1426 _ => {
1427 let hex = self.text.get(self.pos..self.pos + 2);
1428 match hex.and_then(|hex| u8::from_str_radix(hex, 16).ok()) {
1429 Some(byte) => {
1430 self.pos += 2;
1431 bytes.push(byte);
1432 continue;
1433 }
1434 None => return self.fail("that is not an escape"),
1435 }
1436 }
1437 };
1438 self.pos += 1;
1439 bytes.push(escape);
1440 }
1441 _ => bytes.push(byte),
1442 }
1443 }
1444 }
1445
1446 fn u32(&mut self) -> Result<u32, ParseError> {
1447 let word = self.word();
1448 match parse_u32(word) {
1449 Some(number) => Ok(number),
1450 None => self.fail(format!("`{word}` is not a number")),
1451 }
1452 }
1453
1454 fn u16(&mut self) -> Result<u16, ParseError> {
1455 let word = self.word();
1456 match parse_u32(word).and_then(|number| u16::try_from(number).ok()) {
1457 Some(number) => Ok(number),
1458 None => self.fail(format!("`{word}` is not a small number")),
1459 }
1460 }
1461
1462 fn u64(&mut self) -> Result<u64, ParseError> {
1463 let word = self.word();
1464 match parse_u64(word) {
1465 Some(number) => Ok(number),
1466 None => self.fail(format!("`{word}` is not a number")),
1467 }
1468 }
1469
1470 fn i64(&mut self) -> Result<i64, ParseError> {
1471 let word = self.word();
1472 match parse_u64(word).and_then(|number| i64::try_from(number).ok()) {
1473 Some(number) => Ok(number),
1474 None => self.fail(format!("`{word}` is not an offset")),
1475 }
1476 }
1477
1478 fn parenthesised<T>(
1480 &mut self,
1481 from_name: impl Fn(&str) -> Option<T>,
1482 what: &str,
1483 ) -> Result<T, ParseError> {
1484 self.expect("(")?;
1485 let word = self.word();
1486 let Some(value) = from_name(word) else {
1487 return self.fail(format!("`{word}` is not {what}"));
1488 };
1489 self.expect(")")?;
1490 Ok(value)
1491 }
1492
1493 fn fail<T>(&self, message: impl Into<String>) -> Result<T, ParseError> {
1496 Err(ParseError { line: self.line, message: message.into() })
1497 }
1498
1499 fn peek(&self) -> Option<u8> {
1500 self.text.as_bytes().get(self.pos).copied()
1501 }
1502
1503 fn at(&self, text: &str) -> bool {
1504 self.text[self.pos..].starts_with(text)
1505 }
1506
1507 fn at_end(&self) -> bool {
1508 self.pos >= self.text.len()
1509 }
1510
1511 fn peek_is(&self, text: &str) -> bool {
1513 self.text[self.pos..].trim_start_matches([' ', '\t']).starts_with(text)
1514 }
1515
1516 fn spaces(&mut self) {
1517 while matches!(self.peek(), Some(b' ' | b'\t')) {
1518 self.pos += 1;
1519 }
1520 }
1521
1522 fn eat(&mut self, text: &str) -> bool {
1523 self.spaces();
1524 if self.at(text) {
1525 self.pos += text.len();
1526 return true;
1527 }
1528 false
1529 }
1530
1531 fn expect(&mut self, text: &str) -> Result<(), ParseError> {
1532 if self.eat(text) {
1533 return Ok(());
1534 }
1535 self.fail(format!("`{text}` was expected"))
1536 }
1537
1538 fn word(&mut self) -> &'a str {
1540 self.spaces();
1541 self.glued_word()
1542 }
1543
1544 fn glued_word(&mut self) -> &'a str {
1546 let start = self.pos;
1547 while self.peek().is_some_and(|byte| byte.is_ascii_alphanumeric() || byte == b'_') {
1548 self.pos += 1;
1549 }
1550 &self.text[start..self.pos]
1551 }
1552
1553 fn peek_word(&self) -> &'a str {
1555 let rest = self.text[self.pos..].trim_start_matches([' ', '\t']);
1556 let end =
1557 rest.find(|c: char| !(c.is_ascii_alphanumeric() || c == '_')).unwrap_or(rest.len());
1558 &rest[..end]
1559 }
1560
1561 fn eat_word(&mut self, word: &str) -> bool {
1563 if self.peek_word() == word {
1564 self.word();
1565 return true;
1566 }
1567 false
1568 }
1569
1570 fn end_of_line(&mut self) -> Result<(), ParseError> {
1571 self.spaces();
1572 if self.at_end() {
1573 return Ok(());
1574 }
1575 if self.at("\n") {
1576 self.pos += 1;
1577 self.line += 1;
1578 return Ok(());
1579 }
1580 let rest = &self.text[self.pos..];
1581 let end = rest.find('\n').unwrap_or(rest.len());
1582 self.fail(format!("`{}` is left over at the end of the line", &rest[..end]))
1583 }
1584
1585 fn skip_blank_lines(&mut self) {
1586 loop {
1587 let save = self.pos;
1588 self.spaces();
1589 if self.at("\n") {
1590 self.pos += 1;
1591 self.line += 1;
1592 } else {
1593 self.pos = save;
1594 return;
1595 }
1596 }
1597 }
1598}
1599
1600fn inst_calls<'p>(inst: &'p PendingInst<'_>) -> &'p [PendingCall] {
1602 match &inst.extra {
1603 PendingExtra::Targets(targets)
1604 | PendingExtra::Switch { targets, .. }
1605 | PendingExtra::Asm { targets, .. } => targets,
1606 _ => &[],
1607 }
1608}
1609
1610fn build_calls(func: &mut Func, targets: &[PendingCall]) -> Vec<BlockCall> {
1612 targets
1613 .iter()
1614 .map(|call| {
1615 let args: Vec<Value> =
1616 call.args.iter().map(|&number| Value::from_usize(number as usize)).collect();
1617 BlockCall {
1618 block: Block::from_usize(call.block as usize),
1619 args: func.push_values(&args),
1620 }
1621 })
1622 .collect()
1623}
1624
1625fn result_types(inst: &PendingInst<'_>, types: &[Option<Type>]) -> Option<Vec<Type>> {
1630 let mem = gives_mem(inst);
1631 let mut written = ordinary_result_types(inst, types, mem)?;
1632 if mem {
1633 written.push(Type::MEM);
1634 }
1635 Some(written)
1636}
1637
1638fn gives_mem(inst: &PendingInst<'_>) -> bool {
1644 inst.opcode == Opcode::MemEntry || (inst.mem.is_some() && inst.opcode.writes_memory())
1645}
1646
1647fn ordinary_result_types(
1649 inst: &PendingInst<'_>,
1650 types: &[Option<Type>],
1651 mem: bool,
1652) -> Option<Vec<Type>> {
1653 if inst.results.len().saturating_sub(usize::from(mem)) == 0 {
1654 return Some(Vec::new());
1655 }
1656 if !inst.written.is_empty() {
1657 return Some(inst.written.clone());
1658 }
1659 match inst.opcode {
1660 Opcode::GlobalAddr | Opcode::BlockAddr | Opcode::Alloca => Some(vec![Type::PTR]),
1661 Opcode::CapOf
1662 | Opcode::CapLoad
1663 | Opcode::CapNull
1664 | Opcode::CapNarrow
1665 | Opcode::CapRecover => Some(vec![Type::CAP]),
1666 Opcode::ICmp | Opcode::FCmp => {
1667 let ty = arg_type(inst, types)?;
1668 Some(vec![ty.with_lane(Type::I1)])
1669 }
1670 Opcode::Call | Opcode::CallIndirect | Opcode::TailCall => match &inst.extra {
1671 PendingExtra::Call { signature, .. } => Some(signature.return_types().collect()),
1672 _ => None,
1673 },
1674 _ => Some(vec![arg_type(inst, types)?]),
1675 }
1676}
1677
1678fn arg_type(inst: &PendingInst<'_>, types: &[Option<Type>]) -> Option<Type> {
1680 let &first = inst.args.first()?;
1681 *types.get(first as usize)?
1682}
1683
1684fn parse_u64(text: &str) -> Option<u64> {
1686 if text.is_empty() || (text.starts_with('0') && text.len() > 1) {
1687 return None;
1688 }
1689 if !text.bytes().all(|byte| byte.is_ascii_digit()) {
1690 return None;
1691 }
1692 text.parse().ok()
1693}
1694
1695fn parse_u32(text: &str) -> Option<u32> {
1696 parse_u64(text).and_then(|number| u32::try_from(number).ok())
1697}
1698
1699fn parse_i128(text: &str) -> Option<i128> {
1701 let (negative, digits) = match text.strip_prefix('-') {
1702 Some(rest) => (true, rest),
1703 None => (false, text),
1704 };
1705 if digits.is_empty() || (digits.starts_with('0') && digits.len() > 1) {
1706 return None;
1707 }
1708 if negative && digits == "0" {
1709 return None;
1710 }
1711 if !digits.bytes().all(|byte| byte.is_ascii_digit()) {
1712 return None;
1713 }
1714 let magnitude: u128 = digits.parse().ok()?;
1715 if negative {
1716 (magnitude <= 1 << 127).then(|| (magnitude as i128).wrapping_neg())
1719 } else {
1720 i128::try_from(magnitude).ok()
1721 }
1722}
1723
1724fn is_name_byte(byte: u8) -> bool {
1732 byte.is_ascii_alphanumeric() || matches!(byte, b'_' | b'.' | b'$') || byte >= 0x80
1733}
1734
1735#[cfg(test)]
1736mod tests {
1737 use rucc_base::Interner;
1738
1739 use super::*;
1740 use crate::fixtures::{EXAMPLE, SAFETY, SYMBOLS, ZOO};
1741 use crate::print;
1742
1743 fn round_trip(text: &str) -> String {
1745 let mut names = Interner::new();
1746 let module = match parse(text, &mut names) {
1747 Ok(module) => module,
1748 Err(error) => panic!("{error}"),
1749 };
1750 print(&module, &names)
1751 }
1752
1753 fn error(text: &str) -> String {
1754 let mut names = Interner::new();
1755 match parse(text, &mut names) {
1756 Ok(_) => panic!("that was expected to be turned down"),
1757 Err(error) => error.to_string(),
1758 }
1759 }
1760
1761 const HEADER: &str = "\
1762; ModuleID = 'example.c'
1763; format 0
1764target triple = \"x86_64-unknown-linux-gnu\"
1765target datalayout = \"e-p:64:64-i64:64-f80:128-S128\"
1766";
1767
1768 #[test]
1769 fn the_example_in_the_spec_comes_back_byte_for_byte() {
1770 assert_eq!(round_trip(EXAMPLE), EXAMPLE);
1771 }
1772
1773 #[test]
1774 fn one_of_almost_everything_comes_back_byte_for_byte() {
1775 assert_eq!(round_trip(ZOO), ZOO);
1776 }
1777
1778 #[test]
1779 fn a_memory_chain_comes_back_byte_for_byte() {
1780 let text = format!(
1781 "{HEADER}
1782func @f(ptr, i1) -> i32, linkage(external) {{
1783block0(%0: ptr, %1: i1):
1784 %2 = mem_entry
1785 %3 = iconst.i32 7
1786 %4 = store %3 -> %0, align 4 [mem %2]
1787 br_if %1, block1(%4), block2(%4)
1788
1789block1(%5: mem):
1790 %6 = load.i32 %0, align 4 [mem %5]
1791 %7 = memcpy %0, %0, size 4, align 4 [mem %5]
1792 return %6
1793
1794block2(%8: mem):
1795 %9 = atomic_load.i32 %0, align 4, acquire [mem %8]
1796 return %9
1797}}
1798"
1799 );
1800 assert_eq!(round_trip(&text), text);
1801 }
1802
1803 #[test]
1804 fn a_restrict_clique_and_base_come_back_byte_for_byte() {
1805 let text = format!(
1806 "{HEADER}
1807func @f(ptr, ptr), linkage(external) {{
1808block0(%0: ptr, %1: ptr):
1809 %2 = load.i32 %0, align 4, restrict(1, 1)
1810 store %2 -> %1, align 4, restrict(1, 2)
1811 return
1812}}
1813"
1814 );
1815 assert_eq!(round_trip(&text), text);
1816 }
1817
1818 #[test]
1819 fn the_padding_a_member_owns_comes_back_byte_for_byte() {
1820 let text = format!(
1824 "{HEADER}
1825func @f(ptr), linkage(external) {{
1826block0(%0: ptr):
1827 %1 = iconst.i8 1
1828 store %1 -> %0, align 1, owns 4
1829 return
1830}}
1831"
1832 );
1833 assert_eq!(round_trip(&text), text);
1834 }
1835
1836 #[test]
1837 fn a_restrict_base_in_no_clique_is_reported() {
1838 let text = format!(
1839 "{HEADER}
1840func @f(ptr), linkage(external) {{
1841block0(%0: ptr):
1842 %1 = load.i32 %0, align 4, restrict(0, 2)
1843 return
1844}}
1845"
1846 );
1847 assert!(round_trip(&text).contains("load.i32 %0, align 4\n"));
1850 }
1851
1852 #[test]
1853 fn the_shapes_a_symbol_comes_in_come_back_byte_for_byte() {
1854 assert_eq!(round_trip(SYMBOLS), SYMBOLS);
1855 }
1856
1857 #[test]
1858 fn every_safety_instruction_comes_back_byte_for_byte() {
1859 assert_eq!(round_trip(SAFETY), SAFETY);
1860 }
1861
1862 #[test]
1863 fn a_storage_class_nobody_has_heard_of_is_turned_down() {
1864 let text = format!(
1865 "{HEADER}\nfunc @f(ptr, i64), linkage(external) {{\n\
1866 block0(%0: ptr, %1: i64):\n meta_begin %0, %1, class heap\n return\n}}\n"
1867 );
1868 assert_eq!(error(&text), "line 8: `heap` is not a storage class");
1869 }
1870
1871 #[test]
1872 fn a_range_transferred_somewhere_there_is_no_name_for_is_turned_down() {
1873 let text = format!(
1874 "{HEADER}\nfunc @f(ptr, i64), linkage(external) {{\n\
1875 block0(%0: ptr, %1: i64):\n meta_transfer %0, %1, to hardware\n return\n}}\n"
1876 );
1877 assert_eq!(error(&text), "line 8: `hardware` is not somewhere a range can go");
1878 }
1879
1880 #[test]
1881 fn a_fact_nobody_has_heard_of_is_turned_down() {
1882 let text = format!(
1886 "{HEADER}\nfunc @f(ptr), linkage(external) {{\n\
1887 block0(%0: ptr):\n return\n\nfacts:\n %0 = !sorted\n}}\n"
1888 );
1889 assert_eq!(error(&text), "line 11: `sorted` is not a fact");
1890 }
1891
1892 #[test]
1893 fn a_value_said_twice_is_turned_down() {
1894 let text = format!(
1897 "{HEADER}\nfunc @f(ptr), linkage(external) {{\n\
1898 block0(%0: ptr):\n return\n\nfacts:\n %0 = !live\n %0 = !aligned(4)\n}}\n"
1899 );
1900 assert_eq!(error(&text), "line 12: %0 is said twice");
1901 }
1902
1903 #[test]
1904 fn a_fact_about_a_value_that_does_not_exist_is_turned_down() {
1905 let text = format!(
1906 "{HEADER}\nfunc @f(ptr), linkage(external) {{\n\
1907 block0(%0: ptr):\n return\n\nfacts:\n %3 = !live\n}}\n"
1908 );
1909 assert_eq!(error(&text), "line 11: %3 is used and never defined");
1910 }
1911
1912 #[test]
1913 fn a_plane_entry_nobody_has_heard_of_is_turned_down() {
1914 let text = format!("{HEADER}\n!0 = plane unwritten\n");
1915 assert_eq!(error(&text), "line 6: `unwritten` is not a plane entry");
1916 }
1917
1918 #[test]
1919 fn a_metadata_node_of_no_known_kind_is_turned_down() {
1920 let text = format!("{HEADER}\n!0 = scope \"outer\"\n");
1921 assert_eq!(error(&text), "line 6: `scope` is not a kind of metadata node");
1922 }
1923
1924 #[test]
1925 fn a_plane_entry_naming_a_node_that_comes_later_is_turned_down() {
1926 let text = format!("{HEADER}\n!0 = plane !1\n!1 = tbaa \"int\", offset 0\n");
1929 assert_eq!(error(&text), "line 6: a metadata node names one that comes before it");
1930 }
1931
1932 #[test]
1933 fn a_name_that_is_not_ascii_comes_back_byte_for_byte() {
1934 let text = format!("{HEADER}\nglobal @été : i32 = 1, align 4, linkage(external)\n");
1938 assert_eq!(round_trip(&text), text);
1939 }
1940
1941 #[test]
1942 fn a_value_defined_after_it_is_used() {
1943 let text = format!(
1947 "{HEADER}
1948func @late() -> i64, linkage(external) {{
1949block0:
1950 jump block2
1951
1952block1(%0: i64):
1953 %1 = add %2, %0
1954 return %1
1955
1956block2:
1957 %2 = iconst.i64 7
1958 jump block1(%2)
1959}}
1960"
1961 );
1962 assert_eq!(round_trip(&text), text);
1963 }
1964
1965 #[test]
1966 fn what_the_abi_asks_of_a_parameter_comes_back_byte_for_byte() {
1967 let text = format!(
1970 "{HEADER}
1971func @f(ptr sret(24, align 8), ptr byval(16, align 8), i8 zext), linkage(external) {{
1972block0(%0: ptr, %1: ptr, %2: i8):
1973 return
1974}}
1975
1976func @g(i8 sext) -> i8 sext, linkage(external);
1977"
1978 );
1979 assert_eq!(round_trip(&text), text);
1980 }
1981
1982 #[test]
1983 fn a_word_that_is_not_an_attribute_is_not_read_as_one() {
1984 let text = format!(
1985 "{HEADER}
1986func @f(ptr inreg), linkage(external);
1987"
1988 );
1989 assert_eq!(error(&text), "line 6: `)` was expected");
1990 }
1991
1992 #[test]
1993 fn an_empty_module_is_its_header() {
1994 assert_eq!(round_trip(HEADER), HEADER);
1995 }
1996
1997 #[test]
1998 fn the_format_version_is_checked_before_anything_else() {
1999 let text = "; ModuleID = 'a.c'\n; format 99\n";
2000 assert_eq!(error(text), "line 2: this build reads format 0 and the text says format 99");
2001 }
2002
2003 #[test]
2004 fn an_opcode_nobody_has_is_reported_with_its_line() {
2005 let text = format!(
2006 "{HEADER}
2007func @f(), linkage(external) {{
2008block0:
2009 getelementptr %0
2010}}
2011"
2012 );
2013 assert_eq!(error(&text), "line 8: `getelementptr` is not an opcode");
2014 }
2015
2016 #[test]
2019 fn a_slot_written_as_something_that_is_not_one_is_reported() {
2020 let text = format!(
2021 "{HEADER}
2022func @f(ptr) -> ptr, linkage(external) {{
2023block0(%0: ptr):
2024 %1 = va_object %0, size 16, align 8, in(short 8 at 0)
2025 return %1
2026}}
2027"
2028 );
2029 assert_eq!(error(&text), "line 8: `short` is not how a slot is written");
2030 }
2031
2032 #[test]
2033 fn an_abi_on_an_argument_the_signature_names_is_turned_down() {
2034 let text = format!(
2037 "{HEADER}
2038func @f(ptr), linkage(external) {{
2039block0(%0: ptr):
2040 call @p(%0 byval(8, align 8)) : (ptr, ...)
2041 return
2042}}
2043"
2044 );
2045 assert_eq!(
2046 error(&text),
2047 "line 8: the signature is what says how an argument it names travels"
2048 );
2049 }
2050
2051 #[test]
2052 fn a_value_nothing_defines_is_reported() {
2053 let text = format!(
2054 "{HEADER}
2055func @f(i32) -> i32, linkage(external) {{
2056block0(%0: i32):
2057 %1 = add %0, %9
2058 return %1
2059}}
2060"
2061 );
2062 assert_eq!(error(&text), "line 8: %9 is used and never defined");
2063 }
2064
2065 #[test]
2066 fn a_block_nothing_defines_is_reported() {
2067 let text = format!(
2068 "{HEADER}
2069func @f(), linkage(external) {{
2070block0:
2071 jump block7
2072}}
2073"
2074 );
2075 assert_eq!(error(&text), "line 8: block7 is used and never defined");
2076 }
2077
2078 #[test]
2079 fn values_have_to_be_numbered_in_print_order() {
2080 let text = format!(
2081 "{HEADER}
2082func @f() -> i32, linkage(external) {{
2083block0:
2084 %1 = iconst.i32 0
2085 %0 = iconst.i32 1
2086 return %1
2087}}
2088"
2089 );
2090 assert_eq!(error(&text), "line 8: values are numbered in order and %0 comes next");
2091 }
2092
2093 #[test]
2094 fn blocks_have_to_be_numbered_in_print_order() {
2095 let text = format!(
2096 "{HEADER}
2097func @f(), linkage(external) {{
2098block1:
2099 return
2100}}
2101"
2102 );
2103 assert_eq!(error(&text), "line 7: blocks are numbered in order and block0 comes next");
2104 }
2105
2106 #[test]
2107 fn metadata_nobody_defines_is_reported() {
2108 let text = format!(
2109 "{HEADER}
2110func @f(ptr), linkage(external) {{
2111block0(%0: ptr):
2112 %1 = load.i32 %0, align 4, tbaa !3
2113 return
2114}}
2115"
2116 );
2117 assert_eq!(error(&text), "line 8: !3 is used and never defined");
2118 }
2119
2120 #[test]
2121 fn a_type_nothing_says_is_reported_rather_than_guessed() {
2122 let text = format!(
2123 "{HEADER}
2124func @f(), linkage(external) {{
2125block0:
2126 %0 = add
2127 return
2128}}
2129"
2130 );
2131 assert_eq!(error(&text), "line 8: nothing in the text says what add produces");
2132 }
2133
2134 #[test]
2135 fn a_line_with_something_left_on_it_is_turned_down() {
2136 let text = format!(
2137 "{HEADER}
2138global @x : i32 = 0, align 4, linkage(internal) and then some
2139"
2140 );
2141 assert_eq!(error(&text), "line 6: `and then some` is left over at the end of the line");
2142 }
2143
2144 #[test]
2145 fn a_constant_that_is_not_one_is_turned_down() {
2146 let text = format!(
2147 "{HEADER}
2148global @x : i32 = 007, align 4, linkage(internal)
2149"
2150 );
2151 assert_eq!(error(&text), "line 6: `007` is not an i32");
2152 }
2153
2154 #[test]
2155 fn an_image_that_holds_a_capability_is_turned_down() {
2156 let text = format!(
2161 "{HEADER}
2162global @x : cap = 0, align 8, linkage(internal)
2163"
2164 );
2165 assert_eq!(error(&text), "line 6: `0` is not the bits of a cap");
2166 }
2167
2168 #[test]
2169 fn a_number_is_read_the_way_the_printer_writes_it() {
2170 assert_eq!(parse_i128("-1"), Some(-1));
2171 assert_eq!(parse_i128("0"), Some(0));
2172 assert_eq!(parse_i128("-0"), None);
2173 assert_eq!(parse_i128("+1"), None);
2174 assert_eq!(parse_i128("01"), None);
2175 assert_eq!(parse_i128(""), None);
2176 assert_eq!(parse_i128("170141183460469231731687303715884105728"), None);
2177 assert_eq!(parse_i128("-170141183460469231731687303715884105728"), Some(i128::MIN));
2178 }
2179
2180 #[test]
2181 fn every_opcode_says_which_payload_it_carries() {
2182 for opcode in Opcode::all() {
2185 let kind = opcode.extra_kind();
2186 let expected = match opcode {
2187 Opcode::IConst | Opcode::FConst | Opcode::Splat => ExtraKind::Imm,
2188 Opcode::GlobalAddr | Opcode::TargetIntrinsic => ExtraKind::Symbol,
2189 Opcode::ICmp => ExtraKind::IntPred,
2190 Opcode::FCmp => ExtraKind::FloatPred,
2191 Opcode::Fence => ExtraKind::Order,
2192 Opcode::AtomicRmw => ExtraKind::Rmw,
2193 Opcode::Switch => ExtraKind::Switch,
2194 Opcode::InlineAsm => ExtraKind::Asm,
2195 Opcode::Jump | Opcode::BrIf | Opcode::BlockAddr | Opcode::IndirectBr => {
2196 ExtraKind::Targets
2197 }
2198 Opcode::Call | Opcode::CallIndirect | Opcode::TailCall => ExtraKind::Call,
2199 Opcode::Alloca
2200 | Opcode::Load
2201 | Opcode::Store
2202 | Opcode::Memcpy
2203 | Opcode::Memmove
2204 | Opcode::Memset
2205 | Opcode::AtomicLoad
2206 | Opcode::AtomicStore
2207 | Opcode::Cmpxchg
2208 | Opcode::CheckBounds
2209 | Opcode::CheckType
2210 | Opcode::CheckInit
2211 | Opcode::CheckRestrictRead
2212 | Opcode::CheckRestrictWrite
2213 | Opcode::RestrictEnter => ExtraKind::Mem,
2214 Opcode::VaObject => ExtraKind::VaObject,
2215 Opcode::MetaBegin => ExtraKind::Class,
2216 Opcode::MetaTransfer => ExtraKind::Owner,
2217 Opcode::MetaType => ExtraKind::Node,
2218 Opcode::SafeRegionBegin => ExtraKind::Reason,
2219 _ => ExtraKind::None,
2220 };
2221 assert_eq!(kind, expected, "{}", opcode.name());
2222 }
2223 }
2224}