Home | History | Annotate | Download | only in interpreter
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_RUNTIME_INTERPRETER_SAFE_MATH_H_
     18 #define ART_RUNTIME_INTERPRETER_SAFE_MATH_H_
     19 
     20 #include <functional>
     21 #include <type_traits>
     22 
     23 namespace art {
     24 namespace interpreter {
     25 
     26 // Declares a type which is the larger in bit size of the two template parameters.
     27 template <typename T1, typename T2>
     28 struct select_bigger {
     29   typedef typename std::conditional<sizeof(T1) >= sizeof(T2), T1, T2>::type type;
     30 };
     31 
     32 // Perform signed arithmetic Op on 'a' and 'b' with defined wrapping behavior.
     33 template<template <typename OpT> class Op, typename T1, typename T2>
     34 static inline typename select_bigger<T1, T2>::type SafeMath(T1 a, T2 b) {
     35   typedef typename select_bigger<T1, T2>::type biggest_T;
     36   typedef typename std::make_unsigned<biggest_T>::type unsigned_biggest_T;
     37   static_assert(std::is_signed<T1>::value, "Expected T1 to be signed");
     38   static_assert(std::is_signed<T2>::value, "Expected T2 to be signed");
     39   unsigned_biggest_T val1 = static_cast<unsigned_biggest_T>(static_cast<biggest_T>(a));
     40   unsigned_biggest_T val2 = static_cast<unsigned_biggest_T>(b);
     41   return static_cast<biggest_T>(Op<unsigned_biggest_T>()(val1, val2));
     42 }
     43 
     44 // Perform signed a signed add on 'a' and 'b' with defined wrapping behavior.
     45 template<typename T1, typename T2>
     46 static inline typename select_bigger<T1, T2>::type SafeAdd(T1 a, T2 b) {
     47   return SafeMath<std::plus>(a, b);
     48 }
     49 
     50 // Perform signed a signed substract on 'a' and 'b' with defined wrapping behavior.
     51 template<typename T1, typename T2>
     52 static inline typename select_bigger<T1, T2>::type SafeSub(T1 a, T2 b) {
     53   return SafeMath<std::minus>(a, b);
     54 }
     55 
     56 // Perform signed a signed multiply on 'a' and 'b' with defined wrapping behavior.
     57 template<typename T1, typename T2>
     58 static inline typename select_bigger<T1, T2>::type SafeMul(T1 a, T2 b) {
     59   return SafeMath<std::multiplies>(a, b);
     60 }
     61 
     62 }  // namespace interpreter
     63 }  // namespace art
     64 
     65 #endif  // ART_RUNTIME_INTERPRETER_SAFE_MATH_H_
     66