SPIRV-Tools/source/operand.cpp
Dejan Mircevski 961f5dc544 Track uses and defs during parsing.
Replace two other, imperfect mechanisms for use-def tracking.

Use ValidationState_t::entry_points to track entry points.

Concentrate undefined-ID diagnostics in a single place.

Move validate_types.h content into validate.h due to increased
inter-dependency.

Track uses of all IDs: TYPE_ID, SCOPE_ID, ...

Also update some blurbs.

Fix entry-point accumulation and move it outside ProcessIds().

Remove validate_types.h from CMakeLists.txt.

Blurb for spvIsIdType.

Remove redundant diagnostics for undefined IDs.

Join "can not" and reformat.
2016-01-20 17:00:58 -05:00

1384 lines
50 KiB
C++

// Copyright (c) 2015-2016 The Khronos Group Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and/or associated documentation files (the
// "Materials"), to deal in the Materials without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Materials, and to
// permit persons to whom the Materials are furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Materials.
//
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
// https://www.khronos.org/registry/
//
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
#include "operand.h"
#include <assert.h>
#include <string.h>
static const spv_operand_desc_t sourceLanguageEntries[] = {
{"Unknown", SpvSourceLanguageUnknown, 0, {SPV_OPERAND_TYPE_NONE}},
{"ESSL", SpvSourceLanguageESSL, 0, {SPV_OPERAND_TYPE_NONE}},
{"GLSL", SpvSourceLanguageGLSL, 0, {SPV_OPERAND_TYPE_NONE}},
{"OpenCL_C", SpvSourceLanguageOpenCL_C, 0, {SPV_OPERAND_TYPE_NONE}},
{"OpenCL_CPP", SpvSourceLanguageOpenCL_CPP, 0, {SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t executionModelEntries[] = {
{"Vertex",
SpvExecutionModelVertex,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"TessellationControl",
SpvExecutionModelTessellationControl,
SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
{SPV_OPERAND_TYPE_NONE}},
{"TessellationEvaluation",
SpvExecutionModelTessellationEvaluation,
SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
{SPV_OPERAND_TYPE_NONE}},
{"Geometry",
SpvExecutionModelGeometry,
SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometry),
{SPV_OPERAND_TYPE_NONE}},
{"Fragment",
SpvExecutionModelFragment,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"GLCompute",
SpvExecutionModelGLCompute,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"Kernel",
SpvExecutionModelKernel,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t addressingModelEntries[] = {
{"Logical", SpvAddressingModelLogical, 0, {SPV_OPERAND_TYPE_NONE}},
{"Physical32",
SpvAddressingModelPhysical32,
SPV_CAPABILITY_AS_MASK(SpvCapabilityAddresses),
{SPV_OPERAND_TYPE_NONE}},
{"Physical64",
SpvAddressingModelPhysical64,
SPV_CAPABILITY_AS_MASK(SpvCapabilityAddresses),
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t memoryModelEntries[] = {
{"Simple",
SpvMemoryModelSimple,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"GLSL450",
SpvMemoryModelGLSL450,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"OpenCL",
SpvMemoryModelOpenCL,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
};
// Execution mode requiring the given capability and having no operands.
#define ExecMode0(mode, cap) \
#mode, SpvExecutionMode##mode, SPV_CAPABILITY_AS_MASK(SpvCapability##cap), { \
SPV_OPERAND_TYPE_NONE \
}
// Execution mode requiring the given capability and having one literal number
// operand.
#define ExecMode1(mode, cap) \
#mode, SpvExecutionMode##mode, SPV_CAPABILITY_AS_MASK(SpvCapability##cap), { \
SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE \
}
static const spv_operand_desc_t executionModeEntries[] = {
{ExecMode1(Invocations, Geometry)},
{ExecMode0(SpacingEqual, Tessellation)},
{ExecMode0(SpacingFractionalEven, Tessellation)},
{ExecMode0(SpacingFractionalOdd, Tessellation)},
{ExecMode0(VertexOrderCw, Tessellation)},
{ExecMode0(VertexOrderCcw, Tessellation)},
{ExecMode0(PixelCenterInteger, Shader)},
{ExecMode0(OriginUpperLeft, Shader)},
{ExecMode0(OriginLowerLeft, Shader)},
{ExecMode0(EarlyFragmentTests, Shader)},
{ExecMode0(PointMode, Tessellation)},
{ExecMode0(Xfb, TransformFeedback)},
{ExecMode0(DepthReplacing, Shader)},
{ExecMode0(DepthGreater, Shader)},
{ExecMode0(DepthLess, Shader)},
{ExecMode0(DepthUnchanged, Shader)},
{"LocalSize",
SpvExecutionModeLocalSize,
0,
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER,
SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{"LocalSizeHint",
SpvExecutionModeLocalSizeHint,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER,
SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{ExecMode0(InputPoints, Geometry)},
{ExecMode0(InputLines, Geometry)},
{ExecMode0(InputLinesAdjacency, Geometry)},
{"Triangles",
SpvExecutionModeTriangles,
SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometry) |
SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
{SPV_OPERAND_TYPE_NONE}},
{ExecMode0(InputTrianglesAdjacency, Geometry)},
{ExecMode0(Quads, Tessellation)},
{ExecMode0(Isolines, Tessellation)},
{"OutputVertices",
SpvExecutionModeOutputVertices,
SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometry) |
SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{ExecMode0(OutputPoints, Geometry)},
{ExecMode0(OutputLineStrip, Geometry)},
{ExecMode0(OutputTriangleStrip, Geometry)},
{ExecMode1(VecTypeHint, Kernel)},
{ExecMode0(ContractionOff, Kernel)},
};
#undef ExecMode0
#undef ExecMode1
static const spv_operand_desc_t storageClassEntries[] = {
// TODO(dneto): There are more storage classes in Rev32 and later.
{"UniformConstant",
SpvStorageClassUniformConstant,
0,
{SPV_OPERAND_TYPE_NONE}},
{"Input",
SpvStorageClassInput,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"Uniform",
SpvStorageClassUniform,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"Output",
SpvStorageClassOutput,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"Workgroup", SpvStorageClassWorkgroup, 0, {SPV_OPERAND_TYPE_NONE}},
{"CrossWorkgroup",
SpvStorageClassCrossWorkgroup,
0,
{SPV_OPERAND_TYPE_NONE}},
{"Private",
SpvStorageClassPrivate,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"Function", SpvStorageClassFunction, 0, {SPV_OPERAND_TYPE_NONE}},
{"Generic",
SpvStorageClassGeneric,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"PushConstant",
SpvStorageClassPushConstant,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"AtomicCounter",
SpvStorageClassAtomicCounter,
SPV_CAPABILITY_AS_MASK(SpvCapabilityAtomicStorage),
{SPV_OPERAND_TYPE_NONE}},
{"Image", SpvStorageClassImage, 0, {SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t dimensionalityEntries[] = {
{"1D",
SpvDim1D,
SPV_CAPABILITY_AS_MASK(SpvCapabilitySampled1D),
{SPV_OPERAND_TYPE_NONE}},
{"2D", SpvDim2D, 0, {SPV_OPERAND_TYPE_NONE}},
{"3D", SpvDim3D, 0, {SPV_OPERAND_TYPE_NONE}},
{"Cube",
SpvDimCube,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"Rect",
SpvDimRect,
SPV_CAPABILITY_AS_MASK(SpvCapabilitySampledRect),
{SPV_OPERAND_TYPE_NONE}},
{"Buffer",
SpvDimBuffer,
SPV_CAPABILITY_AS_MASK(SpvCapabilitySampledBuffer),
{SPV_OPERAND_TYPE_NONE}},
{"SubpassData",
SpvDimSubpassData,
SPV_CAPABILITY_AS_MASK(SpvCapabilityInputAttachment),
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t samplerAddressingModeEntries[] = {
{"None",
SpvSamplerAddressingModeNone,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"ClampToEdge",
SpvSamplerAddressingModeClampToEdge,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"Clamp",
SpvSamplerAddressingModeClamp,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"Repeat",
SpvSamplerAddressingModeRepeat,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"RepeatMirrored",
SpvSamplerAddressingModeRepeatMirrored,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t samplerFilterModeEntries[] = {
{"Nearest",
SpvSamplerFilterModeNearest,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"Linear",
SpvSamplerFilterModeLinear,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t samplerImageFormatEntries[] = {
#define CASE0(NAME) \
{ \
#NAME, SpvImageFormat##NAME, 0, { SPV_OPERAND_TYPE_NONE } \
}
#define CASE(NAME, CAP) \
{ \
#NAME, SpvImageFormat##NAME, SPV_CAPABILITY_AS_MASK(SpvCapability##CAP), { \
SPV_OPERAND_TYPE_NONE \
} \
}
// clang-format off
CASE0(Unknown),
CASE(Rgba32f, Shader),
CASE(Rgba16f, Shader),
CASE(R32f, Shader),
CASE(Rgba8, Shader),
CASE(Rgba8Snorm, Shader),
CASE(Rg32f, StorageImageExtendedFormats),
CASE(Rg16f, StorageImageExtendedFormats),
CASE(R11fG11fB10f, StorageImageExtendedFormats),
CASE(R16f, StorageImageExtendedFormats),
CASE(Rgba16, StorageImageExtendedFormats),
CASE(Rgb10A2, StorageImageExtendedFormats),
CASE(Rg16, StorageImageExtendedFormats),
CASE(Rg8, StorageImageExtendedFormats),
CASE(R16, StorageImageExtendedFormats),
CASE(R8, StorageImageExtendedFormats),
CASE(Rgba16Snorm, StorageImageExtendedFormats),
CASE(Rg16Snorm, StorageImageExtendedFormats),
CASE(Rg8Snorm, StorageImageExtendedFormats),
CASE(R16Snorm, StorageImageExtendedFormats),
CASE(R8Snorm, StorageImageExtendedFormats),
CASE(Rgba32i, Shader),
CASE(Rgba16i, Shader),
CASE(Rgba8i, Shader),
CASE(R32i, Shader),
CASE(Rg32i, StorageImageExtendedFormats),
CASE(Rg16i, StorageImageExtendedFormats),
CASE(Rg8i, StorageImageExtendedFormats),
CASE(R16i, StorageImageExtendedFormats),
CASE(R8i, StorageImageExtendedFormats),
CASE(Rgba32ui, Shader),
CASE(Rgba16ui, Shader),
CASE(Rgba8ui, Shader),
CASE(R32ui, Shader),
CASE(Rgb10a2ui, StorageImageExtendedFormats),
CASE(Rg32ui, StorageImageExtendedFormats),
CASE(Rg16ui, StorageImageExtendedFormats),
CASE(Rg8ui, StorageImageExtendedFormats),
CASE(R16ui, StorageImageExtendedFormats),
CASE(R8ui, StorageImageExtendedFormats),
// clang-format on
#undef CASE
};
// All image channel orders depend on the Kernel capability.
#define CASE(NAME) \
{ \
#NAME, SpvImageChannelOrder##NAME, \
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel), { \
SPV_OPERAND_TYPE_NONE \
} \
}
static const spv_operand_desc_t imageChannelOrderEntries[] = {
CASE(R), CASE(A), CASE(RG), CASE(RA), CASE(RGB),
CASE(RGBA), CASE(BGRA), CASE(ARGB), CASE(Intensity), CASE(Luminance),
CASE(Rx), CASE(RGx), CASE(RGBx), CASE(Depth), CASE(DepthStencil),
CASE(sRGB), CASE(sRGBx), CASE(sRGBA), CASE(sBGRA),
};
#undef CASE
// All image channel data types depend on the Kernel capability.
#define CASE(NAME) \
{ \
#NAME, SpvImageChannelDataType##NAME, \
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel), { \
SPV_OPERAND_TYPE_NONE \
} \
}
static const spv_operand_desc_t imageChannelDataTypeEntries[] = {
CASE(SnormInt8), CASE(SnormInt16), CASE(UnormInt8),
CASE(UnormInt16), CASE(UnormShort565), CASE(UnormShort555),
CASE(UnormInt101010), CASE(SignedInt8), CASE(SignedInt16),
CASE(SignedInt32), CASE(UnsignedInt8), CASE(UnsignedInt16),
CASE(UnsignedInt32), CASE(HalfFloat), CASE(Float),
CASE(UnormInt24), CASE(UnormInt101010_2),
};
#undef CASE
// Image operand definitions. Each enum value is a mask. When that mask
// bit is set, the instruction should have further ID operands.
// Some mask values depend on a capability.
static const spv_operand_desc_t imageOperandEntries[] = {
// Rev32 and later adds many more enums.
#define CASE(NAME) #NAME, SpvImageOperands##NAME##Mask, 0
#define CASE_CAP(NAME, CAP) #NAME, SpvImageOperands##NAME##Mask, CAP
#define ID SPV_OPERAND_TYPE_ID
#define NONE SPV_OPERAND_TYPE_NONE
{"None", SpvImageOperandsMaskNone, 0, {NONE}},
{CASE_CAP(Bias, SPV_CAPABILITY_AS_MASK(SpvCapabilityShader)), {ID, NONE}},
{CASE(Lod), {ID, NONE}},
{CASE(Grad), {ID, ID, NONE}},
{CASE(ConstOffset), {ID, NONE}},
{CASE_CAP(Offset, SPV_CAPABILITY_AS_MASK(SpvCapabilityImageGatherExtended)),
{ID, NONE}},
{CASE(ConstOffsets), {ID, NONE}},
{CASE(Sample), {ID, NONE}},
{CASE_CAP(MinLod, SPV_CAPABILITY_AS_MASK(SpvCapabilityMinLod)), {ID, NONE}},
#undef CASE
#undef CASE_CAP
#undef ID
#undef NONE
};
static const spv_operand_desc_t fpFastMathModeEntries[] = {
{"None", SpvFPFastMathModeMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
{"NotNaN",
SpvFPFastMathModeNotNaNMask,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"NotInf",
SpvFPFastMathModeNotInfMask,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"NSZ",
SpvFPFastMathModeNSZMask,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"AllowRecip",
SpvFPFastMathModeAllowRecipMask,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"Fast",
SpvFPFastMathModeFastMask,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t fpRoundingModeEntries[] = {
{"RTE",
SpvFPRoundingModeRTE,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"RTZ",
SpvFPRoundingModeRTZ,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"RTP",
SpvFPRoundingModeRTP,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"RTN",
SpvFPRoundingModeRTN,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t linkageTypeEntries[] = {
{"Export",
SpvLinkageTypeExport,
SPV_CAPABILITY_AS_MASK(SpvCapabilityLinkage),
{SPV_OPERAND_TYPE_NONE}},
{"Import",
SpvLinkageTypeImport,
SPV_CAPABILITY_AS_MASK(SpvCapabilityLinkage),
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t accessQualifierEntries[] = {
{"ReadOnly",
SpvAccessQualifierReadOnly,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"WriteOnly",
SpvAccessQualifierWriteOnly,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"ReadWrite",
SpvAccessQualifierReadWrite,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t functionParameterAttributeEntries[] = {
{"Zext",
SpvFunctionParameterAttributeZext,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"Sext",
SpvFunctionParameterAttributeSext,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"ByVal",
SpvFunctionParameterAttributeByVal,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"Sret",
SpvFunctionParameterAttributeSret,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"NoAlias",
SpvFunctionParameterAttributeNoAlias,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"NoCapture",
SpvFunctionParameterAttributeNoCapture,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"NoWrite",
SpvFunctionParameterAttributeNoWrite,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"NoReadWrite",
SpvFunctionParameterAttributeNoReadWrite,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t decorationEntries[] = {
{"RelaxedPrecision",
SpvDecorationRelaxedPrecision,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{
"SpecId",
SpvDecorationSpecId,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_LITERAL_INTEGER},
},
{"Block",
SpvDecorationBlock,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"BufferBlock",
SpvDecorationBufferBlock,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"RowMajor",
SpvDecorationRowMajor,
SPV_CAPABILITY_AS_MASK(SpvCapabilityMatrix),
{SPV_OPERAND_TYPE_NONE}},
{"ColMajor",
SpvDecorationColMajor,
SPV_CAPABILITY_AS_MASK(SpvCapabilityMatrix),
{SPV_OPERAND_TYPE_NONE}},
{"ArrayStride",
SpvDecorationArrayStride,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{"MatrixStride",
SpvDecorationMatrixStride,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{"GLSLShared",
SpvDecorationGLSLShared,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"GLSLPacked",
SpvDecorationGLSLPacked,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"CPacked",
SpvDecorationCPacked,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"BuiltIn",
SpvDecorationBuiltIn,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_BUILT_IN, SPV_OPERAND_TYPE_NONE}},
{"NoPerspective",
SpvDecorationNoPerspective,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"Flat",
SpvDecorationFlat,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"Patch",
SpvDecorationPatch,
SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
{SPV_OPERAND_TYPE_NONE}},
{"Centroid",
SpvDecorationCentroid,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"Sample",
SpvDecorationSample,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"Invariant",
SpvDecorationInvariant,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"Restrict", SpvDecorationRestrict, 0, {SPV_OPERAND_TYPE_NONE}},
{"Aliased", SpvDecorationAliased, 0, {SPV_OPERAND_TYPE_NONE}},
{"Volatile", SpvDecorationVolatile, 0, {SPV_OPERAND_TYPE_NONE}},
{"Constant",
SpvDecorationConstant,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"Coherent", SpvDecorationCoherent, 0, {SPV_OPERAND_TYPE_NONE}},
{"NonWritable", SpvDecorationNonWritable, 0, {SPV_OPERAND_TYPE_NONE}},
{"NonReadable", SpvDecorationNonReadable, 0, {SPV_OPERAND_TYPE_NONE}},
{"Uniform",
SpvDecorationUniform,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"SaturatedConversion",
SpvDecorationSaturatedConversion,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"Stream",
SpvDecorationStream,
SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometryStreams),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{"Location",
SpvDecorationLocation,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{"Component",
SpvDecorationComponent,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{"Index",
SpvDecorationIndex,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{"Binding",
SpvDecorationBinding,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{"DescriptorSet",
SpvDecorationDescriptorSet,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{"Offset",
SpvDecorationOffset,
0,
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{"XfbBuffer",
SpvDecorationXfbBuffer,
SPV_CAPABILITY_AS_MASK(SpvCapabilityTransformFeedback),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{"XfbStride",
SpvDecorationXfbStride,
SPV_CAPABILITY_AS_MASK(SpvCapabilityTransformFeedback),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{"FuncParamAttr",
SpvDecorationFuncParamAttr,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE, SPV_OPERAND_TYPE_NONE}},
{"FPRoundingMode",
SpvDecorationFPRoundingMode,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_NONE}},
{"FPFastMathMode",
SpvDecorationFPFastMathMode,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, SPV_OPERAND_TYPE_NONE}},
{"LinkageAttributes",
SpvDecorationLinkageAttributes,
SPV_CAPABILITY_AS_MASK(SpvCapabilityLinkage),
{SPV_OPERAND_TYPE_LITERAL_STRING, SPV_OPERAND_TYPE_LINKAGE_TYPE,
SPV_OPERAND_TYPE_NONE}},
{"NoContraction",
SpvDecorationNoContraction,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"InputAttachmentIndex",
SpvDecorationInputAttachmentIndex,
SPV_CAPABILITY_AS_MASK(SpvCapabilityInputAttachment),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
{"Alignment",
SpvDecorationAlignment,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t builtInEntries[] = {
{"Position",
SpvBuiltInPosition,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"PointSize",
SpvBuiltInPointSize,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"ClipDistance",
SpvBuiltInClipDistance,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"CullDistance",
SpvBuiltInCullDistance,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"VertexId",
SpvBuiltInVertexId,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"InstanceId",
SpvBuiltInInstanceId,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"PrimitiveId",
SpvBuiltInPrimitiveId,
SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometry) |
SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
{SPV_OPERAND_TYPE_NONE}},
{"InvocationId",
SpvBuiltInInvocationId,
SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometry) |
SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
{SPV_OPERAND_TYPE_NONE}},
{"Layer",
SpvBuiltInLayer,
SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometry),
{SPV_OPERAND_TYPE_NONE}},
{"ViewportIndex",
SpvBuiltInViewportIndex,
SPV_CAPABILITY_AS_MASK(SpvCapabilityGeometry),
{SPV_OPERAND_TYPE_NONE}},
{"TessLevelOuter",
SpvBuiltInTessLevelOuter,
SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
{SPV_OPERAND_TYPE_NONE}},
{"TessLevelInner",
SpvBuiltInTessLevelInner,
SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
{SPV_OPERAND_TYPE_NONE}},
{"TessCoord",
SpvBuiltInTessCoord,
SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
{SPV_OPERAND_TYPE_NONE}},
{"PatchVertices",
SpvBuiltInPatchVertices,
SPV_CAPABILITY_AS_MASK(SpvCapabilityTessellation),
{SPV_OPERAND_TYPE_NONE}},
{"FragCoord",
SpvBuiltInFragCoord,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"PointCoord",
SpvBuiltInPointCoord,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"FrontFacing",
SpvBuiltInFrontFacing,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"SampleId",
SpvBuiltInSampleId,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"SamplePosition",
SpvBuiltInSamplePosition,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"SampleMask",
SpvBuiltInSampleMask,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"FragDepth",
SpvBuiltInFragDepth,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"HelperInvocation",
SpvBuiltInHelperInvocation,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"NumWorkgroups", SpvBuiltInNumWorkgroups, 0, {SPV_OPERAND_TYPE_NONE}},
{"WorkgroupSize", SpvBuiltInWorkgroupSize, 0, {SPV_OPERAND_TYPE_NONE}},
{"WorkgroupId", SpvBuiltInWorkgroupId, 0, {SPV_OPERAND_TYPE_NONE}},
{"LocalInvocationId",
SpvBuiltInLocalInvocationId,
0,
{SPV_OPERAND_TYPE_NONE}},
{"GlobalInvocationId",
SpvBuiltInGlobalInvocationId,
0,
{SPV_OPERAND_TYPE_NONE}},
{"LocalInvocationIndex",
SpvBuiltInLocalInvocationIndex,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"WorkDim",
SpvBuiltInWorkDim,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"GlobalSize",
SpvBuiltInGlobalSize,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"EnqueuedWorkgroupSize",
SpvBuiltInEnqueuedWorkgroupSize,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"GlobalOffset",
SpvBuiltInGlobalOffset,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"GlobalLinearId",
SpvBuiltInGlobalLinearId,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"SubgroupSize",
SpvBuiltInSubgroupSize,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"SubgroupMaxSize",
SpvBuiltInSubgroupMaxSize,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"NumSubgroups",
SpvBuiltInNumSubgroups,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"NumEnqueuedSubgroups",
SpvBuiltInNumEnqueuedSubgroups,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"SubgroupId",
SpvBuiltInSubgroupId,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"SubgroupLocalInvocationId",
SpvBuiltInSubgroupLocalInvocationId,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"VertexIndex",
SpvBuiltInVertexIndex,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"InstanceIndex",
SpvBuiltInInstanceIndex,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t selectionControlEntries[] = {
{"None", SpvSelectionControlMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
{"Flatten", SpvSelectionControlFlattenMask, 0, {SPV_OPERAND_TYPE_NONE}},
{"DontFlatten",
SpvSelectionControlDontFlattenMask,
0,
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t loopControlEntries[] = {
{"None", SpvLoopControlMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
{"Unroll", SpvLoopControlUnrollMask, 0, {SPV_OPERAND_TYPE_NONE}},
{"DontUnroll", SpvLoopControlDontUnrollMask, 0, {SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t functionControlEntries[] = {
{"None", SpvFunctionControlMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
{"Inline", SpvFunctionControlInlineMask, 0, {SPV_OPERAND_TYPE_NONE}},
{"DontInline",
SpvFunctionControlDontInlineMask,
0,
{SPV_OPERAND_TYPE_NONE}},
{"Pure", SpvFunctionControlPureMask, 0, {SPV_OPERAND_TYPE_NONE}},
{"Const", SpvFunctionControlConstMask, 0, {SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t memorySemanticsEntries[] = {
// "Relaxed" should be a synonym for "None".
// Put the Relaxed entry first so that the disassembler
// will prefer to emit "Relaxed".
{"Relaxed", SpvMemorySemanticsMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
{"None", SpvMemorySemanticsMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
{"SequentiallyConsistent",
SpvMemorySemanticsSequentiallyConsistentMask,
0,
{SPV_OPERAND_TYPE_NONE}},
{"Acquire", SpvMemorySemanticsAcquireMask, 0, {SPV_OPERAND_TYPE_NONE}},
{"Release", SpvMemorySemanticsReleaseMask, 0, {SPV_OPERAND_TYPE_NONE}},
{"AcquireRelease",
SpvMemorySemanticsAcquireReleaseMask,
0,
{SPV_OPERAND_TYPE_NONE}},
{"UniformMemory",
SpvMemorySemanticsUniformMemoryMask,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{"SubgroupMemory",
SpvMemorySemanticsSubgroupMemoryMask,
0,
{SPV_OPERAND_TYPE_NONE}},
{"WorkgroupMemory",
SpvMemorySemanticsWorkgroupMemoryMask,
0,
{SPV_OPERAND_TYPE_NONE}},
{"CrossWorkgroupMemory",
SpvMemorySemanticsCrossWorkgroupMemoryMask,
0,
{SPV_OPERAND_TYPE_NONE}},
{"AtomicCounterMemory",
SpvMemorySemanticsAtomicCounterMemoryMask,
SPV_CAPABILITY_AS_MASK(SpvCapabilityShader),
{SPV_OPERAND_TYPE_NONE}},
{
"ImageMemory",
SpvMemorySemanticsImageMemoryMask,
0,
{SPV_OPERAND_TYPE_NONE},
},
};
static const spv_operand_desc_t memoryAccessEntries[] = {
{"None", SpvMemoryAccessMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
{"Volatile", SpvMemoryAccessVolatileMask, 0, {SPV_OPERAND_TYPE_NONE}},
{
"Aligned",
SpvMemoryAccessAlignedMask,
0,
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE},
},
{"Nontemporal", SpvMemoryAccessNontemporalMask, 0, {SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t scopeEntries[] = {
{"CrossDevice", SpvScopeCrossDevice, 0, {SPV_OPERAND_TYPE_NONE}},
{"Device", SpvScopeDevice, 0, {SPV_OPERAND_TYPE_NONE}},
{"Workgroup", SpvScopeWorkgroup, 0, {SPV_OPERAND_TYPE_NONE}},
{"Subgroup", SpvScopeSubgroup, 0, {SPV_OPERAND_TYPE_NONE}},
{
"Invocation", SpvScopeInvocation, 0, {SPV_OPERAND_TYPE_NONE},
},
};
static const spv_operand_desc_t groupOperationEntries[] = {
{"Reduce",
SpvGroupOperationReduce,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"InclusiveScan",
SpvGroupOperationInclusiveScan,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"ExclusiveScan",
SpvGroupOperationExclusiveScan,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t kernelKernelEnqueueFlagssEntries[] = {
{"NoWait",
SpvKernelEnqueueFlagsNoWait,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"WaitKernel",
SpvKernelEnqueueFlagsWaitKernel,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
{"WaitWorkGroup",
SpvKernelEnqueueFlagsWaitWorkGroup,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
};
static const spv_operand_desc_t kernelProfilingInfoEntries[] = {
{"None", SpvKernelProfilingInfoMaskNone, 0, {SPV_OPERAND_TYPE_NONE}},
{"CmdExecTime",
SpvKernelProfilingInfoCmdExecTimeMask,
SPV_CAPABILITY_AS_MASK(SpvCapabilityKernel),
{SPV_OPERAND_TYPE_NONE}},
};
// A macro for defining a capability that doesn't depend on another capability.
#define CASE(NAME) \
{ \
#NAME, SpvCapability##NAME, 0, { SPV_OPERAND_TYPE_NONE } \
}
// A macro for defining a capability that depends on another.
#define CASE_CAP(NAME, CAP) \
{ \
#NAME, SpvCapability##NAME, SPV_CAPABILITY_AS_MASK(SpvCapability##CAP), { \
SPV_OPERAND_TYPE_NONE \
} \
}
// clang-format off
static const spv_operand_desc_t capabilityInfoEntries[] = {
CASE(Matrix),
CASE_CAP(Shader, Matrix),
CASE_CAP(Geometry, Shader),
CASE_CAP(Tessellation, Shader),
CASE(Addresses),
CASE(Linkage),
CASE(Kernel),
CASE_CAP(Vector16, Kernel),
CASE_CAP(Float16Buffer, Kernel),
CASE_CAP(Float16, Float16Buffer),
CASE(Float64),
CASE(Int64),
CASE_CAP(Int64Atomics, Int64),
CASE_CAP(ImageBasic, Kernel),
CASE_CAP(ImageReadWrite, Kernel),
CASE_CAP(ImageMipmap, Kernel),
// Value 16 intentionally missing.
CASE_CAP(Pipes, Kernel),
CASE(Groups),
CASE_CAP(DeviceEnqueue, Kernel),
CASE_CAP(LiteralSampler, Kernel),
CASE_CAP(AtomicStorage, Shader),
CASE(Int16),
CASE_CAP(TessellationPointSize, Tessellation),
CASE_CAP(GeometryPointSize, Geometry),
CASE_CAP(ImageGatherExtended, Shader),
// Value 26 intentionally missing.
CASE_CAP(StorageImageMultisample, Shader),
CASE_CAP(UniformBufferArrayDynamicIndexing, Shader),
CASE_CAP(SampledImageArrayDynamicIndexing, Shader),
CASE_CAP(StorageBufferArrayDynamicIndexing, Shader),
CASE_CAP(StorageImageArrayDynamicIndexing, Shader),
CASE_CAP(ClipDistance, Shader),
CASE_CAP(CullDistance, Shader),
CASE_CAP(ImageCubeArray, SampledCubeArray),
CASE_CAP(SampleRateShading, Shader),
CASE_CAP(ImageRect, SampledRect),
CASE_CAP(SampledRect, Shader),
CASE_CAP(GenericPointer, Addresses),
CASE_CAP(Int8, Kernel),
CASE_CAP(InputAttachment, Shader),
CASE_CAP(SparseResidency, Shader),
CASE_CAP(MinLod, Shader),
CASE_CAP(Sampled1D, Shader),
CASE_CAP(Image1D, Sampled1D),
CASE_CAP(SampledCubeArray, Shader),
CASE_CAP(SampledBuffer, Shader),
CASE_CAP(ImageBuffer, SampledBuffer),
CASE_CAP(ImageMSArray, Shader),
CASE_CAP(StorageImageExtendedFormats, Shader),
CASE_CAP(ImageQuery, Shader),
CASE_CAP(DerivativeControl, Shader),
CASE_CAP(InterpolationFunction, Shader),
CASE_CAP(TransformFeedback, Shader),
CASE_CAP(GeometryStreams, Geometry),
CASE_CAP(StorageImageReadWithoutFormat, Shader),
CASE_CAP(StorageImageWriteWithoutFormat, Shader),
};
// clang-format on
#undef CASE
#undef CASE_CAP
// Evaluates to the number of elements of array A.
// If we could use constexpr, then we could make this a template function.
// If the source arrays were std::array, then we could have used
// std::array::size.
#define ARRAY_SIZE(A) (static_cast<uint32_t>(sizeof(A)/sizeof(A[0])))
static const spv_operand_desc_group_t opcodeEntryTypes[] = {
// TODO(dneto): Reformat this table.
{SPV_OPERAND_TYPE_SOURCE_LANGUAGE,
ARRAY_SIZE(sourceLanguageEntries),
sourceLanguageEntries},
{SPV_OPERAND_TYPE_EXECUTION_MODEL,
ARRAY_SIZE(executionModelEntries),
executionModelEntries},
{SPV_OPERAND_TYPE_ADDRESSING_MODEL,
ARRAY_SIZE(addressingModelEntries),
addressingModelEntries},
{SPV_OPERAND_TYPE_MEMORY_MODEL,
ARRAY_SIZE(memoryModelEntries),
memoryModelEntries},
{SPV_OPERAND_TYPE_EXECUTION_MODE,
ARRAY_SIZE(executionModeEntries),
executionModeEntries},
{SPV_OPERAND_TYPE_STORAGE_CLASS,
ARRAY_SIZE(storageClassEntries),
storageClassEntries},
{SPV_OPERAND_TYPE_DIMENSIONALITY,
ARRAY_SIZE(dimensionalityEntries),
dimensionalityEntries},
{SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE,
ARRAY_SIZE(samplerAddressingModeEntries),
samplerAddressingModeEntries},
{SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE,
ARRAY_SIZE(samplerFilterModeEntries),
samplerFilterModeEntries},
{SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT,
ARRAY_SIZE(samplerImageFormatEntries),
samplerImageFormatEntries},
{SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER,
ARRAY_SIZE(imageChannelOrderEntries),
imageChannelOrderEntries},
{SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE,
ARRAY_SIZE(imageChannelDataTypeEntries),
imageChannelDataTypeEntries},
{SPV_OPERAND_TYPE_IMAGE,
ARRAY_SIZE(imageOperandEntries),
imageOperandEntries},
{SPV_OPERAND_TYPE_OPTIONAL_IMAGE, // Same as *_IMAGE
ARRAY_SIZE(imageOperandEntries),
imageOperandEntries},
{SPV_OPERAND_TYPE_FP_FAST_MATH_MODE,
ARRAY_SIZE(fpFastMathModeEntries),
fpFastMathModeEntries},
{SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
ARRAY_SIZE(fpRoundingModeEntries),
fpRoundingModeEntries},
{SPV_OPERAND_TYPE_LINKAGE_TYPE,
ARRAY_SIZE(linkageTypeEntries),
linkageTypeEntries},
{SPV_OPERAND_TYPE_ACCESS_QUALIFIER,
ARRAY_SIZE(accessQualifierEntries),
accessQualifierEntries},
{SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
ARRAY_SIZE(functionParameterAttributeEntries),
functionParameterAttributeEntries},
{SPV_OPERAND_TYPE_DECORATION,
ARRAY_SIZE(decorationEntries), decorationEntries},
{SPV_OPERAND_TYPE_BUILT_IN,
ARRAY_SIZE(builtInEntries), builtInEntries},
{SPV_OPERAND_TYPE_SELECTION_CONTROL,
ARRAY_SIZE(selectionControlEntries),
selectionControlEntries},
{SPV_OPERAND_TYPE_LOOP_CONTROL,
ARRAY_SIZE(loopControlEntries),
loopControlEntries},
{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
ARRAY_SIZE(functionControlEntries),
functionControlEntries},
{SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID,
ARRAY_SIZE(memorySemanticsEntries),
memorySemanticsEntries},
{SPV_OPERAND_TYPE_MEMORY_ACCESS,
ARRAY_SIZE(memoryAccessEntries),
memoryAccessEntries},
{SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, // Same as *_MEMORY_ACCESS
ARRAY_SIZE(memoryAccessEntries),
memoryAccessEntries},
{SPV_OPERAND_TYPE_SCOPE_ID,
ARRAY_SIZE(scopeEntries), scopeEntries},
{SPV_OPERAND_TYPE_GROUP_OPERATION,
ARRAY_SIZE(groupOperationEntries),
groupOperationEntries},
{SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS,
ARRAY_SIZE(kernelKernelEnqueueFlagssEntries),
kernelKernelEnqueueFlagssEntries},
{SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO,
ARRAY_SIZE(kernelProfilingInfoEntries),
kernelProfilingInfoEntries},
{SPV_OPERAND_TYPE_CAPABILITY,
ARRAY_SIZE(capabilityInfoEntries),
capabilityInfoEntries},
};
spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable) {
if (!pOperandTable) return SPV_ERROR_INVALID_POINTER;
static const spv_operand_table_t table = {ARRAY_SIZE(opcodeEntryTypes),
opcodeEntryTypes};
*pOperandTable = &table;
return SPV_SUCCESS;
}
#undef ARRAY_SIZE
spv_result_t spvOperandTableNameLookup(const spv_operand_table table,
const spv_operand_type_t type,
const char* name,
const size_t nameLength,
spv_operand_desc* pEntry) {
if (!table) return SPV_ERROR_INVALID_TABLE;
if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
if (type == table->types[typeIndex].type) {
for (uint64_t operandIndex = 0;
operandIndex < table->types[typeIndex].count; ++operandIndex) {
if (nameLength ==
strlen(table->types[typeIndex].entries[operandIndex].name) &&
!strncmp(table->types[typeIndex].entries[operandIndex].name, name,
nameLength)) {
*pEntry = &table->types[typeIndex].entries[operandIndex];
return SPV_SUCCESS;
}
}
}
}
return SPV_ERROR_INVALID_LOOKUP;
}
spv_result_t spvOperandTableValueLookup(const spv_operand_table table,
const spv_operand_type_t type,
const uint32_t value,
spv_operand_desc* pEntry) {
if (!table) return SPV_ERROR_INVALID_TABLE;
if (!pEntry) return SPV_ERROR_INVALID_POINTER;
for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
if (type == table->types[typeIndex].type) {
for (uint64_t operandIndex = 0;
operandIndex < table->types[typeIndex].count; ++operandIndex) {
if (value == table->types[typeIndex].entries[operandIndex].value) {
*pEntry = &table->types[typeIndex].entries[operandIndex];
return SPV_SUCCESS;
}
}
}
}
return SPV_ERROR_INVALID_LOOKUP;
}
const char* spvOperandTypeStr(spv_operand_type_t type) {
switch (type) {
case SPV_OPERAND_TYPE_ID:
case SPV_OPERAND_TYPE_OPTIONAL_ID:
return "ID";
case SPV_OPERAND_TYPE_TYPE_ID:
return "type ID";
case SPV_OPERAND_TYPE_RESULT_ID:
return "result ID";
case SPV_OPERAND_TYPE_LITERAL_INTEGER:
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER:
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER:
return "literal number";
case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
return "possibly multi-word literal integer";
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
return "possibly multi-word literal number";
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
return "extension instruction number";
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER:
return "OpSpecConstantOp opcode";
case SPV_OPERAND_TYPE_LITERAL_STRING:
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING:
return "literal string";
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
return "source language";
case SPV_OPERAND_TYPE_EXECUTION_MODEL:
return "execution model";
case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
return "addressing model";
case SPV_OPERAND_TYPE_MEMORY_MODEL:
return "memory model";
case SPV_OPERAND_TYPE_EXECUTION_MODE:
case SPV_OPERAND_TYPE_OPTIONAL_EXECUTION_MODE:
return "execution mode";
case SPV_OPERAND_TYPE_STORAGE_CLASS:
return "storage class";
case SPV_OPERAND_TYPE_DIMENSIONALITY:
return "dimensionality";
case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
return "sampler addressing mode";
case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
return "sampler filter mode";
case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
return "image format";
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
return "floating-point fast math mode";
case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
return "floating-point rounding mode";
case SPV_OPERAND_TYPE_LINKAGE_TYPE:
return "linkage type";
case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
return "access qualifier";
case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
return "function parameter attribute";
case SPV_OPERAND_TYPE_DECORATION:
return "decoration";
case SPV_OPERAND_TYPE_BUILT_IN:
return "built-in";
case SPV_OPERAND_TYPE_SELECTION_CONTROL:
return "selection control";
case SPV_OPERAND_TYPE_LOOP_CONTROL:
return "loop control";
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
return "function control";
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
return "memory semantics ID";
case SPV_OPERAND_TYPE_MEMORY_ACCESS:
case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
return "memory access";
case SPV_OPERAND_TYPE_SCOPE_ID:
return "scope ID";
case SPV_OPERAND_TYPE_GROUP_OPERATION:
return "group operation";
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
return "kernel enqeue flags";
case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
return "kernel profiling info";
case SPV_OPERAND_TYPE_CAPABILITY:
return "capability";
case SPV_OPERAND_TYPE_IMAGE:
case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
return "image";
case SPV_OPERAND_TYPE_OPTIONAL_CIV:
return "context-insensitive value";
// The next values are for values returned from an instruction, not actually
// an operand. So the specific strings don't matter. But let's add them
// for completeness and ease of testing.
case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER:
return "image channel order";
case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE:
return "image channel data type";
case SPV_OPERAND_TYPE_NONE:
return "NONE";
default:
assert(0 && "Unhandled operand type!");
break;
}
return "unknown";
}
void spvPrependOperandTypes(const spv_operand_type_t* types,
spv_operand_pattern_t* pattern) {
const spv_operand_type_t* endTypes;
for (endTypes = types; *endTypes != SPV_OPERAND_TYPE_NONE; ++endTypes)
;
pattern->insert(pattern->begin(), types, endTypes);
}
void spvPrependOperandTypesForMask(const spv_operand_table operandTable,
const spv_operand_type_t type,
const uint32_t mask,
spv_operand_pattern_t* pattern) {
// Scan from highest bits to lowest bits because we will prepend in LIFO
// fashion, and we need the operands for lower order bits to appear first.
for (uint32_t candidate_bit = (1 << 31); candidate_bit; candidate_bit >>= 1) {
if (candidate_bit & mask) {
spv_operand_desc entry = nullptr;
if (SPV_SUCCESS == spvOperandTableValueLookup(operandTable, type,
candidate_bit, &entry)) {
spvPrependOperandTypes(entry->operandTypes, pattern);
}
}
}
}
bool spvOperandIsOptional(spv_operand_type_t type) {
return SPV_OPERAND_TYPE_FIRST_OPTIONAL_TYPE <= type &&
type <= SPV_OPERAND_TYPE_LAST_OPTIONAL_TYPE;
}
bool spvOperandIsVariable(spv_operand_type_t type) {
return SPV_OPERAND_TYPE_FIRST_VARIABLE_TYPE <= type &&
type <= SPV_OPERAND_TYPE_LAST_VARIABLE_TYPE;
}
bool spvExpandOperandSequenceOnce(spv_operand_type_t type,
spv_operand_pattern_t* pattern) {
switch (type) {
case SPV_OPERAND_TYPE_VARIABLE_ID:
pattern->insert(pattern->begin(), {SPV_OPERAND_TYPE_OPTIONAL_ID, type});
return true;
case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER:
pattern->insert(pattern->begin(),
{SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, type});
return true;
case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID:
// Represents Zero or more (Literal number, Id) pairs,
// where the literal number must be a scalar integer.
pattern->insert(pattern->begin(),
{SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER,
SPV_OPERAND_TYPE_ID, type});
return true;
case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER:
// Represents Zero or more (Id, Literal number) pairs.
pattern->insert(pattern->begin(),
{SPV_OPERAND_TYPE_OPTIONAL_ID,
SPV_OPERAND_TYPE_LITERAL_INTEGER, type});
return true;
case SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE:
pattern->insert(pattern->begin(),
{SPV_OPERAND_TYPE_OPTIONAL_EXECUTION_MODE, type});
return true;
default:
break;
}
return false;
}
spv_operand_type_t spvTakeFirstMatchableOperand(
spv_operand_pattern_t* pattern) {
assert(!pattern->empty());
spv_operand_type_t result;
do {
result = pattern->front();
pattern->pop_front();
} while (spvExpandOperandSequenceOnce(result, pattern));
return result;
}
spv_operand_pattern_t spvAlternatePatternFollowingImmediate(
const spv_operand_pattern_t& pattern) {
spv_operand_pattern_t alternatePattern;
for (const auto& operand : pattern) {
if (operand == SPV_OPERAND_TYPE_RESULT_ID) {
alternatePattern.push_back(operand);
alternatePattern.push_back(SPV_OPERAND_TYPE_OPTIONAL_CIV);
return alternatePattern;
}
alternatePattern.push_back(SPV_OPERAND_TYPE_OPTIONAL_CIV);
}
// No result-id found, so just expect CIVs.
return {SPV_OPERAND_TYPE_OPTIONAL_CIV};
}
bool spvIsIdType(spv_operand_type_t type) {
switch (type) {
case SPV_OPERAND_TYPE_ID:
case SPV_OPERAND_TYPE_TYPE_ID:
case SPV_OPERAND_TYPE_RESULT_ID:
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
case SPV_OPERAND_TYPE_SCOPE_ID:
return true;
default:
return false;
}
return false;
}