@@ -9,6 +9,7 @@ use rustpython_bytecode::bytecode;
99mod instructions;
1010
1111use instructions:: FunctionCompiler ;
12+ use std:: convert:: TryFrom ;
1213
1314#[ derive( Debug , thiserror:: Error ) ]
1415pub enum JitCompileError {
@@ -20,10 +21,12 @@ pub enum JitCompileError {
2021 CraneliftError ( #[ from] ModuleError ) ,
2122}
2223
23- #[ derive( Debug , thiserror:: Error ) ]
24+ #[ derive( Debug , thiserror:: Error , Eq , PartialEq ) ]
2425pub enum JitArgumentError {
2526 #[ error( "argument is of wrong type" ) ]
2627 ArgumentTypeMismatch ,
28+ #[ error( "wrong number of arguments" ) ]
29+ WrongNumberOfArguments ,
2730}
2831
2932struct Jit {
@@ -120,16 +123,29 @@ impl CompiledCode {
120123 ArgsBuilder :: new ( self )
121124 }
122125
123- pub fn invoke < ' a > ( & self , args : & Args < ' a > ) -> Option < AbiValue > {
124- debug_assert_eq ! ( self as * const _, args. code as * const _) ;
125- let cif = self . sig . to_cif ( ) ;
126- unsafe {
127- let value = cif. call :: < UnTypedAbiValue > (
128- libffi:: middle:: CodePtr :: from_ptr ( self . code as * const _ ) ,
129- & args. cif_args ,
130- ) ;
131- self . sig . ret . as_ref ( ) . map ( |ty| value. to_typed ( ty) )
126+ pub fn invoke ( & self , args : & [ AbiValue ] ) -> Result < Option < AbiValue > , JitArgumentError > {
127+ if self . sig . args . len ( ) != args. len ( ) {
128+ return Err ( JitArgumentError :: WrongNumberOfArguments ) ;
132129 }
130+
131+ let cif_args = self
132+ . sig
133+ . args
134+ . iter ( )
135+ . zip ( args. iter ( ) )
136+ . map ( |( ty, val) | type_check ( ty, val) . map ( |_| val) )
137+ . map ( |v| v. map ( AbiValue :: to_libffi_arg) )
138+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
139+ Ok ( unsafe { self . invoke_raw ( & cif_args) } )
140+ }
141+
142+ unsafe fn invoke_raw ( & self , cif_args : & [ libffi:: middle:: Arg ] ) -> Option < AbiValue > {
143+ let cif = self . sig . to_cif ( ) ;
144+ let value = cif. call :: < UnTypedAbiValue > (
145+ libffi:: middle:: CodePtr :: from_ptr ( self . code as * const _ ) ,
146+ cif_args,
147+ ) ;
148+ self . sig . ret . as_ref ( ) . map ( |ty| value. to_typed ( ty) )
133149 }
134150}
135151
@@ -170,12 +186,62 @@ impl JitType {
170186 }
171187}
172188
173- #[ derive( Clone ) ]
189+ #[ derive( Debug , Clone , PartialEq ) ]
174190pub enum AbiValue {
175191 Float ( f64 ) ,
176192 Int ( i64 ) ,
177193}
178194
195+ impl AbiValue {
196+ fn to_libffi_arg ( & self ) -> libffi:: middle:: Arg {
197+ match self {
198+ AbiValue :: Int ( ref i) => libffi:: middle:: Arg :: new ( i) ,
199+ AbiValue :: Float ( ref f) => libffi:: middle:: Arg :: new ( f) ,
200+ }
201+ }
202+ }
203+
204+ impl From < i64 > for AbiValue {
205+ fn from ( i : i64 ) -> Self {
206+ AbiValue :: Int ( i)
207+ }
208+ }
209+
210+ impl From < f64 > for AbiValue {
211+ fn from ( f : f64 ) -> Self {
212+ AbiValue :: Float ( f)
213+ }
214+ }
215+
216+ impl TryFrom < AbiValue > for i64 {
217+ type Error = ( ) ;
218+
219+ fn try_from ( value : AbiValue ) -> Result < Self , Self :: Error > {
220+ match value {
221+ AbiValue :: Int ( i) => Ok ( i) ,
222+ AbiValue :: Float ( _) => Err ( ( ) ) ,
223+ }
224+ }
225+ }
226+
227+ impl TryFrom < AbiValue > for f64 {
228+ type Error = ( ) ;
229+
230+ fn try_from ( value : AbiValue ) -> Result < Self , Self :: Error > {
231+ match value {
232+ AbiValue :: Int ( _) => Err ( ( ) ) ,
233+ AbiValue :: Float ( f) => Ok ( f) ,
234+ }
235+ }
236+ }
237+
238+ fn type_check ( ty : & JitType , val : & AbiValue ) -> Result < ( ) , JitArgumentError > {
239+ match ( ty, val) {
240+ ( JitType :: Int , AbiValue :: Int ( _) ) | ( JitType :: Float , AbiValue :: Float ( _) ) => Ok ( ( ) ) ,
241+ _ => Err ( JitArgumentError :: ArgumentTypeMismatch ) ,
242+ }
243+ }
244+
179245#[ derive( Copy , Clone ) ]
180246union UnTypedAbiValue {
181247 float : f64 ,
@@ -222,13 +288,9 @@ impl<'a> ArgsBuilder<'a> {
222288 }
223289
224290 pub fn set ( & mut self , idx : usize , value : AbiValue ) -> Result < ( ) , JitArgumentError > {
225- match ( & self . code . sig . args [ idx] , & value) {
226- ( JitType :: Int , AbiValue :: Int ( _) ) | ( JitType :: Float , AbiValue :: Float ( _) ) => {
227- self . values [ idx] = Some ( value) ;
228- Ok ( ( ) )
229- }
230- _ => Err ( JitArgumentError :: ArgumentTypeMismatch ) ,
231- }
291+ type_check ( & self . code . sig . args [ idx] , & value) . map ( |_| {
292+ self . values [ idx] = Some ( value) ;
293+ } )
232294 }
233295
234296 pub fn is_set ( & self , idx : usize ) -> bool {
@@ -238,12 +300,7 @@ impl<'a> ArgsBuilder<'a> {
238300 pub fn into_args ( self ) -> Option < Args < ' a > > {
239301 self . values
240302 . iter ( )
241- . map ( |v| {
242- v. as_ref ( ) . map ( |v| match v {
243- AbiValue :: Int ( ref i) => libffi:: middle:: Arg :: new ( i) ,
244- AbiValue :: Float ( ref f) => libffi:: middle:: Arg :: new ( f) ,
245- } )
246- } )
303+ . map ( |v| v. as_ref ( ) . map ( AbiValue :: to_libffi_arg) )
247304 . collect :: < Option < _ > > ( )
248305 . map ( |cif_args| Args {
249306 _values : self . values ,
@@ -258,3 +315,9 @@ pub struct Args<'a> {
258315 cif_args : Vec < libffi:: middle:: Arg > ,
259316 code : & ' a CompiledCode ,
260317}
318+
319+ impl < ' a > Args < ' a > {
320+ pub fn invoke ( & self ) -> Option < AbiValue > {
321+ unsafe { self . code . invoke_raw ( & self . cif_args ) }
322+ }
323+ }
0 commit comments