1use std::fmt;
34
35use rucc_base::{Idx, Interner, Symbol};
36use rucc_diag::Span;
37use rucc_target::{TargetInfo, Triple};
38
39use crate::attrs::{AttrSet, Attrs, FpContract};
40use crate::func::Func;
41use crate::inst::{
42 Abi, AsmInfo, Block, BlockCall, CallInfo, Imm, Inst, InstData, MemInfo, Meta, MetaNode, Param,
43 Signature, SwitchInfo, Value,
44};
45use crate::module::{
46 Alias, AliasKind, DataLayout, Datum, Global, Linkage, Module, Reloc, TlsModel, Visibility,
47};
48use crate::{
49 Extra, ExtraKind, FORMAT_VERSION, Flags, FloatPred, IntPred, MemOrder, Opcode, RmwOp, Type,
50};
51
52#[derive(Clone, Debug, PartialEq, Eq)]
58pub struct ParseError {
59 pub line: u32,
61 pub message: String,
63}
64
65impl fmt::Display for ParseError {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 write!(f, "line {}: {}", self.line, self.message)
68 }
69}
70
71impl std::error::Error for ParseError {}
72
73pub fn parse(text: &str, names: &mut Interner) -> Result<Module, ParseError> {
82 Parser::new(text, names).module()
83}
84
85struct Parser<'a, 'n> {
87 text: &'a str,
88 pos: usize,
89 line: u32,
90 names: &'n mut Interner,
91 meta_used: Option<(u32, u32)>,
94}
95
96struct PendingBlock<'a> {
98 params: Vec<(u32, Type)>,
99 insts: Vec<PendingInst<'a>>,
100}
101
102struct PendingInst<'a> {
104 opcode: Opcode,
105 flags: Flags,
106 results: Vec<u32>,
107 written: Vec<Type>,
109 args: Vec<u32>,
110 extra: PendingExtra<'a>,
111 line: u32,
112}
113
114struct PendingCall {
116 block: u32,
117 args: Vec<u32>,
118}
119
120enum PendingExtra<'a> {
122 None,
123 Imm(&'a str),
125 Symbol(Symbol),
126 IntPred(IntPred),
127 FloatPred(FloatPred),
128 Mem(MemInfo),
129 Rmw(RmwOp, MemInfo),
130 Order(MemOrder),
131 Targets(Vec<PendingCall>),
132 Call {
133 callee: Option<Symbol>,
134 signature: Signature,
135 },
136 Switch {
137 targets: Vec<PendingCall>,
138 cases: Vec<&'a str>,
139 },
140 Asm {
141 template: Symbol,
142 constraints: Symbol,
143 clobbers: Symbol,
144 targets: Vec<PendingCall>,
145 },
146}
147
148impl<'a, 'n> Parser<'a, 'n> {
149 fn new(text: &'a str, names: &'n mut Interner) -> Self {
150 Parser { text, pos: 0, line: 1, names, meta_used: None }
151 }
152
153 fn module(mut self) -> Result<Module, ParseError> {
156 let name = self.header_name()?;
157 self.expect("; format ")?;
158 let version = self.u32()?;
159 if version != FORMAT_VERSION {
160 return self.fail(format!(
161 "this build reads format {FORMAT_VERSION} and the text says format {version}"
162 ));
163 }
164 self.end_of_line()?;
165
166 self.expect("target triple = ")?;
167 let triple = self.quoted_str()?;
168 let Ok(triple) = triple.parse::<Triple>() else {
169 return self.fail(format!("`{triple}` is not a target triple"));
170 };
171 self.end_of_line()?;
172
173 self.expect("target datalayout = ")?;
174 let layout = self.quoted_str()?;
175 let Some(datalayout) = DataLayout::parse(&layout) else {
176 return self.fail(format!("`{layout}` is not a data layout"));
177 };
178 self.end_of_line()?;
179
180 let name = self.names.intern(&name);
181 let mut module = Module::new(name, &TargetInfo::new(triple));
182 module.datalayout = datalayout;
183
184 loop {
185 self.skip_blank_lines();
186 if self.at_end() {
187 break;
188 }
189 match self.peek_word() {
190 "global" => self.global(&mut module)?,
191 "alias" | "ifunc" => self.alias(&mut module)?,
192 "func" => self.func(&mut module)?,
193 _ if self.at("!") => self.meta(&mut module)?,
194 other => return self.fail(format!("`{other}` does not start anything")),
195 }
196 }
197
198 if let Some((used, line)) = self.meta_used {
199 let count = module.counts().metadata as u32;
200 if used >= count {
201 self.line = line;
202 return self.fail(format!("!{used} is used and never defined"));
203 }
204 }
205 Ok(module)
206 }
207
208 fn header_name(&mut self) -> Result<String, ParseError> {
210 self.expect("; ModuleID = '")?;
211 let start = self.pos;
212 let Some(end) = self.text[start..].find('\'') else {
213 return self.fail("the module name is not closed");
214 };
215 let name = self.text[start..start + end].to_string();
216 self.pos = start + end + 1;
217 self.end_of_line()?;
218 Ok(name)
219 }
220
221 fn global(&mut self, module: &mut Module) -> Result<(), ParseError> {
224 self.expect("global")?;
225 let name = self.symbol()?;
226 self.expect(":")?;
227
228 let mut global = Global::new(name, 0, 1);
229 if self.eat_word("bytes") {
230 global.size = self.u64()?;
231 if self.eat("=") {
232 self.expect("{")?;
233 let mut data = Vec::new();
234 loop {
235 data.push(self.datum(module)?);
236 if !self.eat(",") {
237 break;
238 }
239 }
240 self.expect("}")?;
241 global.init = Some(module.push_data(&data));
242 }
243 } else {
244 let ty = self.ty()?;
245 self.expect("=")?;
246 let text = self.imm_text()?;
247 let value = self.imm(text, ty)?;
248 let datum = Datum::Scalar { ty, value: module.add_imm(value) };
249 global.size = datum.size(module);
250 global.init = Some(module.push_data(&[datum]));
251 }
252
253 while self.eat(",") {
254 match self.word() {
255 "align" => global.align = self.u32()?,
256 "linkage" => {
257 global.linkage = self.parenthesised(Linkage::from_name, "a linkage")?
258 }
259 "visibility" => {
260 global.visibility =
261 self.parenthesised(Visibility::from_name, "a visibility")?;
262 }
263 "tls" => {
264 global.tls =
265 Some(self.parenthesised(TlsModel::from_name, "a thread-local model")?);
266 }
267 "constant" => global.constant = true,
268 "section" => global.section = Some(self.symbol_from_string()?),
269 other => return self.fail(format!("a global has no `{other}`")),
270 }
271 }
272 self.end_of_line()?;
273 module.add_global(global);
274 Ok(())
275 }
276
277 fn datum(&mut self, module: &mut Module) -> Result<Datum, ParseError> {
279 match self.peek_word() {
280 "zero" => {
281 self.expect("zero")?;
282 Ok(Datum::Zero(self.u64()?))
283 }
284 "bytes" => {
285 self.expect("bytes")?;
286 let bytes = self.string()?;
287 Ok(Datum::Bytes(module.push_bytes(&bytes)))
288 }
289 "addr" => {
290 self.expect("addr")?;
291 self.expect(".")?;
292 let size = self.u32()?;
293 let symbol = self.symbol()?;
294 let addend = if self.eat("+") {
295 self.i64()?
296 } else if self.eat("-") {
297 let amount = self.i64()?;
298 match amount.checked_neg() {
299 Some(negated) => negated,
300 None => return self.fail("that offset has no negative"),
301 }
302 } else {
303 0
304 };
305 Ok(Datum::Addr(module.add_reloc(Reloc { symbol, addend, size })))
306 }
307 _ => {
308 let ty = self.ty()?;
309 let text = self.imm_text()?;
310 let value = self.imm(text, ty)?;
311 Ok(Datum::Scalar { ty, value: module.add_imm(value) })
312 }
313 }
314 }
315
316 fn alias(&mut self, module: &mut Module) -> Result<(), ParseError> {
317 let word = self.word();
318 let Some(kind) = AliasKind::from_name(word) else {
319 return self.fail(format!("`{word}` is not a kind of alias"));
320 };
321 let name = self.symbol()?;
322 self.expect("=")?;
323 let target = self.symbol()?;
324 let mut alias = Alias::new(name, target);
325 alias.kind = kind;
326 while self.eat(",") {
327 match self.word() {
328 "linkage" => alias.linkage = self.parenthesised(Linkage::from_name, "a linkage")?,
329 "visibility" => {
330 alias.visibility = self.parenthesised(Visibility::from_name, "a visibility")?;
331 }
332 other => return self.fail(format!("an alias has no `{other}`")),
333 }
334 }
335 self.end_of_line()?;
336 module.add_alias(alias);
337 Ok(())
338 }
339
340 fn meta(&mut self, module: &mut Module) -> Result<(), ParseError> {
341 let index = self.meta_ref()?;
342 let expected = module.counts().metadata as u32;
343 if index.raw() != expected {
344 return self.fail(format!("metadata is numbered in order and !{expected} comes next"));
345 }
346 self.expect("=")?;
347 self.expect("tbaa")?;
348 let name = self.symbol_from_string()?;
349 let mut node = MetaNode { name, parent: None, offset: 0 };
350 while self.eat(",") {
351 match self.word() {
352 "parent" => node.parent = Some(self.meta_ref()?),
353 "offset" => node.offset = self.u64()?,
354 other => return self.fail(format!("a metadata node has no `{other}`")),
355 }
356 }
357 if node.parent.is_some_and(|parent| parent.raw() >= index.raw()) {
358 return self.fail("a metadata node's parent comes before it");
359 }
360 self.end_of_line()?;
361 module.add_meta(node);
362 Ok(())
363 }
364
365 fn func(&mut self, module: &mut Module) -> Result<(), ParseError> {
368 self.expect("func")?;
369 let name = self.symbol()?;
370 let signature = self.signature()?;
371 let mut func = Func::new(name, signature);
372 while self.eat(",") {
373 match self.word() {
374 "linkage" => func.linkage = self.parenthesised(Linkage::from_name, "a linkage")?,
375 "visibility" => {
376 func.visibility = self.parenthesised(Visibility::from_name, "a visibility")?;
377 }
378 "attrs" => func.attrs = self.attrs()?,
379 "section" => func.section = Some(self.symbol_from_string()?),
380 other => return self.fail(format!("a function has no `{other}`")),
381 }
382 }
383 if self.eat(";") {
384 self.end_of_line()?;
385 module.add_func(func);
386 return Ok(());
387 }
388 self.expect("{")?;
389 self.end_of_line()?;
390 let blocks = self.body()?;
391 self.build(&mut func, &blocks)?;
392 module.add_func(func);
393 Ok(())
394 }
395
396 fn signature(&mut self) -> Result<Signature, ParseError> {
398 self.expect("(")?;
399 let mut signature = Signature::new();
400 if !self.eat(")") {
401 loop {
402 if self.eat("...") {
403 signature.variadic = true;
404 break;
405 }
406 signature.params.push(self.param()?);
407 if !self.eat(",") {
408 break;
409 }
410 }
411 self.expect(")")?;
412 }
413 if self.eat("->") {
414 if self.eat("(") {
415 loop {
416 signature.returns.push(self.param()?);
417 if !self.eat(",") {
418 break;
419 }
420 }
421 self.expect(")")?;
422 } else {
423 signature.returns.push(self.param()?);
424 }
425 }
426 Ok(signature)
427 }
428
429 fn param(&mut self) -> Result<Param, ParseError> {
431 let ty = self.ty()?;
432 let abi = match self.peek_word() {
433 "sext" => {
434 self.word();
435 Abi::Sext
436 }
437 "zext" => {
438 self.word();
439 Abi::Zext
440 }
441 word @ ("byval" | "sret") => {
442 let indirect = word == "byval";
443 self.word();
444 self.expect("(")?;
445 let size = self.u64()?;
446 self.expect(",")?;
447 self.expect("align")?;
448 let align = self.u32()?;
449 self.expect(")")?;
450 if indirect { Abi::ByVal { size, align } } else { Abi::Sret { size, align } }
451 }
452 _ => Abi::Plain,
453 };
454 Ok(Param { ty, abi })
455 }
456
457 fn attrs(&mut self) -> Result<Attrs, ParseError> {
458 self.expect("(")?;
459 let mut attrs = Attrs::NONE;
460 loop {
461 let word = self.word();
462 if self.eat("=") {
463 let value = self.word();
464 match word {
465 "fp_contract" => match FpContract::from_name(value) {
466 Some(contract) => attrs.fp_contract = contract,
467 None => return self.fail(format!("`{value}` is not a contraction")),
468 },
469 other => return self.fail(format!("`{other}` takes no value")),
470 }
471 } else {
472 match AttrSet::from_name(word) {
473 Some(attr) => attrs.set |= attr,
474 None => return self.fail(format!("`{word}` is not an attribute")),
475 }
476 }
477 if !self.eat(",") {
478 break;
479 }
480 }
481 self.expect(")")?;
482 Ok(attrs)
483 }
484
485 fn body(&mut self) -> Result<Vec<PendingBlock<'a>>, ParseError> {
487 let mut blocks: Vec<PendingBlock<'a>> = Vec::new();
488 loop {
489 self.skip_blank_lines();
490 if self.eat("}") {
491 self.end_of_line()?;
492 return Ok(blocks);
493 }
494 if self.at_end() {
495 return self.fail("the function is not closed");
496 }
497 if self.peek_word().starts_with("block") {
498 let number = self.block_ref()?;
499 if number as usize != blocks.len() {
500 return self.fail(format!(
501 "blocks are numbered in order and block{} comes next",
502 blocks.len()
503 ));
504 }
505 let mut params = Vec::new();
506 if self.eat("(") {
507 loop {
508 let value = self.value_ref()?;
509 self.expect(":")?;
510 params.push((value, self.ty()?));
511 if !self.eat(",") {
512 break;
513 }
514 }
515 self.expect(")")?;
516 }
517 self.expect(":")?;
518 self.end_of_line()?;
519 blocks.push(PendingBlock { params, insts: Vec::new() });
520 continue;
521 }
522 let inst = self.inst()?;
523 match blocks.last_mut() {
524 Some(block) => block.insts.push(inst),
525 None => return self.fail("an instruction before any block"),
526 }
527 }
528 }
529
530 fn inst(&mut self) -> Result<PendingInst<'a>, ParseError> {
532 let line = self.line;
533 let mut results = Vec::new();
534 if self.peek_is("%") {
535 results = self.value_list()?;
536 self.expect("=")?;
537 }
538
539 let word = self.word();
540 let Some(opcode) = Opcode::from_name(word) else {
541 return self.fail(format!("`{word}` is not an opcode"));
542 };
543 let (written, flags) = self.suffixes()?;
544
545 let mut args = Vec::new();
546 let extra = match opcode.extra_kind() {
547 ExtraKind::None => {
548 args = self.value_list()?;
549 PendingExtra::None
550 }
551 ExtraKind::Imm => PendingExtra::Imm(self.imm_text()?),
552 ExtraKind::Symbol => {
553 let symbol = self.symbol()?;
554 if self.eat("(") {
555 args = self.value_list()?;
556 self.expect(")")?;
557 }
558 PendingExtra::Symbol(symbol)
559 }
560 ExtraKind::IntPred => {
561 let word = self.word();
562 let Some(pred) = IntPred::from_name(word) else {
563 return self.fail(format!("`{word}` is not an integer comparison"));
564 };
565 args = self.value_list()?;
566 PendingExtra::IntPred(pred)
567 }
568 ExtraKind::FloatPred => {
569 let word = self.word();
570 let Some(pred) = FloatPred::from_name(word) else {
571 return self.fail(format!("`{word}` is not a floating point comparison"));
572 };
573 args = self.value_list()?;
574 PendingExtra::FloatPred(pred)
575 }
576 ExtraKind::Mem => {
577 if matches!(opcode, Opcode::Store | Opcode::AtomicStore) {
578 let value = self.value_ref()?;
580 self.expect("->")?;
581 args = vec![value, self.value_ref()?];
582 } else {
583 args = self.value_list()?;
584 }
585 PendingExtra::Mem(self.mem()?)
586 }
587 ExtraKind::Rmw => {
588 let word = self.word();
589 let Some(op) = RmwOp::from_name(word) else {
590 return self.fail(format!("`{word}` is not a read-modify-write"));
591 };
592 args = self.value_list()?;
593 PendingExtra::Rmw(op, self.mem()?)
594 }
595 ExtraKind::Order => {
596 let word = self.word();
597 let Some(order) = MemOrder::from_name(word) else {
598 return self.fail(format!("`{word}` is not an ordering"));
599 };
600 PendingExtra::Order(order)
601 }
602 ExtraKind::Targets => {
603 args = self.value_list()?;
604 if !args.is_empty() {
605 self.expect(",")?;
606 }
607 let mut targets = Vec::new();
608 loop {
609 targets.push(self.block_call()?);
610 if !self.eat(",") {
611 break;
612 }
613 }
614 PendingExtra::Targets(targets)
615 }
616 ExtraKind::Call => {
617 let callee = if self.peek_is("@") {
618 Some(self.symbol()?)
619 } else {
620 args.push(self.value_ref()?);
621 None
622 };
623 self.expect("(")?;
624 args.extend(self.value_list()?);
625 self.expect(")")?;
626 self.expect(":")?;
627 PendingExtra::Call { callee, signature: self.signature()? }
628 }
629 ExtraKind::Switch => {
630 args = self.value_list()?;
631 let mut targets = Vec::new();
632 let mut cases = Vec::new();
633 if self.eat(",") {
634 targets.push(self.block_call()?);
635 self.expect(",")?;
636 self.expect("[")?;
637 if !self.eat("]") {
638 loop {
639 cases.push(self.imm_text()?);
640 self.expect("=>")?;
641 targets.push(self.block_call()?);
642 if !self.eat(",") {
643 break;
644 }
645 }
646 self.expect("]")?;
647 }
648 }
649 PendingExtra::Switch { targets, cases }
650 }
651 ExtraKind::Asm => {
652 let template = self.symbol_from_string()?;
653 self.expect(",")?;
654 let constraints = self.symbol_from_string()?;
655 self.expect(",")?;
656 let clobbers = self.symbol_from_string()?;
657 self.expect("(")?;
658 args = self.value_list()?;
659 self.expect(")")?;
660 let mut targets = Vec::new();
661 if self.eat(",") {
662 self.expect("labels")?;
663 self.expect("[")?;
664 loop {
665 targets.push(self.block_call()?);
666 if !self.eat(",") {
667 break;
668 }
669 }
670 self.expect("]")?;
671 }
672 PendingExtra::Asm { template, constraints, clobbers, targets }
673 }
674 };
675 self.end_of_line()?;
676 Ok(PendingInst { opcode, flags, results, written, args, extra, line })
677 }
678
679 fn suffixes(&mut self) -> Result<(Vec<Type>, Flags), ParseError> {
681 let mut written = Vec::new();
682 let mut flags = Flags::NONE;
683 while self.at(".") {
684 self.pos += 1;
685 if self.at("(") {
686 self.pos += 1;
687 loop {
688 written.push(self.ty()?);
689 if !self.eat(",") {
690 break;
691 }
692 }
693 self.expect(")")?;
694 continue;
695 }
696 let word = self.glued_word();
697 if let Some(flag) = Flags::from_name(word) {
698 flags |= flag;
699 } else if let Some(ty) = Type::parse(word) {
700 written.push(ty);
701 } else {
702 return self.fail(format!("`{word}` is neither a type nor a flag"));
703 }
704 }
705 Ok((written, flags))
706 }
707
708 fn mem(&mut self) -> Result<MemInfo, ParseError> {
710 let mut info = MemInfo { size: 0, align: 1, order: MemOrder::NotAtomic, tbaa: None };
711 while self.eat(",") {
712 let word = self.word();
713 match word {
714 "size" => info.size = self.u64()?,
715 "align" => info.align = self.u32()?,
716 "tbaa" => info.tbaa = Some(self.meta_ref()?),
717 _ => match MemOrder::from_name(word) {
718 Some(order) => info.order = order,
719 None => return self.fail(format!("an access has no `{word}`")),
720 },
721 }
722 }
723 Ok(info)
724 }
725
726 fn block_call(&mut self) -> Result<PendingCall, ParseError> {
728 let block = self.block_ref()?;
729 let mut args = Vec::new();
730 if self.eat("(") {
731 args = self.value_list()?;
732 self.expect(")")?;
733 }
734 Ok(PendingCall { block, args })
735 }
736
737 fn build(&mut self, func: &mut Func, blocks: &[PendingBlock<'a>]) -> Result<(), ParseError> {
741 let count = self.check_numbering(blocks)?;
742 let types = self.value_types(blocks, count)?;
743
744 let mut next = 0;
745 for pending in blocks {
746 let block = func.create_block();
747 for &(number, ty) in &pending.params {
748 if number != next {
749 self.line = self.line_of(blocks, number);
750 return self
751 .fail(format!("values are numbered in order and %{next} comes next"));
752 }
753 func.append_param(block, ty);
754 next += 1;
755 }
756 for inst in &pending.insts {
757 if inst.results.first().is_some_and(|&first| first != next) {
758 self.line = inst.line;
759 return self
760 .fail(format!("values are numbered in order and %{next} comes next"));
761 }
762 let built = self.build_inst(func, inst, &types)?;
763 func.append_inst(block, built);
764 next += inst.results.len() as u32;
765 }
766 }
767 Ok(())
768 }
769
770 fn check_numbering(&mut self, blocks: &[PendingBlock<'a>]) -> Result<u32, ParseError> {
774 let mut count = 0;
775 for pending in blocks {
776 count += pending.params.len();
777 for inst in &pending.insts {
778 count += inst.results.len();
779 }
780 }
781 let count = count as u32;
782 let total = blocks.len() as u32;
783 for pending in blocks {
784 for inst in &pending.insts {
785 self.line = inst.line;
786 for &arg in &inst.args {
787 if arg >= count {
788 return self.fail(format!("%{arg} is used and never defined"));
789 }
790 }
791 for call in inst_calls(inst) {
792 if call.block >= total {
793 return self.fail(format!("block{} is used and never defined", call.block));
794 }
795 for &arg in &call.args {
796 if arg >= count {
797 return self.fail(format!("%{arg} is used and never defined"));
798 }
799 }
800 }
801 }
802 }
803 Ok(count)
804 }
805
806 fn value_types(
813 &mut self,
814 blocks: &[PendingBlock<'a>],
815 count: u32,
816 ) -> Result<Vec<Option<Type>>, ParseError> {
817 let mut types = vec![None; count as usize];
818 for pending in blocks {
819 for &(number, ty) in &pending.params {
820 types[number as usize] = Some(ty);
821 }
822 }
823 loop {
824 let mut progress = false;
825 for pending in blocks {
826 for inst in &pending.insts {
827 let Some(&first) = inst.results.first() else { continue };
828 if types[first as usize].is_some() {
829 continue;
830 }
831 let Some(resolved) = result_types(inst, &types) else { continue };
832 if resolved.len() != inst.results.len() {
833 self.line = inst.line;
834 return self.fail(format!(
835 "{} produces {} values and the text names {}",
836 inst.opcode.name(),
837 resolved.len(),
838 inst.results.len()
839 ));
840 }
841 for (&number, ty) in inst.results.iter().zip(resolved) {
842 types[number as usize] = Some(ty);
843 }
844 progress = true;
845 }
846 }
847 if !progress {
848 break;
849 }
850 }
851 for pending in blocks {
852 for inst in &pending.insts {
853 if inst.results.first().is_some_and(|&first| types[first as usize].is_none()) {
854 self.line = inst.line;
855 return self.fail(format!(
856 "nothing in the text says what {} produces",
857 inst.opcode.name()
858 ));
859 }
860 }
861 }
862 Ok(types)
863 }
864
865 fn build_inst(
866 &mut self,
867 func: &mut Func,
868 pending: &PendingInst<'a>,
869 types: &[Option<Type>],
870 ) -> Result<Inst, ParseError> {
871 let results: Vec<Type> = pending
872 .results
873 .iter()
874 .map(|&number| types[number as usize].unwrap_or(Type::VOID))
875 .collect();
876 let args: Vec<Value> =
877 pending.args.iter().map(|&number| Value::from_usize(number as usize)).collect();
878 let arg_list = func.push_values(&args);
879
880 let extra = match &pending.extra {
881 PendingExtra::None => Extra::None,
882 PendingExtra::Imm(text) => {
883 let ty = results.first().copied().unwrap_or(Type::VOID);
884 self.line = pending.line;
885 let imm = self.imm(text, ty)?;
886 Extra::Imm(func.add_imm(imm))
887 }
888 PendingExtra::Symbol(symbol) => Extra::Symbol(*symbol),
889 PendingExtra::IntPred(pred) => Extra::IntPred(*pred),
890 PendingExtra::FloatPred(pred) => Extra::FloatPred(*pred),
891 PendingExtra::Mem(info) => Extra::Mem(func.add_mem(*info)),
892 PendingExtra::Rmw(op, info) => Extra::Rmw(*op, func.add_mem(*info)),
893 PendingExtra::Order(order) => Extra::Order(*order),
894 PendingExtra::Targets(targets) => {
895 let calls = build_calls(func, targets);
896 Extra::Targets(func.push_block_calls(&calls))
897 }
898 PendingExtra::Call { callee, signature } => {
899 let sig = func.add_signature(signature.clone());
900 Extra::Call(func.add_call(CallInfo { callee: *callee, signature: sig }))
901 }
902 PendingExtra::Switch { targets, cases } => {
903 let ty = pending
904 .args
905 .first()
906 .and_then(|&number| types[number as usize])
907 .unwrap_or(Type::VOID);
908 self.line = pending.line;
909 let mut imms = Vec::with_capacity(cases.len());
910 for case in cases {
911 imms.push(self.imm(case, ty)?);
912 }
913 let calls = build_calls(func, targets);
914 let targets = func.push_block_calls(&calls);
915 let cases = func.push_imms(&imms);
916 Extra::Switch(func.add_switch(SwitchInfo { targets, cases }))
917 }
918 PendingExtra::Asm { template, constraints, clobbers, targets } => {
919 let calls = build_calls(func, targets);
920 let targets = func.push_block_calls(&calls);
921 Extra::Asm(func.add_asm(AsmInfo {
922 template: *template,
923 constraints: *constraints,
924 clobbers: *clobbers,
925 targets,
926 }))
927 }
928 };
929
930 let data = InstData {
931 opcode: pending.opcode,
932 flags: pending.flags,
933 args: arg_list,
934 extra,
935 ..InstData::new(pending.opcode)
936 };
937 Ok(func.create_inst(data, &results, Span::DUMMY))
938 }
939
940 fn line_of(&self, blocks: &[PendingBlock<'a>], number: u32) -> u32 {
942 for pending in blocks {
943 for inst in &pending.insts {
944 if inst.results.contains(&number) {
945 return inst.line;
946 }
947 }
948 }
949 self.line
950 }
951
952 fn imm(&mut self, text: &str, ty: Type) -> Result<Imm, ParseError> {
956 let scalar = if ty.is_vector() { ty.lane() } else { ty };
957 if scalar.is_int() {
958 match parse_i128(text) {
959 Some(value) => Ok(Imm::int(value, scalar)),
960 None => self.fail(format!("`{text}` is not an {scalar}")),
961 }
962 } else {
963 match text.strip_prefix("0x").and_then(|rest| u128::from_str_radix(rest, 16).ok()) {
964 Some(bits) => Ok(Imm::from_bits(bits)),
965 None => self.fail(format!("`{text}` is not the bits of a {scalar}")),
966 }
967 }
968 }
969
970 fn imm_text(&mut self) -> Result<&'a str, ParseError> {
972 self.spaces();
973 let start = self.pos;
974 if self.at("-") {
975 self.pos += 1;
976 }
977 while self.peek().is_some_and(|byte| byte.is_ascii_alphanumeric()) {
978 self.pos += 1;
979 }
980 if self.pos == start {
981 return self.fail("a constant was expected");
982 }
983 Ok(&self.text[start..self.pos])
984 }
985
986 fn ty(&mut self) -> Result<Type, ParseError> {
987 let word = self.word();
988 match Type::parse(word) {
989 Some(ty) => Ok(ty),
990 None => self.fail(format!("`{word}` is not a type")),
991 }
992 }
993
994 fn value_ref(&mut self) -> Result<u32, ParseError> {
996 self.expect("%")?;
997 self.u32()
998 }
999
1000 fn value_list(&mut self) -> Result<Vec<u32>, ParseError> {
1002 let mut values = Vec::new();
1003 if !self.peek_is("%") {
1004 return Ok(values);
1005 }
1006 loop {
1007 values.push(self.value_ref()?);
1008 let save = self.pos;
1009 if !self.eat(",") {
1010 return Ok(values);
1011 }
1012 if !self.peek_is("%") {
1013 self.pos = save;
1014 return Ok(values);
1015 }
1016 }
1017 }
1018
1019 fn block_ref(&mut self) -> Result<u32, ParseError> {
1021 let word = self.word();
1022 match word.strip_prefix("block").and_then(parse_u32) {
1023 Some(number) => Ok(number),
1024 None => self.fail(format!("`{word}` is not a block")),
1025 }
1026 }
1027
1028 fn meta_ref(&mut self) -> Result<Meta, ParseError> {
1030 self.expect("!")?;
1031 let index = self.u32()?;
1032 let seen = self.meta_used.is_none_or(|(used, _)| index > used);
1033 if seen {
1034 self.meta_used = Some((index, self.line));
1035 }
1036 Ok(Idx::from_usize(index as usize))
1037 }
1038
1039 fn symbol(&mut self) -> Result<Symbol, ParseError> {
1041 self.expect("@")?;
1042 let start = self.pos;
1043 while self.peek().is_some_and(is_name_byte) {
1044 self.pos += 1;
1045 }
1046 if self.pos == start {
1047 return self.fail("a name was expected");
1048 }
1049 let name = &self.text[start..self.pos];
1050 Ok(self.names.intern(name))
1051 }
1052
1053 fn symbol_from_string(&mut self) -> Result<Symbol, ParseError> {
1055 let text = self.quoted_str()?;
1056 Ok(self.names.intern(&text))
1057 }
1058
1059 fn quoted_str(&mut self) -> Result<String, ParseError> {
1061 let bytes = self.string()?;
1062 match String::from_utf8(bytes) {
1063 Ok(text) => Ok(text),
1064 Err(_) => self.fail("that string is not text"),
1065 }
1066 }
1067
1068 fn string(&mut self) -> Result<Vec<u8>, ParseError> {
1070 self.expect("\"")?;
1071 let mut bytes = Vec::new();
1072 loop {
1073 let Some(byte) = self.peek() else {
1074 return self.fail("that string is not closed");
1075 };
1076 self.pos += 1;
1077 match byte {
1078 b'"' => return Ok(bytes),
1079 b'\n' => return self.fail("that string is not closed"),
1080 b'\\' => {
1081 let escape = match self.peek() {
1082 Some(b'"') => b'"',
1083 Some(b'\\') => b'\\',
1084 _ => {
1085 let hex = self.text.get(self.pos..self.pos + 2);
1086 match hex.and_then(|hex| u8::from_str_radix(hex, 16).ok()) {
1087 Some(byte) => {
1088 self.pos += 2;
1089 bytes.push(byte);
1090 continue;
1091 }
1092 None => return self.fail("that is not an escape"),
1093 }
1094 }
1095 };
1096 self.pos += 1;
1097 bytes.push(escape);
1098 }
1099 _ => bytes.push(byte),
1100 }
1101 }
1102 }
1103
1104 fn u32(&mut self) -> Result<u32, ParseError> {
1105 let word = self.word();
1106 match parse_u32(word) {
1107 Some(number) => Ok(number),
1108 None => self.fail(format!("`{word}` is not a number")),
1109 }
1110 }
1111
1112 fn u64(&mut self) -> Result<u64, ParseError> {
1113 let word = self.word();
1114 match parse_u64(word) {
1115 Some(number) => Ok(number),
1116 None => self.fail(format!("`{word}` is not a number")),
1117 }
1118 }
1119
1120 fn i64(&mut self) -> Result<i64, ParseError> {
1121 let word = self.word();
1122 match parse_u64(word).and_then(|number| i64::try_from(number).ok()) {
1123 Some(number) => Ok(number),
1124 None => self.fail(format!("`{word}` is not an offset")),
1125 }
1126 }
1127
1128 fn parenthesised<T>(
1130 &mut self,
1131 from_name: impl Fn(&str) -> Option<T>,
1132 what: &str,
1133 ) -> Result<T, ParseError> {
1134 self.expect("(")?;
1135 let word = self.word();
1136 let Some(value) = from_name(word) else {
1137 return self.fail(format!("`{word}` is not {what}"));
1138 };
1139 self.expect(")")?;
1140 Ok(value)
1141 }
1142
1143 fn fail<T>(&self, message: impl Into<String>) -> Result<T, ParseError> {
1146 Err(ParseError { line: self.line, message: message.into() })
1147 }
1148
1149 fn peek(&self) -> Option<u8> {
1150 self.text.as_bytes().get(self.pos).copied()
1151 }
1152
1153 fn at(&self, text: &str) -> bool {
1154 self.text[self.pos..].starts_with(text)
1155 }
1156
1157 fn at_end(&self) -> bool {
1158 self.pos >= self.text.len()
1159 }
1160
1161 fn peek_is(&self, text: &str) -> bool {
1163 self.text[self.pos..].trim_start_matches([' ', '\t']).starts_with(text)
1164 }
1165
1166 fn spaces(&mut self) {
1167 while matches!(self.peek(), Some(b' ' | b'\t')) {
1168 self.pos += 1;
1169 }
1170 }
1171
1172 fn eat(&mut self, text: &str) -> bool {
1173 self.spaces();
1174 if self.at(text) {
1175 self.pos += text.len();
1176 return true;
1177 }
1178 false
1179 }
1180
1181 fn expect(&mut self, text: &str) -> Result<(), ParseError> {
1182 if self.eat(text) {
1183 return Ok(());
1184 }
1185 self.fail(format!("`{text}` was expected"))
1186 }
1187
1188 fn word(&mut self) -> &'a str {
1190 self.spaces();
1191 self.glued_word()
1192 }
1193
1194 fn glued_word(&mut self) -> &'a str {
1196 let start = self.pos;
1197 while self.peek().is_some_and(|byte| byte.is_ascii_alphanumeric() || byte == b'_') {
1198 self.pos += 1;
1199 }
1200 &self.text[start..self.pos]
1201 }
1202
1203 fn peek_word(&self) -> &'a str {
1205 let rest = self.text[self.pos..].trim_start_matches([' ', '\t']);
1206 let end =
1207 rest.find(|c: char| !(c.is_ascii_alphanumeric() || c == '_')).unwrap_or(rest.len());
1208 &rest[..end]
1209 }
1210
1211 fn eat_word(&mut self, word: &str) -> bool {
1213 if self.peek_word() == word {
1214 self.word();
1215 return true;
1216 }
1217 false
1218 }
1219
1220 fn end_of_line(&mut self) -> Result<(), ParseError> {
1221 self.spaces();
1222 if self.at_end() {
1223 return Ok(());
1224 }
1225 if self.at("\n") {
1226 self.pos += 1;
1227 self.line += 1;
1228 return Ok(());
1229 }
1230 let rest = &self.text[self.pos..];
1231 let end = rest.find('\n').unwrap_or(rest.len());
1232 self.fail(format!("`{}` is left over at the end of the line", &rest[..end]))
1233 }
1234
1235 fn skip_blank_lines(&mut self) {
1236 loop {
1237 let save = self.pos;
1238 self.spaces();
1239 if self.at("\n") {
1240 self.pos += 1;
1241 self.line += 1;
1242 } else {
1243 self.pos = save;
1244 return;
1245 }
1246 }
1247 }
1248}
1249
1250fn inst_calls<'p>(inst: &'p PendingInst<'_>) -> &'p [PendingCall] {
1252 match &inst.extra {
1253 PendingExtra::Targets(targets)
1254 | PendingExtra::Switch { targets, .. }
1255 | PendingExtra::Asm { targets, .. } => targets,
1256 _ => &[],
1257 }
1258}
1259
1260fn build_calls(func: &mut Func, targets: &[PendingCall]) -> Vec<BlockCall> {
1262 targets
1263 .iter()
1264 .map(|call| {
1265 let args: Vec<Value> =
1266 call.args.iter().map(|&number| Value::from_usize(number as usize)).collect();
1267 BlockCall {
1268 block: Block::from_usize(call.block as usize),
1269 args: func.push_values(&args),
1270 }
1271 })
1272 .collect()
1273}
1274
1275fn result_types(inst: &PendingInst<'_>, types: &[Option<Type>]) -> Option<Vec<Type>> {
1280 if inst.results.is_empty() {
1281 return Some(Vec::new());
1282 }
1283 if !inst.written.is_empty() {
1284 return Some(inst.written.clone());
1285 }
1286 match inst.opcode {
1287 Opcode::GlobalAddr | Opcode::BlockAddr | Opcode::Alloca => Some(vec![Type::PTR]),
1288 Opcode::ICmp | Opcode::FCmp => {
1289 let ty = arg_type(inst, types)?;
1290 Some(vec![ty.with_lane(Type::I1)])
1291 }
1292 Opcode::Call | Opcode::CallIndirect | Opcode::TailCall => match &inst.extra {
1293 PendingExtra::Call { signature, .. } => Some(signature.return_types().collect()),
1294 _ => None,
1295 },
1296 _ => Some(vec![arg_type(inst, types)?]),
1297 }
1298}
1299
1300fn arg_type(inst: &PendingInst<'_>, types: &[Option<Type>]) -> Option<Type> {
1302 let &first = inst.args.first()?;
1303 *types.get(first as usize)?
1304}
1305
1306fn parse_u64(text: &str) -> Option<u64> {
1308 if text.is_empty() || (text.starts_with('0') && text.len() > 1) {
1309 return None;
1310 }
1311 if !text.bytes().all(|byte| byte.is_ascii_digit()) {
1312 return None;
1313 }
1314 text.parse().ok()
1315}
1316
1317fn parse_u32(text: &str) -> Option<u32> {
1318 parse_u64(text).and_then(|number| u32::try_from(number).ok())
1319}
1320
1321fn parse_i128(text: &str) -> Option<i128> {
1323 let (negative, digits) = match text.strip_prefix('-') {
1324 Some(rest) => (true, rest),
1325 None => (false, text),
1326 };
1327 if digits.is_empty() || (digits.starts_with('0') && digits.len() > 1) {
1328 return None;
1329 }
1330 if negative && digits == "0" {
1331 return None;
1332 }
1333 if !digits.bytes().all(|byte| byte.is_ascii_digit()) {
1334 return None;
1335 }
1336 let magnitude: u128 = digits.parse().ok()?;
1337 if negative {
1338 (magnitude <= 1 << 127).then(|| (magnitude as i128).wrapping_neg())
1341 } else {
1342 i128::try_from(magnitude).ok()
1343 }
1344}
1345
1346fn is_name_byte(byte: u8) -> bool {
1351 byte.is_ascii_alphanumeric() || matches!(byte, b'_' | b'.' | b'$')
1352}
1353
1354#[cfg(test)]
1355mod tests {
1356 use rucc_base::Interner;
1357
1358 use super::*;
1359 use crate::fixtures::{EXAMPLE, SYMBOLS, ZOO};
1360 use crate::print;
1361
1362 fn round_trip(text: &str) -> String {
1364 let mut names = Interner::new();
1365 let module = match parse(text, &mut names) {
1366 Ok(module) => module,
1367 Err(error) => panic!("{error}"),
1368 };
1369 print(&module, &names)
1370 }
1371
1372 fn error(text: &str) -> String {
1373 let mut names = Interner::new();
1374 match parse(text, &mut names) {
1375 Ok(_) => panic!("that was expected to be turned down"),
1376 Err(error) => error.to_string(),
1377 }
1378 }
1379
1380 const HEADER: &str = "\
1381; ModuleID = 'example.c'
1382; format 0
1383target triple = \"x86_64-unknown-linux-gnu\"
1384target datalayout = \"e-p:64:64-i64:64-f80:128-S128\"
1385";
1386
1387 #[test]
1388 fn the_example_in_the_spec_comes_back_byte_for_byte() {
1389 assert_eq!(round_trip(EXAMPLE), EXAMPLE);
1390 }
1391
1392 #[test]
1393 fn one_of_almost_everything_comes_back_byte_for_byte() {
1394 assert_eq!(round_trip(ZOO), ZOO);
1395 }
1396
1397 #[test]
1398 fn the_shapes_a_symbol_comes_in_come_back_byte_for_byte() {
1399 assert_eq!(round_trip(SYMBOLS), SYMBOLS);
1400 }
1401
1402 #[test]
1403 fn a_value_defined_after_it_is_used() {
1404 let text = format!(
1408 "{HEADER}
1409func @late() -> i64, linkage(external) {{
1410block0:
1411 jump block2
1412
1413block1(%0: i64):
1414 %1 = add %2, %0
1415 return %1
1416
1417block2:
1418 %2 = iconst.i64 7
1419 jump block1(%2)
1420}}
1421"
1422 );
1423 assert_eq!(round_trip(&text), text);
1424 }
1425
1426 #[test]
1427 fn what_the_abi_asks_of_a_parameter_comes_back_byte_for_byte() {
1428 let text = format!(
1431 "{HEADER}
1432func @f(ptr sret(24, align 8), ptr byval(16, align 8), i8 zext), linkage(external) {{
1433block0(%0: ptr, %1: ptr, %2: i8):
1434 return
1435}}
1436
1437func @g(i8 sext) -> i8 sext, linkage(external);
1438"
1439 );
1440 assert_eq!(round_trip(&text), text);
1441 }
1442
1443 #[test]
1444 fn a_word_that_is_not_an_attribute_is_not_read_as_one() {
1445 let text = format!(
1446 "{HEADER}
1447func @f(ptr inreg), linkage(external);
1448"
1449 );
1450 assert_eq!(error(&text), "line 6: `)` was expected");
1451 }
1452
1453 #[test]
1454 fn an_empty_module_is_its_header() {
1455 assert_eq!(round_trip(HEADER), HEADER);
1456 }
1457
1458 #[test]
1459 fn the_format_version_is_checked_before_anything_else() {
1460 let text = "; ModuleID = 'a.c'\n; format 99\n";
1461 assert_eq!(error(text), "line 2: this build reads format 0 and the text says format 99");
1462 }
1463
1464 #[test]
1465 fn an_opcode_nobody_has_is_reported_with_its_line() {
1466 let text = format!(
1467 "{HEADER}
1468func @f(), linkage(external) {{
1469block0:
1470 getelementptr %0
1471}}
1472"
1473 );
1474 assert_eq!(error(&text), "line 8: `getelementptr` is not an opcode");
1475 }
1476
1477 #[test]
1478 fn a_value_nothing_defines_is_reported() {
1479 let text = format!(
1480 "{HEADER}
1481func @f(i32) -> i32, linkage(external) {{
1482block0(%0: i32):
1483 %1 = add %0, %9
1484 return %1
1485}}
1486"
1487 );
1488 assert_eq!(error(&text), "line 8: %9 is used and never defined");
1489 }
1490
1491 #[test]
1492 fn a_block_nothing_defines_is_reported() {
1493 let text = format!(
1494 "{HEADER}
1495func @f(), linkage(external) {{
1496block0:
1497 jump block7
1498}}
1499"
1500 );
1501 assert_eq!(error(&text), "line 8: block7 is used and never defined");
1502 }
1503
1504 #[test]
1505 fn values_have_to_be_numbered_in_print_order() {
1506 let text = format!(
1507 "{HEADER}
1508func @f() -> i32, linkage(external) {{
1509block0:
1510 %1 = iconst.i32 0
1511 %0 = iconst.i32 1
1512 return %1
1513}}
1514"
1515 );
1516 assert_eq!(error(&text), "line 8: values are numbered in order and %0 comes next");
1517 }
1518
1519 #[test]
1520 fn blocks_have_to_be_numbered_in_print_order() {
1521 let text = format!(
1522 "{HEADER}
1523func @f(), linkage(external) {{
1524block1:
1525 return
1526}}
1527"
1528 );
1529 assert_eq!(error(&text), "line 7: blocks are numbered in order and block0 comes next");
1530 }
1531
1532 #[test]
1533 fn metadata_nobody_defines_is_reported() {
1534 let text = format!(
1535 "{HEADER}
1536func @f(ptr), linkage(external) {{
1537block0(%0: ptr):
1538 %1 = load.i32 %0, align 4, tbaa !3
1539 return
1540}}
1541"
1542 );
1543 assert_eq!(error(&text), "line 8: !3 is used and never defined");
1544 }
1545
1546 #[test]
1547 fn a_type_nothing_says_is_reported_rather_than_guessed() {
1548 let text = format!(
1549 "{HEADER}
1550func @f(), linkage(external) {{
1551block0:
1552 %0 = add
1553 return
1554}}
1555"
1556 );
1557 assert_eq!(error(&text), "line 8: nothing in the text says what add produces");
1558 }
1559
1560 #[test]
1561 fn a_line_with_something_left_on_it_is_turned_down() {
1562 let text = format!(
1563 "{HEADER}
1564global @x : i32 = 0, align 4, linkage(internal) and then some
1565"
1566 );
1567 assert_eq!(error(&text), "line 6: `and then some` is left over at the end of the line");
1568 }
1569
1570 #[test]
1571 fn a_constant_that_is_not_one_is_turned_down() {
1572 let text = format!(
1573 "{HEADER}
1574global @x : i32 = 007, align 4, linkage(internal)
1575"
1576 );
1577 assert_eq!(error(&text), "line 6: `007` is not an i32");
1578 }
1579
1580 #[test]
1581 fn a_number_is_read_the_way_the_printer_writes_it() {
1582 assert_eq!(parse_i128("-1"), Some(-1));
1583 assert_eq!(parse_i128("0"), Some(0));
1584 assert_eq!(parse_i128("-0"), None);
1585 assert_eq!(parse_i128("+1"), None);
1586 assert_eq!(parse_i128("01"), None);
1587 assert_eq!(parse_i128(""), None);
1588 assert_eq!(parse_i128("170141183460469231731687303715884105728"), None);
1589 assert_eq!(parse_i128("-170141183460469231731687303715884105728"), Some(i128::MIN));
1590 }
1591
1592 #[test]
1593 fn every_opcode_says_which_payload_it_carries() {
1594 for opcode in Opcode::all() {
1597 let kind = opcode.extra_kind();
1598 let expected = match opcode {
1599 Opcode::IConst | Opcode::FConst | Opcode::Splat => ExtraKind::Imm,
1600 Opcode::GlobalAddr | Opcode::TargetIntrinsic => ExtraKind::Symbol,
1601 Opcode::ICmp => ExtraKind::IntPred,
1602 Opcode::FCmp => ExtraKind::FloatPred,
1603 Opcode::Fence => ExtraKind::Order,
1604 Opcode::AtomicRmw => ExtraKind::Rmw,
1605 Opcode::Switch => ExtraKind::Switch,
1606 Opcode::InlineAsm => ExtraKind::Asm,
1607 Opcode::Jump | Opcode::BrIf | Opcode::BlockAddr | Opcode::IndirectBr => {
1608 ExtraKind::Targets
1609 }
1610 Opcode::Call | Opcode::CallIndirect | Opcode::TailCall => ExtraKind::Call,
1611 Opcode::Alloca
1612 | Opcode::Load
1613 | Opcode::Store
1614 | Opcode::Memcpy
1615 | Opcode::Memmove
1616 | Opcode::Memset
1617 | Opcode::AtomicLoad
1618 | Opcode::AtomicStore
1619 | Opcode::Cmpxchg => ExtraKind::Mem,
1620 _ => ExtraKind::None,
1621 };
1622 assert_eq!(kind, expected, "{}", opcode.name());
1623 }
1624 }
1625}