1
+ use super :: { JitCompileError , JitSig , JitType } ;
2
+ use cranelift:: codegen:: ir:: FuncRef ;
1
3
use cranelift:: prelude:: * ;
2
4
use num_traits:: cast:: ToPrimitive ;
3
5
use rustpython_compiler_core:: bytecode:: {
@@ -6,8 +8,6 @@ use rustpython_compiler_core::bytecode::{
6
8
} ;
7
9
use std:: collections:: HashMap ;
8
10
9
- use super :: { JitCompileError , JitSig , JitType } ;
10
-
11
11
#[ repr( u16 ) ]
12
12
enum CustomTrapCode {
13
13
/// Raised when shifting by a negative number
@@ -27,6 +27,7 @@ enum JitValue {
27
27
Bool ( Value ) ,
28
28
None ,
29
29
Tuple ( Vec < JitValue > ) ,
30
+ FuncRef ( FuncRef ) ,
30
31
}
31
32
32
33
impl JitValue {
@@ -43,14 +44,14 @@ impl JitValue {
43
44
JitValue :: Int ( _) => Some ( JitType :: Int ) ,
44
45
JitValue :: Float ( _) => Some ( JitType :: Float ) ,
45
46
JitValue :: Bool ( _) => Some ( JitType :: Bool ) ,
46
- JitValue :: None | JitValue :: Tuple ( _) => None ,
47
+ JitValue :: None | JitValue :: Tuple ( _) | JitValue :: FuncRef ( _ ) => None ,
47
48
}
48
49
}
49
50
50
51
fn into_value ( self ) -> Option < Value > {
51
52
match self {
52
53
JitValue :: Int ( val) | JitValue :: Float ( val) | JitValue :: Bool ( val) => Some ( val) ,
53
- JitValue :: None | JitValue :: Tuple ( _) => None ,
54
+ JitValue :: None | JitValue :: Tuple ( _) | JitValue :: FuncRef ( _ ) => None ,
54
55
}
55
56
}
56
57
}
@@ -68,6 +69,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
68
69
builder : & ' a mut FunctionBuilder < ' b > ,
69
70
num_variables : usize ,
70
71
arg_types : & [ JitType ] ,
72
+ ret_type : Option < JitType > ,
71
73
entry_block : Block ,
72
74
) -> FunctionCompiler < ' a , ' b > {
73
75
let mut compiler = FunctionCompiler {
@@ -77,7 +79,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
77
79
label_to_block : HashMap :: new ( ) ,
78
80
sig : JitSig {
79
81
args : arg_types. to_vec ( ) ,
80
- ret : None ,
82
+ ret : ret_type ,
81
83
} ,
82
84
} ;
83
85
let params = compiler. builder . func . dfg . block_params ( entry_block) . to_vec ( ) ;
@@ -132,7 +134,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
132
134
}
133
135
JitValue :: Bool ( val) => Ok ( val) ,
134
136
JitValue :: None => Ok ( self . builder . ins ( ) . iconst ( types:: I8 , 0 ) ) ,
135
- JitValue :: Tuple ( _) => Err ( JitCompileError :: NotSupported ) ,
137
+ JitValue :: Tuple ( _) | JitValue :: FuncRef ( _ ) => Err ( JitCompileError :: NotSupported ) ,
136
138
}
137
139
}
138
140
@@ -146,6 +148,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
146
148
147
149
pub fn compile < C : bytecode:: Constant > (
148
150
& mut self ,
151
+ func_ref : FuncRef ,
149
152
bytecode : & CodeObject < C > ,
150
153
) -> Result < ( ) , JitCompileError > {
151
154
// TODO: figure out if this is sufficient -- previously individual labels were associated
@@ -177,7 +180,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
177
180
continue ;
178
181
}
179
182
180
- self . add_instruction ( instruction , arg , & bytecode . constants ) ?;
183
+ self . add_instruction ( func_ref , bytecode , instruction , arg ) ?;
181
184
}
182
185
183
186
Ok ( ( ) )
@@ -229,9 +232,10 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
229
232
230
233
pub fn add_instruction < C : bytecode:: Constant > (
231
234
& mut self ,
235
+ func_ref : FuncRef ,
236
+ bytecode : & CodeObject < C > ,
232
237
instruction : Instruction ,
233
238
arg : OpArg ,
234
- constants : & [ C ] ,
235
239
) -> Result < ( ) , JitCompileError > {
236
240
match instruction {
237
241
Instruction :: ExtendedArg => Ok ( ( ) ) ,
@@ -282,7 +286,8 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
282
286
self . store_variable ( idx. get ( arg) , val)
283
287
}
284
288
Instruction :: LoadConst { idx } => {
285
- let val = self . prepare_const ( constants[ idx. get ( arg) as usize ] . borrow_constant ( ) ) ?;
289
+ let val = self
290
+ . prepare_const ( bytecode. constants [ idx. get ( arg) as usize ] . borrow_constant ( ) ) ?;
286
291
self . stack . push ( val) ;
287
292
Ok ( ( ) )
288
293
}
@@ -311,7 +316,8 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
311
316
self . return_value ( val)
312
317
}
313
318
Instruction :: ReturnConst { idx } => {
314
- let val = self . prepare_const ( constants[ idx. get ( arg) as usize ] . borrow_constant ( ) ) ?;
319
+ let val = self
320
+ . prepare_const ( bytecode. constants [ idx. get ( arg) as usize ] . borrow_constant ( ) ) ?;
315
321
self . return_value ( val)
316
322
}
317
323
Instruction :: CompareOperation { op, .. } => {
@@ -508,6 +514,36 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
508
514
// TODO: block support
509
515
Ok ( ( ) )
510
516
}
517
+ Instruction :: LoadGlobal ( idx) => {
518
+ let name = & bytecode. names [ idx. get ( arg) as usize ] ;
519
+
520
+ if name. as_ref ( ) != bytecode. obj_name . as_ref ( ) {
521
+ Err ( JitCompileError :: NotSupported )
522
+ } else {
523
+ self . stack . push ( JitValue :: FuncRef ( func_ref) ) ;
524
+ Ok ( ( ) )
525
+ }
526
+ }
527
+ Instruction :: CallFunctionPositional { nargs } => {
528
+ let nargs = nargs. get ( arg) ;
529
+
530
+ let mut args = Vec :: new ( ) ;
531
+ for _ in 0 ..nargs {
532
+ let arg = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
533
+ args. push ( arg. into_value ( ) . unwrap ( ) ) ;
534
+ }
535
+
536
+ match self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ? {
537
+ JitValue :: FuncRef ( reference) => {
538
+ let call = self . builder . ins ( ) . call ( reference, & args) ;
539
+ let returns = self . builder . inst_results ( call) ;
540
+ self . stack . push ( JitValue :: Int ( returns[ 0 ] ) ) ;
541
+
542
+ Ok ( ( ) )
543
+ }
544
+ _ => Err ( JitCompileError :: BadBytecode ) ,
545
+ }
546
+ }
511
547
_ => Err ( JitCompileError :: NotSupported ) ,
512
548
}
513
549
}
0 commit comments