// Multiplexer utilities
// Copyright (C) 2020-2024 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
//
// GCC 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
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3.  If not see
// <http://www.gnu.org/licenses/>.

#ifndef GCC_MUX_UTILS_H
#define GCC_MUX_UTILS_H 1

// A class that stores a choice "A or B", where A has type T1 * and B has
// type T2 *.  Both T1 and T2 must have an alignment greater than 1, since
// the low bit is used to identify B over A.  T1 and T2 can be the same.
//
// A can be a null pointer but B cannot.
//
// Barring the requirement that B must be nonnull, using the class is
// equivalent to using:
//
//     union { T1 *A; T2 *B; };
//
// and having a separate tag bit to indicate which alternative is active.
// However, using this class can have two advantages over a union:
//
// - It avoids the need to find somewhere to store the tag bit.
//
// - The compiler is aware that B cannot be null, which can make checks
//   of the form:
//
//       if (auto *B = mux.dyn_cast<T2 *> ())
//
//   more efficient.  With a union-based representation, the dyn_cast
//   check could fail either because MUX is an A or because MUX is a
//   null B, both of which require a run-time test.  With a pointer_mux,
//   only a check for MUX being A is needed.
template<typename T1, typename T2 = T1>
class pointer_mux
{
public:
  // Return an A pointer with the given value.
  static pointer_mux first (T1 *);

  // Return a B pointer with the given (nonnull) value.
  static pointer_mux second (T2 *);

  pointer_mux () = default;

  // Create a null A pointer.
  pointer_mux (std::nullptr_t) : m_ptr (nullptr) {}

  // Create an A or B pointer with the given value.  This is only valid
  // if T1 and T2 are distinct and if T can be resolved to exactly one
  // of them.
  template<typename T,
	   typename Enable = typename
	     std::enable_if<std::is_convertible<T *, T1 *>::value
			    != std::is_convertible<T *, T2 *>::value>::type>
  pointer_mux (T *ptr);

  // Return true unless the pointer is a null A pointer.
  explicit operator bool () const { return m_ptr; }

  // Assign A and B pointers respectively.
  void set_first (T1 *ptr) { *this = first (ptr); }
  void set_second (T2 *ptr) { *this = second (ptr); }

  // Return true if the pointer is an A pointer.
  bool is_first () const { return !(uintptr_t (m_ptr) & 1); }

  // Return true if the pointer is a B pointer.
  bool is_second () const { return uintptr_t (m_ptr) & 1; }

  // Return the contents of the pointer, given that it is known to be
  // an A pointer.
  T1 *known_first () const { return reinterpret_cast<T1 *> (m_ptr); }

  // Return the contents of the pointer, given that it is known to be
  // a B pointer.
  T2 *known_second () const { return reinterpret_cast<T2 *> (m_ptr - 1); }

  // If the pointer is an A pointer, return its contents, otherwise
  // return null.  Thus a null return can mean that the pointer is
  // either a null A pointer or a B pointer.
  //
  // If all A pointers are nonnull, it is more efficient to use:
  //
  //    if (ptr.is_first ())
  //      ...use ptr.known_first ()...
  //
  // over:
  //
  //    if (T1 *a = ptr.first_or_null ())
  //      ...use a...
  T1 *first_or_null () const;

  // If the pointer is a B pointer, return its contents, otherwise
  // return null.  Using:
  //
  //    if (T1 *b = ptr.second_or_null ())
  //      ...use b...
  //
  // should be at least as efficient as:
  //
  //    if (ptr.is_second ())
  //      ...use ptr.known_second ()...
  T2 *second_or_null () const;

  bool operator == (const pointer_mux &pm) const { return m_ptr == pm.m_ptr; }

  bool operator != (const pointer_mux &pm) const { return m_ptr != pm.m_ptr; }

