@@ -28,14 +28,14 @@ use self::{
28
28
utils:: Reset ,
29
29
} ;
30
30
use crate :: {
31
- core:: { FuelCostsProvider , Typed , TypedVal } ,
31
+ core:: { FuelCostsProvider , Typed , TypedVal , ValType } ,
32
32
engine:: {
33
33
translator:: { utils:: FuelInfo , Instr , LabelRef , LabelRegistry , WasmTranslator } ,
34
34
BlockType ,
35
35
CompiledFuncEntity ,
36
36
TranslationError ,
37
37
} ,
38
- ir:: { Const16 , Instruction , Reg } ,
38
+ ir:: { BoundedRegSpan , Const16 , Const32 , Instruction , Reg , RegSpan } ,
39
39
module:: { FuncIdx , ModuleHeader , WasmiValueType } ,
40
40
Engine ,
41
41
Error ,
@@ -250,14 +250,115 @@ impl FuncTranslator {
250
250
251
251
/// Translates the end of the Wasm function enclosing Wasm `block`.
252
252
fn translate_end_func ( & mut self , frame : BlockControlFrame ) -> Result < ( ) , Error > {
253
- let fuel_info = match ( frame. consume_fuel_instr ( ) , & self . fuel_costs ) {
254
- ( Some ( consume_fuel ) , Some ( fuel_costs ) ) => {
253
+ let fuel_info = match ( & self . fuel_costs , frame. consume_fuel_instr ( ) ) {
254
+ ( Some ( fuel_costs ) , Some ( consume_fuel ) ) => {
255
255
FuelInfo :: some ( fuel_costs. clone ( ) , consume_fuel)
256
256
}
257
257
( None , None ) => FuelInfo :: None ,
258
258
_ => unreachable ! ( ) ,
259
259
} ;
260
- todo ! ( )
260
+ let len_results = frame. ty ( ) . len_results ( & self . engine ) ;
261
+ if self . reachable && frame. is_branched_to ( ) && len_results > 1 {
262
+ let height = frame. height ( ) ;
263
+ let len_results = usize:: from ( len_results) ;
264
+ for depth in 0 ..len_results {
265
+ let result = self
266
+ . layout
267
+ . temp_to_reg ( OperandIdx :: from ( height + len_results - depth - 1 ) ) ?;
268
+ match self . stack . operand_to_temp ( depth) {
269
+ Some ( Operand :: Local ( operand) ) => {
270
+ let value = self . layout . local_to_reg ( operand. local_index ( ) ) ?;
271
+ self . instrs . push_instr ( Instruction :: copy ( result, value) ) ;
272
+ }
273
+ Some ( Operand :: Immediate ( operand) ) => {
274
+ let val = operand. val ( ) ;
275
+ let instr = match operand. ty ( ) {
276
+ ValType :: I32 => Instruction :: copy_imm32 ( result, i32:: from ( val) ) ,
277
+ ValType :: I64 => {
278
+ let val = i64:: from ( val) ;
279
+ match <Const32 < i64 > >:: try_from ( val) {
280
+ Ok ( value) => Instruction :: copy_i64imm32 ( result, value) ,
281
+ Err ( _) => {
282
+ let value = self . layout . const_to_reg ( val) ?;
283
+ Instruction :: copy ( result, value)
284
+ }
285
+ }
286
+ }
287
+ ValType :: F32 => Instruction :: copy_imm32 ( result, f32:: from ( val) ) ,
288
+ ValType :: F64 => {
289
+ let val = f64:: from ( val) ;
290
+ match <Const32 < f64 > >:: try_from ( val) {
291
+ Ok ( value) => Instruction :: copy_f64imm32 ( result, value) ,
292
+ Err ( _) => {
293
+ let value = self . layout . const_to_reg ( val) ?;
294
+ Instruction :: copy ( result, value)
295
+ }
296
+ }
297
+ }
298
+ ValType :: V128 | ValType :: FuncRef | ValType :: ExternRef => {
299
+ let value = self . layout . const_to_reg ( val) ?;
300
+ Instruction :: copy ( result, value)
301
+ }
302
+ } ;
303
+ self . instrs . push_instr ( instr) ;
304
+ }
305
+ _ => { }
306
+ }
307
+ }
308
+ }
309
+ self . labels
310
+ . pin_label ( frame. label ( ) , self . instrs . next_instr ( ) )
311
+ . unwrap_or_else ( |err| panic ! ( "failed to pin label: {err}" ) ) ;
312
+ match len_results {
313
+ 0 => {
314
+ self . instrs . push_instr ( Instruction :: Return ) ;
315
+ }
316
+ 1 => {
317
+ let instr = match self . stack . peek ( 0 ) {
318
+ Operand :: Local ( operand) => {
319
+ let value = self . layout . local_to_reg ( operand. local_index ( ) ) ?;
320
+ Instruction :: return_reg ( value)
321
+ }
322
+ Operand :: Temp ( operand) => {
323
+ let value = self . layout . temp_to_reg ( operand. operand_index ( ) ) ?;
324
+ Instruction :: return_reg ( value)
325
+ }
326
+ Operand :: Immediate ( operand) => {
327
+ let val = operand. val ( ) ;
328
+ match operand. ty ( ) {
329
+ ValType :: I32 => Instruction :: return_imm32 ( i32:: from ( val) ) ,
330
+ ValType :: I64 => match <Const32 < i64 > >:: try_from ( i64:: from ( val) ) {
331
+ Ok ( value) => Instruction :: return_i64imm32 ( value) ,
332
+ Err ( _) => {
333
+ let value = self . layout . const_to_reg ( val) ?;
334
+ Instruction :: return_reg ( value)
335
+ }
336
+ } ,
337
+ ValType :: F32 => Instruction :: return_imm32 ( f32:: from ( val) ) ,
338
+ ValType :: F64 => match <Const32 < f64 > >:: try_from ( f64:: from ( val) ) {
339
+ Ok ( value) => Instruction :: return_f64imm32 ( value) ,
340
+ Err ( _) => {
341
+ let value = self . layout . const_to_reg ( val) ?;
342
+ Instruction :: return_reg ( value)
343
+ }
344
+ } ,
345
+ ValType :: V128 | ValType :: FuncRef | ValType :: ExternRef => {
346
+ let value = self . layout . const_to_reg ( val) ?;
347
+ Instruction :: return_reg ( value)
348
+ }
349
+ }
350
+ }
351
+ } ;
352
+ self . instrs . push_instr ( instr) ;
353
+ }
354
+ n => {
355
+ let height = frame. height ( ) ;
356
+ let result = self . layout . temp_to_reg ( OperandIdx :: from ( height - 1 ) ) ?;
357
+ let values = BoundedRegSpan :: new ( RegSpan :: new ( result) , len_results) ;
358
+ self . instrs . push_instr ( Instruction :: return_span ( values) ) ;
359
+ }
360
+ }
361
+ Ok ( ( ) )
261
362
}
262
363
263
364
/// Translates the end of a Wasm `loop` control frame.
0 commit comments