1+ use std:: error:: Error ;
12use std:: fmt;
23use std:: mem;
34
45use cranelift:: prelude:: * ;
5- use cranelift_module:: { Backend , Module , Linkage , FuncId } ;
6+ use cranelift_module:: { Backend , FuncId , Linkage , Module , ModuleError } ;
67use cranelift_simplejit:: { SimpleJITBackend , SimpleJITBuilder } ;
78
9+ use rustpython_bytecode:: bytecode;
10+
11+ mod instructions;
12+
13+ use self :: instructions:: FunctionCompiler ;
14+
15+ #[ derive( Debug ) ]
16+ pub enum JITCompileError {
17+ NotSupported ,
18+ BadBytecode ,
19+ CraneliftError ( ModuleError ) ,
20+ }
21+
22+ impl From < ModuleError > for JITCompileError {
23+ fn from ( err : ModuleError ) -> Self {
24+ JITCompileError :: CraneliftError ( err)
25+ }
26+ }
27+
28+ impl fmt:: Display for JITCompileError {
29+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
30+ match * self {
31+ JITCompileError :: NotSupported => f. write_str ( "Function can't be jitted." ) ,
32+ JITCompileError :: BadBytecode => f. write_str ( "Bad bytecode." ) ,
33+ JITCompileError :: CraneliftError ( ref err) => err. fmt ( f) ,
34+ }
35+ }
36+ }
37+
38+ impl Error for JITCompileError {
39+ fn source ( & self ) -> Option < & ( dyn Error + ' static ) > {
40+ match * self {
41+ JITCompileError :: CraneliftError ( ref err) => Some ( err) ,
42+ _ => None ,
43+ }
44+ }
45+ }
846
947struct JIT {
1048 builder_context : FunctionBuilderContext ,
@@ -23,53 +61,70 @@ impl JIT {
2361 }
2462 }
2563
26- fn build_function ( & mut self ) -> FuncId {
27- let id = self
28- . module
29- . declare_function ( "jitted" , Linkage :: Export , & self . ctx . func . signature )
30- . unwrap ( ) ;
64+ fn build_function (
65+ & mut self ,
66+ bytecode : & bytecode:: CodeObject ,
67+ ) -> Result < FuncId , JITCompileError > {
68+ // currently always returns an int
69+ self . ctx
70+ . func
71+ . signature
72+ . returns
73+ . push ( AbiParam :: new ( types:: I64 ) ) ;
74+
75+ let id = self . module . declare_function (
76+ & format ! ( "jit_{}" , bytecode. obj_name) ,
77+ Linkage :: Export ,
78+ & self . ctx . func . signature ,
79+ ) ?;
3180
3281 let mut builder = FunctionBuilder :: new ( & mut self . ctx . func , & mut self . builder_context ) ;
3382 let entry_block = builder. create_block ( ) ;
3483 // builder.append_block_params_for_function_params(entry_block);
3584 builder. switch_to_block ( entry_block) ;
36- // builder.seal_block(entry_block);
37- builder. ins ( ) . return_ ( & [ ] ) ;
85+ builder. seal_block ( entry_block) ;
86+
87+ {
88+ let mut compiler = FunctionCompiler :: new ( & mut builder) ;
89+
90+ for instruction in & bytecode. instructions {
91+ compiler. add_instruction ( instruction) ?;
92+ }
93+ } ;
94+
3895 builder. finalize ( ) ;
3996
4097 self . module
41- . define_function ( id, & mut self . ctx , & mut codegen:: binemit:: NullTrapSink { } )
42- . unwrap ( ) ;
98+ . define_function ( id, & mut self . ctx , & mut codegen:: binemit:: NullTrapSink { } ) ?;
4399
44100 self . module . clear_context ( & mut self . ctx ) ;
45101
46- id
102+ Ok ( id )
47103 }
48104}
49105
50- pub fn compile ( ) -> CompiledCode {
51-
106+ pub fn compile ( bytecode : & bytecode:: CodeObject ) -> Result < CompiledCode , JITCompileError > {
52107 let mut jit = JIT :: new ( ) ;
53108
54- let id = jit. build_function ( ) ;
109+ let id = jit. build_function ( bytecode ) ? ;
55110
56111 jit. module . finalize_definitions ( ) ;
57112
58113 let code = jit. module . get_finalized_function ( id) ;
59- CompiledCode {
114+ Ok ( CompiledCode {
60115 code,
61- memory : jit. module . finish ( )
62- }
116+ memory : jit. module . finish ( ) ,
117+ } )
63118}
64119
65120pub struct CompiledCode {
66121 code : * const u8 ,
67- memory : <SimpleJITBackend as Backend >:: Product
122+ memory : <SimpleJITBackend as Backend >:: Product ,
68123}
69124
70125impl CompiledCode {
71- pub fn invoke ( & self ) {
72- let func = unsafe { mem:: transmute :: < _ , fn ( ) > ( self . code ) } ;
126+ pub fn invoke ( & self ) -> i64 {
127+ let func = unsafe { mem:: transmute :: < _ , fn ( ) -> i64 > ( self . code ) } ;
73128 func ( )
74129 }
75130}
@@ -79,9 +134,7 @@ unsafe impl Send for CompiledCode {}
79134impl Drop for CompiledCode {
80135 fn drop ( & mut self ) {
81136 // SAFETY: The only pointer that this memory will also be dropped now
82- unsafe {
83- self . memory . free_memory ( )
84- }
137+ unsafe { self . memory . free_memory ( ) }
85138 }
86139}
87140
0 commit comments