  // Return true if the pointer is a T.
  //
  // This is only valid if T1 and T2 are distinct and if T can be
  // resolved to exactly one of them.  The condition is checked using
  // a static assertion rather than SFINAE because it gives a clearer
  // error message.
  template<typename T>
  bool is_a () const;

  // Assert that the pointer is a T and return it as such.  See is_a
  // for the restrictions on T.
  template<typename T>
  T as_a () const;

  // If the pointer is a T, return it as such, otherwise return null.
  // See is_a for the restrictions on T.
  template<typename T>
  T dyn_cast () const;

private:
  pointer_mux (char *ptr) : m_ptr (ptr) {}

  // Points to the first byte of an object for A pointers or the second
  // byte of an object for B pointers.  Using a pointer rather than a
  // uintptr_t tells the compiler that second () can never return null,
  // and that second_or_null () is only null if is_first ().
  char *m_ptr;
};

template<typename T1, typename T2>
inline pointer_mux<T1, T2>
pointer_mux<T1, T2>::first (T1 *ptr)
{
  gcc_checking_assert (!(uintptr_t (ptr) & 1));
  return reinterpret_cast<char *> (ptr);
}

template<typename T1, typename T2>
inline pointer_mux<T1, T2>
pointer_mux<T1, T2>::second (T2 *ptr)
{
  gcc_checking_assert (ptr && !(uintptr_t (ptr) & 1));
  return reinterpret_cast<char *> (ptr) + 1;
}

template<typename T1, typename T2>
template<typename T, typename Enable>
inline pointer_mux<T1, T2>::pointer_mux (T *ptr)
  : m_ptr (reinterpret_cast<char *> (ptr))
{
  if (std::is_convertible<T *, T2 *>::value)
    {
      gcc_checking_assert (m_ptr);
      m_ptr += 1;
    }
}

template<typename T1, typename T2>
inline T1 *
pointer_mux<T1, T2>::first_or_null () const
{
  return is_first () ? known_first () : nullptr;
}

template<typename T1, typename T2>
inline T2 *
pointer_mux<T1, T2>::second_or_null () const
{
  // Micro optimization that's effective as of GCC 11: compute the value
  // of the second pointer as an integer and test that, so that the integer
  // result can be reused as the pointer and so that all computation can
  // happen before a branch on null.  This reduces the number of branches
  // needed for loops.
  return (uintptr_t (m_ptr) - 1) & 1 ? nullptr : known_second ();
}

template<typename T1, typename T2>
template<typename T>
inline bool
pointer_mux<T1, T2>::is_a () const
{
  static_assert (std::is_convertible<T1 *, T>::value
		 != std::is_convertible<T2 *, T>::value,
		 "Ambiguous pointer type");
  if (std::is_convertible<T2 *, T>::value)
    return is_second ();
  else
    return is_first ();
}

template<typename T1, typename T2>
template<typename T>
inline T
pointer_mux<T1, T2>::as_a () const
{
  static_assert (std::is_convertible<T1 *, T>::value
		 != std::is_convertible<T2 *, T>::value,
		 "Ambiguous pointer type");
  if (std::is_convertible<T2 *, T>::value)
    {
      gcc_checking_assert (is_second ());
      return reinterpret_cast<T> (m_ptr - 1);
    }
  else
    {
      gcc_checking_assert (is_first ());
      return reinterpret_cast<T> (m_ptr);
    }
}

template<typename T1, typename T2>
template<typename T>
inline T
pointer_mux<T1, T2>::dyn_cast () const
{
  static_assert (std::is_convertible<T1 *, T>::value
		 != std::is_convertible<T2 *, T>::value,
		 "Ambiguous pointer type");
  if (std::is_convertible<T2 *, T>::value)
    {
      if (is_second ())
	return reinterpret_cast<T> (m_ptr - 1);
    }
  else
    {
      if (is_first ())
	return reinterpret_cast<T> (m_ptr);
    }
  return nullptr;
}

#endif
