Skip to main content

llvm_ir_parser/
parser.rs

1//! Recursive-descent LLVM IR text format parser.
2//!
3//! Entry point: `parse(src) -> Result<(Context, Module), ParseError>`
4
5use std::collections::HashMap;
6use std::fmt;
7
8use llvm_ir::{
9    ArgId, Argument, BasicBlock, BlockId, ConstId, ConstantData, Context, FastMathFlags, FloatKind,
10    FloatPredicate, Function, GlobalId, GlobalVariable, InstrKind, Instruction, IntArithFlags,
11    IntPredicate, Linkage, Module, TailCallKind, TypeData, TypeId, ValueRef,
12};
13
14use crate::lexer::{Keyword, LexError, Lexer, Token};
15
16// ---------------------------------------------------------------------------
17// ParseError
18// ---------------------------------------------------------------------------
19
20/// Public API for `ParseError`.
21#[derive(Clone, Debug)]
22pub struct ParseError {
23    /// Public API for `line`.
24    pub line: usize,
25    /// Public API for `col`.
26    pub col: usize,
27    /// Public API for `message`.
28    pub message: String,
29}
30
31impl fmt::Display for ParseError {
32    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33        write!(
34            f,
35            "parse error at {}:{}: {}",
36            self.line, self.col, self.message
37        )
38    }
39}
40
41impl From<LexError> for ParseError {
42    fn from(e: LexError) -> Self {
43        ParseError {
44            line: e.line,
45            col: e.col,
46            message: e.message,
47        }
48    }
49}
50
51impl From<&LexError> for ParseError {
52    fn from(e: &LexError) -> Self {
53        ParseError {
54            line: e.line,
55            col: e.col,
56            message: e.message.clone(),
57        }
58    }
59}
60
61// ---------------------------------------------------------------------------
62// Parser state
63// ---------------------------------------------------------------------------
64
65struct Parser<'src> {
66    lex: Lexer<'src>,
67    ctx: Context,
68    module: Module,
69    /// Named block forward references: name → BlockId already allocated.
70    pending_blocks: HashMap<String, BlockId>,
71    /// Current function being parsed (None at module level).
72    current_func: Option<usize>, // index into module.functions
73    /// Local value table: name → ValueRef, for the current function.
74    locals: HashMap<String, ValueRef>,
75    /// Unnamed slots: slot number → ValueRef.
76    unnamed: HashMap<u64, ValueRef>,
77}
78
79impl<'src> Parser<'src> {
80    fn new(src: &'src str) -> Self {
81        Parser {
82            lex: Lexer::new(src),
83            ctx: Context::new(),
84            module: Module::new(""),
85            pending_blocks: HashMap::new(),
86            current_func: None,
87            locals: HashMap::new(),
88            unnamed: HashMap::new(),
89        }
90    }
91
92    fn err(&self, msg: impl Into<String>) -> ParseError {
93        ParseError {
94            line: self.lex.current_line(),
95            col: self.lex.current_col(),
96            message: msg.into(),
97        }
98    }
99
100    // -----------------------------------------------------------------------
101    // Top-level module parsing
102    // -----------------------------------------------------------------------
103
104    fn parse_module(&mut self) -> Result<(), ParseError> {
105        loop {
106            match self.lex.peek()? {
107                Token::Eof => break,
108                Token::Kw(Keyword::Source) => {
109                    self.parse_source_filename()?;
110                }
111                Token::Kw(Keyword::Target) => {
112                    self.parse_target()?;
113                }
114                Token::LocalIdent(_) => {
115                    self.parse_named_type_def()?;
116                }
117                Token::GlobalIdent(_) => {
118                    self.parse_global_or_function()?;
119                }
120                Token::Kw(Keyword::Define) => {
121                    self.parse_function(false)?;
122                }
123                Token::Kw(Keyword::Declare) => {
124                    self.parse_function(true)?;
125                }
126                Token::Bang => {
127                    self.parse_metadata_definition_or_skip()?;
128                }
129                _ => {
130                    let t = self.lex.next()?;
131                    return Err(self.err(format!("unexpected top-level token {:?}", t)));
132                }
133            }
134        }
135        Ok(())
136    }
137
138    fn parse_source_filename(&mut self) -> Result<(), ParseError> {
139        self.lex.expect_kw(&Keyword::Source)?;
140        self.lex.expect(&Token::Equal)?;
141        let s = self.lex.expect_string_lit()?;
142        self.module.source_filename = Some(s);
143        Ok(())
144    }
145
146    fn parse_target(&mut self) -> Result<(), ParseError> {
147        self.lex.expect_kw(&Keyword::Target)?;
148        match self.lex.next()? {
149            Token::Kw(Keyword::Triple) => {
150                self.lex.expect(&Token::Equal)?;
151                let s = self.lex.expect_string_lit()?;
152                self.module.target_triple = Some(s);
153            }
154            Token::Kw(Keyword::Datalayout) => {
155                self.lex.expect(&Token::Equal)?;
156                let s = self.lex.expect_string_lit()?;
157                self.module.data_layout = Some(s);
158            }
159            t => return Err(self.err(format!("unexpected after 'target': {:?}", t))),
160        }
161        Ok(())
162    }
163
164    fn parse_named_type_def(&mut self) -> Result<(), ParseError> {
165        // %Name = type <body>
166        let name = self.lex.expect_local_ident()?;
167        self.lex.expect(&Token::Equal)?;
168        self.lex.expect_kw(&Keyword::Type)?;
169        // Allocate the TypeId now (possibly opaque).
170        let ty_id = self.ctx.mk_struct_named(name.clone());
171        // Parse body.
172        match self.lex.peek()? {
173            Token::Kw(Keyword::Void) => {
174                // Opaque struct — leave body empty.
175                self.lex.next()?;
176            }
177            _ => {
178                let fields = self.parse_struct_body()?;
179                self.ctx.define_struct_body(ty_id, fields.0, fields.1);
180            }
181        }
182        self.module.register_named_type(name, ty_id);
183        Ok(())
184    }
185
186    fn parse_global_or_function(&mut self) -> Result<(), ParseError> {
187        // @name = [linkage] (global|constant) type [initializer]
188        let name = self.lex.expect_global_ident()?;
189        self.lex.expect(&Token::Equal)?;
190        let linkage = self.parse_optional_linkage();
191        match self.lex.peek()? {
192            Token::Kw(Keyword::Global) | Token::Kw(Keyword::Constant) => {
193                let is_const = matches!(self.lex.peek()?, Token::Kw(Keyword::Constant));
194                self.lex.next()?;
195                let ty = self.parse_type()?;
196                let init = if !self.at_statement_end() {
197                    let c = self.parse_constant(ty)?;
198                    Some(c)
199                } else {
200                    None
201                };
202                let gv = GlobalVariable {
203                    name,
204                    ty,
205                    initializer: init,
206                    is_constant: is_const,
207                    linkage,
208                };
209                self.module.add_global(gv);
210            }
211            _ => {
212                return Err(self.err(format!("expected 'global' or 'constant' for @{}", name)));
213            }
214        }
215        Ok(())
216    }
217
218    fn at_statement_end(&mut self) -> bool {
219        matches!(
220            self.lex.peek(),
221            Ok(Token::Eof)
222                | Ok(Token::Kw(Keyword::Define))
223                | Ok(Token::Kw(Keyword::Declare))
224                | Ok(Token::GlobalIdent(_))
225                | Ok(Token::LocalIdent(_))
226                | Ok(Token::Kw(Keyword::Target))
227                | Ok(Token::Kw(Keyword::Source))
228                | Ok(Token::Bang)
229        )
230    }
231
232    // -----------------------------------------------------------------------
233    // Linkage
234    // -----------------------------------------------------------------------
235
236    fn parse_optional_linkage(&mut self) -> Linkage {
237        match self.lex.peek() {
238            Ok(Token::Kw(Keyword::Private)) => {
239                let _ = self.lex.next();
240                Linkage::Private
241            }
242            Ok(Token::Kw(Keyword::Internal)) => {
243                let _ = self.lex.next();
244                Linkage::Internal
245            }
246            Ok(Token::Kw(Keyword::External)) => {
247                let _ = self.lex.next();
248                Linkage::External
249            }
250            Ok(Token::Kw(Keyword::Weak)) => {
251                let _ = self.lex.next();
252                Linkage::Weak
253            }
254            Ok(Token::Kw(Keyword::WeakOdr)) => {
255                let _ = self.lex.next();
256                Linkage::WeakOdr
257            }
258            Ok(Token::Kw(Keyword::Linkonce)) => {
259                let _ = self.lex.next();
260                Linkage::LinkOnce
261            }
262            Ok(Token::Kw(Keyword::LinkonceOdr)) => {
263                let _ = self.lex.next();
264                Linkage::LinkOnceOdr
265            }
266            Ok(Token::Kw(Keyword::Common)) => {
267                let _ = self.lex.next();
268                Linkage::Common
269            }
270            Ok(Token::Kw(Keyword::AvailableExternally)) => {
271                let _ = self.lex.next();
272                Linkage::AvailableExternally
273            }
274            _ => Linkage::External,
275        }
276    }
277
278    // -----------------------------------------------------------------------
279    // Type parsing
280    // -----------------------------------------------------------------------
281
282    fn parse_type(&mut self) -> Result<TypeId, ParseError> {
283        let base = match self.lex.peek()? {
284            Token::Kw(Keyword::Void) => {
285                self.lex.next()?;
286                self.ctx.void_ty
287            }
288            Token::Kw(Keyword::Half) => {
289                self.lex.next()?;
290                self.ctx.mk_float(FloatKind::Half)
291            }
292            Token::Kw(Keyword::Bfloat) => {
293                self.lex.next()?;
294                self.ctx.mk_float(FloatKind::BFloat)
295            }
296            Token::Kw(Keyword::Float) => {
297                self.lex.next()?;
298                self.ctx.f32_ty
299            }
300            Token::Kw(Keyword::Double) => {
301                self.lex.next()?;
302                self.ctx.f64_ty
303            }
304            Token::Kw(Keyword::Fp128) => {
305                self.lex.next()?;
306                self.ctx.mk_float(FloatKind::Fp128)
307            }
308            Token::Kw(Keyword::X86Fp80) => {
309                self.lex.next()?;
310                self.ctx.mk_float(FloatKind::X86Fp80)
311            }
312            Token::Kw(Keyword::Label) => {
313                self.lex.next()?;
314                self.ctx.label_ty
315            }
316            Token::Kw(Keyword::Ptr) => {
317                self.lex.next()?;
318                self.ctx.ptr_ty
319            }
320            Token::IntType(bits) => {
321                let b = *bits;
322                self.lex.next()?;
323                self.ctx.mk_int(b)
324            }
325            Token::LBracket => self.parse_array_type()?,
326            Token::LAngle => self.parse_vector_type()?,
327            Token::LBrace => {
328                let (fields, packed) = self.parse_struct_body()?;
329                self.ctx.mk_struct_anon(fields, packed)
330            }
331            Token::LocalIdent(_) => {
332                // Named struct reference: %Name
333                let name = self.lex.expect_local_ident()?;
334                self.ctx.mk_struct_named(name)
335            }
336            _ => {
337                let t = self.lex.next()?;
338                return Err(self.err(format!("expected type, got {:?}", t)));
339            }
340        };
341
342        // Handle pointer suffix `*` (old-style IR) — consume but return ptr.
343        if self.lex.eat(&Token::Star) {
344            return Ok(self.ctx.ptr_ty);
345        }
346
347        Ok(base)
348    }
349
350    fn parse_array_type(&mut self) -> Result<TypeId, ParseError> {
351        self.lex.expect(&Token::LBracket)?;
352        let len = self.lex.expect_uint_lit()?;
353        self.lex.expect_kw(&Keyword::X)?;
354        let elem = self.parse_type()?;
355        self.lex.expect(&Token::RBracket)?;
356        Ok(self.ctx.mk_array(elem, len))
357    }
358
359    fn parse_vector_type(&mut self) -> Result<TypeId, ParseError> {
360        self.lex.expect(&Token::LAngle)?;
361        // Could be `<vscale x N x T>` or `<N x T>`.
362        let scalable = self.lex.eat_kw(Keyword::Vscale);
363        if scalable {
364            self.lex.expect_kw(&Keyword::X)?;
365        }
366        let len = self.lex.expect_uint_lit()? as u32;
367        self.lex.expect_kw(&Keyword::X)?;
368        let elem = self.parse_type()?;
369        self.lex.expect(&Token::RAngle)?;
370        Ok(self.ctx.mk_vector(elem, len, scalable))
371    }
372
373    /// Parse `{ field, field, ... }` or `<{ ... }>` (packed).
374    fn parse_struct_body(&mut self) -> Result<(Vec<TypeId>, bool), ParseError> {
375        let packed = self.lex.eat(&Token::LAngle);
376        self.lex.expect(&Token::LBrace)?;
377        let mut fields = Vec::new();
378        if !matches!(self.lex.peek()?, Token::RBrace) {
379            fields.push(self.parse_type()?);
380            while self.lex.eat(&Token::Comma) {
381                fields.push(self.parse_type()?);
382            }
383        }
384        self.lex.expect(&Token::RBrace)?;
385        if packed {
386            self.lex.expect(&Token::RAngle)?;
387        }
388        Ok((fields, packed))
389    }
390
391    #[allow(dead_code)]
392    fn parse_function_type(&mut self, ret: TypeId) -> Result<TypeId, ParseError> {
393        self.lex.expect(&Token::LParen)?;
394        let mut params = Vec::new();
395        let mut variadic = false;
396        if !matches!(self.lex.peek()?, Token::RParen) {
397            if self.lex.eat(&Token::Ellipsis) {
398                variadic = true;
399            } else {
400                params.push(self.parse_type()?);
401                while self.lex.eat(&Token::Comma) {
402                    if self.lex.eat(&Token::Ellipsis) {
403                        variadic = true;
404                        break;
405                    }
406                    params.push(self.parse_type()?);
407                }
408            }
409        }
410        self.lex.expect(&Token::RParen)?;
411        Ok(self.ctx.mk_fn_type(ret, params, variadic))
412    }
413
414    // -----------------------------------------------------------------------
415    // Function parsing
416    // -----------------------------------------------------------------------
417
418    fn parse_function(&mut self, is_declaration: bool) -> Result<(), ParseError> {
419        if is_declaration {
420            self.lex.expect_kw(&Keyword::Declare)?;
421        } else {
422            self.lex.expect_kw(&Keyword::Define)?;
423        }
424
425        let linkage = self.parse_optional_linkage();
426
427        // Skip optional function attributes before return type.
428        // (dso_local, etc. — we skip unknown bare words here)
429        self.skip_fn_attrs()?;
430
431        let ret_ty = self.parse_type()?;
432        let name = self.lex.expect_global_ident()?;
433
434        // Parse parameter list.
435        self.lex.expect(&Token::LParen)?;
436        let mut params: Vec<(TypeId, String)> = Vec::new();
437        let mut variadic = false;
438        if !matches!(self.lex.peek()?, Token::RParen) {
439            if self.lex.eat(&Token::Ellipsis) {
440                variadic = true;
441            } else {
442                let (ty, pname) = self.parse_param()?;
443                params.push((ty, pname));
444                while self.lex.eat(&Token::Comma) {
445                    if self.lex.eat(&Token::Ellipsis) {
446                        variadic = true;
447                        break;
448                    }
449                    let (ty, pname) = self.parse_param()?;
450                    params.push((ty, pname));
451                }
452            }
453        }
454        self.lex.expect(&Token::RParen)?;
455
456        // Skip trailing function attributes (e.g. #0, nounwind, ...).
457        self.skip_trailing_fn_attrs()?;
458
459        let fn_ty =
460            self.ctx
461                .mk_fn_type(ret_ty, params.iter().map(|(ty, _)| *ty).collect(), variadic);
462        let args: Vec<Argument> = params
463            .into_iter()
464            .enumerate()
465            .map(|(i, (ty, nm))| Argument {
466                name: nm,
467                ty,
468                index: i as u32,
469            })
470            .collect();
471
472        // Reset local state for this function.
473        self.locals.clear();
474        self.unnamed.clear();
475        self.pending_blocks.clear();
476
477        // Populate arg name table.
478        for (i, arg) in args.iter().enumerate() {
479            let vref = ValueRef::Argument(ArgId(i as u32));
480            if !arg.name.is_empty() {
481                self.locals.insert(arg.name.clone(), vref);
482            }
483        }
484
485        if is_declaration {
486            let func = Function::new_declaration(&name, fn_ty, args, linkage);
487            let idx = self.module.add_function(func);
488            self.current_func = Some(idx.0 as usize);
489            return Ok(());
490        }
491
492        // Parse body.
493        let func = Function::new(&name, fn_ty, args, linkage);
494        let idx = self.module.add_function(func);
495        self.current_func = Some(idx.0 as usize);
496
497        self.lex.expect(&Token::LBrace)?;
498        loop {
499            match self.lex.peek()? {
500                Token::RBrace => {
501                    self.lex.next()?;
502                    break;
503                }
504                _ => {
505                    self.parse_block()?;
506                }
507            }
508        }
509
510        Ok(())
511    }
512
513    fn parse_param(&mut self) -> Result<(TypeId, String), ParseError> {
514        let ty = self.parse_type()?;
515        // Optional parameter attributes (noundef, etc.) — skip.
516        self.skip_param_attrs()?;
517        // Optional name.
518        let name = match self.lex.peek() {
519            Ok(Token::LocalIdent(_)) => self.lex.expect_local_ident()?,
520            _ => String::new(),
521        };
522        Ok((ty, name))
523    }
524
525    // -----------------------------------------------------------------------
526    // Block parsing
527    // -----------------------------------------------------------------------
528
529    fn parse_block(&mut self) -> Result<(), ParseError> {
530        // Block label: `name:` or bare (for entry).
531        let bb_name = match self.lex.peek()? {
532            Token::LocalIdent(_) => {
533                let n = self.lex.expect_local_ident()?;
534                // Optionally followed by `:`.
535                self.lex.eat(&Token::Colon);
536                n
537            }
538            Token::IntLit(n) => {
539                let n = *n as u64;
540                let s = n.to_string();
541                self.lex.next()?;
542                self.lex.eat(&Token::Colon);
543                s
544            }
545            _ => "entry".to_string(),
546        };
547
548        let fid = self
549            .current_func
550            .ok_or_else(|| self.err("block outside function"))?;
551        let func = &mut self.module.functions[fid];
552
553        // Reuse pre-allocated BlockId if this block was forward-referenced.
554        let bid = if let Some(&existing) = self.pending_blocks.get(&bb_name) {
555            existing
556        } else {
557            let bb = BasicBlock::new(&bb_name);
558            let bid = func.add_block(bb);
559            self.pending_blocks.insert(bb_name.clone(), bid);
560            bid
561        };
562
563        // Make sure the BasicBlock exists with the right name.
564        // (If it was a forward ref, the block already exists.)
565
566        // Register block label as local value for branch targets.
567        // (We don't represent labels as ValueRef currently, but names are used for br targets.)
568
569        // Parse instructions until we see another block label or `}`.
570        loop {
571            match self.lex.peek()? {
572                Token::RBrace => break,
573                Token::LocalIdent(_) | Token::IntLit(_) => {
574                    // If the current block already has a terminator, any ident or
575                    // integer token must be the start of the next block label.
576                    if self.block_is_complete(bid) {
577                        break;
578                    }
579                    self.parse_instruction(bid)?;
580                }
581                _ => {
582                    self.parse_instruction(bid)?;
583                }
584            }
585        }
586
587        Ok(())
588    }
589
590    fn block_is_complete(&self, bid: BlockId) -> bool {
591        let fid = match self.current_func {
592            Some(f) => f,
593            None => return false,
594        };
595        self.module.functions[fid].block(bid).is_complete()
596    }
597
598    // -----------------------------------------------------------------------
599    // Instruction parsing
600    // -----------------------------------------------------------------------
601
602    fn parse_instruction(&mut self, bid: BlockId) -> Result<(), ParseError> {
603        let fid = self
604            .current_func
605            .ok_or_else(|| self.err("instruction outside function"))?;
606
607        // Parse optional result assignment: `%name = ` or `%N = `.
608        let (result_name, result_slot) = match self.lex.peek()? {
609            Token::LocalIdent(_) => {
610                // Peek ahead: if next is `=`, this is an assignment.
611                // We consume the ident and then check for `=`.
612                let n = self.lex.expect_local_ident()?;
613                if self.lex.eat(&Token::Equal) {
614                    // Named result.
615                    (Some(n), None)
616                } else {
617                    // Bare word (shouldn't happen in valid IR).
618                    return Err(self.err(format!("unexpected identifier '{}'", n)));
619                }
620            }
621            Token::IntLit(slot) => {
622                let slot = *slot as u64;
623                self.lex.next()?;
624                if self.lex.eat(&Token::Equal) {
625                    (None, Some(slot))
626                } else {
627                    return Err(self.err("expected '=' after slot number"));
628                }
629            }
630            _ => (None, None),
631        };
632
633        let (kind, ty) = self.parse_instr_kind()?;
634        let metadata_attachments = self.parse_optional_metadata_attachments()?;
635        let is_term = kind.is_terminator();
636
637        let instr_name = result_name.clone();
638        let instr = Instruction::new(instr_name, ty, kind);
639        let iid = self.module.functions[fid].alloc_instr(instr);
640        for (key, value) in metadata_attachments {
641            self.module.functions[fid].add_instr_metadata(iid, key.clone(), value.clone());
642            if key == "dbg" {
643                if let Some(loc_id) = Self::parse_metadata_ref_id(&value) {
644                    self.module.functions[fid].set_instr_dbg_loc(iid, loc_id);
645                }
646            }
647        }
648
649        if is_term {
650            self.module.functions[fid]
651                .block_mut(bid)
652                .set_terminator(iid);
653        } else {
654            self.module.functions[fid].block_mut(bid).append_instr(iid);
655        }
656
657        let vref = ValueRef::Instruction(iid);
658        if let Some(name) = result_name {
659            self.locals.insert(name, vref);
660        } else if let Some(slot) = result_slot {
661            self.unnamed.insert(slot, vref);
662        }
663
664        Ok(())
665    }
666
667    fn parse_instr_kind(&mut self) -> Result<(InstrKind, TypeId), ParseError> {
668        match self.lex.peek()? {
669            // --- Integer arithmetic ---
670            Token::Kw(Keyword::Add) => {
671                self.lex.next()?;
672                let flags = self.parse_int_arith_flags();
673                let (lhs, ty) = self.parse_typed_value()?;
674                self.lex.expect(&Token::Comma)?;
675                let rhs = self.parse_value(ty)?;
676                Ok((InstrKind::Add { flags, lhs, rhs }, ty))
677            }
678            Token::Kw(Keyword::Sub) => {
679                self.lex.next()?;
680                let flags = self.parse_int_arith_flags();
681                let (lhs, ty) = self.parse_typed_value()?;
682                self.lex.expect(&Token::Comma)?;
683                let rhs = self.parse_value(ty)?;
684                Ok((InstrKind::Sub { flags, lhs, rhs }, ty))
685            }
686            Token::Kw(Keyword::Mul) => {
687                self.lex.next()?;
688                let flags = self.parse_int_arith_flags();
689                let (lhs, ty) = self.parse_typed_value()?;
690                self.lex.expect(&Token::Comma)?;
691                let rhs = self.parse_value(ty)?;
692                Ok((InstrKind::Mul { flags, lhs, rhs }, ty))
693            }
694            Token::Kw(Keyword::Udiv) => {
695                self.lex.next()?;
696                let exact = self.lex.eat_kw(Keyword::Exact);
697                let (lhs, ty) = self.parse_typed_value()?;
698                self.lex.expect(&Token::Comma)?;
699                let rhs = self.parse_value(ty)?;
700                Ok((InstrKind::UDiv { exact, lhs, rhs }, ty))
701            }
702            Token::Kw(Keyword::Sdiv) => {
703                self.lex.next()?;
704                let exact = self.lex.eat_kw(Keyword::Exact);
705                let (lhs, ty) = self.parse_typed_value()?;
706                self.lex.expect(&Token::Comma)?;
707                let rhs = self.parse_value(ty)?;
708                Ok((InstrKind::SDiv { exact, lhs, rhs }, ty))
709            }
710            Token::Kw(Keyword::Urem) => {
711                self.lex.next()?;
712                let (lhs, ty) = self.parse_typed_value()?;
713                self.lex.expect(&Token::Comma)?;
714                let rhs = self.parse_value(ty)?;
715                Ok((InstrKind::URem { lhs, rhs }, ty))
716            }
717            Token::Kw(Keyword::Srem) => {
718                self.lex.next()?;
719                let (lhs, ty) = self.parse_typed_value()?;
720                self.lex.expect(&Token::Comma)?;
721                let rhs = self.parse_value(ty)?;
722                Ok((InstrKind::SRem { lhs, rhs }, ty))
723            }
724            // --- Bitwise ---
725            Token::Kw(Keyword::And) => {
726                self.lex.next()?;
727                let (lhs, ty) = self.parse_typed_value()?;
728                self.lex.expect(&Token::Comma)?;
729                let rhs = self.parse_value(ty)?;
730                Ok((InstrKind::And { lhs, rhs }, ty))
731            }
732            Token::Kw(Keyword::Or) => {
733                self.lex.next()?;
734                let (lhs, ty) = self.parse_typed_value()?;
735                self.lex.expect(&Token::Comma)?;
736                let rhs = self.parse_value(ty)?;
737                Ok((InstrKind::Or { lhs, rhs }, ty))
738            }
739            Token::Kw(Keyword::Xor) => {
740                self.lex.next()?;
741                let (lhs, ty) = self.parse_typed_value()?;
742                self.lex.expect(&Token::Comma)?;
743                let rhs = self.parse_value(ty)?;
744                Ok((InstrKind::Xor { lhs, rhs }, ty))
745            }
746            Token::Kw(Keyword::Shl) => {
747                self.lex.next()?;
748                let flags = self.parse_int_arith_flags();
749                let (lhs, ty) = self.parse_typed_value()?;
750                self.lex.expect(&Token::Comma)?;
751                let rhs = self.parse_value(ty)?;
752                Ok((InstrKind::Shl { flags, lhs, rhs }, ty))
753            }
754            Token::Kw(Keyword::Lshr) => {
755                self.lex.next()?;
756                let exact = self.lex.eat_kw(Keyword::Exact);
757                let (lhs, ty) = self.parse_typed_value()?;
758                self.lex.expect(&Token::Comma)?;
759                let rhs = self.parse_value(ty)?;
760                Ok((InstrKind::LShr { exact, lhs, rhs }, ty))
761            }
762            Token::Kw(Keyword::Ashr) => {
763                self.lex.next()?;
764                let exact = self.lex.eat_kw(Keyword::Exact);
765                let (lhs, ty) = self.parse_typed_value()?;
766                self.lex.expect(&Token::Comma)?;
767                let rhs = self.parse_value(ty)?;
768                Ok((InstrKind::AShr { exact, lhs, rhs }, ty))
769            }
770            // --- FP arithmetic ---
771            Token::Kw(Keyword::Fadd) => {
772                self.lex.next()?;
773                let flags = self.parse_fast_math_flags();
774                let (lhs, ty) = self.parse_typed_value()?;
775                self.lex.expect(&Token::Comma)?;
776                let rhs = self.parse_value(ty)?;
777                Ok((InstrKind::FAdd { flags, lhs, rhs }, ty))
778            }
779            Token::Kw(Keyword::Fsub) => {
780                self.lex.next()?;
781                let flags = self.parse_fast_math_flags();
782                let (lhs, ty) = self.parse_typed_value()?;
783                self.lex.expect(&Token::Comma)?;
784                let rhs = self.parse_value(ty)?;
785                Ok((InstrKind::FSub { flags, lhs, rhs }, ty))
786            }
787            Token::Kw(Keyword::Fmul) => {
788                self.lex.next()?;
789                let flags = self.parse_fast_math_flags();
790                let (lhs, ty) = self.parse_typed_value()?;
791                self.lex.expect(&Token::Comma)?;
792                let rhs = self.parse_value(ty)?;
793                Ok((InstrKind::FMul { flags, lhs, rhs }, ty))
794            }
795            Token::Kw(Keyword::Fdiv) => {
796                self.lex.next()?;
797                let flags = self.parse_fast_math_flags();
798                let (lhs, ty) = self.parse_typed_value()?;
799                self.lex.expect(&Token::Comma)?;
800                let rhs = self.parse_value(ty)?;
801                Ok((InstrKind::FDiv { flags, lhs, rhs }, ty))
802            }
803            Token::Kw(Keyword::Frem) => {
804                self.lex.next()?;
805                let flags = self.parse_fast_math_flags();
806                let (lhs, ty) = self.parse_typed_value()?;
807                self.lex.expect(&Token::Comma)?;
808                let rhs = self.parse_value(ty)?;
809                Ok((InstrKind::FRem { flags, lhs, rhs }, ty))
810            }
811            Token::Kw(Keyword::Fneg) => {
812                self.lex.next()?;
813                let flags = self.parse_fast_math_flags();
814                let (operand, ty) = self.parse_typed_value()?;
815                Ok((InstrKind::FNeg { flags, operand }, ty))
816            }
817            // --- Comparisons ---
818            Token::Kw(Keyword::Icmp) => {
819                self.lex.next()?;
820                let pred = self.parse_int_pred()?;
821                let (lhs, _ty) = self.parse_typed_value()?;
822                self.lex.expect(&Token::Comma)?;
823                let rhs = self.parse_value(_ty)?;
824                let i1 = self.ctx.i1_ty;
825                Ok((InstrKind::ICmp { pred, lhs, rhs }, i1))
826            }
827            Token::Kw(Keyword::Fcmp) => {
828                self.lex.next()?;
829                let flags = self.parse_fast_math_flags();
830                let pred = self.parse_float_pred()?;
831                let (lhs, _ty) = self.parse_typed_value()?;
832                self.lex.expect(&Token::Comma)?;
833                let rhs = self.parse_value(_ty)?;
834                let i1 = self.ctx.i1_ty;
835                Ok((
836                    InstrKind::FCmp {
837                        flags,
838                        pred,
839                        lhs,
840                        rhs,
841                    },
842                    i1,
843                ))
844            }
845            // --- Memory ---
846            Token::Kw(Keyword::Alloca) => {
847                self.lex.next()?;
848                let alloc_ty = self.parse_type()?;
849                // Parse optional `, <num_elements>` and/or `, align N`.
850                // When we eat a comma and see `align` directly (no
851                // num_elements), the comma is already consumed so we must NOT
852                // go through parse_optional_align (which expects its own
853                // leading comma).
854                let (num_elements, comma_before_align_consumed) =
855                    if self.lex.eat(&Token::Comma) {
856                        match self.lex.peek()? {
857                            Token::Kw(Keyword::Align) => (None, true),
858                            _ => {
859                                let (ne, _) = self.parse_typed_value()?;
860                                (Some(ne), false)
861                            }
862                        }
863                    } else {
864                        (None, false)
865                    };
866                let align = if comma_before_align_consumed {
867                    // Comma was already consumed; parse `align N` directly.
868                    if self.lex.eat_kw(Keyword::Align) {
869                        let a = self.lex.expect_uint_lit()? as u32;
870                        Some(a)
871                    } else {
872                        None
873                    }
874                } else {
875                    self.parse_optional_align()?
876                };
877                let ptr_ty = self.ctx.ptr_ty;
878                Ok((
879                    InstrKind::Alloca {
880                        alloc_ty,
881                        num_elements,
882                        align,
883                    },
884                    ptr_ty,
885                ))
886            }
887            Token::Kw(Keyword::Load) => {
888                self.lex.next()?;
889                let volatile = self.lex.eat_kw(Keyword::Volatile);
890                let ty = self.parse_type()?;
891                self.lex.expect(&Token::Comma)?;
892                let (_ptr_ty, ptr) = {
893                    let ptype = self.parse_type()?;
894                    (ptype, self.parse_value(ptype)?)
895                };
896                let align = self.parse_optional_align()?;
897                Ok((
898                    InstrKind::Load {
899                        ty,
900                        ptr,
901                        align,
902                        volatile,
903                    },
904                    ty,
905                ))
906            }
907            Token::Kw(Keyword::Store) => {
908                self.lex.next()?;
909                let volatile = self.lex.eat_kw(Keyword::Volatile);
910                let (val, _val_ty) = self.parse_typed_value()?;
911                self.lex.expect(&Token::Comma)?;
912                let ptr_ty2 = self.parse_type()?;
913                let ptr = self.parse_value(ptr_ty2)?;
914                let align = self.parse_optional_align()?;
915                let void_ty = self.ctx.void_ty;
916                Ok((
917                    InstrKind::Store {
918                        val,
919                        ptr,
920                        align,
921                        volatile,
922                    },
923                    void_ty,
924                ))
925            }
926            Token::Kw(Keyword::Getelementptr) => {
927                self.lex.next()?;
928                let inbounds = self.lex.eat_kw(Keyword::Inbounds);
929                let base_ty = self.parse_type()?;
930                self.lex.expect(&Token::Comma)?;
931                let ptr_ty2 = self.parse_type()?;
932                let ptr = self.parse_value(ptr_ty2)?;
933                let mut indices = Vec::new();
934                while self.lex.eat(&Token::Comma) {
935                    let (idx, _) = self.parse_typed_value()?;
936                    indices.push(idx);
937                }
938                let ptr_ty = self.ctx.ptr_ty;
939                Ok((
940                    InstrKind::GetElementPtr {
941                        inbounds,
942                        base_ty,
943                        ptr,
944                        indices,
945                    },
946                    ptr_ty,
947                ))
948            }
949            // --- Casts ---
950            Token::Kw(Keyword::Trunc) => {
951                self.lex.next()?;
952                let (val, _) = self.parse_typed_value()?;
953                self.lex.expect_kw(&Keyword::To)?;
954                let to = self.parse_type()?;
955                Ok((InstrKind::Trunc { val, to }, to))
956            }
957            Token::Kw(Keyword::Zext) => {
958                self.lex.next()?;
959                let (val, _) = self.parse_typed_value()?;
960                self.lex.expect_kw(&Keyword::To)?;
961                let to = self.parse_type()?;
962                Ok((InstrKind::ZExt { val, to }, to))
963            }
964            Token::Kw(Keyword::Sext) => {
965                self.lex.next()?;
966                let (val, _) = self.parse_typed_value()?;
967                self.lex.expect_kw(&Keyword::To)?;
968                let to = self.parse_type()?;
969                Ok((InstrKind::SExt { val, to }, to))
970            }
971            Token::Kw(Keyword::Fptrunc) => {
972                self.lex.next()?;
973                let (val, _) = self.parse_typed_value()?;
974                self.lex.expect_kw(&Keyword::To)?;
975                let to = self.parse_type()?;
976                Ok((InstrKind::FPTrunc { val, to }, to))
977            }
978            Token::Kw(Keyword::Fpext) => {
979                self.lex.next()?;
980                let (val, _) = self.parse_typed_value()?;
981                self.lex.expect_kw(&Keyword::To)?;
982                let to = self.parse_type()?;
983                Ok((InstrKind::FPExt { val, to }, to))
984            }
985            Token::Kw(Keyword::Fptoui) => {
986                self.lex.next()?;
987                let (val, _) = self.parse_typed_value()?;
988                self.lex.expect_kw(&Keyword::To)?;
989                let to = self.parse_type()?;
990                Ok((InstrKind::FPToUI { val, to }, to))
991            }
992            Token::Kw(Keyword::Fptosi) => {
993                self.lex.next()?;
994                let (val, _) = self.parse_typed_value()?;
995                self.lex.expect_kw(&Keyword::To)?;
996                let to = self.parse_type()?;
997                Ok((InstrKind::FPToSI { val, to }, to))
998            }
999            Token::Kw(Keyword::Uitofp) => {
1000                self.lex.next()?;
1001                let (val, _) = self.parse_typed_value()?;
1002                self.lex.expect_kw(&Keyword::To)?;
1003                let to = self.parse_type()?;
1004                Ok((InstrKind::UIToFP { val, to }, to))
1005            }
1006            Token::Kw(Keyword::Sitofp) => {
1007                self.lex.next()?;
1008                let (val, _) = self.parse_typed_value()?;
1009                self.lex.expect_kw(&Keyword::To)?;
1010                let to = self.parse_type()?;
1011                Ok((InstrKind::SIToFP { val, to }, to))
1012            }
1013            Token::Kw(Keyword::Ptrtoint) => {
1014                self.lex.next()?;
1015                let (val, _) = self.parse_typed_value()?;
1016                self.lex.expect_kw(&Keyword::To)?;
1017                let to = self.parse_type()?;
1018                Ok((InstrKind::PtrToInt { val, to }, to))
1019            }
1020            Token::Kw(Keyword::Inttoptr) => {
1021                self.lex.next()?;
1022                let (val, _) = self.parse_typed_value()?;
1023                self.lex.expect_kw(&Keyword::To)?;
1024                let to = self.parse_type()?;
1025                Ok((InstrKind::IntToPtr { val, to }, to))
1026            }
1027            Token::Kw(Keyword::Bitcast) => {
1028                self.lex.next()?;
1029                let (val, _) = self.parse_typed_value()?;
1030                self.lex.expect_kw(&Keyword::To)?;
1031                let to = self.parse_type()?;
1032                Ok((InstrKind::BitCast { val, to }, to))
1033            }
1034            Token::Kw(Keyword::Addrspacecast) => {
1035                self.lex.next()?;
1036                let (val, _) = self.parse_typed_value()?;
1037                self.lex.expect_kw(&Keyword::To)?;
1038                let to = self.parse_type()?;
1039                Ok((InstrKind::AddrSpaceCast { val, to }, to))
1040            }
1041            Token::Kw(Keyword::Freeze) => {
1042                self.lex.next()?;
1043                let (val, ty) = self.parse_typed_value()?;
1044                Ok((InstrKind::Freeze { val }, ty))
1045            }
1046            // --- Misc ---
1047            Token::Kw(Keyword::Select) => {
1048                self.lex.next()?;
1049                let (cond, _) = self.parse_typed_value()?;
1050                self.lex.expect(&Token::Comma)?;
1051                let (then_val, ty) = self.parse_typed_value()?;
1052                self.lex.expect(&Token::Comma)?;
1053                // else_val may have an explicit type prefix (standard LLVM IR) or not.
1054                let (else_val, _) = self.parse_typed_value()?;
1055                Ok((
1056                    InstrKind::Select {
1057                        cond,
1058                        then_val,
1059                        else_val,
1060                    },
1061                    ty,
1062                ))
1063            }
1064            Token::Kw(Keyword::Phi) => {
1065                self.lex.next()?;
1066                let ty = self.parse_type()?;
1067                let mut incoming = Vec::new();
1068                loop {
1069                    // [ value, %label ]
1070                    self.lex.expect(&Token::LBracket)?;
1071                    let val = self.parse_value(ty)?;
1072                    self.lex.expect(&Token::Comma)?;
1073                    let block_name = self.lex.expect_local_ident()?;
1074                    let bid = self.get_or_create_block(&block_name)?;
1075                    self.lex.expect(&Token::RBracket)?;
1076                    incoming.push((val, bid));
1077                    if !self.lex.eat(&Token::Comma) {
1078                        break;
1079                    }
1080                }
1081                Ok((InstrKind::Phi { ty, incoming }, ty))
1082            }
1083            Token::Kw(Keyword::Extractvalue) => {
1084                self.lex.next()?;
1085                let (aggregate, agg_ty) = self.parse_typed_value()?;
1086                let mut indices = Vec::new();
1087                while self.lex.eat(&Token::Comma) {
1088                    let idx = self.lex.expect_uint_lit()? as u32;
1089                    indices.push(idx);
1090                }
1091                // Walk the index chain to find the actual element type.
1092                let mut result_ty = agg_ty;
1093                for &idx in &indices {
1094                    result_ty = match self.ctx.get_type(result_ty) {
1095                        TypeData::Struct(s) => {
1096                            s.fields.get(idx as usize).copied().unwrap_or(result_ty)
1097                        }
1098                        TypeData::Array { element, .. } => *element,
1099                        TypeData::Vector { element, .. } => *element,
1100                        _ => result_ty,
1101                    };
1102                }
1103                Ok((InstrKind::ExtractValue { aggregate, indices }, result_ty))
1104            }
1105            Token::Kw(Keyword::Insertvalue) => {
1106                self.lex.next()?;
1107                let (aggregate, agg_ty) = self.parse_typed_value()?;
1108                self.lex.expect(&Token::Comma)?;
1109                let (val, _val_ty) = self.parse_typed_value()?;
1110                let mut indices = Vec::new();
1111                while self.lex.eat(&Token::Comma) {
1112                    let idx = self.lex.expect_uint_lit()? as u32;
1113                    indices.push(idx);
1114                }
1115                Ok((
1116                    InstrKind::InsertValue {
1117                        aggregate,
1118                        val,
1119                        indices,
1120                    },
1121                    agg_ty,
1122                ))
1123            }
1124            Token::Kw(Keyword::Extractelement) => {
1125                self.lex.next()?;
1126                let (vec, vec_ty) = self.parse_typed_value()?;
1127                self.lex.expect(&Token::Comma)?;
1128                let (idx, _) = self.parse_typed_value()?;
1129                // Result type is the element type of the vector.
1130                let elem_ty = match self.ctx.get_type(vec_ty) {
1131                    llvm_ir::types::TypeData::Vector { element, .. } => *element,
1132                    _ => vec_ty,
1133                };
1134                Ok((InstrKind::ExtractElement { vec, idx }, elem_ty))
1135            }
1136            Token::Kw(Keyword::Insertelement) => {
1137                self.lex.next()?;
1138                let (vec, vec_ty) = self.parse_typed_value()?;
1139                self.lex.expect(&Token::Comma)?;
1140                let (val, _) = self.parse_typed_value()?;
1141                self.lex.expect(&Token::Comma)?;
1142                let (idx, _) = self.parse_typed_value()?;
1143                Ok((InstrKind::InsertElement { vec, val, idx }, vec_ty))
1144            }
1145            Token::Kw(Keyword::Shufflevector) => {
1146                self.lex.next()?;
1147                let (v1, vec_ty) = self.parse_typed_value()?;
1148                self.lex.expect(&Token::Comma)?;
1149                let (v2, _) = self.parse_typed_value()?;
1150                self.lex.expect(&Token::Comma)?;
1151                // Mask: <i32 N, i32 M, ...> or undef
1152                let mask = self.parse_shuffle_mask()?;
1153                Ok((InstrKind::ShuffleVector { v1, v2, mask }, vec_ty))
1154            }
1155            // --- Call ---
1156            Token::Kw(Keyword::Call)
1157            | Token::Kw(Keyword::Tail)
1158            | Token::Kw(Keyword::Musttail)
1159            | Token::Kw(Keyword::Notail) => {
1160                let tail = match self.lex.peek()? {
1161                    Token::Kw(Keyword::Tail) => {
1162                        self.lex.next()?;
1163                        TailCallKind::Tail
1164                    }
1165                    Token::Kw(Keyword::Musttail) => {
1166                        self.lex.next()?;
1167                        TailCallKind::MustTail
1168                    }
1169                    Token::Kw(Keyword::Notail) => {
1170                        self.lex.next()?;
1171                        TailCallKind::NoTail
1172                    }
1173                    _ => TailCallKind::None,
1174                };
1175                self.lex.expect_kw(&Keyword::Call)?;
1176                // Optional fast-math flags.
1177                let _fmf = self.parse_fast_math_flags();
1178                // Return type.
1179                let ret_ty = self.parse_type()?;
1180                // Callee.
1181                let callee = match self.lex.peek()? {
1182                    Token::GlobalIdent(_) => {
1183                        let gname = self.lex.expect_global_ident()?;
1184                        self.resolve_global_ref(&gname)?
1185                    }
1186                    Token::LocalIdent(_) => {
1187                        let lname = self.lex.expect_local_ident()?;
1188                        self.resolve_local(&lname)?
1189                    }
1190                    _ => return Err(self.err("expected callee name")),
1191                };
1192                // Arg list.
1193                self.lex.expect(&Token::LParen)?;
1194                let mut args = Vec::new();
1195                if !matches!(self.lex.peek()?, Token::RParen) {
1196                    let (a, _) = self.parse_typed_value()?;
1197                    args.push(a);
1198                    while self.lex.eat(&Token::Comma) {
1199                        if self.lex.eat(&Token::Ellipsis) {
1200                            break;
1201                        }
1202                        let (a, _) = self.parse_typed_value()?;
1203                        args.push(a);
1204                    }
1205                }
1206                self.lex.expect(&Token::RParen)?;
1207                // Build a function type from what we know.
1208                let param_tys: Vec<TypeId> = args.iter().map(|a| self.type_of_vref(*a)).collect();
1209                let callee_ty = self.ctx.mk_fn_type(ret_ty, param_tys, false);
1210                Ok((
1211                    InstrKind::Call {
1212                        tail,
1213                        callee_ty,
1214                        callee,
1215                        args,
1216                    },
1217                    ret_ty,
1218                ))
1219            }
1220            // --- Terminators ---
1221            Token::Kw(Keyword::Ret) => {
1222                self.lex.next()?;
1223                let void_ty = self.ctx.void_ty;
1224                if self.lex.eat_kw(Keyword::Void) {
1225                    Ok((InstrKind::Ret { val: None }, void_ty))
1226                } else {
1227                    let (val, _) = self.parse_typed_value()?;
1228                    Ok((InstrKind::Ret { val: Some(val) }, void_ty))
1229                }
1230            }
1231            Token::Kw(Keyword::Br) => {
1232                self.lex.next()?;
1233                let void_ty = self.ctx.void_ty;
1234                // `br label %dest` or `br i1 %cond, label %then, label %else`
1235                match self.lex.peek()? {
1236                    Token::Kw(Keyword::Label) => {
1237                        self.lex.next()?;
1238                        let dest_name = self.lex.expect_local_ident()?;
1239                        let dest = self.get_or_create_block(&dest_name)?;
1240                        Ok((InstrKind::Br { dest }, void_ty))
1241                    }
1242                    _ => {
1243                        let (cond, _) = self.parse_typed_value()?;
1244                        self.lex.expect(&Token::Comma)?;
1245                        self.lex.expect_kw(&Keyword::Label)?;
1246                        let then_name = self.lex.expect_local_ident()?;
1247                        let then_dest = self.get_or_create_block(&then_name)?;
1248                        self.lex.expect(&Token::Comma)?;
1249                        self.lex.expect_kw(&Keyword::Label)?;
1250                        let else_name = self.lex.expect_local_ident()?;
1251                        let else_dest = self.get_or_create_block(&else_name)?;
1252                        Ok((
1253                            InstrKind::CondBr {
1254                                cond,
1255                                then_dest,
1256                                else_dest,
1257                            },
1258                            void_ty,
1259                        ))
1260                    }
1261                }
1262            }
1263            Token::Kw(Keyword::Switch) => {
1264                self.lex.next()?;
1265                let void_ty = self.ctx.void_ty;
1266                let (val, _val_ty) = self.parse_typed_value()?;
1267                self.lex.expect(&Token::Comma)?;
1268                self.lex.expect_kw(&Keyword::Label)?;
1269                let default_name = self.lex.expect_local_ident()?;
1270                let default = self.get_or_create_block(&default_name)?;
1271                self.lex.expect(&Token::LBracket)?;
1272                let mut cases = Vec::new();
1273                while !matches!(self.lex.peek()?, Token::RBracket) {
1274                    // Case values always carry an explicit type in standard LLVM IR (e.g. `i32 0`).
1275                    let (case_val, _) = self.parse_typed_value()?;
1276                    self.lex.expect(&Token::Comma)?;
1277                    self.lex.expect_kw(&Keyword::Label)?;
1278                    let dest_name = self.lex.expect_local_ident()?;
1279                    let dest = self.get_or_create_block(&dest_name)?;
1280                    cases.push((case_val, dest));
1281                }
1282                self.lex.expect(&Token::RBracket)?;
1283                Ok((
1284                    InstrKind::Switch {
1285                        val,
1286                        default,
1287                        cases,
1288                    },
1289                    void_ty,
1290                ))
1291            }
1292            Token::Kw(Keyword::Unreachable) => {
1293                self.lex.next()?;
1294                let void_ty = self.ctx.void_ty;
1295                Ok((InstrKind::Unreachable, void_ty))
1296            }
1297            _ => {
1298                let t = self.lex.next()?;
1299                Err(self.err(format!("unknown instruction opcode: {:?}", t)))
1300            }
1301        }
1302    }
1303
1304    // -----------------------------------------------------------------------
1305    // Operand helpers
1306    // -----------------------------------------------------------------------
1307
1308    fn parse_typed_value(&mut self) -> Result<(ValueRef, TypeId), ParseError> {
1309        let ty = self.parse_type()?;
1310        let val = self.parse_value(ty)?;
1311        Ok((val, ty))
1312    }
1313
1314    fn parse_value(&mut self, ty: TypeId) -> Result<ValueRef, ParseError> {
1315        match self.lex.peek()? {
1316            Token::LocalIdent(_) => {
1317                let name = self.lex.expect_local_ident()?;
1318                self.resolve_local(&name)
1319            }
1320            Token::GlobalIdent(_) => {
1321                let name = self.lex.expect_global_ident()?;
1322                self.resolve_global_ref(&name)
1323            }
1324            Token::IntLit(_) | Token::UIntLit(_) => {
1325                let n = self.lex.expect_uint_lit()?;
1326                let c = self.ctx.const_int(ty, n);
1327                Ok(ValueRef::Constant(c))
1328            }
1329            Token::FloatLit(_) => {
1330                if let Token::FloatLit(f) = self.lex.next()? {
1331                    let bits = f.to_bits();
1332                    let c = self.ctx.const_float(ty, bits);
1333                    Ok(ValueRef::Constant(c))
1334                } else {
1335                    unreachable!()
1336                }
1337            }
1338            Token::Kw(Keyword::Undef) => {
1339                self.lex.next()?;
1340                Ok(ValueRef::Constant(self.ctx.const_undef(ty)))
1341            }
1342            Token::Kw(Keyword::Poison) => {
1343                self.lex.next()?;
1344                Ok(ValueRef::Constant(self.ctx.const_poison(ty)))
1345            }
1346            Token::Kw(Keyword::Null) => {
1347                self.lex.next()?;
1348                Ok(ValueRef::Constant(self.ctx.const_null(ty)))
1349            }
1350            Token::Kw(Keyword::Zeroinitializer) => {
1351                self.lex.next()?;
1352                Ok(ValueRef::Constant(self.ctx.const_zero(ty)))
1353            }
1354            Token::Kw(Keyword::True) => {
1355                self.lex.next()?;
1356                let i1 = self.ctx.i1_ty;
1357                Ok(ValueRef::Constant(self.ctx.const_int(i1, 1)))
1358            }
1359            Token::Kw(Keyword::False) => {
1360                self.lex.next()?;
1361                let i1 = self.ctx.i1_ty;
1362                Ok(ValueRef::Constant(self.ctx.const_int(i1, 0)))
1363            }
1364            _ => {
1365                let t = self.lex.next()?;
1366                Err(self.err(format!("expected value, got {:?}", t)))
1367            }
1368        }
1369    }
1370
1371    fn parse_constant(&mut self, ty: TypeId) -> Result<ConstId, ParseError> {
1372        let vref = self.parse_value(ty)?;
1373        match vref {
1374            ValueRef::Constant(c) => Ok(c),
1375            _ => Err(self.err("expected constant")),
1376        }
1377    }
1378
1379    fn resolve_local(&self, name: &str) -> Result<ValueRef, ParseError> {
1380        if let Some(&v) = self.locals.get(name) {
1381            return Ok(v);
1382        }
1383        // Try numeric slot.
1384        if let Ok(slot) = name.parse::<u64>() {
1385            if let Some(&v) = self.unnamed.get(&slot) {
1386                return Ok(v);
1387            }
1388        }
1389        Err(ParseError {
1390            line: self.lex.current_line(),
1391            col: self.lex.current_col(),
1392            message: format!("undefined local value '%{}'", name),
1393        })
1394    }
1395
1396    fn resolve_global_ref(&mut self, name: &str) -> Result<ValueRef, ParseError> {
1397        let ptr_ty = self.ctx.ptr_ty;
1398        // Look up in module globals first.
1399        if let Some(gid) = self.module.get_global_id(name) {
1400            let c = self.ctx.push_const(ConstantData::GlobalRef {
1401                ty: ptr_ty,
1402                id: gid,
1403                name: name.to_string(),
1404            });
1405            return Ok(ValueRef::Constant(c));
1406        }
1407        // Functions are also referenced by @name (as function pointers / callees).
1408        // Use GlobalId::MAX as a sentinel meaning "function reference".
1409        if self.module.get_function_id(name).is_some() {
1410            let c = self.ctx.push_const(ConstantData::GlobalRef {
1411                ty: ptr_ty,
1412                id: GlobalId(u32::MAX),
1413                name: name.to_string(),
1414            });
1415            return Ok(ValueRef::Constant(c));
1416        }
1417        // Forward/unknown reference — record name for future resolution.
1418        let c = self.ctx.push_const(ConstantData::GlobalRef {
1419            ty: ptr_ty,
1420            id: GlobalId(u32::MAX),
1421            name: name.to_string(),
1422        });
1423        Ok(ValueRef::Constant(c))
1424    }
1425
1426    fn type_of_vref(&self, vref: ValueRef) -> TypeId {
1427        if let Some(fid) = self.current_func {
1428            if fid < self.module.functions.len() {
1429                let func = &self.module.functions[fid];
1430                match vref {
1431                    ValueRef::Instruction(id) if (id.0 as usize) < func.instructions.len() => {
1432                        return func.instr(id).ty;
1433                    }
1434                    ValueRef::Argument(id) if (id.0 as usize) < func.args.len() => {
1435                        return func.arg(id).ty;
1436                    }
1437                    _ => {}
1438                }
1439            }
1440        }
1441        match vref {
1442            ValueRef::Constant(c) => self.ctx.type_of_const(c),
1443            _ => self.ctx.ptr_ty,
1444        }
1445    }
1446
1447    fn get_or_create_block(&mut self, name: &str) -> Result<BlockId, ParseError> {
1448        let fid = self
1449            .current_func
1450            .ok_or_else(|| self.err("block reference outside function"))?;
1451        if let Some(&bid) = self.pending_blocks.get(name) {
1452            return Ok(bid);
1453        }
1454        let bb = BasicBlock::new(name);
1455        let bid = self.module.functions[fid].add_block(bb);
1456        self.pending_blocks.insert(name.to_string(), bid);
1457        Ok(bid)
1458    }
1459
1460    // -----------------------------------------------------------------------
1461    // Flag helpers
1462    // -----------------------------------------------------------------------
1463
1464    fn parse_int_arith_flags(&mut self) -> IntArithFlags {
1465        let mut flags = IntArithFlags::default();
1466        loop {
1467            if self.lex.eat_kw(Keyword::Nuw) {
1468                flags.nuw = true;
1469            } else if self.lex.eat_kw(Keyword::Nsw) {
1470                flags.nsw = true;
1471            } else {
1472                break;
1473            }
1474        }
1475        flags
1476    }
1477
1478    fn parse_fast_math_flags(&mut self) -> FastMathFlags {
1479        let mut f = FastMathFlags::default();
1480        loop {
1481            if self.lex.eat_kw(Keyword::Fast) {
1482                f.fast = true;
1483                break;
1484            } else if self.lex.eat_kw(Keyword::Nnan) {
1485                f.nnan = true;
1486            } else if self.lex.eat_kw(Keyword::Ninf) {
1487                f.ninf = true;
1488            } else if self.lex.eat_kw(Keyword::Nsz) {
1489                f.nsz = true;
1490            } else if self.lex.eat_kw(Keyword::Arcp) {
1491                f.arcp = true;
1492            } else if self.lex.eat_kw(Keyword::Contract) {
1493                f.contract = true;
1494            } else if self.lex.eat_kw(Keyword::Afn) {
1495                f.afn = true;
1496            } else if self.lex.eat_kw(Keyword::Reassoc) {
1497                f.reassoc = true;
1498            } else {
1499                break;
1500            }
1501        }
1502        f
1503    }
1504
1505    fn parse_int_pred(&mut self) -> Result<IntPredicate, ParseError> {
1506        match self.lex.next()? {
1507            Token::Kw(Keyword::Eq) => Ok(IntPredicate::Eq),
1508            Token::Kw(Keyword::Ne) => Ok(IntPredicate::Ne),
1509            Token::Kw(Keyword::Ugt) => Ok(IntPredicate::Ugt),
1510            Token::Kw(Keyword::Uge) => Ok(IntPredicate::Uge),
1511            Token::Kw(Keyword::Ult) => Ok(IntPredicate::Ult),
1512            Token::Kw(Keyword::Ule) => Ok(IntPredicate::Ule),
1513            Token::Kw(Keyword::Sgt) => Ok(IntPredicate::Sgt),
1514            Token::Kw(Keyword::Sge) => Ok(IntPredicate::Sge),
1515            Token::Kw(Keyword::Slt) => Ok(IntPredicate::Slt),
1516            Token::Kw(Keyword::Sle) => Ok(IntPredicate::Sle),
1517            t => Err(self.err(format!("expected icmp predicate, got {:?}", t))),
1518        }
1519    }
1520
1521    fn parse_float_pred(&mut self) -> Result<FloatPredicate, ParseError> {
1522        match self.lex.next()? {
1523            Token::Kw(Keyword::False) => Ok(FloatPredicate::False),
1524            Token::Kw(Keyword::Oeq) => Ok(FloatPredicate::Oeq),
1525            Token::Kw(Keyword::Ogt) => Ok(FloatPredicate::Ogt),
1526            Token::Kw(Keyword::Oge) => Ok(FloatPredicate::Oge),
1527            Token::Kw(Keyword::Olt) => Ok(FloatPredicate::Olt),
1528            Token::Kw(Keyword::Ole) => Ok(FloatPredicate::Ole),
1529            Token::Kw(Keyword::One) => Ok(FloatPredicate::One),
1530            Token::Kw(Keyword::Ord) => Ok(FloatPredicate::Ord),
1531            Token::Kw(Keyword::Uno) => Ok(FloatPredicate::Uno),
1532            Token::Kw(Keyword::Ueq) => Ok(FloatPredicate::Ueq),
1533            Token::Kw(Keyword::Ugt) => Ok(FloatPredicate::Ugt),
1534            Token::Kw(Keyword::Uge) => Ok(FloatPredicate::Uge),
1535            Token::Kw(Keyword::Ult) => Ok(FloatPredicate::Ult),
1536            Token::Kw(Keyword::Ule) => Ok(FloatPredicate::Ule),
1537            Token::Kw(Keyword::Une) => Ok(FloatPredicate::Une),
1538            Token::Kw(Keyword::True) => Ok(FloatPredicate::True),
1539            t => Err(self.err(format!("expected fcmp predicate, got {:?}", t))),
1540        }
1541    }
1542
1543    fn parse_optional_align(&mut self) -> Result<Option<u32>, ParseError> {
1544        if self.lex.eat(&Token::Comma) {
1545            self.lex.expect_kw(&Keyword::Align)?;
1546            let a = self.lex.expect_uint_lit()? as u32;
1547            Ok(Some(a))
1548        } else {
1549            Ok(None)
1550        }
1551    }
1552
1553    fn parse_shuffle_mask(&mut self) -> Result<Vec<i32>, ParseError> {
1554        // Mask is either `undef` or a typed constant vector.
1555        // LLVM IR requires the type annotation: `<N x i32> <i32 0, i32 1, ...>`.
1556        // Older (pre-typed-pointer) IR sometimes omits the outer type, so we
1557        // accept both forms.
1558        if self.lex.eat_kw(Keyword::Undef) {
1559            return Ok(vec![]);
1560        }
1561        // Consume optional outer type annotation `<N x i32>`.
1562        if matches!(self.lex.peek()?, Token::LAngle) {
1563            // We don't know yet whether this is the type prefix or the inner
1564            // constant itself. Speculatively parse it as a type; if the next
1565            // token after `>` is `<` we consumed the type prefix and the inner
1566            // constant follows.  Either way we discard the type — we care only
1567            // about the integer values.
1568            let _outer_ty = self.parse_type()?;
1569            // If the next token is NOT `<`, we've already consumed the whole
1570            // mask (old short form without type prefix) — but that can't happen
1571            // here because `parse_type` would have parsed `<i32 0,...>` as a
1572            // vector type, not as a constant. So after consuming the outer type
1573            // the next token must be `<` starting the actual constant.
1574        }
1575        self.lex.expect(&Token::LAngle)?;
1576        let mut mask = Vec::new();
1577        loop {
1578            // Each element: `i32 <int_literal>`.
1579            let _ = self.parse_type()?;
1580            let n = self.lex.expect_int_lit()? as i32;
1581            mask.push(n);
1582            if !self.lex.eat(&Token::Comma) {
1583                break;
1584            }
1585        }
1586        self.lex.expect(&Token::RAngle)?;
1587        Ok(mask)
1588    }
1589
1590    // -----------------------------------------------------------------------
1591    // Skip helpers (for things we don't fully model yet)
1592    // -----------------------------------------------------------------------
1593
1594    fn skip_fn_attrs(&mut self) -> Result<(), ParseError> {
1595        // Skip bare word attributes like `dso_local`, `nounwind`, etc.
1596        // that appear between `define`/`declare` and the return type.
1597        loop {
1598            match self.lex.peek()? {
1599                // These are valid type-starting tokens — stop skipping.
1600                Token::Kw(Keyword::Void)
1601                | Token::Kw(Keyword::Half)
1602                | Token::Kw(Keyword::Bfloat)
1603                | Token::Kw(Keyword::Float)
1604                | Token::Kw(Keyword::Double)
1605                | Token::Kw(Keyword::Fp128)
1606                | Token::Kw(Keyword::X86Fp80)
1607                | Token::Kw(Keyword::Ptr)
1608                | Token::IntType(_)
1609                | Token::LBracket
1610                | Token::LAngle
1611                | Token::LBrace
1612                | Token::LocalIdent(_) => break,
1613                // Linkage keywords already consumed.
1614                Token::Kw(Keyword::Private)
1615                | Token::Kw(Keyword::Internal)
1616                | Token::Kw(Keyword::External)
1617                | Token::Kw(Keyword::Weak) => {
1618                    self.lex.next()?;
1619                }
1620                Token::Hash => {
1621                    self.lex.next()?;
1622                    self.lex.next()?; // skip number
1623                }
1624                _ => break,
1625            }
1626        }
1627        Ok(())
1628    }
1629
1630    fn skip_trailing_fn_attrs(&mut self) -> Result<(), ParseError> {
1631        // Skip `#N`, bare word attrs, etc. until `{`, EOF, or next top-level token.
1632        // Stopping at top-level tokens prevents consuming into the next definition
1633        // when parsing a declaration (which has no `{`).
1634        loop {
1635            match self.lex.peek()? {
1636                Token::LBrace
1637                | Token::Eof
1638                | Token::Kw(Keyword::Define)
1639                | Token::Kw(Keyword::Declare)
1640                | Token::GlobalIdent(_)
1641                | Token::LocalIdent(_)
1642                | Token::Kw(Keyword::Target)
1643                | Token::Kw(Keyword::Source) => break,
1644                Token::Hash => {
1645                    self.lex.next()?;
1646                    self.lex.next()?;
1647                }
1648                Token::Bang => {
1649                    self.parse_metadata_definition_or_skip()?;
1650                    break;
1651                }
1652                _ => {
1653                    self.lex.next()?;
1654                }
1655            }
1656        }
1657        Ok(())
1658    }
1659
1660    fn skip_param_attrs(&mut self) -> Result<(), ParseError> {
1661        // Skip param attrs like `noundef`, `nonnull`, `%N` alignment hints.
1662        //
1663        // Fuzzing found that malformed parameters can otherwise consume through
1664        // top-level tokens and then spin forever on EOF. Stop at boundaries that
1665        // cannot be part of a parameter attribute so the caller reports a normal
1666        // parse error instead of hanging.
1667        loop {
1668            match self.lex.peek()? {
1669                Token::Comma
1670                | Token::RParen
1671                | Token::LocalIdent(_)
1672                | Token::Eof
1673                | Token::Kw(Keyword::Define)
1674                | Token::Kw(Keyword::Declare)
1675                | Token::Kw(Keyword::Source)
1676                | Token::Kw(Keyword::Target)
1677                | Token::GlobalIdent(_)
1678                | Token::Bang => break,
1679                Token::Kw(Keyword::Align) => {
1680                    self.lex.next()?;
1681                    self.lex.next()?; // alignment number
1682                }
1683                Token::Hash => {
1684                    self.lex.next()?;
1685                    self.lex.next()?;
1686                }
1687                _ => {
1688                    self.lex.next()?;
1689                }
1690            }
1691        }
1692        Ok(())
1693    }
1694
1695    fn parse_optional_metadata_attachments(&mut self) -> Result<Vec<(String, String)>, ParseError> {
1696        let mut attachments = Vec::new();
1697        while self.lex.eat(&Token::Comma) {
1698            if !self.lex.eat(&Token::Bang) {
1699                break;
1700            }
1701            let key = self.lex.expect_local_ident()?;
1702            let value = self.parse_metadata_value_text()?;
1703            attachments.push((key, value));
1704        }
1705        Ok(attachments)
1706    }
1707
1708    fn parse_metadata_definition_or_skip(&mut self) -> Result<(), ParseError> {
1709        // Supports:
1710        //   !12 = !DIFile(...)
1711        //   !llvm.dbg.cu = !{!0}
1712        self.lex.expect(&Token::Bang)?;
1713        let lhs = match self.lex.peek()? {
1714            Token::IntLit(_) | Token::UIntLit(_) => Some((Some(self.lex.expect_uint_lit()? as u32), None)),
1715            Token::LocalIdent(_) => Some((None, Some(self.lex.expect_local_ident()?))),
1716            _ => {
1717                self.skip_one_metadata_value()?;
1718                return Ok(());
1719            }
1720        };
1721        if !self.lex.eat(&Token::Equal) {
1722            self.skip_one_metadata_value()?;
1723            return Ok(());
1724        }
1725        let value = self.parse_metadata_value_text()?;
1726        if let Some((maybe_id, maybe_name)) = lhs {
1727            if let Some(id) = maybe_id {
1728                self.module.set_metadata_node(id, value.clone());
1729                if let Some(loc) = Self::parse_dilocation_from_text(&value) {
1730                    self.module.set_debug_location(id, loc);
1731                }
1732            } else if let Some(name) = maybe_name {
1733                self.module.set_named_metadata(name, value);
1734            }
1735        }
1736        Ok(())
1737    }
1738
1739    fn parse_metadata_ref_id(value: &str) -> Option<u32> {
1740        let rest = value.strip_prefix('!')?;
1741        if !rest.is_empty() && rest.chars().all(|c| c.is_ascii_digit()) {
1742            return rest.parse().ok();
1743        }
1744        None
1745    }
1746
1747    fn parse_dilocation_from_text(text: &str) -> Option<llvm_ir::DebugLocation> {
1748        let mut s = text.trim();
1749        if let Some(rest) = s.strip_prefix('!') {
1750            s = rest;
1751        }
1752        if !s.starts_with("DILocation") {
1753            return None;
1754        }
1755        let open = s.find('(')?;
1756        let close = s.rfind(')')?;
1757        if close <= open {
1758            return None;
1759        }
1760        let body = &s[open + 1..close];
1761        let line = Self::parse_named_u32(body, "line")?;
1762        let column = Self::parse_named_u32(body, "column").unwrap_or(0);
1763        Some(llvm_ir::DebugLocation { line, column })
1764    }
1765
1766    fn parse_named_u32(body: &str, name: &str) -> Option<u32> {
1767        let needle = format!("{name}:");
1768        let idx = body.find(&needle)?;
1769        let mut i = idx + needle.len();
1770        while i < body.len() && body.as_bytes()[i].is_ascii_whitespace() {
1771            i += 1;
1772        }
1773        let start = i;
1774        while i < body.len() && body.as_bytes()[i].is_ascii_digit() {
1775            i += 1;
1776        }
1777        if i == start {
1778            None
1779        } else {
1780            body[start..i].parse().ok()
1781        }
1782    }
1783
1784    fn parse_metadata_value_text(&mut self) -> Result<String, ParseError> {
1785        let mut out = String::new();
1786        let mut prev: Option<Token> = None;
1787        let mut depth = 0usize;
1788
1789        if matches!(self.lex.peek()?, Token::LocalIdent(s) if s == "distinct") {
1790            let tok = self.lex.next()?;
1791            Self::push_token_text(&mut out, prev.as_ref(), &tok);
1792            prev = Some(tok);
1793        }
1794
1795        loop {
1796            let tok = self.lex.next()?;
1797            if matches!(tok, Token::Eof) {
1798                break;
1799            }
1800            if Self::is_open_delim(&tok) {
1801                depth += 1;
1802            } else if Self::is_close_delim(&tok) {
1803                if depth == 0 {
1804                    return Err(self.err(format!("unbalanced metadata token {:?}", tok)));
1805                }
1806                depth -= 1;
1807            }
1808            Self::push_token_text(&mut out, prev.as_ref(), &tok);
1809            prev = Some(tok);
1810
1811            if depth == 0 {
1812                let peek = self.lex.peek()?;
1813                if matches!(
1814                    peek,
1815                    Token::Comma
1816                        | Token::Eof
1817                        | Token::RParen
1818                        | Token::RBracket
1819                        | Token::RBrace
1820                        | Token::RAngle
1821                        | Token::Kw(Keyword::Define)
1822                        | Token::Kw(Keyword::Declare)
1823                        | Token::Kw(Keyword::Source)
1824                        | Token::Kw(Keyword::Target)
1825                ) {
1826                    break;
1827                }
1828                if matches!(peek, Token::Bang) && !matches!(prev.as_ref(), Some(Token::Bang)) {
1829                    break;
1830                }
1831                if matches!(peek, Token::LocalIdent(_) | Token::GlobalIdent(_))
1832                    && matches!(
1833                        prev.as_ref(),
1834                        Some(
1835                            Token::RParen
1836                                | Token::RBracket
1837                                | Token::RBrace
1838                                | Token::RAngle
1839                                | Token::IntLit(_)
1840                                | Token::UIntLit(_)
1841                                | Token::StringLit(_)
1842                                | Token::Kw(_)
1843                                | Token::LocalIdent(_)
1844                                | Token::GlobalIdent(_)
1845                        )
1846                    )
1847                {
1848                    break;
1849                }
1850            }
1851        }
1852        Ok(out)
1853    }
1854
1855    fn is_open_delim(tok: &Token) -> bool {
1856        matches!(
1857            tok,
1858            Token::LParen | Token::LBrace | Token::LBracket | Token::LAngle
1859        )
1860    }
1861
1862    fn is_close_delim(tok: &Token) -> bool {
1863        matches!(
1864            tok,
1865            Token::RParen | Token::RBrace | Token::RBracket | Token::RAngle
1866        )
1867    }
1868
1869    fn push_token_text(out: &mut String, prev: Option<&Token>, tok: &Token) {
1870        if let Some(p) = prev {
1871            if Self::needs_space_between(p, tok) {
1872                out.push(' ');
1873            }
1874        }
1875        out.push_str(&Self::token_text(tok));
1876    }
1877
1878    fn needs_space_between(prev: &Token, cur: &Token) -> bool {
1879        if matches!(prev, Token::Bang) {
1880            return false;
1881        }
1882        if matches!(
1883            cur,
1884            Token::Comma | Token::Colon | Token::RParen | Token::RBracket | Token::RBrace | Token::RAngle
1885        ) {
1886            return false;
1887        }
1888        if matches!(
1889            prev,
1890            Token::LParen
1891                | Token::LBracket
1892                | Token::LBrace
1893                | Token::LAngle
1894                | Token::Comma
1895                | Token::Colon
1896                | Token::Bang
1897        ) {
1898            return false;
1899        }
1900        if matches!(cur, Token::LParen) {
1901            return false;
1902        }
1903        true
1904    }
1905
1906    fn token_text(tok: &Token) -> String {
1907        match tok {
1908            Token::LocalIdent(s) => s.clone(),
1909            Token::GlobalIdent(s) => format!("@{}", s),
1910            Token::IntType(bits) => format!("i{}", bits),
1911            Token::IntLit(n) => n.to_string(),
1912            Token::UIntLit(n) => n.to_string(),
1913            Token::FloatLit(n) => n.to_string(),
1914            Token::StringLit(s) => format!("{:?}", s),
1915            Token::Kw(k) => Self::keyword_text(k).to_string(),
1916            Token::Equal => "=".to_string(),
1917            Token::Comma => ",".to_string(),
1918            Token::Colon => ":".to_string(),
1919            Token::Star => "*".to_string(),
1920            Token::LParen => "(".to_string(),
1921            Token::RParen => ")".to_string(),
1922            Token::LBracket => "[".to_string(),
1923            Token::RBracket => "]".to_string(),
1924            Token::LBrace => "{".to_string(),
1925            Token::RBrace => "}".to_string(),
1926            Token::LAngle => "<".to_string(),
1927            Token::RAngle => ">".to_string(),
1928            Token::Ellipsis => "...".to_string(),
1929            Token::Bang => "!".to_string(),
1930            Token::Hash => "#".to_string(),
1931            Token::Eof => String::new(),
1932        }
1933    }
1934
1935    fn keyword_text(kw: &Keyword) -> &'static str {
1936        match kw {
1937            Keyword::Source => "source_filename",
1938            Keyword::Target => "target",
1939            Keyword::Triple => "triple",
1940            Keyword::Datalayout => "datalayout",
1941            Keyword::Define => "define",
1942            Keyword::Declare => "declare",
1943            Keyword::Type => "type",
1944            Keyword::Private => "private",
1945            Keyword::Internal => "internal",
1946            Keyword::External => "external",
1947            Keyword::Weak => "weak",
1948            Keyword::WeakOdr => "weak_odr",
1949            Keyword::Linkonce => "linkonce",
1950            Keyword::LinkonceOdr => "linkonce_odr",
1951            Keyword::Common => "common",
1952            Keyword::AvailableExternally => "available_externally",
1953            Keyword::Void => "void",
1954            Keyword::Half => "half",
1955            Keyword::Bfloat => "bfloat",
1956            Keyword::Float => "float",
1957            Keyword::Double => "double",
1958            Keyword::Fp128 => "fp128",
1959            Keyword::X86Fp80 => "x86_fp80",
1960            Keyword::Label => "label",
1961            Keyword::Metadata => "metadata",
1962            Keyword::Ptr => "ptr",
1963            Keyword::Global => "global",
1964            Keyword::Constant => "constant",
1965            Keyword::Inbounds => "inbounds",
1966            Keyword::Exact => "exact",
1967            Keyword::Nuw => "nuw",
1968            Keyword::Nsw => "nsw",
1969            Keyword::Volatile => "volatile",
1970            Keyword::Tail => "tail",
1971            Keyword::Musttail => "musttail",
1972            Keyword::Notail => "notail",
1973            Keyword::Fast => "fast",
1974            Keyword::Nnan => "nnan",
1975            Keyword::Ninf => "ninf",
1976            Keyword::Nsz => "nsz",
1977            Keyword::Arcp => "arcp",
1978            Keyword::Contract => "contract",
1979            Keyword::Afn => "afn",
1980            Keyword::Reassoc => "reassoc",
1981            Keyword::Add => "add",
1982            Keyword::Sub => "sub",
1983            Keyword::Mul => "mul",
1984            Keyword::Udiv => "udiv",
1985            Keyword::Sdiv => "sdiv",
1986            Keyword::Urem => "urem",
1987            Keyword::Srem => "srem",
1988            Keyword::And => "and",
1989            Keyword::Or => "or",
1990            Keyword::Xor => "xor",
1991            Keyword::Shl => "shl",
1992            Keyword::Lshr => "lshr",
1993            Keyword::Ashr => "ashr",
1994            Keyword::Fadd => "fadd",
1995            Keyword::Fsub => "fsub",
1996            Keyword::Fmul => "fmul",
1997            Keyword::Fdiv => "fdiv",
1998            Keyword::Frem => "frem",
1999            Keyword::Fneg => "fneg",
2000            Keyword::Icmp => "icmp",
2001            Keyword::Fcmp => "fcmp",
2002            Keyword::Alloca => "alloca",
2003            Keyword::Load => "load",
2004            Keyword::Store => "store",
2005            Keyword::Getelementptr => "getelementptr",
2006            Keyword::Trunc => "trunc",
2007            Keyword::Zext => "zext",
2008            Keyword::Sext => "sext",
2009            Keyword::Fptrunc => "fptrunc",
2010            Keyword::Fpext => "fpext",
2011            Keyword::Fptoui => "fptoui",
2012            Keyword::Fptosi => "fptosi",
2013            Keyword::Uitofp => "uitofp",
2014            Keyword::Sitofp => "sitofp",
2015            Keyword::Ptrtoint => "ptrtoint",
2016            Keyword::Inttoptr => "inttoptr",
2017            Keyword::Bitcast => "bitcast",
2018            Keyword::Addrspacecast => "addrspacecast",
2019            Keyword::Freeze => "freeze",
2020            Keyword::Select => "select",
2021            Keyword::Phi => "phi",
2022            Keyword::Extractvalue => "extractvalue",
2023            Keyword::Insertvalue => "insertvalue",
2024            Keyword::Extractelement => "extractelement",
2025            Keyword::Insertelement => "insertelement",
2026            Keyword::Shufflevector => "shufflevector",
2027            Keyword::Call => "call",
2028            Keyword::Ret => "ret",
2029            Keyword::Br => "br",
2030            Keyword::Switch => "switch",
2031            Keyword::Unreachable => "unreachable",
2032            Keyword::Eq => "eq",
2033            Keyword::Ne => "ne",
2034            Keyword::Ugt => "ugt",
2035            Keyword::Uge => "uge",
2036            Keyword::Ult => "ult",
2037            Keyword::Ule => "ule",
2038            Keyword::Sgt => "sgt",
2039            Keyword::Sge => "sge",
2040            Keyword::Slt => "slt",
2041            Keyword::Sle => "sle",
2042            Keyword::False => "false",
2043            Keyword::Oeq => "oeq",
2044            Keyword::Ogt => "ogt",
2045            Keyword::Oge => "oge",
2046            Keyword::Olt => "olt",
2047            Keyword::Ole => "ole",
2048            Keyword::One => "one",
2049            Keyword::Ord => "ord",
2050            Keyword::Uno => "uno",
2051            Keyword::Ueq => "ueq",
2052            Keyword::Une => "une",
2053            Keyword::True => "true",
2054            Keyword::Zeroinitializer => "zeroinitializer",
2055            Keyword::Undef => "undef",
2056            Keyword::Poison => "poison",
2057            Keyword::Null => "null",
2058            Keyword::Align => "align",
2059            Keyword::To => "to",
2060            Keyword::X => "x",
2061            Keyword::Vscale => "vscale",
2062        }
2063    }
2064
2065    fn skip_one_metadata_value(&mut self) -> Result<(), ParseError> {
2066        let _ = self.parse_metadata_value_text()?;
2067        Ok(())
2068    }
2069
2070}
2071
2072// ---------------------------------------------------------------------------
2073// Public entry point
2074// ---------------------------------------------------------------------------
2075
2076/// Public API for `parse`.
2077pub fn parse(src: &str) -> Result<(Context, Module), ParseError> {
2078    let mut parser = Parser::new(src);
2079    parser.parse_module()?;
2080    Ok((parser.ctx, parser.module))
2081}
2082
2083#[cfg(test)]
2084mod tests {
2085    use super::*;
2086    use llvm_ir::printer::Printer;
2087
2088    #[test]
2089    fn parse_empty_function() {
2090        let src = r#"
2091define void @empty() {
2092entry:
2093  ret void
2094}
2095"#;
2096        let (_ctx, module) = parse(src).expect("parse failed");
2097        assert_eq!(module.functions.len(), 1);
2098        let f = &module.functions[0];
2099        assert_eq!(f.name, "empty");
2100        assert!(!f.is_declaration);
2101        assert_eq!(f.blocks.len(), 1);
2102        assert_eq!(f.blocks[0].name, "entry");
2103    }
2104
2105    #[test]
2106    fn parse_add_function() {
2107        let src = r#"
2108define i32 @add(i32 %a, i32 %b) {
2109entry:
2110  %result = add i32 %a, %b
2111  ret i32 %result
2112}
2113"#;
2114        let (_ctx, module) = parse(src).expect("parse failed");
2115        let f = &module.functions[0];
2116        assert_eq!(f.name, "add");
2117        assert_eq!(f.args.len(), 2);
2118        let bb = &f.blocks[0];
2119        assert_eq!(bb.body.len(), 1);
2120        assert!(bb.is_complete());
2121    }
2122
2123    #[test]
2124    fn parse_declaration() {
2125        let src = "declare i32 @printf(ptr, ...)";
2126        let (_ctx, module) = parse(src).expect("parse failed");
2127        assert_eq!(module.functions.len(), 1);
2128        assert!(module.functions[0].is_declaration);
2129    }
2130
2131    #[test]
2132    fn malformed_param_attrs_stop_at_module_boundaries() {
2133        // Regression for a libFuzzer timeout found from the llvm-stress corpus:
2134        // a malformed parameter comment caused skip_param_attrs to consume
2135        // across top-level tokens and then spin forever on EOF.
2136        let src = "; ModuleID = '/tmp/autogen.bc'\n\
2137source_filename = \"/tmp/autogen.bc\"\n\n\
2138define void @autogen_SD0(ptr; ModuleID = '/tmp/autogen %0, ptr %1, ptr %2, i32 .bc'\n\
2139source_filename = \"/tmp/autogen.bc\"\n\n\
2140define void %3, i64@au";
2141
2142        let err = match parse(src) {
2143            Ok(_) => panic!("malformed input should fail"),
2144            Err(err) => err,
2145        };
2146        assert!(err.message.contains("expected RParen"));
2147    }
2148
2149    #[test]
2150    fn parse_global() {
2151        let src = "@x = global i32 42";
2152        let (_ctx, module) = parse(src).expect("parse failed");
2153        assert_eq!(module.globals.len(), 1);
2154        assert_eq!(module.globals[0].name, "x");
2155    }
2156
2157    #[test]
2158    fn parse_target_metadata() {
2159        let src = r#"
2160source_filename = "test.c"
2161target triple = "x86_64-unknown-linux-gnu"
2162target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
2163"#;
2164        let (_ctx, module) = parse(src).expect("parse failed");
2165        assert_eq!(module.source_filename.as_deref(), Some("test.c"));
2166        assert_eq!(
2167            module.target_triple.as_deref(),
2168            Some("x86_64-unknown-linux-gnu")
2169        );
2170    }
2171
2172    #[test]
2173    fn parse_cond_br() {
2174        let src = r#"
2175define void @check(i1 %cond) {
2176entry:
2177  br i1 %cond, label %then, label %else
2178then:
2179  ret void
2180else:
2181  ret void
2182}
2183"#;
2184        let (_ctx, module) = parse(src).expect("parse failed");
2185        let f = &module.functions[0];
2186        assert_eq!(f.blocks.len(), 3);
2187    }
2188
2189    #[test]
2190    fn parse_dbg_attachment_and_dilocation() {
2191        let src = r#"
2192source_filename = "dbg.ll"
2193define i32 @f() {
2194entry:
2195  ret i32 0, !dbg !12, !tbaa !14
2196}
2197!12 = !DILocation(line: 27, column: 3, scope: !1)
2198!14 = !{!"int", !15}
2199!15 = !{!"omnipotent char", !16}
2200!16 = !{!"Simple C/C++ TBAA"}
2201"#;
2202        let (_ctx, module) = parse(src).expect("parse failed");
2203        let f = &module.functions[0];
2204        let tid = f.blocks[0].terminator.expect("terminator");
2205        assert_eq!(f.instr_dbg_loc(tid), Some(12));
2206        let attachments = f.instr_metadata(tid).expect("metadata attachments");
2207        assert_eq!(attachments.len(), 2);
2208        assert_eq!(attachments[0].0, "dbg");
2209        assert_eq!(attachments[0].1, "!12");
2210        assert_eq!(attachments[1].0, "tbaa");
2211        assert_eq!(attachments[1].1, "!14");
2212        let loc = module.debug_location(12).expect("dilocation");
2213        assert_eq!(loc.line, 27);
2214        assert_eq!(loc.column, 3);
2215        assert_eq!(
2216            module.metadata_node(14),
2217            Some("!{!\"int\",!15}")
2218        );
2219    }
2220
2221    #[test]
2222    fn metadata_roundtrip_preserves_named_and_numbered_nodes() {
2223        let src = r#"
2224define i32 @f() {
2225entry:
2226  ret i32 0, !dbg !12
2227}
2228!llvm.dbg.cu = !{!0}
2229!0 = distinct !DICompileUnit(language: 12, file: !1, producer: !"codex", isOptimized: false, runtimeVersion: 0, emissionKind: 1)
2230!1 = !DIFile(filename: !"a.c", directory: !"/tmp")
2231!12 = !DILocation(line: 7, column: 2, scope: !0)
2232"#;
2233        let (ctx, module) = parse(src).expect("parse failed");
2234        let printed = Printer::new(&ctx).print_module(&module);
2235        let (_ctx2, module2) = parse(&printed).expect("roundtrip parse failed");
2236        assert_eq!(
2237            module2.named_metadata,
2238            vec![("llvm.dbg.cu".to_string(), "!{!0}".to_string())]
2239        );
2240        assert_eq!(module2.metadata_node(0).map(|s| s.contains("DICompileUnit")), Some(true));
2241        assert_eq!(module2.metadata_node(1).map(|s| s.contains("DIFile")), Some(true));
2242        assert_eq!(module2.metadata_node(12), Some("!DILocation(line:7,column:2,scope:!0)"));
2243        let loc = module2.debug_location(12).expect("dilocation");
2244        assert_eq!(loc.line, 7);
2245        assert_eq!(loc.column, 2);
2246    }
2247}