@@ -8,6 +8,12 @@ use std::collections::HashMap;
88
99use super :: { JitCompileError , JitSig , JitType } ;
1010
11+ #[ repr( u16 ) ]
12+ enum CustomTrapCode {
13+ /// Raised when shifting by a negative number
14+ NegativeShiftCount = 0 ,
15+ }
16+
1117#[ derive( Clone ) ]
1218struct Local {
1319 var : Variable ,
@@ -340,64 +346,75 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
340346 // the rhs is popped off first
341347 let b = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
342348 let a = self . stack . pop ( ) . ok_or ( JitCompileError :: BadBytecode ) ?;
343- match ( a. ty , b. ty ) {
344- ( JitType :: Int , JitType :: Int ) => match op {
345- BinaryOperator :: Add => {
346- let ( out, carry) = self . builder . ins ( ) . iadd_ifcout ( a. val , b. val ) ;
347- self . builder . ins ( ) . trapif (
348- IntCC :: Overflow ,
349- carry,
350- TrapCode :: IntegerOverflow ,
351- ) ;
352- self . stack . push ( JitValue {
353- val : out,
354- ty : JitType :: Int ,
355- } ) ;
356- Ok ( ( ) )
357- }
358- BinaryOperator :: Subtract => {
359- let out = self . compile_sub ( a. val , b. val ) ;
360- self . stack . push ( JitValue {
361- val : out,
362- ty : JitType :: Int ,
363- } ) ;
364- Ok ( ( ) )
365- }
366- _ => Err ( JitCompileError :: NotSupported ) ,
367- } ,
368- ( JitType :: Float , JitType :: Float ) => match op {
369- BinaryOperator :: Add => {
370- self . stack . push ( JitValue {
371- val : self . builder . ins ( ) . fadd ( a. val , b. val ) ,
372- ty : JitType :: Float ,
373- } ) ;
374- Ok ( ( ) )
375- }
376- BinaryOperator :: Subtract => {
377- self . stack . push ( JitValue {
378- val : self . builder . ins ( ) . fsub ( a. val , b. val ) ,
379- ty : JitType :: Float ,
380- } ) ;
381- Ok ( ( ) )
382- }
383- BinaryOperator :: Multiply => {
384- self . stack . push ( JitValue {
385- val : self . builder . ins ( ) . fmul ( a. val , b. val ) ,
386- ty : JitType :: Float ,
387- } ) ;
388- Ok ( ( ) )
389- }
390- BinaryOperator :: Divide => {
391- self . stack . push ( JitValue {
392- val : self . builder . ins ( ) . fdiv ( a. val , b. val ) ,
393- ty : JitType :: Float ,
394- } ) ;
395- Ok ( ( ) )
396- }
397- _ => Err ( JitCompileError :: NotSupported ) ,
398- } ,
399- _ => Err ( JitCompileError :: NotSupported ) ,
400- }
349+ let ( val, ty) = match ( op, a. ty , b. ty ) {
350+ ( BinaryOperator :: Add , JitType :: Int , JitType :: Int ) => {
351+ let ( out, carry) = self . builder . ins ( ) . iadd_ifcout ( a. val , b. val ) ;
352+ self . builder . ins ( ) . trapif (
353+ IntCC :: Overflow ,
354+ carry,
355+ TrapCode :: IntegerOverflow ,
356+ ) ;
357+ ( out, JitType :: Int )
358+ }
359+ ( BinaryOperator :: Subtract , JitType :: Int , JitType :: Int ) => {
360+ ( self . compile_sub ( a. val , b. val ) , JitType :: Int )
361+ }
362+ ( BinaryOperator :: FloorDivide , JitType :: Int , JitType :: Int ) => {
363+ ( self . builder . ins ( ) . sdiv ( a. val , b. val ) , JitType :: Int )
364+ }
365+ ( BinaryOperator :: Modulo , JitType :: Int , JitType :: Int ) => {
366+ ( self . builder . ins ( ) . srem ( a. val , b. val ) , JitType :: Int )
367+ }
368+ (
369+ BinaryOperator :: Lshift | BinaryOperator :: Rshift ,
370+ JitType :: Int ,
371+ JitType :: Int ,
372+ ) => {
373+ // Shifts throw an exception if we have a negative shift count
374+ // Remove all bits except the sign bit, and trap if its 1 (i.e. negative).
375+ let sign = self . builder . ins ( ) . ushr_imm ( b. val , 63 ) ;
376+ self . builder . ins ( ) . trapnz (
377+ sign,
378+ TrapCode :: User ( CustomTrapCode :: NegativeShiftCount as u16 ) ,
379+ ) ;
380+
381+ let out = if * op == BinaryOperator :: Lshift {
382+ self . builder . ins ( ) . ishl ( a. val , b. val )
383+ } else {
384+ self . builder . ins ( ) . sshr ( a. val , b. val )
385+ } ;
386+
387+ ( out, JitType :: Int )
388+ }
389+ ( BinaryOperator :: And , JitType :: Int , JitType :: Int ) => {
390+ ( self . builder . ins ( ) . band ( a. val , b. val ) , JitType :: Int )
391+ }
392+ ( BinaryOperator :: Or , JitType :: Int , JitType :: Int ) => {
393+ ( self . builder . ins ( ) . bor ( a. val , b. val ) , JitType :: Int )
394+ }
395+ ( BinaryOperator :: Xor , JitType :: Int , JitType :: Int ) => {
396+ ( self . builder . ins ( ) . bxor ( a. val , b. val ) , JitType :: Int )
397+ }
398+
399+ // Floats
400+ ( BinaryOperator :: Add , JitType :: Float , JitType :: Float ) => {
401+ ( self . builder . ins ( ) . fadd ( a. val , b. val ) , JitType :: Float )
402+ }
403+ ( BinaryOperator :: Subtract , JitType :: Float , JitType :: Float ) => {
404+ ( self . builder . ins ( ) . fsub ( a. val , b. val ) , JitType :: Float )
405+ }
406+ ( BinaryOperator :: Multiply , JitType :: Float , JitType :: Float ) => {
407+ ( self . builder . ins ( ) . fmul ( a. val , b. val ) , JitType :: Float )
408+ }
409+ ( BinaryOperator :: Divide , JitType :: Float , JitType :: Float ) => {
410+ ( self . builder . ins ( ) . fdiv ( a. val , b. val ) , JitType :: Float )
411+ }
412+ _ => return Err ( JitCompileError :: NotSupported ) ,
413+ } ;
414+
415+ self . stack . push ( JitValue { val, ty } ) ;
416+
417+ Ok ( ( ) )
401418 }
402419 Instruction :: SetupLoop { .. } | Instruction :: PopBlock => {
403420 // TODO: block support
0 commit comments