@@ -9,7 +9,7 @@ use region::Protection;
99use std:: mem:: transmute;
1010use std:: ptr:: { self , write_unaligned} ;
1111use wasmtime_environ:: {
12- compile_module, Compilation , Module , ModuleTranslation , Relocation , RelocationTarget ,
12+ compile_module, Compilation , Export , Module , ModuleTranslation , Relocation , RelocationTarget ,
1313} ;
1414
1515/// Executes a module that has been translated with the `wasmtime-environ` environment
@@ -125,15 +125,12 @@ fn make_vmctx(instance: &mut Instance, mem_base_addrs: &mut [*mut u8]) -> Vec<*m
125125 vmctx
126126}
127127
128- /// Jumps to the code region of memory and execute the start function of the module.
129- pub fn execute (
128+ /// prepares the execution context
129+ pub fn finish_instantiation (
130130 module : & Module ,
131131 compilation : & Compilation ,
132132 instance : & mut Instance ,
133- ) -> Result < ( ) , String > {
134- let start_index = module
135- . start_func
136- . ok_or_else ( || String :: from ( "No start function defined, aborting execution" ) ) ?;
133+ ) -> Result < Vec < * mut u8 > , String > {
137134 // TODO: Put all the function bodies into a page-aligned memory region, and
138135 // then make them ReadExecute rather than ReadWriteExecute.
139136 for code_buf in compilation. functions . values ( ) {
@@ -154,26 +151,62 @@ pub fn execute(
154151 }
155152 }
156153
157- let code_buf =
158- & compilation. functions [ module
159- . defined_func_index ( start_index)
160- . expect ( "imported start functions not supported yet" ) ] ;
161-
162154 // Collect all memory base addresses and Vec.
163155 let mut mem_base_addrs = instance
164156 . memories
165157 . iter_mut ( )
166158 . map ( LinearMemory :: base_addr)
167159 . collect :: < Vec < _ > > ( ) ;
160+
168161 let vmctx = make_vmctx ( instance, & mut mem_base_addrs) ;
169162
163+ if let Ok ( start_index) = module
164+ . start_func
165+ . ok_or_else ( || String :: from ( "No start function defined, aborting execution" ) )
166+ {
167+ let code_buf =
168+ & compilation. functions [ module
169+ . defined_func_index ( start_index)
170+ . expect ( "imported start functions not supported yet" ) ] ;
171+
172+ // Rather than writing inline assembly to jump to the code region, we use the fact that
173+ // the Rust ABI for calling a function with no arguments and no return matches the one of
174+ // the generated code. Thanks to this, we can transmute the code region into a first-class
175+ // Rust function and call it.
176+ unsafe {
177+ let start_func = transmute :: < _ , fn ( * const * mut u8 ) > ( code_buf. as_ptr ( ) ) ;
178+ start_func ( vmctx. as_ptr ( ) ) ;
179+ }
180+ }
181+
182+ Ok ( vmctx)
183+ }
184+
185+ /// Jumps to the code region of memory and execute the exported function
186+ pub fn execute (
187+ module : & Module ,
188+ compilation : & Compilation ,
189+ vmctx : & mut Vec < * mut u8 > ,
190+ function : & str ,
191+ ) -> Result < ( ) , String > {
192+ let fn_index = match module. exports . get ( function) {
193+ Some ( Export :: Function ( index) ) => * index,
194+ Some ( _) => return Err ( format ! ( "exported item \" {}\" is not a function" , function) ) ,
195+ None => return Err ( format ! ( "no export named \" {}\" " , function) ) ,
196+ } ;
197+
198+ let code_buf =
199+ & compilation. functions [ module
200+ . defined_func_index ( fn_index)
201+ . expect ( "imported start functions not supported yet" ) ] ;
202+
170203 // Rather than writing inline assembly to jump to the code region, we use the fact that
171204 // the Rust ABI for calling a function with no arguments and no return matches the one of
172205 // the generated code. Thanks to this, we can transmute the code region into a first-class
173206 // Rust function and call it.
174207 unsafe {
175- let start_func = transmute :: < _ , fn ( * const * mut u8 ) > ( code_buf. as_ptr ( ) ) ;
176- start_func ( vmctx. as_ptr ( ) ) ;
208+ let func = transmute :: < _ , fn ( * const * mut u8 ) > ( code_buf. as_ptr ( ) ) ;
209+ func ( vmctx. as_ptr ( ) ) ;
177210 }
178211 Ok ( ( ) )
179212}
0 commit comments