//===--- hlsl_alias_intrinsics.h - HLSL alias definitions for intrinsics --===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _HLSL_HLSL_ALIAS_INTRINSICS_H_
#define _HLSL_HLSL_ALIAS_INTRINSICS_H_

namespace hlsl {

// Note: Functions in this file are sorted alphabetically, then grouped by base
// element type, and the element types are sorted by size, then singed integer,
// unsigned integer and floating point. Keeping this ordering consistent will
// help keep this file manageable as it grows.

#define _HLSL_BUILTIN_ALIAS(builtin)                                           \
  __attribute__((clang_builtin_alias(builtin)))
#define _HLSL_AVAILABILITY(platform, version)                                  \
  __attribute__((availability(platform, introduced = version)))
#define _HLSL_AVAILABILITY_STAGE(platform, version, stage)                     \
  __attribute__((                                                              \
      availability(platform, introduced = version, environment = stage)))

#ifdef __HLSL_ENABLE_16_BIT
#define _HLSL_16BIT_AVAILABILITY(platform, version, ...)                       \
  __attribute__((availability(platform, introduced = version)))
#define _HLSL_16BIT_AVAILABILITY_STAGE(platform, version, stage)               \
  __attribute__((                                                              \
      availability(platform, introduced = version, environment = stage)))
#define _HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()                         \
  _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
#else
#define _HLSL_16BIT_AVAILABILITY(platform, version, ...)                       \
  __VA_OPT__(_HLSL_AVAILABILITY(platform, __VA_ARGS__))
#define _HLSL_16BIT_AVAILABILITY_STAGE(environment, version, stage)
#define _HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
#endif

// Generated by clang-tblgen from HLSLIntrinsics.td (alias intrinsics).
#include "hlsl_alias_intrinsics_gen.inc"

//===----------------------------------------------------------------------===//
// mul builtins
//===----------------------------------------------------------------------===//

/// \fn R mul(X x, Y y)
/// \brief Multiplies x and y using matrix math.
/// \param x [in] The first input value. If x is a vector, it is treated as a
///   row vector.
/// \param y [in] The second input value. If y is a vector, it is treated as a
///   column vector.
///
/// The inner dimension x-columns and y-rows must be equal. The result has the
/// dimension x-rows x y-columns. When both x and y are vectors, the result is
/// a dot product (scalar). Scalar operands are multiplied element-wise.
///
/// This function supports 9 overloaded forms:
///   1. scalar * scalar -> scalar
///   2. scalar * vector -> vector
///   3. scalar * matrix -> matrix
///   4. vector * scalar -> vector
///   5. vector * vector -> scalar (dot product)
///   6. vector * matrix -> vector
///   7. matrix * scalar -> matrix
///   8. matrix * vector -> vector
///   9. matrix * matrix -> matrix

// Cases 1, 2, 3, 4, 5, and 7 of mul are defined in hlsl_intrinsics.h as
// header-only implementations because they are elementwise operations and dot
// products easily expressed in HLSL.

// Cases 6, 8, and 9 are defined below to alias the mul builtin so that they can
// be lowered to the llvm.matrix.multiply intrinsic which is not exposed
// directly to HLSL.

// Case 6: vector * matrix -> vector
template <int R, int C>
_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mul) vector<half, C> mul(vector<half, R>,
                                                            matrix<half, R, C>);

template <typename T, int R, int C>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mul)
vector<T, C> mul(vector<T, R>, matrix<T, R, C>);

// Case 8: matrix * vector -> vector
template <int R, int C>
_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mul) vector<half, R> mul(matrix<half, R, C>,
                                                            vector<half, C>);

template <typename T, int R, int C>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mul)
vector<T, R> mul(matrix<T, R, C>, vector<T, C>);

// Case 9: matrix * matrix -> matrix
template <int R, int K, int C>
_HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT()
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mul) matrix<half, R, C> mul(
    matrix<half, R, K>, matrix<half, K, C>);

template <typename T, int R, int K, int C>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mul)
matrix<T, R, C> mul(matrix<T, R, K>, matrix<T, K, C>);

