// Copyright 2026 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

////////////////////////////////////////////////////////////////////////////////
// File generated by 'tools/src/cmd/gen' using the template:
//   src/tint/lang/core/enums.h.tmpl
//
// To regenerate run: './tools/run gen'
//
//                       Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////

#ifndef SRC_TINT_LANG_CORE_ENUMS_H_
#define SRC_TINT_LANG_CORE_ENUMS_H_

// clang-format off

#include <cstdint>

#include "src/tint/utils/reflection/reflection.h"
#include "src/tint/utils/rtti/traits.h"

namespace tint::core {

/// Access of a given pointer.
enum class Access : uint8_t {
    kUndefined,
    kRead,
    kReadWrite,
    kWrite,
};

/// @param value the enum value
/// @returns the string for the given enum value
std::string_view ToString(Access value);

/// @param out the stream to write to
/// @param value the Access
/// @returns @p out so calls can be chained
template <typename STREAM>
    requires(traits::IsOStream<STREAM>)
auto& operator<<(STREAM& out, Access value) {
    return out << ToString(value);
}

/// ParseAccess parses a Access from a string.
/// @param str the string to parse
/// @returns the parsed enum, or Access::kUndefined if the string could not be parsed.
Access ParseAccess(std::string_view str);

constexpr std::string_view kAccessStrings[] = {
    "read",
    "read_write",
    "write",
};

/// Address space of a given pointer.
enum class AddressSpace : uint8_t {
    kUndefined,
    kIn,  // Tint-internal enum entry - not parsed
    kOut,  // Tint-internal enum entry - not parsed
    kFunction,
    kHandle,  // Tint-internal enum entry - not parsed
    kImmediate,
    kPixelLocal,
    kPrivate,
    kStorage,
    kUniform,
    kWorkgroup,
};

/// @param value the enum value
/// @returns the string for the given enum value
std::string_view ToString(AddressSpace value);

/// @param out the stream to write to
/// @param value the AddressSpace
/// @returns @p out so calls can be chained
template <typename STREAM>
    requires(traits::IsOStream<STREAM>)
auto& operator<<(STREAM& out, AddressSpace value) {
    return out << ToString(value);
}

/// ParseAddressSpace parses a AddressSpace from a string.
/// @param str the string to parse
/// @returns the parsed enum, or AddressSpace::kUndefined if the string could not be parsed.
AddressSpace ParseAddressSpace(std::string_view str);

constexpr std::string_view kAddressSpaceStrings[] = {
    "function",
    "immediate",
    "pixel_local",
    "private",
    "storage",
    "uniform",
    "workgroup",
};

/// @returns true if the AddressSpace is host-shareable
/// @param address_space the AddressSpace
/// @see https://gpuweb.github.io/gpuweb/wgsl.html#host-shareable
inline bool IsHostShareable(AddressSpace address_space) {
    return address_space == AddressSpace::kUniform ||
           address_space == AddressSpace::kStorage ||
           address_space == AddressSpace::kImmediate;
}

/// The interpolation sampling.
enum class InterpolationSampling : uint8_t {
    kUndefined,
    kCenter,
    kCentroid,
    kEither,
    kFirst,
    kSample,
};

/// @param value the enum value
/// @returns the string for the given enum value
std::string_view ToString(InterpolationSampling value);

/// @param out the stream to write to
/// @param value the InterpolationSampling
/// @returns @p out so calls can be chained
template <typename STREAM>
    requires(traits::IsOStream<STREAM>)
auto& operator<<(STREAM& out, InterpolationSampling value) {
    return out << ToString(value);
}

/// ParseInterpolationSampling parses a InterpolationSampling from a string.
/// @param str the string to parse
/// @returns the parsed enum, or InterpolationSampling::kUndefined if the string could not be parsed.
InterpolationSampling ParseInterpolationSampling(std::string_view str);

constexpr std::string_view kInterpolationSamplingStrings[] = {
    "center",
    "centroid",
    "either",
    "first",
    "sample",
};

/// The interpolation type.
enum class InterpolationType : uint8_t {
    kUndefined,
    kFlat,
    kLinear,
    kPerspective,
};

/// @param value the enum value
/// @returns the string for the given enum value
std::string_view ToString(InterpolationType value);

/// @param out the stream to write to
/// @param value the InterpolationType
/// @returns @p out so calls can be chained
template <typename STREAM>
    requires(traits::IsOStream<STREAM>)
auto& operator<<(STREAM& out, InterpolationType value) {
    return out << ToString(value);
}

/// ParseInterpolationType parses a InterpolationType from a string.
/// @param str the string to parse
/// @returns the parsed enum, or InterpolationType::kUndefined if the string could not be parsed.
InterpolationType ParseInterpolationType(std::string_view str);

constexpr std::string_view kInterpolationTypeStrings[] = {
    "flat",
    "linear",
    "perspective",
};

/// The majorness of a matrix.
enum class Majorness : uint8_t {
    kUndefined,
    kColMajor,
    kRowMajor,
};

/// @param value the enum value
/// @returns the string for the given enum value
std::string_view ToString(Majorness value);

/// @param out the stream to write to
/// @param value the Majorness
/// @returns @p out so calls can be chained
template <typename STREAM>
    requires(traits::IsOStream<STREAM>)
auto& operator<<(STREAM& out, Majorness value) {
    return out << ToString(value);
}

/// ParseMajorness parses a Majorness from a string.
/// @param str the string to parse
/// @returns the parsed enum, or Majorness::kUndefined if the string could not be parsed.
Majorness ParseMajorness(std::string_view str);

constexpr std::string_view kMajornessStrings[] = {
    "col_major",
    "row_major",
};

/// The kind of subgroup matrix.
enum class SubgroupMatrixKind : uint8_t {
    kUndefined,
    kLeft,
    kResult,
    kRight,
};

/// @param value the enum value
/// @returns the string for the given enum value
std::string_view ToString(SubgroupMatrixKind value);

/// @param out the stream to write to
/// @param value the SubgroupMatrixKind
/// @returns @p out so calls can be chained
template <typename STREAM>
    requires(traits::IsOStream<STREAM>)
auto& operator<<(STREAM& out, SubgroupMatrixKind value) {
    return out << ToString(value);
}

/// ParseSubgroupMatrixKind parses a SubgroupMatrixKind from a string.
/// @param str the string to parse
/// @returns the parsed enum, or SubgroupMatrixKind::kUndefined if the string could not be parsed.
SubgroupMatrixKind ParseSubgroupMatrixKind(std::string_view str);

constexpr std::string_view kSubgroupMatrixKindStrings[] = {
    "left",
    "result",
    "right",
};

/// Enumerator of texel formats
enum class TexelFormat : uint8_t {
    kUndefined,
    kBgra8Unorm,
    kR16Float,
    kR16Sint,
    kR16Snorm,
    kR16Uint,
    kR16Unorm,
    kR32Float,
    kR32Sint,
    kR32Uint,
    kR8Sint,
    kR8Snorm,
    kR8Uint,
    kR8Unorm,
    kRg11B10Ufloat,
    kRg16Float,
    kRg16Sint,
    kRg16Snorm,
    kRg16Uint,
    kRg16Unorm,
    kRg32Float,
    kRg32Sint,
    kRg32Uint,
    kRg8Sint,
    kRg8Snorm,
    kRg8Uint,
    kRg8Unorm,
    kRgb10A2Uint,
    kRgb10A2Unorm,
    kRgba16Float,
    kRgba16Sint,
    kRgba16Snorm,
    kRgba16Uint,
    kRgba16Unorm,
    kRgba32Float,
    kRgba32Sint,
    kRgba32Uint,
    kRgba8Sint,
    kRgba8Snorm,
    kRgba8Uint,
    kRgba8Unorm,
};

/// @param value the enum value
/// @returns the string for the given enum value
std::string_view ToString(TexelFormat value);

/// @param out the stream to write to
/// @param value the TexelFormat
/// @returns @p out so calls can be chained
template <typename STREAM>
    requires(traits::IsOStream<STREAM>)
auto& operator<<(STREAM& out, TexelFormat value) {
    return out << ToString(value);
}

/// ParseTexelFormat parses a TexelFormat from a string.
/// @param str the string to parse
/// @returns the parsed enum, or TexelFormat::kUndefined if the string could not be parsed.
TexelFormat ParseTexelFormat(std::string_view str);

constexpr std::string_view kTexelFormatStrings[] = {
    "bgra8unorm",
    "r16float",
    "r16sint",
    "r16snorm",
    "r16uint",
    "r16unorm",
    "r32float",
    "r32sint",
    "r32uint",
    "r8sint",
    "r8snorm",
    "r8uint",
    "r8unorm",
    "rg11b10ufloat",
    "rg16float",
    "rg16sint",
    "rg16snorm",
    "rg16uint",
    "rg16unorm",
    "rg32float",
    "rg32sint",
    "rg32uint",
    "rg8sint",
    "rg8snorm",
    "rg8uint",
    "rg8unorm",
    "rgb10a2uint",
    "rgb10a2unorm",
    "rgba16float",
    "rgba16sint",
    "rgba16snorm",
    "rgba16uint",
    "rgba16unorm",
    "rgba32float",
    "rgba32sint",
    "rgba32uint",
    "rgba8sint",
    "rgba8snorm",
    "rgba8uint",
    "rgba8unorm",
};

/// An enumerator of builtin types.
enum class BuiltinType : uint8_t {
    kUndefined,
    kAtomicCompareExchangeResultI32,
    kAtomicCompareExchangeResultU32,
    kFrexpResultAbstract,
    kFrexpResultF16,
    kFrexpResultF32,
    kFrexpResultVec2Abstract,
    kFrexpResultVec2F16,
    kFrexpResultVec2F32,
    kFrexpResultVec3Abstract,
    kFrexpResultVec3F16,
    kFrexpResultVec3F32,
    kFrexpResultVec4Abstract,
    kFrexpResultVec4F16,
    kFrexpResultVec4F32,
    kModfResultAbstract,
    kModfResultF16,
    kModfResultF32,
    kModfResultVec2Abstract,
    kModfResultVec2F16,
    kModfResultVec2F32,
    kModfResultVec3Abstract,
    kModfResultVec3F16,
    kModfResultVec3F32,
    kModfResultVec4Abstract,
    kModfResultVec4F16,
    kModfResultVec4F32,
    kArray,
    kAtomic,
    kBindingArray,
    kBool,
    kBuffer,
    kF16,
    kF32,
    kI32,
    kI8,
    kInputAttachment,
    kMat2X2,
    kMat2X2F,
    kMat2X2H,
    kMat2X3,
    kMat2X3F,
    kMat2X3H,
    kMat2X4,
    kMat2X4F,
    kMat2X4H,
    kMat3X2,
    kMat3X2F,
    kMat3X2H,
    kMat3X3,
    kMat3X3F,
    kMat3X3H,
    kMat3X4,
    kMat3X4F,
    kMat3X4H,
    kMat4X2,
    kMat4X2F,
    kMat4X2H,
    kMat4X3,
    kMat4X3F,
    kMat4X3H,
    kMat4X4,
    kMat4X4F,
    kMat4X4H,
    kPtr,
    kSampler,
    kSamplerComparison,
    kSubgroupMatrixLeft,
    kSubgroupMatrixResult,
    kSubgroupMatrixRight,
    kTexelBuffer,
    kTexture1D,
    kTexture2D,
    kTexture2DArray,
    kTexture3D,
    kTextureCube,
    kTextureCubeArray,
    kTextureDepth2D,
    kTextureDepth2DArray,
    kTextureDepthCube,
    kTextureDepthCubeArray,
    kTextureDepthMultisampled2D,
    kTextureExternal,
    kTextureMultisampled2D,
    kTextureStorage1D,
    kTextureStorage2D,
    kTextureStorage2DArray,
    kTextureStorage3D,
    kU16,
    kU32,
    kU8,
    kVec2,
    kVec2F,
    kVec2H,
    kVec2I,
    kVec2U,
    kVec3,
    kVec3F,
    kVec3H,
    kVec3I,
    kVec3U,
    kVec4,
    kVec4F,
    kVec4H,
    kVec4I,
    kVec4U,
};

/// @param value the enum value
/// @returns the string for the given enum value
std::string_view ToString(BuiltinType value);

/// @param out the stream to write to
/// @param value the BuiltinType
/// @returns @p out so calls can be chained
template <typename STREAM>
    requires(traits::IsOStream<STREAM>)
auto& operator<<(STREAM& out, BuiltinType value) {
    return out << ToString(value);
}

/// ParseBuiltinType parses a BuiltinType from a string.
/// @param str the string to parse
/// @returns the parsed enum, or BuiltinType::kUndefined if the string could not be parsed.
BuiltinType ParseBuiltinType(std::string_view str);

constexpr std::string_view kBuiltinTypeStrings[] = {
    "__atomic_compare_exchange_result_i32",
    "__atomic_compare_exchange_result_u32",
    "__frexp_result_abstract",
    "__frexp_result_f16",
    "__frexp_result_f32",
    "__frexp_result_vec2_abstract",
    "__frexp_result_vec2_f16",
    "__frexp_result_vec2_f32",
    "__frexp_result_vec3_abstract",
    "__frexp_result_vec3_f16",
    "__frexp_result_vec3_f32",
    "__frexp_result_vec4_abstract",
    "__frexp_result_vec4_f16",
    "__frexp_result_vec4_f32",
    "__modf_result_abstract",
    "__modf_result_f16",
    "__modf_result_f32",
    "__modf_result_vec2_abstract",
    "__modf_result_vec2_f16",
    "__modf_result_vec2_f32",
    "__modf_result_vec3_abstract",
    "__modf_result_vec3_f16",
    "__modf_result_vec3_f32",
    "__modf_result_vec4_abstract",
    "__modf_result_vec4_f16",
    "__modf_result_vec4_f32",
    "array",
    "atomic",
    "binding_array",
    "bool",
    "buffer",
    "f16",
    "f32",
    "i32",
    "i8",
    "input_attachment",
    "mat2x2",
    "mat2x2f",
    "mat2x2h",
    "mat2x3",
    "mat2x3f",
    "mat2x3h",
    "mat2x4",
    "mat2x4f",
    "mat2x4h",
    "mat3x2",
    "mat3x2f",
    "mat3x2h",
    "mat3x3",
    "mat3x3f",
    "mat3x3h",
    "mat3x4",
    "mat3x4f",
    "mat3x4h",
    "mat4x2",
    "mat4x2f",
    "mat4x2h",
    "mat4x3",
    "mat4x3f",
    "mat4x3h",
    "mat4x4",
    "mat4x4f",
    "mat4x4h",
    "ptr",
    "sampler",
    "sampler_comparison",
    "subgroup_matrix_left",
    "subgroup_matrix_result",
    "subgroup_matrix_right",
    "texel_buffer",
    "texture_1d",
    "texture_2d",
    "texture_2d_array",
    "texture_3d",
    "texture_cube",
    "texture_cube_array",
    "texture_depth_2d",
    "texture_depth_2d_array",
    "texture_depth_cube",
    "texture_depth_cube_array",
    "texture_depth_multisampled_2d",
    "texture_external",
    "texture_multisampled_2d",
    "texture_storage_1d",
    "texture_storage_2d",
    "texture_storage_2d_array",
    "texture_storage_3d",
    "u16",
    "u32",
    "u8",
    "vec2",
    "vec2f",
    "vec2h",
    "vec2i",
    "vec2u",
    "vec3",
    "vec3f",
    "vec3h",
    "vec3i",
    "vec3u",
    "vec4",
    "vec4f",
    "vec4h",
    "vec4i",
    "vec4u",
};

/// Builtin value defined with `@builtin(<name>)`.
enum class BuiltinValue : uint8_t {
    kUndefined,
    kCullDistance,  // Tint-internal enum entry - not parsed
    kPointSize,  // Tint-internal enum entry - not parsed
    kBarycentricCoord,
    kClipDistances,
    kFragDepth,
    kFrontFacing,
    kGlobalInvocationId,
    kGlobalInvocationIndex,
    kInstanceIndex,
    kLocalInvocationId,
    kLocalInvocationIndex,
    kNumSubgroups,
    kNumWorkgroups,
    kPosition,
    kPrimitiveIndex,
    kSampleIndex,
    kSampleMask,
    kSubgroupId,
    kSubgroupInvocationId,
    kSubgroupSize,
    kVertexIndex,
    kWorkgroupId,
    kWorkgroupIndex,
};

/// @param value the enum value
/// @returns the string for the given enum value
std::string_view ToString(BuiltinValue value);

/// @param out the stream to write to
/// @param value the BuiltinValue
/// @returns @p out so calls can be chained
template <typename STREAM>
    requires(traits::IsOStream<STREAM>)
auto& operator<<(STREAM& out, BuiltinValue value) {
    return out << ToString(value);
}

/// ParseBuiltinValue parses a BuiltinValue from a string.
/// @param str the string to parse
/// @returns the parsed enum, or BuiltinValue::kUndefined if the string could not be parsed.
BuiltinValue ParseBuiltinValue(std::string_view str);

constexpr std::string_view kBuiltinValueStrings[] = {
    "barycentric_coord",
    "clip_distances",
    "frag_depth",
    "front_facing",
    "global_invocation_id",
    "global_invocation_index",
    "instance_index",
    "local_invocation_id",
    "local_invocation_index",
    "num_subgroups",
    "num_workgroups",
    "position",
    "primitive_index",
    "sample_index",
    "sample_mask",
    "subgroup_id",
    "subgroup_invocation_id",
    "subgroup_size",
    "vertex_index",
    "workgroup_id",
    "workgroup_index",
};

/// Builtin depth mode defined with `@builtin(<name>, <depth_mode>)`.
enum class BuiltinDepthMode : uint8_t {
    kUndefined,
    kGreater,
    kLess,
};

/// @param value the enum value
/// @returns the string for the given enum value
std::string_view ToString(BuiltinDepthMode value);

/// @param out the stream to write to
/// @param value the BuiltinDepthMode
/// @returns @p out so calls can be chained
template <typename STREAM>
    requires(traits::IsOStream<STREAM>)
auto& operator<<(STREAM& out, BuiltinDepthMode value) {
    return out << ToString(value);
}

/// ParseBuiltinDepthMode parses a BuiltinDepthMode from a string.
/// @param str the string to parse
/// @returns the parsed enum, or BuiltinDepthMode::kUndefined if the string could not be parsed.
BuiltinDepthMode ParseBuiltinDepthMode(std::string_view str);

constexpr std::string_view kBuiltinDepthModeStrings[] = {
    "greater",
    "less",
};

/// Address space of a given pointer.
enum class Attribute : uint8_t {
    kUndefined,
    kAlign,
    kBinding,
    kBlendSrc,
    kBuiltin,
    kColor,
    kCompute,
    kDiagnostic,
    kFragment,
    kGroup,
    kId,
    kInputAttachmentIndex,
    kInterpolate,
    kInvariant,
    kLocation,
    kMustUse,
    kSize,
    kSubgroupSize,
    kVertex,
    kWorkgroupSize,
};

/// @param value the enum value
/// @returns the string for the given enum value
std::string_view ToString(Attribute value);

/// @param out the stream to write to
/// @param value the Attribute
/// @returns @p out so calls can be chained
template <typename STREAM>
    requires(traits::IsOStream<STREAM>)
auto& operator<<(STREAM& out, Attribute value) {
    return out << ToString(value);
}

/// ParseAttribute parses a Attribute from a string.
/// @param str the string to parse
/// @returns the parsed enum, or Attribute::kUndefined if the string could not be parsed.
Attribute ParseAttribute(std::string_view str);

constexpr std::string_view kAttributeStrings[] = {
    "align",
    "binding",
    "blend_src",
    "builtin",
    "color",
    "compute",
    "diagnostic",
    "fragment",
    "group",
    "id",
    "input_attachment_index",
    "interpolate",
    "invariant",
    "location",
    "must_use",
    "size",
    "subgroup_size",
    "vertex",
    "workgroup_size",
};

/// ParameterUsage is extra metadata for identifying a parameter based on its
/// overload position
enum class ParameterUsage : uint8_t {
    kArrayIndex,
    kBase,
    kBias,
    kBits,
    kColMajor,
    kCompareValue,
    kComponent,
    kConstOffset,
    kCoords,
    kCount,
    kDdx,
    kDdy,
    kDelta,
    kDepth,
    kDepthRef,
    kDir,
    kDref,
    kE,
    kElements,
    kExp,
    kGroupOperation,
    kHeight,
    kI,
    kId,
    kImage,
    kImageOperands,
    kIndex,
    kInputAttachment,
    kInsert,
    kLevel,
    kLocation,
    kLod,
    kM,
    kMask,
    kNumLevels,
    kOffset,
    kOriginalValue,
    kRefz,
    kResult,
    kS,
    kSample,
    kSampleIndex,
    kSampler,
    kSamples,
    kScope,
    kSourceLaneIndex,
    kStride,
    kTexel,
    kTexture,
    kValue,
    kW,
    kWidth,
    kX,
    kXy,
    kXyz,
    kY,
    kYz,
    kZ,
    kZw,
    kZyw,
    kNone,
};

/// @param value the enum value
/// @returns the string for the given enum value
std::string_view ToString(ParameterUsage value);

/// @param out the stream to write to
/// @param value the ParameterUsage
/// @returns @p out so calls can be chained
template <typename STREAM>
    requires(traits::IsOStream<STREAM>)
auto& operator<<(STREAM& out, ParameterUsage value) {
    return out << ToString(value);
}

/// Enumerator of all builtin functions
enum class BuiltinFn : uint8_t {
    kAbs,
    kAcos,
    kAcosh,
    kAll,
    kAny,
    kArrayLength,
    kAsin,
    kAsinh,
    kAtan,
    kAtan2,
    kAtanh,
    kBitcast,
    kCeil,
    kClamp,
    kCos,
    kCosh,
    kCountLeadingZeros,
    kCountOneBits,
    kCountTrailingZeros,
    kCross,
    kDegrees,
    kDeterminant,
    kDistance,
    kDot,
    kDot4I8Packed,
    kDot4U8Packed,
    kDpdx,
    kDpdxCoarse,
    kDpdxFine,
    kDpdy,
    kDpdyCoarse,
    kDpdyFine,
    kExp,
    kExp2,
    kExtractBits,
    kFaceForward,
    kFirstLeadingBit,
    kFirstTrailingBit,
    kFloor,
    kFma,
    kFract,
    kFrexp,
    kFwidth,
    kFwidthCoarse,
    kFwidthFine,
    kInsertBits,
    kInverseSqrt,
    kLdexp,
    kLength,
    kLog,
    kLog2,
    kMax,
    kMin,
    kMix,
    kModf,
    kNormalize,
    kPack2X16Float,
    kPack2X16Snorm,
    kPack2X16Unorm,
    kPack4X8Snorm,
    kPack4X8Unorm,
    kPack4XI8,
    kPack4XU8,
    kPack4XI8Clamp,
    kPack4XU8Clamp,
    kPow,
    kQuantizeToF16,
    kRadians,
    kReflect,
    kRefract,
    kReverseBits,
    kRound,
    kSaturate,
    kSelect,
    kSign,
    kSin,
    kSinh,
    kSmoothstep,
    kSqrt,
    kStep,
    kTan,
    kTanh,
    kTranspose,
    kTrunc,
    kUnpack2X16Float,
    kUnpack2X16Snorm,
    kUnpack2X16Unorm,
    kUnpack4X8Snorm,
    kUnpack4X8Unorm,
    kUnpack4XI8,
    kUnpack4XU8,
    kAddSat,
    kStorageBarrier,
    kWorkgroupBarrier,
    kTextureBarrier,
    kTextureDimensions,
    kTextureGather,
    kTextureGatherCompare,
    kTextureNumLayers,
    kTextureNumLevels,
    kTextureNumSamples,
    kTextureSample,
    kTextureSampleBias,
    kTextureSampleCompare,
    kTextureSampleCompareLevel,
    kTextureSampleGrad,
    kTextureSampleLevel,
    kTextureSampleBaseClampToEdge,
    kTextureStore,
    kTextureLoad,
    kInputAttachmentLoad,
    kAtomicLoad,
    kAtomicStore,
    kAtomicAdd,
    kAtomicSub,
    kAtomicMax,
    kAtomicMin,
    kAtomicAnd,
    kAtomicOr,
    kAtomicXor,
    kAtomicExchange,
    kAtomicCompareExchangeWeak,
    kAtomicStoreMax,
    kAtomicStoreMin,
    kSubgroupBallot,
    kSubgroupElect,
    kSubgroupBroadcast,
    kSubgroupBroadcastFirst,
    kSubgroupShuffle,
    kSubgroupShuffleXor,
    kSubgroupShuffleUp,
    kSubgroupShuffleDown,
    kSubgroupAdd,
    kSubgroupInclusiveAdd,
    kSubgroupExclusiveAdd,
    kSubgroupMul,
    kSubgroupInclusiveMul,
    kSubgroupExclusiveMul,
    kSubgroupAnd,
    kSubgroupOr,
    kSubgroupXor,
    kSubgroupMin,
    kSubgroupMax,
    kSubgroupAll,
    kSubgroupAny,
    kQuadBroadcast,
    kQuadSwapX,
    kQuadSwapY,
    kQuadSwapDiagonal,
    kSubgroupMatrixLoad,
    kSubgroupMatrixStore,
    kSubgroupMatrixMultiply,
    kSubgroupMatrixMultiplyAccumulate,
    kSubgroupMatrixScalarAdd,
    kSubgroupMatrixScalarSubtract,
    kSubgroupMatrixScalarMultiply,
    kBufferView,
    kBufferArrayView,
    kBufferLength,
    kPrint,
    kHasResource,
    kGetResource,
    kNone,
};

/// Matches the BuiltinFn by name
/// @param name the builtin name to parse
/// @returns the parsed BuiltinFn, or BuiltinFn::kNone if `name` did not
/// match any builtin function.
BuiltinFn ParseBuiltinFn(std::string_view name);

/// @returns the name of the builtin function type. The spelling, including
/// case, matches the name in the WGSL spec.
const char* str(BuiltinFn i);

/// Emits the name of the builtin function type. The spelling, including case,
/// matches the name in the WGSL spec.
template <typename STREAM>
    requires(traits::IsOStream<STREAM>)
auto& operator<<(STREAM& o, BuiltinFn i) {
  return o << str(i);
}

/// All builtin functions
constexpr BuiltinFn kBuiltinFns[] = {
    BuiltinFn::kAbs,
    BuiltinFn::kAcos,
    BuiltinFn::kAcosh,
    BuiltinFn::kAll,
    BuiltinFn::kAny,
    BuiltinFn::kArrayLength,
    BuiltinFn::kAsin,
    BuiltinFn::kAsinh,
    BuiltinFn::kAtan,
    BuiltinFn::kAtan2,
    BuiltinFn::kAtanh,
    BuiltinFn::kBitcast,
    BuiltinFn::kCeil,
    BuiltinFn::kClamp,
    BuiltinFn::kCos,
    BuiltinFn::kCosh,
    BuiltinFn::kCountLeadingZeros,
    BuiltinFn::kCountOneBits,
    BuiltinFn::kCountTrailingZeros,
    BuiltinFn::kCross,
    BuiltinFn::kDegrees,
    BuiltinFn::kDeterminant,
    BuiltinFn::kDistance,
    BuiltinFn::kDot,
    BuiltinFn::kDot4I8Packed,
    BuiltinFn::kDot4U8Packed,
    BuiltinFn::kDpdx,
    BuiltinFn::kDpdxCoarse,
    BuiltinFn::kDpdxFine,
    BuiltinFn::kDpdy,
    BuiltinFn::kDpdyCoarse,
    BuiltinFn::kDpdyFine,
    BuiltinFn::kExp,
    BuiltinFn::kExp2,
    BuiltinFn::kExtractBits,
    BuiltinFn::kFaceForward,
    BuiltinFn::kFirstLeadingBit,
    BuiltinFn::kFirstTrailingBit,
    BuiltinFn::kFloor,
    BuiltinFn::kFma,
    BuiltinFn::kFract,
    BuiltinFn::kFrexp,
    BuiltinFn::kFwidth,
    BuiltinFn::kFwidthCoarse,
    BuiltinFn::kFwidthFine,
    BuiltinFn::kInsertBits,
    BuiltinFn::kInverseSqrt,
    BuiltinFn::kLdexp,
    BuiltinFn::kLength,
    BuiltinFn::kLog,
    BuiltinFn::kLog2,
    BuiltinFn::kMax,
    BuiltinFn::kMin,
    BuiltinFn::kMix,
    BuiltinFn::kModf,
    BuiltinFn::kNormalize,
    BuiltinFn::kPack2X16Float,
    BuiltinFn::kPack2X16Snorm,
    BuiltinFn::kPack2X16Unorm,
    BuiltinFn::kPack4X8Snorm,
    BuiltinFn::kPack4X8Unorm,
    BuiltinFn::kPack4XI8,
    BuiltinFn::kPack4XU8,
    BuiltinFn::kPack4XI8Clamp,
    BuiltinFn::kPack4XU8Clamp,
    BuiltinFn::kPow,
    BuiltinFn::kQuantizeToF16,
    BuiltinFn::kRadians,
    BuiltinFn::kReflect,
    BuiltinFn::kRefract,
    BuiltinFn::kReverseBits,
    BuiltinFn::kRound,
    BuiltinFn::kSaturate,
    BuiltinFn::kSelect,
    BuiltinFn::kSign,
    BuiltinFn::kSin,
    BuiltinFn::kSinh,
    BuiltinFn::kSmoothstep,
    BuiltinFn::kSqrt,
    BuiltinFn::kStep,
    BuiltinFn::kTan,
    BuiltinFn::kTanh,
    BuiltinFn::kTranspose,
    BuiltinFn::kTrunc,
    BuiltinFn::kUnpack2X16Float,
    BuiltinFn::kUnpack2X16Snorm,
    BuiltinFn::kUnpack2X16Unorm,
    BuiltinFn::kUnpack4X8Snorm,
    BuiltinFn::kUnpack4X8Unorm,
    BuiltinFn::kUnpack4XI8,
    BuiltinFn::kUnpack4XU8,
    BuiltinFn::kAddSat,
    BuiltinFn::kStorageBarrier,
    BuiltinFn::kWorkgroupBarrier,
    BuiltinFn::kTextureBarrier,
    BuiltinFn::kTextureDimensions,
    BuiltinFn::kTextureGather,
    BuiltinFn::kTextureGatherCompare,
    BuiltinFn::kTextureNumLayers,
    BuiltinFn::kTextureNumLevels,
    BuiltinFn::kTextureNumSamples,
    BuiltinFn::kTextureSample,
    BuiltinFn::kTextureSampleBias,
    BuiltinFn::kTextureSampleCompare,
    BuiltinFn::kTextureSampleCompareLevel,
    BuiltinFn::kTextureSampleGrad,
    BuiltinFn::kTextureSampleLevel,
    BuiltinFn::kTextureSampleBaseClampToEdge,
    BuiltinFn::kTextureStore,
    BuiltinFn::kTextureLoad,
    BuiltinFn::kInputAttachmentLoad,
    BuiltinFn::kAtomicLoad,
    BuiltinFn::kAtomicStore,
    BuiltinFn::kAtomicAdd,
    BuiltinFn::kAtomicSub,
    BuiltinFn::kAtomicMax,
    BuiltinFn::kAtomicMin,
    BuiltinFn::kAtomicAnd,
    BuiltinFn::kAtomicOr,
    BuiltinFn::kAtomicXor,
    BuiltinFn::kAtomicExchange,
    BuiltinFn::kAtomicCompareExchangeWeak,
    BuiltinFn::kAtomicStoreMax,
    BuiltinFn::kAtomicStoreMin,
    BuiltinFn::kSubgroupBallot,
    BuiltinFn::kSubgroupElect,
    BuiltinFn::kSubgroupBroadcast,
    BuiltinFn::kSubgroupBroadcastFirst,
    BuiltinFn::kSubgroupShuffle,
    BuiltinFn::kSubgroupShuffleXor,
    BuiltinFn::kSubgroupShuffleUp,
    BuiltinFn::kSubgroupShuffleDown,
    BuiltinFn::kSubgroupAdd,
    BuiltinFn::kSubgroupInclusiveAdd,
    BuiltinFn::kSubgroupExclusiveAdd,
    BuiltinFn::kSubgroupMul,
    BuiltinFn::kSubgroupInclusiveMul,
    BuiltinFn::kSubgroupExclusiveMul,
    BuiltinFn::kSubgroupAnd,
    BuiltinFn::kSubgroupOr,
    BuiltinFn::kSubgroupXor,
    BuiltinFn::kSubgroupMin,
    BuiltinFn::kSubgroupMax,
    BuiltinFn::kSubgroupAll,
    BuiltinFn::kSubgroupAny,
    BuiltinFn::kQuadBroadcast,
    BuiltinFn::kQuadSwapX,
    BuiltinFn::kQuadSwapY,
    BuiltinFn::kQuadSwapDiagonal,
    BuiltinFn::kSubgroupMatrixLoad,
    BuiltinFn::kSubgroupMatrixStore,
    BuiltinFn::kSubgroupMatrixMultiply,
    BuiltinFn::kSubgroupMatrixMultiplyAccumulate,
    BuiltinFn::kSubgroupMatrixScalarAdd,
    BuiltinFn::kSubgroupMatrixScalarSubtract,
    BuiltinFn::kSubgroupMatrixScalarMultiply,
    BuiltinFn::kBufferView,
    BuiltinFn::kBufferArrayView,
    BuiltinFn::kBufferLength,
    BuiltinFn::kPrint,
    BuiltinFn::kHasResource,
    BuiltinFn::kGetResource,
};

/// All builtin function names
constexpr const char* kBuiltinFnStrings[] = {
    "abs",
    "acos",
    "acosh",
    "all",
    "any",
    "arrayLength",
    "asin",
    "asinh",
    "atan",
    "atan2",
    "atanh",
    "bitcast",
    "ceil",
    "clamp",
    "cos",
    "cosh",
    "countLeadingZeros",
    "countOneBits",
    "countTrailingZeros",
    "cross",
    "degrees",
    "determinant",
    "distance",
    "dot",
    "dot4I8Packed",
    "dot4U8Packed",
    "dpdx",
    "dpdxCoarse",
    "dpdxFine",
    "dpdy",
    "dpdyCoarse",
    "dpdyFine",
    "exp",
    "exp2",
    "extractBits",
    "faceForward",
    "firstLeadingBit",
    "firstTrailingBit",
    "floor",
    "fma",
    "fract",
    "frexp",
    "fwidth",
    "fwidthCoarse",
    "fwidthFine",
    "insertBits",
    "inverseSqrt",
    "ldexp",
    "length",
    "log",
    "log2",
    "max",
    "min",
    "mix",
    "modf",
    "normalize",
    "pack2x16float",
    "pack2x16snorm",
    "pack2x16unorm",
    "pack4x8snorm",
    "pack4x8unorm",
    "pack4xI8",
    "pack4xU8",
    "pack4xI8Clamp",
    "pack4xU8Clamp",
    "pow",
    "quantizeToF16",
    "radians",
    "reflect",
    "refract",
    "reverseBits",
    "round",
    "saturate",
    "select",
    "sign",
    "sin",
    "sinh",
    "smoothstep",
    "sqrt",
    "step",
    "tan",
    "tanh",
    "transpose",
    "trunc",
    "unpack2x16float",
    "unpack2x16snorm",
    "unpack2x16unorm",
    "unpack4x8snorm",
    "unpack4x8unorm",
    "unpack4xI8",
    "unpack4xU8",
    "addSat",
    "storageBarrier",
    "workgroupBarrier",
    "textureBarrier",
    "textureDimensions",
    "textureGather",
    "textureGatherCompare",
    "textureNumLayers",
    "textureNumLevels",
    "textureNumSamples",
    "textureSample",
    "textureSampleBias",
    "textureSampleCompare",
    "textureSampleCompareLevel",
    "textureSampleGrad",
    "textureSampleLevel",
    "textureSampleBaseClampToEdge",
    "textureStore",
    "textureLoad",
    "inputAttachmentLoad",
    "atomicLoad",
    "atomicStore",
    "atomicAdd",
    "atomicSub",
    "atomicMax",
    "atomicMin",
    "atomicAnd",
    "atomicOr",
    "atomicXor",
    "atomicExchange",
    "atomicCompareExchangeWeak",
    "atomicStoreMax",
    "atomicStoreMin",
    "subgroupBallot",
    "subgroupElect",
    "subgroupBroadcast",
    "subgroupBroadcastFirst",
    "subgroupShuffle",
    "subgroupShuffleXor",
    "subgroupShuffleUp",
    "subgroupShuffleDown",
    "subgroupAdd",
    "subgroupInclusiveAdd",
    "subgroupExclusiveAdd",
    "subgroupMul",
    "subgroupInclusiveMul",
    "subgroupExclusiveMul",
    "subgroupAnd",
    "subgroupOr",
    "subgroupXor",
    "subgroupMin",
    "subgroupMax",
    "subgroupAll",
    "subgroupAny",
    "quadBroadcast",
    "quadSwapX",
    "quadSwapY",
    "quadSwapDiagonal",
    "subgroupMatrixLoad",
    "subgroupMatrixStore",
    "subgroupMatrixMultiply",
    "subgroupMatrixMultiplyAccumulate",
    "subgroupMatrixScalarAdd",
    "subgroupMatrixScalarSubtract",
    "subgroupMatrixScalarMultiply",
    "bufferView",
    "bufferArrayView",
    "bufferLength",
    "print",
    "hasResource",
    "getResource",
};

/// Determines if the given `f` is a coarse derivative.
/// @param f the builtin type
/// @returns true if the given derivative is coarse.
bool IsCoarseDerivative(BuiltinFn f);

/// Determines if the given `f` is a fine derivative.
/// @param f the builtin type
/// @returns true if the given derivative is fine.
bool IsFineDerivative(BuiltinFn f);

/// Determine if the given `f` is a derivative builtin.
/// @param f the builtin type
/// @returns true if the given `f` is a derivative builtin
bool IsDerivative(BuiltinFn f);

/// Determines if the given `f` is a texture operation builtin.
/// @param f the builtin type
/// @returns true if the given `f` is a texture operation builtin
bool IsTexture(BuiltinFn f);

/// Determines if the given `f` is an image query builtin.
/// @param f the builtin type
/// @returns true if the given `f` is an image query builtin
bool IsImageQuery(BuiltinFn f);

/// Determines if the given `f` is a data packing builtin.
/// @param f the builtin type
/// @returns true if the given `f` is a data packing builtin
bool IsDataPacking(BuiltinFn f);

/// Determines if the given `f` is a data unpacking builtin.
/// @param f the builtin type
/// @returns true if the given `f` is a data unpacking builtin
bool IsDataUnpacking(BuiltinFn f);

/// Determines if the given `f` is a barrier builtin.
/// @param f the builtin type
/// @returns true if the given `f` is a barrier builtin
bool IsBarrier(BuiltinFn f);

/// Determines if the given `f` is an atomic builtin.
/// @param f the builtin type
/// @returns true if the given `f` is an atomic builtin
bool IsAtomic(BuiltinFn f);

/// Determines if the given `f` is a builtin defined in the language extension
/// `packed_4x8_integer_dot_product`.
/// @param f the builtin type
/// @returns true if the given `f` is a builtin defined in the language extension
/// `packed_4x8_integer_dot_product`.
bool IsPacked4x8IntegerDotProductBuiltin(BuiltinFn f);

/// Determines if the given `f` is a subgroup builtin.
/// @param f the builtin type
/// @returns true if the given `f` is a subgroup builtin
bool IsSubgroup(BuiltinFn f);

/// Determines if the given `f` may have side-effects (i.e. writes to at least one of its inputs)
/// @returns true if intrinsic may have side-effects
bool HasSideEffects(BuiltinFn f);

}  // namespace tint::core

namespace tint {

/// Access reflection information
TINT_REFLECT_ENUM_RANGE(core::Access, kUndefined, kWrite);

/// SubgroupMatrixType reflection information
TINT_REFLECT_ENUM_RANGE(core::SubgroupMatrixKind, kUndefined, kRight);

}  // namespace tint

// clang-format on

#endif  // SRC_TINT_LANG_CORE_ENUMS_H_
