lucet_module_data/
types.rs1use cranelift_codegen::ir;
2use serde::{Deserialize, Serialize};
3use std::convert::TryFrom;
4use std::fmt::{Display, Formatter};
5
6#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
7pub enum ValueType {
8 I32,
9 I64,
10 F32,
11 F64,
12}
13
14impl Display for ValueType {
15 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
16 match self {
17 ValueType::I32 => write!(f, "I32"),
18 ValueType::I64 => write!(f, "I64"),
19 ValueType::F32 => write!(f, "F32"),
20 ValueType::F64 => write!(f, "F64"),
21 }
22 }
23}
24
25#[derive(Debug)]
26pub enum ValueError {
27 Unrepresentable,
28 InvalidVMContext,
29}
30
31impl TryFrom<&ir::AbiParam> for ValueType {
32 type Error = ValueError;
33
34 fn try_from(value: &ir::AbiParam) -> Result<Self, Self::Error> {
35 match value {
36 ir::AbiParam {
37 value_type: cranelift_ty,
38 purpose: ir::ArgumentPurpose::Normal,
39 extension: ir::ArgumentExtension::None,
40 location: ir::ArgumentLoc::Unassigned,
41 } => {
42 let size = cranelift_ty.bits();
43
44 if cranelift_ty.is_int() {
45 match size {
46 32 => Ok(ValueType::I32),
47 64 => Ok(ValueType::I64),
48 _ => Err(ValueError::Unrepresentable),
49 }
50 } else if cranelift_ty.is_float() {
51 match size {
52 32 => Ok(ValueType::F32),
53 64 => Ok(ValueType::F64),
54 _ => Err(ValueError::Unrepresentable),
55 }
56 } else {
57 Err(ValueError::Unrepresentable)
58 }
59 }
60 _ => Err(ValueError::Unrepresentable),
61 }
62 }
63}
64
65#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
70pub struct Signature {
71 pub params: Vec<ValueType>,
72 pub ret_ty: Option<ValueType>,
74}
75
76impl Display for Signature {
77 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
78 write!(f, "(")?;
79 for (i, p) in self.params.iter().enumerate() {
80 if i == 0 {
81 write!(f, "{}", p)?;
82 } else {
83 write!(f, ", {}", p)?;
84 }
85 }
86 write!(f, ") -> ")?;
87 match self.ret_ty {
88 Some(ty) => write!(f, "{}", ty),
89 None => write!(f, "()"),
90 }
91 }
92}
93
94#[macro_export]
95macro_rules! lucet_signature {
96 ((() -> ())) => {
97 $crate::Signature {
98 params: vec![],
99 ret_ty: None
100 }
101 };
102 (($($arg_ty:ident),*) -> ()) => {
103 $crate::Signature {
104 params: vec![$($crate::ValueType::$arg_ty),*],
105 ret_ty: None,
106 }
107 };
108 (($($arg_ty:ident),*) -> $ret_ty:ident) => {
109 $crate::Signature {
110 params: vec![$($crate::ValueType::$arg_ty),*],
111 ret_ty: Some($crate::ValueType::$ret_ty),
112 }
113 };
114}
115
116#[derive(Debug)]
117pub enum SignatureError {
118 BadElement(ir::AbiParam, ValueError),
119 BadSignature,
120}
121
122impl TryFrom<&ir::Signature> for Signature {
123 type Error = SignatureError;
124
125 fn try_from(value: &ir::Signature) -> Result<Self, Self::Error> {
126 let mut params: Vec<ValueType> = Vec::new();
127
128 let mut param_iter = value.params.iter();
129
130 if let Some(param) = param_iter.next() {
133 match ¶m {
134 ir::AbiParam {
135 value_type: value,
136 purpose: ir::ArgumentPurpose::VMContext,
137 extension: ir::ArgumentExtension::None,
138 location: ir::ArgumentLoc::Unassigned,
139 } => {
140 if value.is_int() && value.bits() == 64 {
141 } else {
143 return Err(SignatureError::BadElement(
144 param.to_owned(),
145 ValueError::InvalidVMContext,
146 ));
147 }
148 }
149 _ => {
150 return Err(SignatureError::BadElement(
151 param.to_owned(),
152 ValueError::InvalidVMContext,
153 ));
154 }
155 }
156 } else {
157 return Err(SignatureError::BadSignature);
158 }
159
160 for param in param_iter {
161 let value_ty = ValueType::try_from(param)
162 .map_err(|e| SignatureError::BadElement(param.clone(), e))?;
163
164 params.push(value_ty);
165 }
166
167 let ret_ty: Option<ValueType> = match value.returns.as_slice() {
168 &[] => None,
169 &[ref ret_ty] => {
170 let value_ty = ValueType::try_from(ret_ty)
171 .map_err(|e| SignatureError::BadElement(ret_ty.clone(), e))?;
172
173 Some(value_ty)
174 }
175 _ => {
176 return Err(SignatureError::BadSignature);
177 }
178 };
179
180 Ok(Signature { params, ret_ty })
181 }
182}