1#[cfg(features = "std")]
2use std::collections::{HashMap as Map};
3#[cfg(not(features = "std"))]
4use std::collections::{BTreeMap as Map};
5
6use xwasm::elements;
7
8pub struct UnknownInstruction;
9
10#[derive(Debug, PartialEq, Eq, Copy, Clone)]
11pub enum Metering {
12 Regular,
13 Forbidden,
14 Fixed(u32),
15}
16
17#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
18pub enum InstructionType {
19 Bit,
20 Add,
21 Mul,
22 Div,
23 Load,
24 Store,
25 Const,
26 FloatConst,
27 Local,
28 Global,
29 ControlFlow,
30 IntegerComparsion,
31 FloatComparsion,
32 Float,
33 Conversion,
34 FloatConversion,
35 Reinterpretation,
36 Unreachable,
37 Nop,
38 CurrentMemory,
39 GrowMemory,
40}
41
42impl ::std::str::FromStr for InstructionType {
43 type Err = UnknownInstruction;
44
45 fn from_str(s: &str) -> Result<Self, Self::Err> {
46 match s {
47 "bit" => Ok(InstructionType::Bit),
48 "add" => Ok(InstructionType::Add),
49 "mul" => Ok(InstructionType::Mul),
50 "div" => Ok(InstructionType::Div),
51 "load" => Ok(InstructionType::Load),
52 "store" => Ok(InstructionType::Store),
53 "const" => Ok(InstructionType::Const),
54 "local" => Ok(InstructionType::Local),
55 "global" => Ok(InstructionType::Global),
56 "flow" => Ok(InstructionType::ControlFlow),
57 "integer_comp" => Ok(InstructionType::IntegerComparsion),
58 "float_comp" => Ok(InstructionType::FloatComparsion),
59 "float" => Ok(InstructionType::Float),
60 "conversion" => Ok(InstructionType::Conversion),
61 "float_conversion" => Ok(InstructionType::FloatConversion),
62 "reinterpret" => Ok(InstructionType::Reinterpretation),
63 "unreachable" => Ok(InstructionType::Unreachable),
64 "nop" => Ok(InstructionType::Nop),
65 "current_mem" => Ok(InstructionType::CurrentMemory),
66 "grow_mem" => Ok(InstructionType::GrowMemory),
67 _ => Err(UnknownInstruction),
68 }
69 }
70}
71
72impl InstructionType {
73 pub fn op(instruction: &elements::Instruction) -> Self {
74 use xwasm::elements::Instruction::*;
75
76 match *instruction {
77 Unreachable => InstructionType::Unreachable,
78 Nop => InstructionType::Nop,
79 Block(_) => InstructionType::ControlFlow,
80 Loop(_) => InstructionType::ControlFlow,
81 If(_) => InstructionType::ControlFlow,
82 Else => InstructionType::ControlFlow,
83 End => InstructionType::ControlFlow,
84 Br(_) => InstructionType::ControlFlow,
85 BrIf(_) => InstructionType::ControlFlow,
86 BrTable(_, _) => InstructionType::ControlFlow,
87 Return => InstructionType::ControlFlow,
88 Call(_) => InstructionType::ControlFlow,
89 CallIndirect(_, _) => InstructionType::ControlFlow,
90 Drop => InstructionType::ControlFlow,
91 Select => InstructionType::ControlFlow,
92
93 GetLocal(_) => InstructionType::Local,
94 SetLocal(_) => InstructionType::Local,
95 TeeLocal(_) => InstructionType::Local,
96 GetGlobal(_) => InstructionType::Local,
97 SetGlobal(_) => InstructionType::Local,
98
99 I32Load(_, _) => InstructionType::Load,
100 I64Load(_, _) => InstructionType::Load,
101 F32Load(_, _) => InstructionType::Load,
102 F64Load(_, _) => InstructionType::Load,
103 I32Load8S(_, _) => InstructionType::Load,
104 I32Load8U(_, _) => InstructionType::Load,
105 I32Load16S(_, _) => InstructionType::Load,
106 I32Load16U(_, _) => InstructionType::Load,
107 I64Load8S(_, _) => InstructionType::Load,
108 I64Load8U(_, _) => InstructionType::Load,
109 I64Load16S(_, _) => InstructionType::Load,
110 I64Load16U(_, _) => InstructionType::Load,
111 I64Load32S(_, _) => InstructionType::Load,
112 I64Load32U(_, _) => InstructionType::Load,
113
114 I32Store(_, _) => InstructionType::Store,
115 I64Store(_, _) => InstructionType::Store,
116 F32Store(_, _) => InstructionType::Store,
117 F64Store(_, _) => InstructionType::Store,
118 I32Store8(_, _) => InstructionType::Store,
119 I32Store16(_, _) => InstructionType::Store,
120 I64Store8(_, _) => InstructionType::Store,
121 I64Store16(_, _) => InstructionType::Store,
122 I64Store32(_, _) => InstructionType::Store,
123
124 CurrentMemory(_) => InstructionType::CurrentMemory,
125 GrowMemory(_) => InstructionType::GrowMemory,
126
127 I32Const(_) => InstructionType::Const,
128 I64Const(_) => InstructionType::Const,
129
130 F32Const(_) => InstructionType::FloatConst,
131 F64Const(_) => InstructionType::FloatConst,
132
133 I32Eqz => InstructionType::IntegerComparsion,
134 I32Eq => InstructionType::IntegerComparsion,
135 I32Ne => InstructionType::IntegerComparsion,
136 I32LtS => InstructionType::IntegerComparsion,
137 I32LtU => InstructionType::IntegerComparsion,
138 I32GtS => InstructionType::IntegerComparsion,
139 I32GtU => InstructionType::IntegerComparsion,
140 I32LeS => InstructionType::IntegerComparsion,
141 I32LeU => InstructionType::IntegerComparsion,
142 I32GeS => InstructionType::IntegerComparsion,
143 I32GeU => InstructionType::IntegerComparsion,
144
145 I64Eqz => InstructionType::IntegerComparsion,
146 I64Eq => InstructionType::IntegerComparsion,
147 I64Ne => InstructionType::IntegerComparsion,
148 I64LtS => InstructionType::IntegerComparsion,
149 I64LtU => InstructionType::IntegerComparsion,
150 I64GtS => InstructionType::IntegerComparsion,
151 I64GtU => InstructionType::IntegerComparsion,
152 I64LeS => InstructionType::IntegerComparsion,
153 I64LeU => InstructionType::IntegerComparsion,
154 I64GeS => InstructionType::IntegerComparsion,
155 I64GeU => InstructionType::IntegerComparsion,
156
157 F32Eq => InstructionType::FloatComparsion,
158 F32Ne => InstructionType::FloatComparsion,
159 F32Lt => InstructionType::FloatComparsion,
160 F32Gt => InstructionType::FloatComparsion,
161 F32Le => InstructionType::FloatComparsion,
162 F32Ge => InstructionType::FloatComparsion,
163
164 F64Eq => InstructionType::FloatComparsion,
165 F64Ne => InstructionType::FloatComparsion,
166 F64Lt => InstructionType::FloatComparsion,
167 F64Gt => InstructionType::FloatComparsion,
168 F64Le => InstructionType::FloatComparsion,
169 F64Ge => InstructionType::FloatComparsion,
170
171 I32Clz => InstructionType::Bit,
172 I32Ctz => InstructionType::Bit,
173 I32Popcnt => InstructionType::Bit,
174 I32Add => InstructionType::Add,
175 I32Sub => InstructionType::Add,
176 I32Mul => InstructionType::Mul,
177 I32DivS => InstructionType::Div,
178 I32DivU => InstructionType::Div,
179 I32RemS => InstructionType::Div,
180 I32RemU => InstructionType::Div,
181 I32And => InstructionType::Bit,
182 I32Or => InstructionType::Bit,
183 I32Xor => InstructionType::Bit,
184 I32Shl => InstructionType::Bit,
185 I32ShrS => InstructionType::Bit,
186 I32ShrU => InstructionType::Bit,
187 I32Rotl => InstructionType::Bit,
188 I32Rotr => InstructionType::Bit,
189
190 I64Clz => InstructionType::Bit,
191 I64Ctz => InstructionType::Bit,
192 I64Popcnt => InstructionType::Bit,
193 I64Add => InstructionType::Add,
194 I64Sub => InstructionType::Add,
195 I64Mul => InstructionType::Mul,
196 I64DivS => InstructionType::Div,
197 I64DivU => InstructionType::Div,
198 I64RemS => InstructionType::Div,
199 I64RemU => InstructionType::Div,
200 I64And => InstructionType::Bit,
201 I64Or => InstructionType::Bit,
202 I64Xor => InstructionType::Bit,
203 I64Shl => InstructionType::Bit,
204 I64ShrS => InstructionType::Bit,
205 I64ShrU => InstructionType::Bit,
206 I64Rotl => InstructionType::Bit,
207 I64Rotr => InstructionType::Bit,
208
209 F32Abs => InstructionType::Float,
210 F32Neg => InstructionType::Float,
211 F32Ceil => InstructionType::Float,
212 F32Floor => InstructionType::Float,
213 F32Trunc => InstructionType::Float,
214 F32Nearest => InstructionType::Float,
215 F32Sqrt => InstructionType::Float,
216 F32Add => InstructionType::Float,
217 F32Sub => InstructionType::Float,
218 F32Mul => InstructionType::Float,
219 F32Div => InstructionType::Float,
220 F32Min => InstructionType::Float,
221 F32Max => InstructionType::Float,
222 F32Copysign => InstructionType::Float,
223 F64Abs => InstructionType::Float,
224 F64Neg => InstructionType::Float,
225 F64Ceil => InstructionType::Float,
226 F64Floor => InstructionType::Float,
227 F64Trunc => InstructionType::Float,
228 F64Nearest => InstructionType::Float,
229 F64Sqrt => InstructionType::Float,
230 F64Add => InstructionType::Float,
231 F64Sub => InstructionType::Float,
232 F64Mul => InstructionType::Float,
233 F64Div => InstructionType::Float,
234 F64Min => InstructionType::Float,
235 F64Max => InstructionType::Float,
236 F64Copysign => InstructionType::Float,
237
238 I32WrapI64 => InstructionType::Conversion,
239 I64ExtendSI32 => InstructionType::Conversion,
240 I64ExtendUI32 => InstructionType::Conversion,
241
242 I32TruncSF32 => InstructionType::FloatConversion,
243 I32TruncUF32 => InstructionType::FloatConversion,
244 I32TruncSF64 => InstructionType::FloatConversion,
245 I32TruncUF64 => InstructionType::FloatConversion,
246 I64TruncSF32 => InstructionType::FloatConversion,
247 I64TruncUF32 => InstructionType::FloatConversion,
248 I64TruncSF64 => InstructionType::FloatConversion,
249 I64TruncUF64 => InstructionType::FloatConversion,
250 F32ConvertSI32 => InstructionType::FloatConversion,
251 F32ConvertUI32 => InstructionType::FloatConversion,
252 F32ConvertSI64 => InstructionType::FloatConversion,
253 F32ConvertUI64 => InstructionType::FloatConversion,
254 F32DemoteF64 => InstructionType::FloatConversion,
255 F64ConvertSI32 => InstructionType::FloatConversion,
256 F64ConvertUI32 => InstructionType::FloatConversion,
257 F64ConvertSI64 => InstructionType::FloatConversion,
258 F64ConvertUI64 => InstructionType::FloatConversion,
259 F64PromoteF32 => InstructionType::FloatConversion,
260
261 I32ReinterpretF32 => InstructionType::Reinterpretation,
262 I64ReinterpretF64 => InstructionType::Reinterpretation,
263 F32ReinterpretI32 => InstructionType::Reinterpretation,
264 F64ReinterpretI64 => InstructionType::Reinterpretation,
265 }
266 }
267}
268
269#[derive(Debug)]
270pub struct Set {
271 regular: u32,
272 entries: Map<InstructionType, Metering>,
273 grow: u32,
274}
275
276impl Default for Set {
277 fn default() -> Self {
278 Set {
279 regular: 1,
280 entries: Map::new(),
281 grow: 0,
282 }
283 }
284}
285
286impl Set {
287 pub fn new(regular: u32, entries: Map<InstructionType, Metering>) -> Self {
288 Set { regular: regular, entries: entries, grow: 0 }
289 }
290
291 pub fn process(&self, instruction: &elements::Instruction) -> Result<u32, ()> {
292 match self.entries.get(&InstructionType::op(instruction)).map(|x| *x) {
293 None | Some(Metering::Regular) => Ok(self.regular),
294 Some(Metering::Forbidden) => Err(()),
295 Some(Metering::Fixed(val)) => Ok(val),
296 }
297 }
298
299 pub fn grow_cost(&self) -> u32 {
300 self.grow
301 }
302
303 pub fn with_grow_cost(mut self, val: u32) -> Self {
304 self.grow = val;
305 self
306 }
307
308 pub fn with_forbidden_floats(mut self) -> Self {
309 self.entries.insert(InstructionType::Float, Metering::Forbidden);
310 self.entries.insert(InstructionType::FloatComparsion, Metering::Forbidden);
311 self.entries.insert(InstructionType::FloatConst, Metering::Forbidden);
312 self.entries.insert(InstructionType::FloatConversion, Metering::Forbidden);
313 self
314 }
315}