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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use arret_syntax::span::Span;
use crate::codegen::GenAbi;
use crate::mir::builder::Builder;
use crate::mir::error::{Error, Result};
use crate::mir::eval_hir::EvalHirCtx;
use crate::mir::ops;
use crate::mir::polymorph::PolymorphAbi;
use crate::mir::value::Value;
use crate::rfi;
use crate::ty;
use crate::ty::purity::Purity;
use crate::ty::Ty;
pub fn rust_fun_purity_upper_bound(rust_fun: &rfi::Fun) -> Purity {
let arret_fun_type = rust_fun.arret_fun_type();
if arret_fun_type.ret().is_never() {
Purity::Impure
} else if arret_fun_type.purity() == &Purity::Pure.into() {
Purity::Pure
} else {
Purity::Impure
}
}
pub fn build_rust_fun_app(
ehx: &mut EvalHirCtx,
b: &mut Builder,
span: Span,
ret_ty: &ty::Ref<ty::Mono>,
rust_fun: &rfi::Fun,
call_purity: Purity,
arg_list_value: Value,
) -> Result<Value> {
use crate::mir::arg_list::build_save_arg_list_to_regs;
use crate::mir::ops::*;
use crate::mir::value::from_reg::reg_to_value;
use arret_runtime::abitype::RetAbiType;
let mut arg_abi_types = rust_fun
.params()
.iter()
.map(|param_abi_type| ¶m_abi_type.abi_type);
let rest_abi_type = if rust_fun.has_rest() {
arg_abi_types.next_back()
} else {
None
};
let arg_regs =
build_save_arg_list_to_regs(ehx, b, span, arg_list_value, arg_abi_types, rest_abi_type);
let purity_upper_bound = rust_fun_purity_upper_bound(rust_fun);
let abi = GenAbi {
takes_task: rust_fun.takes_task(),
params: rust_fun.params().to_owned().into(),
ret: rust_fun.ret().clone(),
};
ehx.register_rust_fun_with_jit(rust_fun);
let callee = ops::Callee::StaticSymbol(ops::StaticSymbol {
symbol: rust_fun.symbol(),
impure: purity_upper_bound == Purity::Impure,
abi,
});
let ret_reg = b.push_reg(
span,
OpKind::Call,
CallOp {
callee,
impure: call_purity == Purity::Impure,
args: arg_regs.into_boxed_slice(),
},
);
match rust_fun.ret() {
RetAbiType::Void => Ok(Value::List(Box::new([]), None)),
RetAbiType::Never => {
b.push(span, OpKind::Unreachable);
Err(Error::Diverged)
}
RetAbiType::Inhabited(abi_type) => Ok(reg_to_value(ehx, ret_reg, abi_type, ret_ty)),
}
}
pub fn ops_for_rust_fun(
ehx: &mut EvalHirCtx,
rust_fun: &rfi::Fun,
wanted_abi: PolymorphAbi,
) -> ops::Fun {
use crate::mir::arg_list::{build_load_arg_list_value, LoadedArgList};
use crate::mir::optimise::optimise_fun;
use crate::mir::ret_value::build_value_ret;
let mut b = Builder::new();
let span = rust_fun.span();
let fun_symbol = format!("{}_adapter", rust_fun.symbol());
let LoadedArgList {
param_regs,
arg_list_value,
..
} = build_load_arg_list_value(ehx, &mut b, &wanted_abi, rust_fun.arret_fun_type().params());
let purity_upper_bound = rust_fun_purity_upper_bound(rust_fun);
let ret_ty = Ty::Any.into();
let app_result = build_rust_fun_app(
ehx,
&mut b,
span,
&ret_ty,
rust_fun,
purity_upper_bound,
arg_list_value,
);
build_value_ret(ehx, &mut b, span, app_result, &wanted_abi.ret);
optimise_fun(ops::Fun {
span,
source_name: Some(fun_symbol.into()),
abi: wanted_abi.into(),
param_regs,
ops: b.into_ops(),
})
}