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
use arret_syntax::span::Span;
use arret_runtime::abitype;
use arret_runtime::boxed;
use crate::mir::builder::{Builder, BuiltReg};
use crate::mir::eval_hir::EvalHirCtx;
use crate::mir::value::build_reg::value_to_reg;
use crate::mir::value::types::possible_type_tags_for_value;
use crate::mir::value::Value;
pub enum NumOperand {
Int(BuiltReg),
Float(BuiltReg),
}
impl NumOperand {
pub fn try_from_value(
ehx: &mut EvalHirCtx,
b: &mut Builder,
span: Span,
value: &Value,
) -> Option<NumOperand> {
let possible_type_tags = possible_type_tags_for_value(value);
if !possible_type_tags.contains(boxed::TypeTag::Float) {
let int64_reg = value_to_reg(ehx, b, span, value, &abitype::AbiType::Int);
Some(NumOperand::Int(int64_reg))
} else if !possible_type_tags.contains(boxed::TypeTag::Int) {
let float_reg = value_to_reg(ehx, b, span, value, &abitype::AbiType::Float);
Some(NumOperand::Float(float_reg))
} else {
None
}
}
}
pub fn num_value_to_float_reg(
ehx: &mut EvalHirCtx,
outer_b: &mut Builder,
span: Span,
value: &Value,
) -> BuiltReg {
use crate::mir::ops::*;
let num_type_tags = [boxed::TypeTag::Int, boxed::TypeTag::Float]
.iter()
.collect();
let possible_type_tags = possible_type_tags_for_value(value) & num_type_tags;
if possible_type_tags == boxed::TypeTag::Float.into() {
value_to_reg(ehx, outer_b, span, value, &abitype::AbiType::Float)
} else if possible_type_tags == boxed::TypeTag::Int.into() {
let int64_reg = value_to_reg(ehx, outer_b, span, value, &abitype::AbiType::Int);
outer_b.push_reg(span, OpKind::Int64ToFloat, int64_reg.into())
} else {
let boxed_any_reg = value_to_reg(
ehx,
outer_b,
span,
value,
&abitype::BoxedAbiType::Any.into(),
)
.into();
let value_type_tag_reg = outer_b.push_reg(
span,
OpKind::LoadBoxedTypeTag,
LoadBoxedTypeTagOp {
subject_reg: boxed_any_reg,
possible_type_tags: num_type_tags,
},
);
let float_tag_reg = outer_b.push_reg(span, OpKind::ConstTypeTag, boxed::TypeTag::Float);
let is_float_reg = outer_b.push_reg(
span,
OpKind::TypeTagEqual,
BinaryOp {
lhs_reg: value_type_tag_reg.into(),
rhs_reg: float_tag_reg.into(),
},
);
let mut is_float_b = Builder::new();
let is_float_result_reg =
value_to_reg(ehx, &mut is_float_b, span, value, &abitype::AbiType::Float);
let mut is_int_b = Builder::new();
let int64_reg = value_to_reg(ehx, &mut is_int_b, span, value, &abitype::AbiType::Int);
let is_int_result_reg = is_int_b.push_reg(span, OpKind::Int64ToFloat, int64_reg.into());
let output_reg = RegId::alloc();
outer_b.push(
span,
OpKind::Cond(CondOp {
reg_phi: Some(RegPhi {
output_reg,
true_result_reg: is_float_result_reg.into(),
false_result_reg: is_int_result_reg.into(),
}),
test_reg: is_float_reg.into(),
true_ops: is_float_b.into_ops(),
false_ops: is_int_b.into_ops(),
}),
);
BuiltReg::Local(output_reg)
}
}
pub fn try_value_to_i64(value: Value) -> Option<i64> {
match value {
Value::Const(any_ref) => any_ref
.downcast_ref::<boxed::Int>()
.map(|int_ref| int_ref.value()),
_ => None,
}
}