1use super::*;
2
3pub(crate) fn emit_collection_borrow_instr_tokens(
4 instr: &MirInstr,
5 mut_locals: &HashSet<MirLocalId>,
6 read_locals: &HashSet<MirLocalId>,
7 function_names: &FunctionNames,
8) -> Option<rust::Tokens> {
9 let mut tokens = rust::Tokens::new();
10 match instr {
11 MirInstr::CollectionLen { collection, dst } => {
12 let collection = function_names.local_ident(*collection);
13 let value = quote!($collection.len() as i64);
14 emit_local_binding(
15 &mut tokens,
16 *dst,
17 value.clone(),
18 value,
19 true,
20 mut_locals,
21 read_locals,
22 function_names,
23 );
24 Some(tokens)
25 }
26 MirInstr::IndexBorrowRo {
27 collection,
28 index,
29 dst,
30 } => {
31 let collection = function_names.local_ident(*collection);
32 let index = function_names.local_ident(*index);
33 let value = quote!(&$collection[$index as usize]);
34 emit_local_binding(
35 &mut tokens,
36 *dst,
37 value.clone(),
38 value,
39 false,
40 mut_locals,
41 read_locals,
42 function_names,
43 );
44 Some(tokens)
45 }
46 MirInstr::IndexBorrowMut {
47 collection,
48 index,
49 dst,
50 } => {
51 let collection = function_names.local_ident(*collection);
52 let index = function_names.local_ident(*index);
53 let value = quote!(&mut $collection[$index as usize]);
54 emit_local_binding(
55 &mut tokens,
56 *dst,
57 value.clone(),
58 value,
59 false,
60 mut_locals,
61 read_locals,
62 function_names,
63 );
64 Some(tokens)
65 }
66 MirInstr::SliceBorrowRo {
67 collection,
68 start,
69 end,
70 dst,
71 } => {
72 let collection = function_names.local_ident(*collection);
73 let slice_expr =
74 emit_slice_expr_tokens(&collection, *start, *end, function_names, false);
75 emit_local_binding(
76 &mut tokens,
77 *dst,
78 slice_expr.clone(),
79 slice_expr,
80 false,
81 mut_locals,
82 read_locals,
83 function_names,
84 );
85 Some(tokens)
86 }
87 MirInstr::SliceBorrowMut {
88 collection,
89 start,
90 end,
91 dst,
92 } => {
93 let collection = function_names.local_ident(*collection);
94 let slice_expr =
95 emit_slice_expr_tokens(&collection, *start, *end, function_names, true);
96 emit_local_binding(
97 &mut tokens,
98 *dst,
99 slice_expr.clone(),
100 slice_expr,
101 false,
102 mut_locals,
103 read_locals,
104 function_names,
105 );
106 Some(tokens)
107 }
108 MirInstr::FieldBorrowRo { base, field, dst } => {
109 let base = function_names.local_ident(*base);
110 let field_expr = if let Ok(index) = field.parse::<usize>() {
111 quote!(#$index)
112 } else {
113 let field = field.clone();
114 quote!($field)
115 };
116 let value = quote!(&$base.$field_expr);
117 emit_local_binding(
118 &mut tokens,
119 *dst,
120 value.clone(),
121 value,
122 false,
123 mut_locals,
124 read_locals,
125 function_names,
126 );
127 Some(tokens)
128 }
129 MirInstr::FieldBorrowMut { base, field, dst } => {
130 let base = function_names.local_ident(*base);
131 let field_expr = if let Ok(index) = field.parse::<usize>() {
132 quote!(#$index)
133 } else {
134 let field = field.clone();
135 quote!($field)
136 };
137 let value = quote!(&mut $base.$field_expr);
138 emit_local_binding(
139 &mut tokens,
140 *dst,
141 value.clone(),
142 value,
143 false,
144 mut_locals,
145 read_locals,
146 function_names,
147 );
148 Some(tokens)
149 }
150 _ => None,
151 }
152}
153
154pub(crate) fn emit_int_binary_instr_tokens(
155 instr: &MirInstr,
156 mut_locals: &HashSet<MirLocalId>,
157 read_locals: &HashSet<MirLocalId>,
158 function_names: &FunctionNames,
159) -> Option<rust::Tokens> {
160 let mut tokens = rust::Tokens::new();
161 let (lhs, rhs, dst, value) = match instr {
162 MirInstr::IntLt { lhs, rhs, dst } => (*lhs, *rhs, *dst, "lt"),
163 MirInstr::IntGt { lhs, rhs, dst } => (*lhs, *rhs, *dst, "gt"),
164 MirInstr::IntLtEq { lhs, rhs, dst } => (*lhs, *rhs, *dst, "lteq"),
165 MirInstr::IntGtEq { lhs, rhs, dst } => (*lhs, *rhs, *dst, "gteq"),
166 MirInstr::IntEq { lhs, rhs, dst } => (*lhs, *rhs, *dst, "eq"),
167 MirInstr::IntNeq { lhs, rhs, dst } => (*lhs, *rhs, *dst, "neq"),
168 MirInstr::IntAdd { lhs, rhs, dst } => (*lhs, *rhs, *dst, "add"),
169 MirInstr::IntSub { lhs, rhs, dst } => (*lhs, *rhs, *dst, "sub"),
170 MirInstr::IntMul { lhs, rhs, dst } => (*lhs, *rhs, *dst, "mul"),
171 MirInstr::IntDiv { lhs, rhs, dst } => (*lhs, *rhs, *dst, "div"),
172 MirInstr::IntMod { lhs, rhs, dst } => (*lhs, *rhs, *dst, "mod"),
173 _ => return None,
174 };
175 let lhs = function_names.local_ident(lhs);
176 let rhs = function_names.local_ident(rhs);
177 let expr = match value {
178 "lt" => quote!($lhs < $rhs),
179 "gt" => quote!($lhs > $rhs),
180 "lteq" => quote!($lhs <= $rhs),
181 "gteq" => quote!($lhs >= $rhs),
182 "eq" => quote!($lhs == $rhs),
183 "neq" => quote!($lhs != $rhs),
184 "add" => quote!($lhs + $rhs),
185 "sub" => quote!($lhs - $rhs),
186 "mul" => quote!($lhs * $rhs),
187 "div" => quote!($lhs / $rhs),
188 "mod" => quote!($lhs % $rhs),
189 _ => unreachable!("unsupported int op"),
190 };
191 emit_local_binding(
192 &mut tokens,
193 dst,
194 expr.clone(),
195 expr,
196 true,
197 mut_locals,
198 read_locals,
199 function_names,
200 );
201 Some(tokens)
202}
203
204pub(crate) fn emit_local_binding(
205 mut tokens: &mut rust::Tokens,
206 dst: MirLocalId,
207 binding_value: rust::Tokens,
208 discard_value: rust::Tokens,
209 allow_mut: bool,
210 mut_locals: &HashSet<MirLocalId>,
211 read_locals: &HashSet<MirLocalId>,
212 function_names: &FunctionNames,
213) {
214 if read_locals.contains(&dst) {
215 let dst_name = function_names.local_ident(dst);
216 if allow_mut && mut_locals.contains(&dst) {
217 quote_in!(tokens => let mut $dst_name = $binding_value;);
218 } else {
219 quote_in!(tokens => let $dst_name = $binding_value;);
220 }
221 } else {
222 quote_in!(tokens => let _ = $discard_value;);
223 }
224}
225
226pub(crate) fn collect_mutable_locals(stmts: &[MirStmt], mutable_locals: &mut HashSet<MirLocalId>) {
227 for stmt in stmts {
228 match stmt {
229 MirStmt::Instr(MirInstr::Call { args, .. }) => {
230 for arg in args {
231 if arg.is_mutable_borrow() {
232 let _ = mutable_locals.insert(arg.local);
233 }
234 }
235 }
236 MirStmt::Instr(MirInstr::CallExtern { args, .. }) => {
237 for arg in args {
238 if arg.is_mutable_borrow() {
239 let _ = mutable_locals.insert(arg.local);
240 }
241 }
242 }
243 MirStmt::Instr(MirInstr::CallIntrinsic { args, .. }) => {
244 for arg in args {
245 if arg.is_mutable_borrow() {
246 let _ = mutable_locals.insert(arg.local);
247 }
248 }
249 }
250 MirStmt::Instr(MirInstr::IndexBorrowMut { collection, .. }) => {
251 let _ = mutable_locals.insert(*collection);
252 }
253 MirStmt::Instr(MirInstr::SliceBorrowMut { collection, .. }) => {
254 let _ = mutable_locals.insert(*collection);
255 }
256 MirStmt::Instr(MirInstr::PointerBorrowMut { pointer, .. }) => {
257 let _ = mutable_locals.insert(*pointer);
258 }
259 MirStmt::Instr(MirInstr::FieldBorrowMut { base, .. }) => {
260 let _ = mutable_locals.insert(*base);
261 }
262 MirStmt::Instr(MirInstr::AssignLocal { dst, .. }) => {
263 let _ = mutable_locals.insert(*dst);
264 }
265 MirStmt::Instr(MirInstr::AssignFieldPath { base, .. }) => {
266 let _ = mutable_locals.insert(*base);
267 }
268 MirStmt::Instr(_) => {}
269 MirStmt::If {
270 then_body,
271 else_body,
272 ..
273 } => {
274 collect_mutable_locals(then_body, mutable_locals);
275 collect_mutable_locals(else_body, mutable_locals);
276 }
277 MirStmt::While {
278 loop_params,
279 cond_body,
280 body,
281 ..
282 } => {
283 for local in loop_params {
284 let _ = mutable_locals.insert(*local);
285 }
286 collect_mutable_locals(cond_body, mutable_locals);
287 collect_mutable_locals(body, mutable_locals);
288 }
289 MirStmt::Return { .. } => {}
290 }
291 }
292}
293
294pub(crate) fn collect_read_locals(stmts: &[MirStmt], read_locals: &mut HashSet<MirLocalId>) {
295 for stmt in stmts {
296 match stmt {
297 MirStmt::Instr(instr) => collect_instr_reads(instr, read_locals),
298 MirStmt::If {
299 cond,
300 then_body,
301 else_body,
302 } => {
303 let _ = read_locals.insert(*cond);
304 collect_read_locals(then_body, read_locals);
305 collect_read_locals(else_body, read_locals);
306 }
307 MirStmt::While {
308 init_args,
309 cond_body,
310 cond,
311 body,
312 step_args,
313 ..
314 } => {
315 for local in init_args {
316 let _ = read_locals.insert(*local);
317 }
318 collect_read_locals(cond_body, read_locals);
319 let _ = read_locals.insert(*cond);
320 collect_read_locals(body, read_locals);
321 for local in step_args {
322 let _ = read_locals.insert(*local);
323 }
324 }
325 MirStmt::Return { value } => {
326 let _ = read_locals.insert(*value);
327 }
328 }
329 }
330}
331
332pub(crate) fn collect_instr_reads(instr: &MirInstr, read_locals: &mut HashSet<MirLocalId>) {
333 match instr {
334 MirInstr::ConstUnit { .. }
335 | MirInstr::ConstInt { .. }
336 | MirInstr::ConstFloat { .. }
337 | MirInstr::ConstString { .. }
338 | MirInstr::ConstBool { .. }
339 | MirInstr::ConstNull { .. } => {}
340 MirInstr::PointerNew { src, .. } => {
341 let _ = read_locals.insert(*src);
342 }
343 MirInstr::MakeArray { items, .. } => {
344 for item in items {
345 let _ = read_locals.insert(item.local);
346 }
347 }
348 MirInstr::MakeTuple { items, .. } => {
349 for item in items {
350 let _ = read_locals.insert(item.local);
351 }
352 }
353 MirInstr::MakeStruct { fields, .. } => {
354 for (_, value) in fields {
355 let _ = read_locals.insert(*value);
356 }
357 }
358 MirInstr::MakeEnum { payload, .. } => {
359 for item in payload {
360 let _ = read_locals.insert(item.local);
361 }
362 }
363 MirInstr::ReadField { base, .. }
364 | MirInstr::FieldBorrowRo { base, .. }
365 | MirInstr::FieldBorrowMut { base, .. } => {
366 let _ = read_locals.insert(*base);
367 }
368 MirInstr::EnumIsVariant { value, .. } | MirInstr::EnumGetField { value, .. } => {
369 let _ = read_locals.insert(*value);
370 }
371 MirInstr::Copy { src, .. }
372 | MirInstr::Move { src, .. }
373 | MirInstr::NumCast { src, .. }
374 | MirInstr::CheckedIntCast { src, .. }
375 | MirInstr::DerefCopy { src, .. } => {
376 let _ = read_locals.insert(*src);
377 }
378 MirInstr::AssignLocal { src, dst } => {
379 let _ = read_locals.insert(*src);
380 let _ = read_locals.insert(*dst);
381 }
382 MirInstr::StoreRef { src, dst_ref } => {
383 let _ = read_locals.insert(*src);
384 let _ = read_locals.insert(*dst_ref);
385 }
386 MirInstr::AssignFieldPath { base, src, .. } => {
387 let _ = read_locals.insert(*base);
388 let _ = read_locals.insert(*src);
389 }
390 MirInstr::Call { args, .. } => {
391 for arg in args {
392 let _ = read_locals.insert(arg.local);
393 }
394 }
395 MirInstr::CallExtern { args, .. } => {
396 for arg in args {
397 let _ = read_locals.insert(arg.local);
398 }
399 }
400 MirInstr::CallIntrinsic { args, .. } => {
401 for arg in args {
402 let _ = read_locals.insert(arg.local);
403 }
404 }
405 MirInstr::CollectionLen { collection, .. } => {
406 let _ = read_locals.insert(*collection);
407 }
408 MirInstr::IndexBorrowRo {
409 collection, index, ..
410 }
411 | MirInstr::IndexBorrowMut {
412 collection, index, ..
413 } => {
414 let _ = read_locals.insert(*collection);
415 let _ = read_locals.insert(*index);
416 }
417 MirInstr::SliceBorrowRo {
418 collection,
419 start,
420 end,
421 ..
422 }
423 | MirInstr::SliceBorrowMut {
424 collection,
425 start,
426 end,
427 ..
428 } => {
429 let _ = read_locals.insert(*collection);
430 if let Some(start) = start {
431 let _ = read_locals.insert(*start);
432 }
433 if let Some(end) = end {
434 let _ = read_locals.insert(*end);
435 }
436 }
437 MirInstr::PointerIsSome { pointer, .. }
438 | MirInstr::PointerBorrowRo { pointer, .. }
439 | MirInstr::PointerBorrowMut { pointer, .. } => {
440 let _ = read_locals.insert(*pointer);
441 }
442 MirInstr::ReleaseHeap { local } => {
443 let _ = read_locals.insert(*local);
444 }
445 MirInstr::IntLt { lhs, rhs, .. }
446 | MirInstr::IntGt { lhs, rhs, .. }
447 | MirInstr::IntLtEq { lhs, rhs, .. }
448 | MirInstr::IntGtEq { lhs, rhs, .. }
449 | MirInstr::IntEq { lhs, rhs, .. }
450 | MirInstr::IntNeq { lhs, rhs, .. }
451 | MirInstr::IntAdd { lhs, rhs, .. }
452 | MirInstr::IntSub { lhs, rhs, .. }
453 | MirInstr::IntMul { lhs, rhs, .. }
454 | MirInstr::IntDiv { lhs, rhs, .. }
455 | MirInstr::IntMod { lhs, rhs, .. } => {
456 let _ = read_locals.insert(*lhs);
457 let _ = read_locals.insert(*rhs);
458 }
459 }
460}
461
462pub(crate) fn emit_slice_expr_tokens(
463 collection: &str,
464 start: Option<MirLocalId>,
465 end: Option<MirLocalId>,
466 function_names: &FunctionNames,
467 mutable: bool,
468) -> rust::Tokens {
469 let start_tokens = start.map(|value| function_names.local_ident(value));
470 let end_tokens = end.map(|value| function_names.local_ident(value));
471 match (start_tokens, end_tokens, mutable) {
472 (Some(start), Some(end), false) => {
473 quote!(&$collection[$start as usize..$end as usize])
474 }
475 (Some(start), None, false) => quote!(&$collection[$start as usize..]),
476 (None, Some(end), false) => quote!(&$collection[..$end as usize]),
477 (None, None, false) => quote!(&$collection[..]),
478 (Some(start), Some(end), true) => {
479 quote!(&mut $collection[$start as usize..$end as usize])
480 }
481 (Some(start), None, true) => quote!(&mut $collection[$start as usize..]),
482 (None, Some(end), true) => quote!(&mut $collection[..$end as usize]),
483 (None, None, true) => quote!(&mut $collection[..]),
484 }
485}
486
487pub(crate) fn collect_ref_locals(
488 function: &MirFunction,
489) -> (HashSet<MirLocalId>, HashSet<MirLocalId>) {
490 let mut ro_refs = HashSet::new();
491 let mut mut_refs = HashSet::new();
492 for (local_id, info) in function.locals.iter() {
493 if info.is_place() {
494 if info.is_mutable_place() {
495 let _ = mut_refs.insert(local_id);
496 } else {
497 let _ = ro_refs.insert(local_id);
498 }
499 }
500 }
501 (ro_refs, mut_refs)
502}
503
504pub(crate) fn collect_slice_locals(function: &MirFunction) -> HashSet<MirLocalId> {
505 let mut slices = HashSet::new();
506 for (local_id, info) in function.locals.iter() {
507 if matches!(info.ty, Ty::Slice(_)) {
508 let _ = slices.insert(local_id);
509 }
510 }
511 slices
512}
513
514pub(crate) fn emit_array_items(
515 items: &[MirAggregateArg],
516 function_names: &FunctionNames,
517) -> rust::Tokens {
518 let mut out = rust::Tokens::new();
519 for (index, item) in items.iter().enumerate() {
520 let local = function_names.local_ident(item.local);
521 if index > 0 {
522 quote_in!(out => ,);
523 }
524 if item.is_owned_move() {
525 quote_in!(out => $local)
526 } else if item.is_owned_copy() {
527 quote_in!(out => $local.clone())
528 } else {
529 panic!("borrowed aggregate arg mode is not valid for array literals")
530 }
531 }
532 quote!([$out])
533}
534
535pub(crate) fn emit_boxed_slice_items(
536 items: &[MirAggregateArg],
537 function_names: &FunctionNames,
538) -> rust::Tokens {
539 let mut out = rust::Tokens::new();
540 for (index, item) in items.iter().enumerate() {
541 let local = function_names.local_ident(item.local);
542 if index > 0 {
543 quote_in!(out => ,);
544 }
545 if item.is_owned_move() {
546 quote_in!(out => $local)
547 } else if item.is_owned_copy() {
548 quote_in!(out => $local.clone())
549 } else {
550 panic!("borrowed aggregate arg mode is not valid for slice literals")
551 }
552 }
553 quote!(vec![$out])
554}
555
556pub(crate) fn emit_enum_payload_items(
557 items: &[MirAggregateArg],
558 function_names: &FunctionNames,
559) -> rust::Tokens {
560 let mut out = rust::Tokens::new();
561 for (index, item) in items.iter().enumerate() {
562 let local = function_names.local_ident(item.local);
563 if index > 0 {
564 quote_in!(out => ,);
565 }
566 if item.is_owned_move() {
567 quote_in!(out => $local)
568 } else if item.is_owned_copy() {
569 quote_in!(out => $local.clone())
570 } else {
571 panic!("borrowed aggregate arg mode is not valid for enum constructors")
572 }
573 }
574 out
575}
576
577pub(crate) fn emit_enum_get_field_expr(
578 value: &str,
579 enum_name: &str,
580 variant: &str,
581 index: usize,
582) -> rust::Tokens {
583 let mut bindings = rust::Tokens::new();
584 for field_index in 0..=index {
585 if field_index > 0 {
586 quote_in!(bindings => ,);
587 }
588 if field_index == index {
589 quote_in!(bindings => value);
590 } else {
591 quote_in!(bindings => _);
592 }
593 }
594 quote!(match &$value {
595 $enum_name::$variant($bindings) => value.clone(),
596 _ => unreachable!("enum_get_field matched wrong variant"),
597 })
598}
599
600pub(crate) fn emit_enum_variant_wildcard_pattern(
601 enum_name: &str,
602 variant: &str,
603 payload_len: usize,
604) -> rust::Tokens {
605 if payload_len == 0 {
606 quote!($enum_name::$variant)
607 } else {
608 let mut wildcards = rust::Tokens::new();
609 for index in 0..payload_len {
610 if index > 0 {
611 quote_in!(wildcards => ,);
612 }
613 quote_in!(wildcards => _);
614 }
615 quote!($enum_name::$variant($wildcards))
616 }
617}
618
619pub(crate) fn emit_intrinsic_call_expr(
620 function: &MirFunction,
621 intrinsic: MirIntrinsic,
622 args: &[MirCallArg],
623 function_names: &FunctionNames,
624) -> rust::Tokens {
625 match intrinsic {
626 MirIntrinsic::Ptr => {
627 let args = emit_extern_call_args(function, args, function_names);
628 quote!(ruka_runtime::ptr::Ptr::new($args))
629 }
630 MirIntrinsic::Array => {
631 let init = emit_extern_call_args(function, &args[0..1], function_names);
632 let len = emit_extern_call_args(function, &args[1..2], function_names);
633 quote!(vec![$init; $len as usize])
634 }
635 }
636}
637
638pub(crate) fn emit_internal_call_args(
639 function: &MirFunction,
640 args: &[MirCallArg],
641 function_names: &FunctionNames,
642) -> rust::Tokens {
643 let mut items = rust::Tokens::new();
644 for (index, arg) in args.iter().enumerate() {
645 if index > 0 {
646 quote_in!(items => ,);
647 }
648 let local = function_names.local_ident(arg.local);
649 let binding = function.call_arg_binding(arg);
650 if binding.is_borrowed() {
651 if binding.requires_deref_read() {
652 quote_in!(items => &*$local)
653 } else {
654 quote_in!(items => &$local)
655 }
656 } else if binding.is_mutable_borrow() {
657 if binding.is_mutable_place() {
658 quote_in!(items => &mut *$local)
659 } else {
660 quote_in!(items => &mut $local)
661 }
662 } else if binding.is_owned_move() {
663 if binding.requires_deref_read() {
664 let cloned = emit_place_read_clone_expr(binding, &local);
665 quote_in!(items => $cloned)
666 } else {
667 quote_in!(items => $local)
668 }
669 } else {
670 debug_assert!(binding.is_owned_copy());
671 if binding.requires_deref_read() {
672 let cloned = emit_place_read_clone_expr(binding, &local);
673 quote_in!(items => $cloned)
674 } else {
675 quote_in!(items => $local.clone())
676 }
677 }
678 }
679 items
680}
681
682pub(crate) fn emit_extern_call_args(
683 function: &MirFunction,
684 args: &[MirCallArg],
685 function_names: &FunctionNames,
686) -> rust::Tokens {
687 let mut items = rust::Tokens::new();
688 for (index, arg) in args.iter().enumerate() {
689 if index > 0 {
690 quote_in!(items => ,);
691 }
692 let local = function_names.local_ident(arg.local);
693 let binding = function.call_arg_binding(arg);
694 if binding.is_borrowed() {
695 if binding.requires_deref_read() {
696 let cloned = emit_place_read_clone_expr(binding, &local);
697 quote_in!(items => $cloned)
698 } else {
699 quote_in!(items => $local.clone())
700 }
701 } else if binding.is_mutable_borrow() {
702 if binding.is_mutable_place() {
703 quote_in!(items => &mut *$local)
704 } else {
705 quote_in!(items => &mut $local)
706 }
707 } else if binding.is_owned_move() {
708 if binding.requires_deref_read() {
709 let cloned = emit_place_read_clone_expr(binding, &local);
710 quote_in!(items => $cloned)
711 } else {
712 quote_in!(items => $local)
713 }
714 } else {
715 debug_assert!(binding.is_owned_copy());
716 if binding.requires_deref_read() {
717 let cloned = emit_place_read_clone_expr(binding, &local);
718 quote_in!(items => $cloned)
719 } else {
720 quote_in!(items => $local.clone())
721 }
722 }
723 }
724 items
725}
726
727fn emit_place_read_clone_expr(
729 binding: ruka_mir::MirCallArgBinding<'_>,
730 local: &str,
731) -> rust::Tokens {
732 if matches!(binding.place_item_ty(), Some(Ty::Slice(_))) {
733 quote!($local.to_vec())
734 } else {
735 quote!((*$local).clone())
736 }
737}
738
739pub(crate) fn emit_extern_call_expr(
740 function: &MirFunction,
741 symbol: &str,
742 args: &[MirCallArg],
743 function_names: &FunctionNames,
744) -> rust::Tokens {
745 let runtime_symbol = symbol.strip_prefix("std::").unwrap_or(symbol);
746 let callee = format!("ruka_runtime::{runtime_symbol}");
747 let args = emit_extern_call_args(function, args, function_names);
748 quote!($callee($args))
749}
750
751pub(crate) fn emit_function_params(
752 function: &MirFunction,
753 function_names: &FunctionNames,
754 read_locals: &HashSet<MirLocalId>,
755) -> rust::Tokens {
756 let mut params = rust::Tokens::new();
757 for binding in function.param_bindings() {
758 if binding.index > 0 {
759 quote_in!(params => ,);
760 }
761 let name = incoming_param_ident(
762 function_names,
763 binding.local_id,
764 binding.index,
765 read_locals.contains(&binding.local_id),
766 );
767 let ty_tokens = if binding.expects_view() || binding.expects_mut_borrow() {
768 emit_borrowed_param_ty_tokens(binding.semantic_ty())
769 } else {
770 emit_ty_tokens(binding.semantic_ty())
771 };
772 if binding.expects_view() {
773 quote_in!(params => $name: &$ty_tokens)
774 } else if binding.expects_mut_borrow() {
775 quote_in!(params => $name: &mut $ty_tokens)
776 } else {
777 quote_in!(params => $name: $ty_tokens)
778 }
779 }
780 params
781}