/* * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #ifndef SHARE_VM_METAPROGRAMMING_INTEGERTYPES_HPP #define SHARE_VM_METAPROGRAMMING_INTEGERTYPES_HPP #include "memory/allocation.hpp" #include "metaprogramming/enableIf.hpp" #include "metaprogramming/integralConstant.hpp" #include "metaprogramming/isFloatingPoint.hpp" #include "metaprogramming/isIntegral.hpp" #include "metaprogramming/isRegisteredEnum.hpp" #include "utilities/debug.hpp" class IntegerTypes : public AllStatic { public: // Return a value of type T with the same representation as x. // // T and U must be of the same size. // // At least one of T or U must be an integral type. The other must // be an integral, floating point, or pointer type. template static T cast(U x); // Support thin wrappers over primitive types. // If derived from TrueType, provides representational conversion // from T to some other type. When true, must provide // - Value: typedef for T. // - Decayed: typedef for decayed type. // - static Decayed decay(T x): return value of type Decayed with // the same representation as x. // - static T recover(Decayed x): return a value of type T with the // same representation as x. template struct Translate : public FalseType {}; private: template struct Cast; template static T cast_using_union(U x); }; // Return an object of type T with the same value representation as x. // // T and U must be of the same size. It is expected that one of T and // U is an integral type, and the other is an integral type, a // (registered) enum type, or a floating point type // // This implementation uses the "union trick", which seems to be the // best of a bad set of options. Though technically undefined // behavior, it is widely and well supported, producing good code. In // some cases, such as gcc, that support is explicitly documented. // // Using memcpy is the correct method, but some compilers produce // wretched code for that method, even at maximal optimization levels. // // Using static_cast is only possible for integral and enum types, not // for floating point types. And for integral and enum conversions, // static_cast has unspecified or implementation-defined behavior for // some cases. C++11 can be used to avoid most or all // of those unspecified or implementation-defined issues, though that // may require multi-step conversions. // // Using reinterpret_cast of references has undefined behavior for // many cases, and there is much less empirical basis for its use, as // compared to the union trick. template inline T IntegerTypes::cast_using_union(U x) { STATIC_ASSERT(sizeof(T) == sizeof(U)); union { T t; U u; }; u = x; return t; } ////////////////////////////////////////////////////////////////////////////// // cast(x) // // Cast // Give an informative error if the sizes differ. template struct IntegerTypes::Cast VALUE_OBJ_CLASS_SPEC { STATIC_ASSERT(sizeof(T) == sizeof(U)); }; // Conversion between integral types. template struct IntegerTypes::Cast< T, U, true, typename EnableIf::value && IsIntegral::value>::type> VALUE_OBJ_CLASS_SPEC { T operator()(U x) const { return cast_using_union(x); } }; // Convert an enum or floating point value to an integer value. template struct IntegerTypes::Cast< T, U, true, typename EnableIf::value && (IsRegisteredEnum::value || IsFloatingPoint::value)>::type> VALUE_OBJ_CLASS_SPEC { T operator()(U x) const { return cast_using_union(x); } }; // Convert an integer to an enum or floating point value. template struct IntegerTypes::Cast< T, U, true, typename EnableIf::value && (IsRegisteredEnum::value || IsFloatingPoint::value)>::type> VALUE_OBJ_CLASS_SPEC { T operator()(U x) const { return cast_using_union(x); } }; // Convert a pointer to an integral value. template struct IntegerTypes::Cast< T, U*, true, typename EnableIf::value>::type> VALUE_OBJ_CLASS_SPEC { T operator()(U* x) const { return reinterpret_cast(x); } }; // Convert an integral value to a pointer. template struct IntegerTypes::Cast< T*, U, true, typename EnableIf::value>::type> VALUE_OBJ_CLASS_SPEC { T* operator()(U x) const { return reinterpret_cast(x); } }; template inline T IntegerTypes::cast(U x) { return Cast()(x); } #endif // SHARE_VM_METAPROGRAMMING_INTEGERTYPES_HPP