1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_VM_METAPROGRAMMING_INTEGERTYPES_HPP 26 #define SHARE_VM_METAPROGRAMMING_INTEGERTYPES_HPP 27 28 #include "memory/allocation.hpp" 29 #include "metaprogramming/enableIf.hpp" 30 #include "metaprogramming/integralConstant.hpp" 31 #include "metaprogramming/isFloatingPoint.hpp" 32 #include "metaprogramming/isIntegral.hpp" 33 #include "metaprogramming/isRegisteredEnum.hpp" 34 #include "utilities/debug.hpp" 35 36 class IntegerTypes : public AllStatic { 37 public: 38 // Return a value of type T with the same representation as x. 39 // 40 // T and U must be of the same size. 41 // 42 // At least one of T or U must be an integral type. The other must 43 // be an integral, floating point, or pointer type. 44 template<typename T, typename U> static T cast(U x); 45 46 // Support thin wrappers over primitive types. 47 // If derived from TrueType, provides representational conversion 48 // from T to some other type. When true, must provide 49 // - Value: typedef for T. 50 // - Decayed: typedef for decayed type. 51 // - static Decayed decay(T x): return value of type Decayed with 52 // the same representation as x. 53 // - static T recover(Decayed x): return a value of type T with the 54 // same representation as x. 55 template<typename T> struct Translate : public FalseType {}; 56 57 private: 58 59 template<typename T, 60 typename U, 61 bool same_size = sizeof(T) == sizeof(U), 62 typename Enable = void> 63 struct Cast; 64 65 template<typename T, typename U> static T cast_using_union(U x); 66 }; 67 68 // Return an object of type T with the same value representation as x. 69 // 70 // T and U must be of the same size. It is expected that one of T and 71 // U is an integral type, and the other is an integral type, a 72 // (registered) enum type, or a floating point type 73 // 74 // This implementation uses the "union trick", which seems to be the 75 // best of a bad set of options. Though technically undefined 76 // behavior, it is widely and well supported, producing good code. In 77 // some cases, such as gcc, that support is explicitly documented. 78 // 79 // Using memcpy is the correct method, but some compilers produce 80 // wretched code for that method, even at maximal optimization levels. 81 // 82 // Using static_cast is only possible for integral and enum types, not 83 // for floating point types. And for integral and enum conversions, 84 // static_cast has unspecified or implementation-defined behavior for 85 // some cases. C++11 <type_traits> can be used to avoid most or all 86 // of those unspecified or implementation-defined issues, though that 87 // may require multi-step conversions. 88 // 89 // Using reinterpret_cast of references has undefined behavior for 90 // many cases, and there is much less empirical basis for its use, as 91 // compared to the union trick. 92 template<typename T, typename U> 93 inline T IntegerTypes::cast_using_union(U x) { 94 STATIC_ASSERT(sizeof(T) == sizeof(U)); 95 union { T t; U u; }; 96 u = x; 97 return t; 98 } 99 100 ////////////////////////////////////////////////////////////////////////////// 101 // cast<T>(x) 102 // 103 // Cast<T, U, same_size, Enable> 104 105 // Give an informative error if the sizes differ. 106 template<typename T, typename U> 107 struct IntegerTypes::Cast<T, U, false> VALUE_OBJ_CLASS_SPEC { 108 STATIC_ASSERT(sizeof(T) == sizeof(U)); 109 }; 110 111 // Conversion between integral types. 112 template<typename T, typename U> 113 struct IntegerTypes::Cast< 114 T, U, true, 115 typename EnableIf<IsIntegral<T>::value && IsIntegral<U>::value>::type> 116 VALUE_OBJ_CLASS_SPEC 117 { 118 T operator()(U x) const { return cast_using_union<T>(x); } 119 }; 120 121 // Convert an enum or floating point value to an integer value. 122 template<typename T, typename U> 123 struct IntegerTypes::Cast< 124 T, U, true, 125 typename EnableIf<IsIntegral<T>::value && 126 (IsRegisteredEnum<U>::value || 127 IsFloatingPoint<U>::value)>::type> 128 VALUE_OBJ_CLASS_SPEC 129 { 130 T operator()(U x) const { return cast_using_union<T>(x); } 131 }; 132 133 // Convert an integer to an enum or floating point value. 134 template<typename T, typename U> 135 struct IntegerTypes::Cast< 136 T, U, true, 137 typename EnableIf<IsIntegral<U>::value && 138 (IsRegisteredEnum<T>::value || 139 IsFloatingPoint<T>::value)>::type> 140 VALUE_OBJ_CLASS_SPEC 141 { 142 T operator()(U x) const { return cast_using_union<T>(x); } 143 }; 144 145 // Convert a pointer to an integral value. 146 template<typename T, typename U> 147 struct IntegerTypes::Cast< 148 T, U*, true, 149 typename EnableIf<IsIntegral<T>::value>::type> 150 VALUE_OBJ_CLASS_SPEC 151 { 152 T operator()(U* x) const { return reinterpret_cast<T>(x); } 153 }; 154 155 // Convert an integral value to a pointer. 156 template<typename T, typename U> 157 struct IntegerTypes::Cast< 158 T*, U, true, 159 typename EnableIf<IsIntegral<U>::value>::type> 160 VALUE_OBJ_CLASS_SPEC 161 { 162 T* operator()(U x) const { return reinterpret_cast<T*>(x); } 163 }; 164 165 template<typename T, typename U> 166 inline T IntegerTypes::cast(U x) { 167 return Cast<T, U>()(x); 168 } 169 170 #endif // SHARE_VM_METAPROGRAMMING_INTEGERTYPES_HPP