xwasm_utils/
rules.rs

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}