//===----------------------------------------------------------------------===//
// transpose builtins
//===----------------------------------------------------------------------===//

/// \fn matrix<T, C, R> transpose(matrix<T, R, C> x)
/// \brief Returns the transpose of the input matrix.
/// \param x [in] The input matrix.

template <int R, int C>
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_transpose) matrix<half, C, R> transpose(
    matrix<half, R, C>);

template <typename T, int R, int C>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_transpose)
matrix<T, C, R> transpose(matrix<T, R, C>);

//===----------------------------------------------------------------------===//
// select builtins
//===----------------------------------------------------------------------===//

/// \fn T select(bool Cond, T TrueVal, T FalseVal)
/// \brief ternary operator.
/// \param Cond The Condition input value.
/// \param TrueVal The Value returned if Cond is true.
/// \param FalseVal The Value returned if Cond is false.

template <typename T>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select)
T select(bool, T, T);

/// \fn vector<T,Sz> select(vector<bool,Sz> Conds, vector<T,Sz> TrueVals,
///                         vector<T,Sz> FalseVals)
/// \brief ternary operator for vectors. All vectors must be the same size.
/// \param Conds The Condition input values.
/// \param TrueVals The vector values are chosen from when conditions are true.
/// \param FalseVals The vector values are chosen from when conditions are
/// false.

template <typename T>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select)
vector<T, 2> select(vector<bool, 2>, vector<T, 2>, vector<T, 2>);

template <typename T>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select)
vector<T, 3> select(vector<bool, 3>, vector<T, 3>, vector<T, 3>);

template <typename T>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select)
vector<T, 4> select(vector<bool, 4>, vector<T, 4>, vector<T, 4>);

/// \fn vector<T,Sz> select(vector<bool,Sz> Conds, T TrueVal,
///                         vector<T,Sz> FalseVals)
/// \brief ternary operator for vectors. All vectors must be the same size.
/// \param Conds The Condition input values.
/// \param TrueVal The scalar value to splat from when conditions are true.
/// \param FalseVals The vector values are chosen from when conditions are
/// false.

template <typename T>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select)
vector<T, 2> select(vector<bool, 2>, T, vector<T, 2>);

template <typename T>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select)
vector<T, 3> select(vector<bool, 3>, T, vector<T, 3>);

template <typename T>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select)
vector<T, 4> select(vector<bool, 4>, T, vector<T, 4>);

/// \fn vector<T,Sz> select(vector<bool,Sz> Conds, vector<T,Sz> TrueVals,
///                         T FalseVal)
/// \brief ternary operator for vectors. All vectors must be the same size.
/// \param Conds The Condition input values.
/// \param TrueVals The vector values are chosen from when conditions are true.
/// \param FalseVal The scalar value to splat from when conditions are false.

template <typename T>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select)
vector<T, 2> select(vector<bool, 2>, vector<T, 2>, T);

template <typename T>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select)
vector<T, 3> select(vector<bool, 3>, vector<T, 3>, T);

template <typename T>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select)
vector<T, 4> select(vector<bool, 4>, vector<T, 4>, T);

/// \fn vector<T,Sz> select(vector<bool,Sz> Conds, vector<T,Sz> TrueVals,
///                         T FalseVal)
/// \brief ternary operator for vectors. All vectors must be the same size.
/// \param Conds The Condition input values.
/// \param TrueVal The scalar value to splat from when conditions are true.
/// \param FalseVal The scalar value to splat from when conditions are false.

template <typename T>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select)
__detail::enable_if_t<__detail::is_arithmetic<T>::Value, vector<T, 2>> select(
    vector<bool, 2>, T, T);

template <typename T>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select)
__detail::enable_if_t<__detail::is_arithmetic<T>::Value, vector<T, 3>> select(
    vector<bool, 3>, T, T);

template <typename T>
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_select)
__detail::enable_if_t<__detail::is_arithmetic<T>::Value, vector<T, 4>> select(
    vector<bool, 4>, T, T);

} // namespace hlsl
#endif //_HLSL_HLSL_ALIAS_INTRINSICS_H_