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 "utilities/debug.hpp" 30 #include "metaprogramming/enableIf.hpp" 31 #include "metaprogramming/integralConstant.hpp" 32 #include "metaprogramming/isFloatingPoint.hpp" 33 #include "metaprogramming/isPointer.hpp" 34 #include "metaprogramming/isRegisteredEnum.hpp" 35 #include "metaprogramming/isIntegral.hpp" 36 37 class IntegerTypes : public AllStatic { 38 public: 39 // Return a value of type T with the same representation as x. 40 // 41 // T and U must be of the same size. 42 // 43 // At least one of T or U must be an integral type. The other must 44 // be an integral, floating point, or pointer type. 45 template<typename T, typename U> static T cast(U x); 46 47 // Support thin wrappers over primitive types. 48 // If derived from TrueType, provides representational conversion 49 // from T to some other type. When true, must provide 50 // - Value: typedef for T. 51 // - Decayed: typedef for decayed type. 52 // - static Decayed decay(T x): return value of type Decayed with 53 // the same representation as x. 54 // - static T recover(Decayed x): return a value of type T with the 55 // same representation as x. 56 template<typename T> struct Translate : public FalseType {}; 57 58 // Value categories. For internal use, but needs to be public. 59 enum Category { 60 INTEGRAL, 61 ENUM, 62 FLOAT, 63 POINTER 64 }; 65 66 private: 67 68 template<typename T, typename Enable = void> struct GetCategory; 69 70 template<typename T, 71 typename U, 72 bool same_size = sizeof(T) == sizeof(U), 73 Category to_category = GetCategory<T>::value, 74 Category from_category = GetCategory<U>::value> 75 struct Cast; 76 77 template<typename T, typename U> static T cast_integral(U x); 78 template<typename T, typename U> static T cast_floating_point(U x); 79 }; 80 81 #define DEFINE_GET_CATEGORY(Predicate, Value) \ 82 template<typename T> \ 83 struct IntegerTypes::GetCategory< \ 84 T, \ 85 typename EnableIf<Predicate<T>::value>::type> \ 86 : IntegralConstant<IntegerTypes::Category, IntegerTypes::Value> \ 87 {}; 88 89 DEFINE_GET_CATEGORY(IsIntegral, INTEGRAL) 90 DEFINE_GET_CATEGORY(IsRegisteredEnum, ENUM) 91 DEFINE_GET_CATEGORY(IsFloatingPoint, FLOAT) 92 DEFINE_GET_CATEGORY(IsPointer, POINTER) 93 94 #undef DEFINE_GET_CATEGORY 95 96 // Convert between different integral types of the same size. 97 // See C++03 3.10/15 for discussion of reinterpret_cast to a reference 98 // as a means for converting integral types while keeping the representation. 99 template<typename T, typename U> 100 inline T IntegerTypes::cast_integral(U x) { 101 STATIC_ASSERT(sizeof(T) == sizeof(U)); 102 return reinterpret_cast<T&>(x); 103 } 104 105 // Convert between an integral type and a floating point type of the 106 // same size. The only truly correct way to do this is with memcpy. 107 // Both the union trick and type punning via casts are undefined 108 // behavior. gcc generates exactly the same code for all three methods, 109 // except where the UB of type punning causes it to go off into the weeds. 110 // (gcc explicitly supports the union trick.) Other compilers may vary. 111 // In particular, not all compilers do a good job with the memcpy. 112 template<typename T, typename U> 113 inline T IntegerTypes::cast_floating_point(U x) { 114 STATIC_ASSERT(sizeof(T) == sizeof(U)); 115 T result; 116 memcpy(&result, &x, sizeof(x)); 117 return result; 118 } 119 120 ////////////////////////////////////////////////////////////////////////////// 121 // cast<T>(x) 122 // 123 // Cast<T, U, same_size, to_category, from_category> 124 125 // Give an informative error if the sizes differ. 126 template<typename T, typename U, 127 IntegerTypes::Category to_category, 128 IntegerTypes::Category from_category> 129 struct IntegerTypes::Cast<T, U, false, to_category, from_category> 130 VALUE_OBJ_CLASS_SPEC 131 { 132 STATIC_ASSERT(sizeof(T) == sizeof(U)); 133 }; 134 135 #define DEFINE_INTEGER_TYPES_CAST(To, From, Convert) \ 136 template<typename T, typename U> \ 137 struct IntegerTypes::Cast<T, U, true, \ 138 IntegerTypes::To, \ 139 IntegerTypes::From> \ 140 VALUE_OBJ_CLASS_SPEC \ 141 { \ 142 T operator()(U x) const { return Convert<T>(x); } \ 143 }; 144 145 DEFINE_INTEGER_TYPES_CAST(INTEGRAL, INTEGRAL, cast_integral) 146 DEFINE_INTEGER_TYPES_CAST(ENUM, INTEGRAL, cast_integral) 147 DEFINE_INTEGER_TYPES_CAST(INTEGRAL, ENUM, cast_integral) 148 DEFINE_INTEGER_TYPES_CAST(FLOAT, INTEGRAL, cast_floating_point) 149 DEFINE_INTEGER_TYPES_CAST(INTEGRAL, FLOAT, cast_floating_point) 150 DEFINE_INTEGER_TYPES_CAST(POINTER, INTEGRAL, reinterpret_cast) 151 DEFINE_INTEGER_TYPES_CAST(INTEGRAL, POINTER, reinterpret_cast) 152 153 #undef DEFINE_INTEGER_TYPES_CAST 154 155 template<typename T, typename U> 156 inline T IntegerTypes::cast(U x) { 157 return Cast<T, U>()(x); 158 } 159 160 #endif // SHARE_VM_METAPROGRAMMING_INTEGERTYPES_HPP