@@ -12,12 +12,13 @@ use llvm::{self, ValueRef};
12
12
use rustc:: middle:: const_val:: ConstVal ;
13
13
use rustc_const_eval:: ErrKind ;
14
14
use rustc_const_math:: ConstInt :: * ;
15
+ use rustc_const_math:: ConstMathErr ;
15
16
use rustc:: hir:: def_id:: DefId ;
16
17
use rustc:: infer:: TransNormalize ;
17
18
use rustc:: mir:: repr as mir;
18
19
use rustc:: mir:: tcx:: LvalueTy ;
19
20
use rustc:: traits;
20
- use rustc:: ty:: { self , Ty , TypeFoldable } ;
21
+ use rustc:: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
21
22
use rustc:: ty:: cast:: { CastTy , IntTy } ;
22
23
use rustc:: ty:: subst:: Substs ;
23
24
use { abi, adt, base, Disr } ;
@@ -713,73 +714,28 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
713
714
let ty = lhs. ty ;
714
715
let binop_ty = self . mir . binop_ty ( tcx, op, lhs. ty , rhs. ty ) ;
715
716
let ( lhs, rhs) = ( lhs. llval , rhs. llval ) ;
716
- assert ! ( !ty. is_simd( ) ) ;
717
- let is_float = ty. is_fp ( ) ;
718
- let signed = ty. is_signed ( ) ;
719
-
720
- if let ( Some ( lhs) , Some ( rhs) ) = ( to_const_int ( lhs, ty, tcx) ,
721
- to_const_int ( rhs, ty, tcx) ) {
722
- let result = match op {
723
- mir:: BinOp :: Add => lhs + rhs,
724
- mir:: BinOp :: Sub => lhs - rhs,
725
- mir:: BinOp :: Mul => lhs * rhs,
726
- mir:: BinOp :: Div => lhs / rhs,
727
- mir:: BinOp :: Rem => lhs % rhs,
728
- mir:: BinOp :: Shl => lhs << rhs,
729
- mir:: BinOp :: Shr => lhs >> rhs,
730
- _ => Ok ( lhs)
731
- } ;
732
- consts:: const_err ( self . ccx , span,
733
- result. map_err ( ErrKind :: Math ) ,
734
- TrueConst :: Yes ) ?;
735
- }
736
-
737
- let llval = unsafe {
738
- match op {
739
- mir:: BinOp :: Add if is_float => llvm:: LLVMConstFAdd ( lhs, rhs) ,
740
- mir:: BinOp :: Add => llvm:: LLVMConstAdd ( lhs, rhs) ,
741
-
742
- mir:: BinOp :: Sub if is_float => llvm:: LLVMConstFSub ( lhs, rhs) ,
743
- mir:: BinOp :: Sub => llvm:: LLVMConstSub ( lhs, rhs) ,
744
-
745
- mir:: BinOp :: Mul if is_float => llvm:: LLVMConstFMul ( lhs, rhs) ,
746
- mir:: BinOp :: Mul => llvm:: LLVMConstMul ( lhs, rhs) ,
747
-
748
- mir:: BinOp :: Div if is_float => llvm:: LLVMConstFDiv ( lhs, rhs) ,
749
- mir:: BinOp :: Div if signed => llvm:: LLVMConstSDiv ( lhs, rhs) ,
750
- mir:: BinOp :: Div => llvm:: LLVMConstUDiv ( lhs, rhs) ,
717
+ Const :: new ( const_scalar_binop ( op, lhs, rhs, ty) , binop_ty)
718
+ }
751
719
752
- mir:: BinOp :: Rem if is_float => llvm:: LLVMConstFRem ( lhs, rhs) ,
753
- mir:: BinOp :: Rem if signed => llvm:: LLVMConstSRem ( lhs, rhs) ,
754
- mir:: BinOp :: Rem => llvm:: LLVMConstURem ( lhs, rhs) ,
720
+ mir:: Rvalue :: CheckedBinaryOp ( op, ref lhs, ref rhs) => {
721
+ let lhs = self . const_operand ( lhs, span) ?;
722
+ let rhs = self . const_operand ( rhs, span) ?;
723
+ let ty = lhs. ty ;
724
+ let val_ty = self . mir . binop_ty ( tcx, op, lhs. ty , rhs. ty ) ;
725
+ let binop_ty = tcx. mk_tup ( vec ! [ val_ty, tcx. types. bool ] ) ;
726
+ let ( lhs, rhs) = ( lhs. llval , rhs. llval ) ;
727
+ assert ! ( !ty. is_fp( ) ) ;
755
728
756
- mir:: BinOp :: BitXor => llvm:: LLVMConstXor ( lhs, rhs) ,
757
- mir:: BinOp :: BitAnd => llvm:: LLVMConstAnd ( lhs, rhs) ,
758
- mir:: BinOp :: BitOr => llvm:: LLVMConstOr ( lhs, rhs) ,
759
- mir:: BinOp :: Shl => {
760
- let rhs = base:: cast_shift_const_rhs ( op. to_hir_binop ( ) , lhs, rhs) ;
761
- llvm:: LLVMConstShl ( lhs, rhs)
762
- }
763
- mir:: BinOp :: Shr => {
764
- let rhs = base:: cast_shift_const_rhs ( op. to_hir_binop ( ) , lhs, rhs) ;
765
- if signed { llvm:: LLVMConstAShr ( lhs, rhs) }
766
- else { llvm:: LLVMConstLShr ( lhs, rhs) }
767
- }
768
- mir:: BinOp :: Eq | mir:: BinOp :: Ne |
769
- mir:: BinOp :: Lt | mir:: BinOp :: Le |
770
- mir:: BinOp :: Gt | mir:: BinOp :: Ge => {
771
- if is_float {
772
- let cmp = base:: bin_op_to_fcmp_predicate ( op. to_hir_binop ( ) ) ;
773
- llvm:: ConstFCmp ( cmp, lhs, rhs)
774
- } else {
775
- let cmp = base:: bin_op_to_icmp_predicate ( op. to_hir_binop ( ) ,
776
- signed) ;
777
- llvm:: ConstICmp ( cmp, lhs, rhs)
778
- }
779
- }
729
+ match const_scalar_checked_binop ( tcx, op, lhs, rhs, ty) {
730
+ Some ( ( llval, of) ) => {
731
+ let llof = C_bool ( self . ccx , of) ;
732
+ Const :: new ( C_struct ( self . ccx , & [ llval, llof] , false ) , binop_ty)
780
733
}
781
- } ;
782
- Const :: new ( llval, binop_ty)
734
+ None => {
735
+ span_bug ! ( span, "{:?} got non-integer operands: {:?} and {:?}" ,
736
+ rvalue, Value ( lhs) , Value ( rhs) ) ;
737
+ }
738
+ }
783
739
}
784
740
785
741
mir:: Rvalue :: UnaryOp ( op, ref operand) => {
@@ -792,11 +748,6 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
792
748
}
793
749
}
794
750
mir:: UnOp :: Neg => {
795
- if let Some ( cval) = to_const_int ( lloperand, operand. ty , tcx) {
796
- consts:: const_err ( self . ccx , span,
797
- ( -cval) . map_err ( ErrKind :: Math ) ,
798
- TrueConst :: Yes ) ?;
799
- }
800
751
let is_float = operand. ty . is_fp ( ) ;
801
752
unsafe {
802
753
if is_float {
@@ -815,6 +766,97 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
815
766
816
767
Ok ( val)
817
768
}
769
+
770
+ }
771
+
772
+ pub fn const_scalar_binop ( op : mir:: BinOp ,
773
+ lhs : ValueRef ,
774
+ rhs : ValueRef ,
775
+ input_ty : Ty ) -> ValueRef {
776
+ assert ! ( !input_ty. is_simd( ) ) ;
777
+ let is_float = input_ty. is_fp ( ) ;
778
+ let signed = input_ty. is_signed ( ) ;
779
+
780
+ unsafe {
781
+ match op {
782
+ mir:: BinOp :: Add if is_float => llvm:: LLVMConstFAdd ( lhs, rhs) ,
783
+ mir:: BinOp :: Add => llvm:: LLVMConstAdd ( lhs, rhs) ,
784
+
785
+ mir:: BinOp :: Sub if is_float => llvm:: LLVMConstFSub ( lhs, rhs) ,
786
+ mir:: BinOp :: Sub => llvm:: LLVMConstSub ( lhs, rhs) ,
787
+
788
+ mir:: BinOp :: Mul if is_float => llvm:: LLVMConstFMul ( lhs, rhs) ,
789
+ mir:: BinOp :: Mul => llvm:: LLVMConstMul ( lhs, rhs) ,
790
+
791
+ mir:: BinOp :: Div if is_float => llvm:: LLVMConstFDiv ( lhs, rhs) ,
792
+ mir:: BinOp :: Div if signed => llvm:: LLVMConstSDiv ( lhs, rhs) ,
793
+ mir:: BinOp :: Div => llvm:: LLVMConstUDiv ( lhs, rhs) ,
794
+
795
+ mir:: BinOp :: Rem if is_float => llvm:: LLVMConstFRem ( lhs, rhs) ,
796
+ mir:: BinOp :: Rem if signed => llvm:: LLVMConstSRem ( lhs, rhs) ,
797
+ mir:: BinOp :: Rem => llvm:: LLVMConstURem ( lhs, rhs) ,
798
+
799
+ mir:: BinOp :: BitXor => llvm:: LLVMConstXor ( lhs, rhs) ,
800
+ mir:: BinOp :: BitAnd => llvm:: LLVMConstAnd ( lhs, rhs) ,
801
+ mir:: BinOp :: BitOr => llvm:: LLVMConstOr ( lhs, rhs) ,
802
+ mir:: BinOp :: Shl => {
803
+ let rhs = base:: cast_shift_const_rhs ( op. to_hir_binop ( ) , lhs, rhs) ;
804
+ llvm:: LLVMConstShl ( lhs, rhs)
805
+ }
806
+ mir:: BinOp :: Shr => {
807
+ let rhs = base:: cast_shift_const_rhs ( op. to_hir_binop ( ) , lhs, rhs) ;
808
+ if signed { llvm:: LLVMConstAShr ( lhs, rhs) }
809
+ else { llvm:: LLVMConstLShr ( lhs, rhs) }
810
+ }
811
+ mir:: BinOp :: Eq | mir:: BinOp :: Ne |
812
+ mir:: BinOp :: Lt | mir:: BinOp :: Le |
813
+ mir:: BinOp :: Gt | mir:: BinOp :: Ge => {
814
+ if is_float {
815
+ let cmp = base:: bin_op_to_fcmp_predicate ( op. to_hir_binop ( ) ) ;
816
+ llvm:: ConstFCmp ( cmp, lhs, rhs)
817
+ } else {
818
+ let cmp = base:: bin_op_to_icmp_predicate ( op. to_hir_binop ( ) ,
819
+ signed) ;
820
+ llvm:: ConstICmp ( cmp, lhs, rhs)
821
+ }
822
+ }
823
+ }
824
+ }
825
+ }
826
+
827
+ pub fn const_scalar_checked_binop < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
828
+ op : mir:: BinOp ,
829
+ lllhs : ValueRef ,
830
+ llrhs : ValueRef ,
831
+ input_ty : Ty < ' tcx > )
832
+ -> Option < ( ValueRef , bool ) > {
833
+ if let ( Some ( lhs) , Some ( rhs) ) = ( to_const_int ( lllhs, input_ty, tcx) ,
834
+ to_const_int ( llrhs, input_ty, tcx) ) {
835
+ let result = match op {
836
+ mir:: BinOp :: Add => lhs + rhs,
837
+ mir:: BinOp :: Sub => lhs - rhs,
838
+ mir:: BinOp :: Mul => lhs * rhs,
839
+ mir:: BinOp :: Shl => lhs << rhs,
840
+ mir:: BinOp :: Shr => lhs >> rhs,
841
+ _ => {
842
+ bug ! ( "Operator `{:?}` is not a checkable operator" , op)
843
+ }
844
+ } ;
845
+
846
+ let of = match result {
847
+ Ok ( _) => false ,
848
+ Err ( ConstMathErr :: Overflow ( _) ) |
849
+ Err ( ConstMathErr :: ShiftNegative ) => true ,
850
+ Err ( err) => {
851
+ bug ! ( "Operator `{:?}` on `{:?}` and `{:?}` errored: {}" ,
852
+ op, lhs, rhs, err. description( ) ) ;
853
+ }
854
+ } ;
855
+
856
+ Some ( ( const_scalar_binop ( op, lllhs, llrhs, input_ty) , of) )
857
+ } else {
858
+ None
859
+ }
818
860
}
819
861
820
862
impl < ' bcx , ' tcx > MirContext < ' bcx , ' tcx > {
0 commit comments