corevm_engine/
pvm.rs

1/// Args for invoking an inner PVM.
2#[derive(Debug)]
3pub struct InvokeArgs {
4	pub gas: i64,
5	pub regs: [u64; 13],
6}
7
8impl InvokeArgs {
9	/// Initialize the gas to the specified value, initialize the registers to zeroes.
10	pub fn new(gas: i64) -> Self {
11		Self { gas, regs: Default::default() }
12	}
13
14	/// Get the value of the specified register.
15	pub fn reg(&self, reg: Reg) -> u64 {
16		self.regs[reg as usize]
17	}
18
19	/// Set the value of the specified register.
20	pub fn set_reg(&mut self, reg: Reg, value: u64) {
21		self.regs[reg as usize] = value;
22	}
23
24	/// Set the contents of `A0` and optinally `A1` registers that typically store the return value
25	/// of a function call.
26	pub fn set_return_value<T: SetReturnValue>(&mut self, value: T) {
27		value.set_return_value(self);
28	}
29
30	/// Get the value of the `i`-th argument's register.
31	pub fn get_arg_reg(&self, i: usize) -> u64 {
32		self.reg(Reg::ARG_REGS[i])
33	}
34
35	/// Get the value of the `i`-th argument.
36	pub fn get_arg<T: Arg>(&mut self, i: &mut usize) -> T {
37		Arg::get(self, i)
38	}
39
40	/// Set the value of the `i`-th argument's register.
41	pub fn set_arg_reg(&mut self, i: usize, value: u64) {
42		self.set_reg(Reg::ARG_REGS[i], value)
43	}
44
45	/// Set the value of the `i`-th argument.
46	pub fn set_arg<T: Arg>(&mut self, i: &mut usize, value: T) {
47		value.set(self, i)
48	}
49}
50
51impl From<jam_types::InvokeArgs> for InvokeArgs {
52	fn from(other: jam_types::InvokeArgs) -> Self {
53		Self { gas: other.gas, regs: other.regs }
54	}
55}
56
57impl From<InvokeArgs> for jam_types::InvokeArgs {
58	fn from(other: InvokeArgs) -> Self {
59		Self { gas: other.gas, regs: other.regs }
60	}
61}
62
63/// Available registers.
64#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
65#[repr(u32)]
66pub enum Reg {
67	RA = 0,
68	SP = 1,
69	T0 = 2,
70	T1 = 3,
71	T2 = 4,
72	S0 = 5,
73	S1 = 6,
74	A0 = 7,
75	A1 = 8,
76	A2 = 9,
77	A3 = 10,
78	A4 = 11,
79	A5 = 12,
80}
81
82impl Reg {
83	pub const ARG_REGS: [Reg; 9] =
84		[Reg::A0, Reg::A1, Reg::A2, Reg::A3, Reg::A4, Reg::A5, Reg::T0, Reg::T1, Reg::T2];
85}
86
87pub trait SetReturnValue {
88	fn set_return_value(self, args: &mut InvokeArgs);
89}
90
91impl SetReturnValue for () {
92	fn set_return_value(self, _args: &mut InvokeArgs) {}
93}
94
95impl SetReturnValue for u64 {
96	fn set_return_value(self, args: &mut InvokeArgs) {
97		args.set_reg(Reg::A0, self);
98	}
99}
100
101set_return_value_impl_as! {
102	bool => u64,
103	u8 => u64,
104	u16 => u64,
105	u32 => u64,
106	i8 => u64,
107	i16 => u64,
108	i32 => u64,
109	i64 => u64
110}
111
112pub trait Arg {
113	fn get(args: &InvokeArgs, i: &mut usize) -> Self
114	where
115		Self: Sized;
116
117	fn set(self, args: &mut InvokeArgs, i: &mut usize);
118}
119
120impl Arg for u64 {
121	fn get(args: &InvokeArgs, i: &mut usize) -> Self {
122		let value = args.get_arg_reg(*i);
123		*i += 1;
124		value
125	}
126
127	fn set(self, args: &mut InvokeArgs, i: &mut usize) {
128		args.set_arg_reg(*i, self);
129		*i += 1;
130	}
131}
132
133impl Arg for usize {
134	fn get(args: &InvokeArgs, i: &mut usize) -> Self {
135		u64::get(args, i) as usize
136	}
137
138	fn set(self, args: &mut InvokeArgs, i: &mut usize) {
139		(self as u64).set(args, i);
140	}
141}
142
143impl<T> Arg for *const T {
144	fn get(args: &InvokeArgs, i: &mut usize) -> Self {
145		usize::get(args, i) as Self
146	}
147
148	fn set(self, args: &mut InvokeArgs, i: &mut usize) {
149		(self as usize).set(args, i);
150	}
151}
152
153impl<T> Arg for *mut T {
154	fn get(args: &InvokeArgs, i: &mut usize) -> Self {
155		usize::get(args, i) as Self
156	}
157
158	fn set(self, args: &mut InvokeArgs, i: &mut usize) {
159		(self as usize).set(args, i);
160	}
161}
162
163impl Arg for bool {
164	fn get(args: &InvokeArgs, i: &mut usize) -> Self {
165		u64::get(args, i) != 0
166	}
167
168	fn set(self, args: &mut InvokeArgs, i: &mut usize) {
169		(self as u64).set(args, i);
170	}
171}
172
173arg_impl_as! {
174	u8 => u64,
175	u16 => u64,
176	i8 => u64,
177	i16 => u64,
178	i32 => u64,
179	i64 => u64
180}
181
182macro_rules! set_return_value_impl_as {
183    ($($type:ty => $as_type:ty),+) => {
184        $(
185            impl SetReturnValue for $type {
186                fn set_return_value(self, args: &mut InvokeArgs) {
187                    (self as $as_type).set_return_value(args);
188                }
189            }
190        )+
191    };
192}
193
194use set_return_value_impl_as;
195
196macro_rules! arg_impl_as {
197    ($($type:ty => $as_type:ty),+) => {
198        $(
199            impl Arg for $type {
200                fn get(args: &InvokeArgs, i: &mut usize) -> Self {
201                    <$as_type>::get(args, i) as Self
202                }
203
204                fn set(self, args: &mut InvokeArgs, i: &mut usize) {
205                    (self as $as_type).set(args, i);
206                }
207            }
208        )+
209    };
210}
211
212use arg_impl_as;