1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use arret_syntax::span::Span;
use arret_runtime::abitype;
use crate::mir::builder::{Builder, BuiltReg};
use crate::mir::eval_hir::EvalHirCtx;
use crate::mir::ops;
use crate::mir::polymorph::PolymorphAbi;
use crate::mir::value::Value;
use crate::ty;
pub struct LoadedArgList {
pub captures_reg: Option<BuiltReg>,
pub param_regs: Box<[ops::RegId]>,
pub arg_list_value: Value,
}
pub fn build_load_arg_list_value(
ehx: &mut EvalHirCtx,
b: &mut Builder,
polymorph_abi: &PolymorphAbi,
param_list_poly: &ty::List<ty::Poly>,
) -> LoadedArgList {
use crate::mir::value::from_reg::reg_to_value;
use crate::ty::list_iter::ListIterator;
let captures_reg: Option<BuiltReg> = if polymorph_abi.has_captures {
Some(b.alloc_local())
} else {
None
};
let mut param_list_poly_iter = ListIterator::new(param_list_poly);
let fixed_reg_values: Vec<(ops::RegId, Value)> = polymorph_abi
.fixed_params
.iter()
.map(|abi_type| {
let reg = b.alloc_local();
let param_type = param_list_poly_iter.next().unwrap();
(reg.into(), reg_to_value(ehx, reg, abi_type, param_type))
})
.collect();
let rest_reg_value: Option<(ops::RegId, Value)> =
polymorph_abi.rest_param.as_ref().map(|abi_type| {
let reg = b.alloc_local();
let tail_type = param_list_poly_iter.tail_type();
(
reg.into(),
reg_to_value(ehx, reg, abi_type, &tail_type.into()),
)
});
let param_regs = captures_reg
.into_iter()
.map(Into::into)
.chain(fixed_reg_values.iter().map(|(reg, _)| *reg))
.chain(rest_reg_value.iter().map(|(reg, _)| *reg))
.collect();
let arg_list_value = Value::List(
fixed_reg_values
.into_iter()
.map(|(_, value)| value)
.collect(),
rest_reg_value.map(|(_, value)| Box::new(value)),
);
LoadedArgList {
captures_reg,
param_regs,
arg_list_value,
}
}
pub fn build_save_arg_list_to_regs<'a>(
ehx: &mut EvalHirCtx,
b: &mut Builder,
span: Span,
arg_list_value: Value,
fixed_abi_types: impl ExactSizeIterator<Item = &'a abitype::AbiType>,
rest_abi_type: Option<&'a abitype::AbiType>,
) -> Vec<ops::RegId> {
use crate::mir::value::build_reg::value_to_reg;
let mut list_iter = arg_list_value.into_unsized_list_iter();
let mut arg_regs = vec![];
for abi_type in fixed_abi_types {
let fixed_value = list_iter.next_unchecked(b, span);
let reg_id = value_to_reg(ehx, b, span, &fixed_value, abi_type);
arg_regs.push(reg_id.into());
}
if let Some(rest_abi_type) = rest_abi_type {
let reg_id = value_to_reg(ehx, b, span, &list_iter.into_rest(), rest_abi_type);
arg_regs.push(reg_id.into());
};
arg_regs
}