Skip to main content

vicis_core/ir/function/instruction/
parser.rs

1use super::{
2    Alloca, Br, Call, Cast, CondBr, GetElementPtr, ICmp, ICmpCond, Instruction, InstructionId,
3    IntBinary, Invoke, LandingPad, Load, Opcode, Operand, Phi, Resume, Ret, Store,
4};
5use crate::ir::{
6    function::{
7        instruction::{ExtractValue, InsertValue},
8        param_attrs::{parser::parse_param_attrs, ParameterAttribute},
9        parser::ParserContext,
10    },
11    module::{
12        attributes::parser::parse_attributes, metadata, metadata::Metadata,
13        name::parser::identifier,
14    },
15    types::I32,
16    util::string_literal,
17};
18use crate::ir::{module::name, types, util::spaces, value};
19use nom::{
20    branch::alt,
21    bytes::complete::tag,
22    character::complete::{char, digit1},
23    combinator::{map, opt},
24    error::VerboseError,
25    sequence::{preceded, tuple},
26    Err::Error,
27    IResult,
28};
29use rustc_hash::FxHashMap;
30
31pub fn parse_alloca<'a, 'b>(
32    source: &'a str,
33    ctx: &mut ParserContext<'b>,
34) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
35    let (source, _) = preceded(spaces, tag("alloca"))(source)?;
36    let (source, ty) = types::parse(source, ctx.types)?;
37    let (source, align) = opt(preceded(
38        spaces,
39        preceded(
40            char(','),
41            preceded(spaces, preceded(tag("align"), preceded(spaces, digit1))),
42        ),
43    ))(source)?;
44    // TODO: Implement parser for num_elements
45    let num_elements = value::ConstantData::Int(value::ConstantInt::Int32(1));
46    let inst = Opcode::Alloca
47        .with_block(ctx.cur_block)
48        .with_operand(Operand::Alloca(Alloca {
49            tys: [ty, I32],
50            num_elements,
51            align: align.map_or(0, |align| align.parse::<u32>().unwrap_or(0)),
52        }));
53    Ok((source, inst))
54}
55
56pub fn parse_phi<'a, 'b>(
57    source: &'a str,
58    ctx: &mut ParserContext<'b>,
59) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
60    let (source, _) = preceded(spaces, tag("phi"))(source)?;
61    let (mut source, ty) = types::parse(source, ctx.types)?;
62    let mut args = vec![];
63    let mut blocks = vec![];
64    loop {
65        let (source_, _) = preceded(spaces, char('['))(source)?;
66        let (source_, arg) = value::parse(source_, ctx, ty)?;
67        args.push(arg);
68        let (source_, _) = preceded(spaces, char(','))(source_)?;
69        let (source_, name) = preceded(spaces, preceded(char('%'), name::parse))(source_)?;
70        let block = ctx.get_or_create_named_block(name);
71        blocks.push(block);
72        let (source_, _) = preceded(spaces, char(']'))(source_)?;
73        if let Ok((source_, _)) = preceded(spaces, char(','))(source_) {
74            source = source_;
75            continue;
76        }
77        let inst = Opcode::Phi
78            .with_block(ctx.cur_block)
79            .with_operand(Operand::Phi(Phi { ty, args, blocks }));
80        return Ok((source_, inst));
81    }
82}
83
84pub fn parse_load<'a, 'b>(
85    source: &'a str,
86    ctx: &mut ParserContext<'b>,
87) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
88    let (source, _) = preceded(spaces, tag("load"))(source)?;
89    let (source, ty) = types::parse(source, ctx.types)?;
90    let (source, _) = preceded(spaces, char(','))(source)?;
91    let (source, addr_ty) = types::parse(source, ctx.types)?;
92    let (source, addr) = value::parse(source, ctx, addr_ty)?;
93    let (source, align) = opt(preceded(
94        spaces,
95        preceded(
96            char(','),
97            preceded(spaces, preceded(tag("align"), preceded(spaces, digit1))),
98        ),
99    ))(source)?;
100    let (source, _) = opt(parse_metadata("!nonnull"))(source)?; // TODO: FIXME: don't ignore !nonnull
101    let (source, _) = opt(parse_metadata("!range"))(source)?; // TODO: FIXME: don't ignore !range
102    let inst = Opcode::Load
103        .with_block(ctx.cur_block)
104        .with_operand(Operand::Load(Load {
105            tys: [ty, addr_ty],
106            addr,
107            align: align.map_or(0, |align| align.parse::<u32>().unwrap_or(0)),
108        }));
109    Ok((source, inst))
110}
111
112pub fn parse_store<'a, 'b>(
113    source: &'a str,
114    ctx: &mut ParserContext<'b>,
115) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
116    let (source, _) = preceded(spaces, preceded(tag("store"), spaces))(source)?;
117    let (source, src_ty) = types::parse(source, ctx.types)?;
118    let (source, src) = value::parse(source, ctx, src_ty)?;
119    let (source, _) = preceded(spaces, char(','))(source)?;
120    let (source, dst_ty) = types::parse(source, ctx.types)?;
121    let (source, dst) = value::parse(source, ctx, dst_ty)?;
122    let (source, align) = opt(preceded(
123        spaces,
124        preceded(
125            char(','),
126            preceded(spaces, preceded(tag("align"), preceded(spaces, digit1))),
127        ),
128    ))(source)?;
129    Ok((
130        source,
131        Opcode::Store
132            .with_block(ctx.cur_block)
133            .with_operand(Operand::Store(Store {
134                tys: [src_ty, dst_ty],
135                args: [src, dst],
136                align: align.map_or(0, |align| align.parse::<u32>().unwrap_or(0)),
137            })),
138    ))
139}
140
141pub fn parse_insertvalue<'a, 'b>(
142    source: &'a str,
143    ctx: &mut ParserContext<'b>,
144) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
145    let (source, _) = preceded(spaces, tag("insertvalue"))(source)?;
146    let (source, aggre_ty) = types::parse(source, ctx.types)?;
147    let (source, val) = value::parse(source, ctx, aggre_ty)?;
148    let (source, _) = preceded(spaces, char(','))(source)?;
149    let (source, ty) = types::parse(source, ctx.types)?;
150    let (source, elt) = value::parse(source, ctx, ty)?;
151    let (source, _) = preceded(spaces, char(','))(source)?;
152    let mut args = vec![val, elt];
153    let (mut source, idx) = value::parse(source, ctx, I32)?;
154    args.push(idx);
155    loop {
156        if let Ok((source_, _)) = preceded(spaces, char(','))(source) {
157            let (source_, idx) = value::parse(source_, ctx, I32)?;
158            args.push(idx);
159            source = source_;
160            continue;
161        }
162        return Ok((
163            source,
164            Opcode::InsertValue
165                .with_block(ctx.cur_block)
166                .with_operand(Operand::InsertValue(InsertValue {
167                    tys: [aggre_ty, ty],
168                    args,
169                })),
170        ));
171    }
172}
173
174pub fn parse_extractvalue<'a, 'b>(
175    source: &'a str,
176    ctx: &mut ParserContext<'b>,
177) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
178    let (source, _) = preceded(spaces, tag("extractvalue"))(source)?;
179    let (source, aggre_ty) = types::parse(source, ctx.types)?;
180    let (source, val) = value::parse(source, ctx, aggre_ty)?;
181    let (source, _) = preceded(spaces, char(','))(source)?;
182    let mut args = vec![val];
183    let (mut source, idx) = value::parse(source, ctx, I32)?;
184    args.push(idx);
185    loop {
186        if let Ok((source_, _)) = preceded(spaces, char(','))(source) {
187            let (source_, idx) = value::parse(source_, ctx, I32)?;
188            args.push(idx);
189            source = source_;
190            continue;
191        }
192        return Ok((
193            source,
194            Opcode::ExtractValue
195                .with_block(ctx.cur_block)
196                .with_operand(Operand::ExtractValue(ExtractValue { ty: aggre_ty, args })),
197        ));
198    }
199}
200
201pub fn parse_add_sub_mul<'a, 'b>(
202    source: &'a str,
203    ctx: &mut ParserContext<'b>,
204) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
205    let (source, opcode) = preceded(
206        spaces,
207        alt((
208            map(tag("add"), |_| Opcode::Add),
209            map(tag("sub"), |_| Opcode::Sub),
210            map(tag("mul"), |_| Opcode::Mul),
211            map(tag("sdiv"), |_| Opcode::SDiv),
212            map(tag("srem"), |_| Opcode::SRem),
213            map(tag("and"), |_| Opcode::And),
214            map(tag("lshr"), |_| Opcode::LShr),
215        )),
216    )(source)?;
217    // TODO: `and` doesn't need nuw/nsw/exact keywords. We had better show error when they appear.
218    let (source, nuw) = opt(preceded(spaces, tag("nuw")))(source)?;
219    let (source, nsw) = opt(preceded(spaces, tag("nsw")))(source)?;
220    let (source, exact) = opt(preceded(spaces, tag("exact")))(source)?;
221    let (source, ty) = types::parse(source, ctx.types)?;
222    let (source, lhs) = value::parse(source, ctx, ty)?;
223    let (source, _) = preceded(spaces, char(','))(source)?;
224    let (source, rhs) = value::parse(source, ctx, ty)?;
225    let inst = opcode
226        .with_block(ctx.cur_block)
227        .with_operand(Operand::IntBinary(IntBinary {
228            ty,
229            args: [lhs, rhs],
230            nuw: nuw.map_or(false, |_| true),
231            nsw: nsw.map_or(false, |_| true),
232            exact: exact.map_or(false, |_| true),
233        }));
234    Ok((source, inst))
235}
236
237pub fn parse_icmp<'a, 'b>(
238    source: &'a str,
239    ctx: &mut ParserContext<'b>,
240) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
241    pub fn icmp_cond(source: &str) -> IResult<&str, ICmpCond, VerboseError<&str>> {
242        alt((
243            map(tag("eq"), |_| ICmpCond::Eq),
244            map(tag("ne"), |_| ICmpCond::Ne),
245            map(tag("ugt"), |_| ICmpCond::Ugt),
246            map(tag("uge"), |_| ICmpCond::Uge),
247            map(tag("ult"), |_| ICmpCond::Ult),
248            map(tag("ule"), |_| ICmpCond::Ule),
249            map(tag("sgt"), |_| ICmpCond::Sgt),
250            map(tag("sge"), |_| ICmpCond::Sge),
251            map(tag("slt"), |_| ICmpCond::Slt),
252            map(tag("sle"), |_| ICmpCond::Sle),
253        ))(source)
254    }
255
256    let (source, _) = preceded(spaces, tag("icmp"))(source)?;
257    let (source, cond) = preceded(spaces, icmp_cond)(source)?;
258    let (source, ty) = types::parse(source, ctx.types)?;
259    let (source, lhs) = value::parse(source, ctx, ty)?;
260    let (source, _) = preceded(spaces, char(','))(source)?;
261    let (source, rhs) = value::parse(source, ctx, ty)?;
262    let inst = Opcode::ICmp
263        .with_block(ctx.cur_block)
264        .with_operand(Operand::ICmp(ICmp {
265            ty,
266            args: [lhs, rhs],
267            cond,
268        }));
269    Ok((source, inst))
270}
271
272pub fn parse_cast<'a, 'b>(
273    source: &'a str,
274    ctx: &mut ParserContext<'b>,
275) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
276    let (source, opcode) = preceded(
277        spaces,
278        alt((
279            map(tag("sext"), |_| Opcode::Sext),
280            map(tag("zext"), |_| Opcode::Zext),
281            map(tag("bitcast"), |_| Opcode::Bitcast),
282            map(tag("trunc"), |_| Opcode::Trunc),
283            map(tag("inttoptr"), |_| Opcode::IntToPtr),
284        )),
285    )(source)?;
286    let (source, from) = types::parse(source, ctx.types)?;
287    let (source, arg) = value::parse(source, ctx, from)?;
288    let (source, _) = preceded(spaces, tag("to"))(source)?;
289    let (source, to) = types::parse(source, ctx.types)?;
290    let inst = opcode
291        .with_block(ctx.cur_block)
292        .with_operand(Operand::Cast(Cast {
293            tys: [from, to],
294            arg,
295        }));
296    Ok((source, inst))
297}
298
299type CallArguments = (
300    Vec<types::Type>,
301    Vec<Vec<ParameterAttribute>>,
302    Vec<value::ValueId>,
303);
304
305pub fn parse_call_args<'a, 'b>(
306    source: &'a str,
307    ctx: &mut ParserContext<'b>,
308) -> IResult<&'a str, CallArguments, VerboseError<&'a str>> {
309    let (mut source, _) = preceded(spaces, char('('))(source)?;
310
311    if let Ok((source, _)) = preceded(spaces, char(')'))(source) {
312        return Ok((source, (vec![], vec![], vec![])));
313    }
314
315    let mut arg_types = vec![];
316    let mut arg_attr_lists = vec![];
317    let mut arg_values = vec![];
318    loop {
319        let (source_, ty) = types::parse(source, ctx.types)?;
320        let (source_, attrs) = parse_param_attrs(source_, ctx.types)?;
321        let (source_, arg) = value::parse(source_, ctx, ty)?;
322        arg_types.push(ty);
323        arg_attr_lists.push(attrs);
324        arg_values.push(arg);
325
326        if let Ok((source_, _)) = preceded(spaces, char(','))(source_) {
327            source = source_;
328            continue;
329        }
330        if let Ok((source, _)) = preceded(spaces, char(')'))(source_) {
331            return Ok((source, (arg_types, arg_attr_lists, arg_values)));
332        }
333    }
334}
335
336pub fn parse_getelementptr<'a, 'b>(
337    source: &'a str,
338    ctx: &mut ParserContext<'b>,
339) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
340    let (source, _) = preceded(spaces, tag("getelementptr"))(source)?;
341    let (source, inbounds) = opt(preceded(spaces, tag("inbounds")))(source)?;
342    let (source, ty) = types::parse(source, ctx.types)?;
343    let (mut source, _) = preceded(spaces, char(','))(source)?;
344    let mut args = vec![];
345    let mut tys = vec![ty];
346    loop {
347        let (source_, ty) = types::parse(source, ctx.types)?;
348        let (source_, arg) = value::parse(source_, ctx, ty)?;
349        tys.push(ty);
350        args.push(arg);
351        if let Ok((source_, _)) = preceded(spaces, char(','))(source_) {
352            source = source_;
353            continue;
354        }
355        let inst = Opcode::GetElementPtr
356            .with_block(ctx.cur_block)
357            .with_operand(Operand::GetElementPtr(GetElementPtr {
358                inbounds: inbounds.is_some(),
359                tys,
360                args,
361            }));
362        return Ok((source_, inst));
363    }
364}
365
366pub fn parse_call<'a, 'b>(
367    source: &'a str,
368    ctx: &mut ParserContext<'b>,
369) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
370    let (source, _) = preceded(spaces, tag("call"))(source)?;
371    let (source, ret_attrs) = parse_param_attrs(source, ctx.types)?;
372    let (source, ty) = types::parse(source, ctx.types)?;
373    let (source, callee) = parse_callee(source, ctx, ty)?;
374    let (source, (mut tys, param_attrs, mut args)) = parse_call_args(source, ctx)?;
375    let (source, func_attrs) = parse_attributes(source)?;
376    let (source, _) = opt(parse_metadata("!srcloc"))(source)?; // TODO: FIXME: don't ignore !srcloc
377    tys.insert(0, ty);
378    args.insert(0, callee);
379    let inst = Opcode::Call
380        .with_block(ctx.cur_block)
381        .with_operand(Operand::Call(Call {
382            tys,
383            args,
384            param_attrs,
385            ret_attrs,
386            func_attrs,
387        }));
388    Ok((source, inst))
389}
390
391pub fn parse_callee<'a, 'b>(
392    source: &'a str,
393    ctx: &mut ParserContext<'b>,
394    ty: types::Type,
395) -> IResult<&'a str, value::ValueId, VerboseError<&'a str>> {
396    if let Ok((source, asm)) = parse_call_asm(source) {
397        return Ok((source, ctx.data.create_value(value::Value::InlineAsm(asm))));
398    }
399
400    let (source, callee) = value::parse(source, ctx, ty)?;
401    Ok((source, callee))
402}
403
404pub fn parse_call_asm(source: &str) -> IResult<&str, value::InlineAsm, VerboseError<&str>> {
405    let (source, _) = preceded(spaces, tag("asm"))(source)?;
406    let (source, sideeffect) = opt(tuple((spaces, tag("sideeffect"))))(source)?;
407    let (source, constraints) = preceded(spaces, string_literal)(source)?;
408    let (source, _) = preceded(spaces, char(','))(source)?;
409    let (source, body) = preceded(spaces, string_literal)(source)?;
410    Ok((
411        source,
412        value::InlineAsm {
413            constraints,
414            body,
415            sideeffect: sideeffect.is_some(),
416        },
417    ))
418}
419
420pub fn parse_invoke<'a, 'b>(
421    source: &'a str,
422    ctx: &mut ParserContext<'b>,
423) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
424    let (source, _) = preceded(spaces, tag("invoke"))(source)?;
425    let (source, ret_attrs) = parse_param_attrs(source, ctx.types)?;
426    let (source, ty) = types::parse(source, ctx.types)?;
427    let (source, callee) = value::parse(source, ctx, ty)?;
428    let (source, (mut tys, param_attrs, mut args)) = parse_call_args(source, ctx)?;
429    tys.insert(0, ty);
430    args.insert(0, callee);
431    let (source, func_attrs) = parse_attributes(source)?;
432    let (source, (_, _, _, _, _, _, normal)) = tuple((
433        spaces,
434        tag("to"),
435        spaces,
436        tag("label"),
437        spaces,
438        char('%'),
439        name::parse,
440    ))(source)?;
441    let (source, (_, _, _, _, _, _, exception)) = tuple((
442        spaces,
443        tag("unwind"),
444        spaces,
445        tag("label"),
446        spaces,
447        char('%'),
448        name::parse,
449    ))(source)?;
450    let normal = ctx.get_or_create_named_block(normal);
451    let exception = ctx.get_or_create_named_block(exception);
452    let inst = Opcode::Invoke
453        .with_block(ctx.cur_block)
454        .with_operand(Operand::Invoke(Invoke {
455            tys,
456            args,
457            param_attrs,
458            ret_attrs,
459            func_attrs,
460            blocks: vec![normal, exception],
461        }));
462    Ok((source, inst))
463}
464
465pub fn parse_landingpad<'a, 'b>(
466    source: &'a str,
467    ctx: &mut ParserContext<'b>,
468) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
469    let (source, _) = preceded(spaces, tag("landingpad"))(source)?;
470    let (source, ty) = types::parse(source, ctx.types)?;
471    let (source, _) = preceded(spaces, tag("cleanup"))(source)?;
472    let inst = Opcode::LandingPad
473        .with_block(ctx.cur_block)
474        .with_operand(Operand::LandingPad(LandingPad { ty }));
475    Ok((source, inst))
476}
477
478pub fn parse_resume<'a, 'b>(
479    source: &'a str,
480    ctx: &mut ParserContext<'b>,
481) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
482    let (source, _) = preceded(spaces, tag("resume"))(source)?;
483    let (source, ty) = types::parse(source, ctx.types)?;
484    let (source, arg) = value::parse(source, ctx, ty)?;
485    let inst = Opcode::Resume
486        .with_block(ctx.cur_block)
487        .with_operand(Operand::Resume(Resume { ty, arg }));
488    Ok((source, inst))
489}
490
491pub fn parse_br<'a, 'b>(
492    source: &'a str,
493    ctx: &mut ParserContext<'b>,
494) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
495    let (source, _) = preceded(spaces, tag("br"))(source)?;
496    if let Ok((source, _)) = preceded(spaces, tag("label"))(source) {
497        let (source, label) = preceded(spaces, preceded(char('%'), name::parse))(source)?;
498        let block = ctx.get_or_create_named_block(label);
499        let inst = Opcode::Br
500            .with_block(ctx.cur_block)
501            .with_operand(Operand::Br(Br { block }));
502        Ok((source, inst))
503    } else {
504        let (source, ty) = types::parse(source, ctx.types)?;
505        assert!(ty.is_i1());
506        let (source, arg) = value::parse(source, ctx, ty)?;
507        let (source, _) = preceded(spaces, char(','))(source)?;
508        let (source, iftrue) = preceded(
509            spaces,
510            preceded(
511                tag("label"),
512                preceded(spaces, preceded(char('%'), name::parse)),
513            ),
514        )(source)?;
515        let (source, _) = preceded(spaces, char(','))(source)?;
516        let (source, iffalse) = preceded(
517            spaces,
518            preceded(
519                tag("label"),
520                preceded(spaces, preceded(char('%'), name::parse)),
521            ),
522        )(source)?;
523        let iftrue = ctx.get_or_create_named_block(iftrue);
524        let iffalse = ctx.get_or_create_named_block(iffalse);
525        let inst = Opcode::CondBr
526            .with_block(ctx.cur_block)
527            .with_operand(Operand::CondBr(CondBr {
528                arg,
529                blocks: [iftrue, iffalse],
530            }));
531        Ok((source, inst))
532    }
533}
534
535pub fn parse_ret<'a, 'b>(
536    source: &'a str,
537    ctx: &mut ParserContext<'b>,
538) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
539    let (source, _) = preceded(spaces, preceded(tag("ret"), spaces))(source)?;
540    let (source, ty) = types::parse(source, ctx.types)?;
541    let (source, val) = if ty.is_void() {
542        (source, None)
543    } else {
544        let (source, val) = value::parse(source, ctx, ty)?;
545        (source, Some(val))
546    };
547    Ok((
548        source,
549        Opcode::Ret
550            .with_block(ctx.cur_block)
551            .with_operand(Operand::Ret(Ret { val, ty })),
552    ))
553}
554
555pub fn parse_unreachable<'a, 'b>(
556    source: &'a str,
557    ctx: &mut ParserContext<'b>,
558) -> IResult<&'a str, Instruction, VerboseError<&'a str>> {
559    let (source, _) = preceded(spaces, preceded(tag("unreachable"), spaces))(source)?;
560    Ok((
561        source,
562        Opcode::Unreachable
563            .with_block(ctx.cur_block)
564            .with_operand(Operand::Unreachable),
565    ))
566}
567
568fn parse_metadata<'a>(
569    name: &'static str,
570) -> impl Fn(&'a str) -> IResult<&'a str, &'a str, VerboseError<&'a str>> {
571    move |source: &'a str| {
572        let (source, (_, _, _, _, _, _, num)) = tuple((
573            spaces,
574            char(','),
575            spaces,
576            tag(name),
577            spaces,
578            char('!'),
579            digit1,
580        ))(source)?;
581        Ok((source, num))
582    }
583}
584
585fn parse_metadata_if_any(
586    types: &types::Types,
587) -> impl Fn(&str) -> IResult<&str, FxHashMap<String, Metadata>, VerboseError<&str>> + '_ {
588    move |mut source| {
589        let mut metadata = FxHashMap::default();
590        loop {
591            match preceded(spaces, char(','))(source) {
592                Ok((src, _)) => source = src,
593                Err(_) => return Ok((source, metadata)),
594            }
595            let (src, kind) = preceded(spaces, preceded(char('!'), identifier))(source)?;
596            let (src, meta) = metadata::parse_operand(types)(src)?;
597            metadata.insert(kind.to_owned(), meta);
598            source = src;
599        }
600    }
601}
602
603/// Only parses `source` as Instruction. Doesn't append instruction to block.
604pub fn parse<'a, 'b>(
605    source: &'a str,
606    ctx: &mut ParserContext<'b>,
607) -> IResult<&'a str, InstructionId, VerboseError<&'a str>> {
608    let (source, name) = opt(tuple((spaces, char('%'), name::parse, spaces, char('='))))(source)?;
609    let name = name.map(|(_, _, name, _, _)| name);
610    for f in [
611        parse_alloca,
612        parse_phi,
613        parse_load,
614        parse_store,
615        parse_insertvalue,
616        parse_extractvalue,
617        parse_add_sub_mul,
618        parse_icmp,
619        parse_cast,
620        parse_getelementptr,
621        parse_call,
622        parse_invoke,
623        parse_landingpad,
624        parse_resume,
625        parse_br,
626        parse_ret,
627        parse_unreachable,
628    ]
629    .iter()
630    {
631        if let Ok((source, mut inst)) = f(source, ctx) {
632            let (source, metadata) = parse_metadata_if_any(ctx.types)(source)?;
633            inst = inst.with_metadata(metadata);
634
635            if let Some(name) = name {
636                if let Some(inner) = ctx.name_to_value.get(&name) {
637                    if let value::Value::Instruction(id) = ctx.data.values[*inner] {
638                        ctx.data.replace_inst(id, inst.with_dest(name));
639                        return Ok((source, id));
640                    }
641                }
642
643                let id = ctx.data.create_inst(inst.with_dest(name.clone()));
644                ctx.name_to_value
645                    .insert(name, ctx.data.create_value(value::Value::Instruction(id)));
646                return Ok((source, id));
647            }
648
649            return Ok((source, ctx.data.create_inst(inst)));
650        }
651    }
652    Err(Error(VerboseError { errors: vec![] }))
653}