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 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)?; let (source, _) = opt(parse_metadata("!range"))(source)?; 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 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)?; 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
603pub 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}