utils: Add a vscode extension for SPIR-V disassembly files (#2987)

This is a very simple Visual Studio code extension that adds syntax highlighting to .spirv disassembly files.
This commit is contained in:
Ben Clayton 2019-10-28 17:06:14 +00:00 committed by Steven Perron
parent 5ea7099374
commit 42f8852381
9 changed files with 594 additions and 0 deletions

1
utils/vscode/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
cache/

7
utils/vscode/README.md Normal file
View File

@ -0,0 +1,7 @@
# Visual Studio Code extension for SPIR-V disassembly files
This directory holds a Visual Studio Code extension adding syntax highlighting for SPIR-V disassembly files (.spirv)
## Installing (macOS / Linux)
Simply run `install.sh`

26
utils/vscode/install.sh Executable file
View File

@ -0,0 +1,26 @@
#!/usr/bin/env bash
# Copyright (c) 2019 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -e # Fail on any error.
EXT_PATH=~/.vscode/extensions/google.spirvls-0.0.1
ROOT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
go run ${ROOT_PATH}/src/tools/gen-grammar.go --cache ${ROOT_PATH}/cache --template ${ROOT_PATH}/spirv.json.tmpl --out ${ROOT_PATH}/spirv.json
mkdir -p ${EXT_PATH}
cp ${ROOT_PATH}/package.json ${EXT_PATH}
cp ${ROOT_PATH}/spirv.configuration.json ${EXT_PATH}
cp ${ROOT_PATH}/spirv.json ${EXT_PATH}

33
utils/vscode/package.json Normal file
View File

@ -0,0 +1,33 @@
{
"name": "spirv",
"description": "Language support for SPIR-V disassembly files",
"author": "Google",
"license": "Apache-2.0",
"version": "0.0.1",
"private": true,
"publisher": "Google",
"engines": {
"vscode": "^0.10.10"
},
"categories": [
"Programming Languages"
],
"contributes": {
"languages": [
{
"id": "spirv",
"configuration": "spirv.configuration.json",
"extensions": [
"spirv"
]
}
],
"grammars": [
{
"language": "spirv",
"scopeName": "source.spirv",
"path": "spirv.json"
}
]
}
}

View File

@ -0,0 +1,6 @@
{
"comments": {
"lineComment": ";"
},
"wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)"
}

212
utils/vscode/spirv.json Normal file
View File

@ -0,0 +1,212 @@
{
"scopeName": "source.spirv",
"name": "SPIR-V",
"comment": "Generated by gen-grammar.go --template=../../spirv.json.tmpl --out=../../spirv.json. Do not modify this file directly.",
"patterns": [
{ "include": "#BitEnum_ImageOperands" },
{ "include": "#BitEnum_FPFastMathMode" },
{ "include": "#BitEnum_SelectionControl" },
{ "include": "#BitEnum_LoopControl" },
{ "include": "#BitEnum_FunctionControl" },
{ "include": "#BitEnum_MemorySemantics" },
{ "include": "#BitEnum_MemoryAccess" },
{ "include": "#BitEnum_KernelProfilingInfo" },
{ "include": "#ValueEnum_SourceLanguage" },
{ "include": "#ValueEnum_ExecutionModel" },
{ "include": "#ValueEnum_AddressingModel" },
{ "include": "#ValueEnum_MemoryModel" },
{ "include": "#ValueEnum_ExecutionMode" },
{ "include": "#ValueEnum_StorageClass" },
{ "include": "#ValueEnum_Dim" },
{ "include": "#ValueEnum_SamplerAddressingMode" },
{ "include": "#ValueEnum_SamplerFilterMode" },
{ "include": "#ValueEnum_ImageFormat" },
{ "include": "#ValueEnum_ImageChannelOrder" },
{ "include": "#ValueEnum_ImageChannelDataType" },
{ "include": "#ValueEnum_FPRoundingMode" },
{ "include": "#ValueEnum_LinkageType" },
{ "include": "#ValueEnum_AccessQualifier" },
{ "include": "#ValueEnum_FunctionParameterAttribute" },
{ "include": "#ValueEnum_Decoration" },
{ "include": "#ValueEnum_BuiltIn" },
{ "include": "#ValueEnum_Scope" },
{ "include": "#ValueEnum_GroupOperation" },
{ "include": "#ValueEnum_KernelEnqueueFlags" },
{ "include": "#ValueEnum_Capability" },
{ "include": "#opcode" },
{ "include": "#identifier" },
{ "include": "#number" },
{ "include": "#string" },
{ "include": "#comment" },
{ "include": "#operator" }
],
"repository": {
"BitEnum_ImageOperands": {
"match": "\\b(None|Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample|MinLod|MakeTexelAvailable|MakeTexelAvailableKHR|MakeTexelVisible|MakeTexelVisibleKHR|NonPrivateTexel|NonPrivateTexelKHR|VolatileTexel|VolatileTexelKHR|SignExtend|ZeroExtend)\\b",
"name": "keyword.spirv"
},
"BitEnum_FPFastMathMode": {
"match": "\\b(None|NotNaN|NotInf|NSZ|AllowRecip|Fast)\\b",
"name": "keyword.spirv"
},
"BitEnum_SelectionControl": {
"match": "\\b(None|Flatten|DontFlatten)\\b",
"name": "keyword.spirv"
},
"BitEnum_LoopControl": {
"match": "\\b(None|Unroll|DontUnroll|DependencyInfinite|DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount)\\b",
"name": "keyword.spirv"
},
"BitEnum_FunctionControl": {
"match": "\\b(None|Inline|DontInline|Pure|Const)\\b",
"name": "keyword.spirv"
},
"BitEnum_MemorySemantics": {
"match": "\\b(Relaxed|None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|OutputMemoryKHR|MakeAvailable|MakeAvailableKHR|MakeVisible|MakeVisibleKHR|Volatile)\\b",
"name": "keyword.spirv"
},
"BitEnum_MemoryAccess": {
"match": "\\b(None|Volatile|Aligned|Nontemporal|MakePointerAvailable|MakePointerAvailableKHR|MakePointerVisible|MakePointerVisibleKHR|NonPrivatePointer|NonPrivatePointerKHR)\\b",
"name": "keyword.spirv"
},
"BitEnum_KernelProfilingInfo": {
"match": "\\b(None|CmdExecTime)\\b",
"name": "keyword.spirv"
},
"ValueEnum_SourceLanguage": {
"match": "\\b(Unknown|ESSL|GLSL|OpenCL_C|OpenCL_CPP|HLSL)\\b",
"name": "keyword.spirv"
},
"ValueEnum_ExecutionModel": {
"match": "\\b(Vertex|TessellationControl|TessellationEvaluation|Geometry|Fragment|GLCompute|Kernel|TaskNV|MeshNV|RayGenerationNV|IntersectionNV|AnyHitNV|ClosestHitNV|MissNV|CallableNV)\\b",
"name": "keyword.spirv"
},
"ValueEnum_AddressingModel": {
"match": "\\b(Logical|Physical32|Physical64|PhysicalStorageBuffer64|PhysicalStorageBuffer64EXT)\\b",
"name": "keyword.spirv"
},
"ValueEnum_MemoryModel": {
"match": "\\b(Simple|GLSL450|OpenCL|Vulkan|VulkanKHR)\\b",
"name": "keyword.spirv"
},
"ValueEnum_ExecutionMode": {
"match": "\\b(Invocations|SpacingEqual|SpacingFractionalEven|SpacingFractionalOdd|VertexOrderCw|VertexOrderCcw|PixelCenterInteger|OriginUpperLeft|OriginLowerLeft|EarlyFragmentTests|PointMode|Xfb|DepthReplacing|DepthGreater|DepthLess|DepthUnchanged|LocalSize|LocalSizeHint|InputPoints|InputLines|InputLinesAdjacency|Triangles|InputTrianglesAdjacency|Quads|Isolines|OutputVertices|OutputPoints|OutputLineStrip|OutputTriangleStrip|VecTypeHint|ContractionOff|Initializer|Finalizer|SubgroupSize|SubgroupsPerWorkgroup|SubgroupsPerWorkgroupId|LocalSizeId|LocalSizeHintId|PostDepthCoverage|DenormPreserve|DenormFlushToZero|SignedZeroInfNanPreserve|RoundingModeRTE|RoundingModeRTZ|StencilRefReplacingEXT|OutputLinesNV|OutputPrimitivesNV|DerivativeGroupQuadsNV|DerivativeGroupLinearNV|OutputTrianglesNV|PixelInterlockOrderedEXT|PixelInterlockUnorderedEXT|SampleInterlockOrderedEXT|SampleInterlockUnorderedEXT|ShadingRateInterlockOrderedEXT|ShadingRateInterlockUnorderedEXT)\\b",
"name": "keyword.spirv"
},
"ValueEnum_StorageClass": {
"match": "\\b(UniformConstant|Input|Uniform|Output|Workgroup|CrossWorkgroup|Private|Function|Generic|PushConstant|AtomicCounter|Image|StorageBuffer|CallableDataNV|IncomingCallableDataNV|RayPayloadNV|HitAttributeNV|IncomingRayPayloadNV|ShaderRecordBufferNV|PhysicalStorageBuffer|PhysicalStorageBufferEXT)\\b",
"name": "keyword.spirv"
},
"ValueEnum_Dim": {
"match": "\\b(1D|2D|3D|Cube|Rect|Buffer|SubpassData)\\b",
"name": "keyword.spirv"
},
"ValueEnum_SamplerAddressingMode": {
"match": "\\b(None|ClampToEdge|Clamp|Repeat|RepeatMirrored)\\b",
"name": "keyword.spirv"
},
"ValueEnum_SamplerFilterMode": {
"match": "\\b(Nearest|Linear)\\b",
"name": "keyword.spirv"
},
"ValueEnum_ImageFormat": {
"match": "\\b(Unknown|Rgba32f|Rgba16f|R32f|Rgba8|Rgba8Snorm|Rg32f|Rg16f|R11fG11fB10f|R16f|Rgba16|Rgb10A2|Rg16|Rg8|R16|R8|Rgba16Snorm|Rg16Snorm|Rg8Snorm|R16Snorm|R8Snorm|Rgba32i|Rgba16i|Rgba8i|R32i|Rg32i|Rg16i|Rg8i|R16i|R8i|Rgba32ui|Rgba16ui|Rgba8ui|R32ui|Rgb10a2ui|Rg32ui|Rg16ui|Rg8ui|R16ui|R8ui)\\b",
"name": "keyword.spirv"
},
"ValueEnum_ImageChannelOrder": {
"match": "\\b(R|A|RG|RA|RGB|RGBA|BGRA|ARGB|Intensity|Luminance|Rx|RGx|RGBx|Depth|DepthStencil|sRGB|sRGBx|sRGBA|sBGRA|ABGR)\\b",
"name": "keyword.spirv"
},
"ValueEnum_ImageChannelDataType": {
"match": "\\b(SnormInt8|SnormInt16|UnormInt8|UnormInt16|UnormShort565|UnormShort555|UnormInt101010|SignedInt8|SignedInt16|SignedInt32|UnsignedInt8|UnsignedInt16|UnsignedInt32|HalfFloat|Float|UnormInt24|UnormInt101010_2)\\b",
"name": "keyword.spirv"
},
"ValueEnum_FPRoundingMode": {
"match": "\\b(RTE|RTZ|RTP|RTN)\\b",
"name": "keyword.spirv"
},
"ValueEnum_LinkageType": {
"match": "\\b(Export|Import)\\b",
"name": "keyword.spirv"
},
"ValueEnum_AccessQualifier": {
"match": "\\b(ReadOnly|WriteOnly|ReadWrite)\\b",
"name": "keyword.spirv"
},
"ValueEnum_FunctionParameterAttribute": {
"match": "\\b(Zext|Sext|ByVal|Sret|NoAlias|NoCapture|NoWrite|NoReadWrite)\\b",
"name": "keyword.spirv"
},
"ValueEnum_Decoration": {
"match": "\\b(RelaxedPrecision|SpecId|Block|BufferBlock|RowMajor|ColMajor|ArrayStride|MatrixStride|GLSLShared|GLSLPacked|CPacked|BuiltIn|NoPerspective|Flat|Patch|Centroid|Sample|Invariant|Restrict|Aliased|Volatile|Constant|Coherent|NonWritable|NonReadable|Uniform|UniformId|SaturatedConversion|Stream|Location|Component|Index|Binding|DescriptorSet|Offset|XfbBuffer|XfbStride|FuncParamAttr|FPRoundingMode|FPFastMathMode|LinkageAttributes|NoContraction|InputAttachmentIndex|Alignment|MaxByteOffset|AlignmentId|MaxByteOffsetId|NoSignedWrap|NoUnsignedWrap|ExplicitInterpAMD|OverrideCoverageNV|PassthroughNV|ViewportRelativeNV|SecondaryViewportRelativeNV|PerPrimitiveNV|PerViewNV|PerTaskNV|PerVertexNV|NonUniform|NonUniformEXT|RestrictPointer|RestrictPointerEXT|AliasedPointer|AliasedPointerEXT|CounterBuffer|HlslCounterBufferGOOGLE|UserSemantic|HlslSemanticGOOGLE|UserTypeGOOGLE)\\b",
"name": "keyword.spirv"
},
"ValueEnum_BuiltIn": {
"match": "\\b(Position|PointSize|ClipDistance|CullDistance|VertexId|InstanceId|PrimitiveId|InvocationId|Layer|ViewportIndex|TessLevelOuter|TessLevelInner|TessCoord|PatchVertices|FragCoord|PointCoord|FrontFacing|SampleId|SamplePosition|SampleMask|FragDepth|HelperInvocation|NumWorkgroups|WorkgroupSize|WorkgroupId|LocalInvocationId|GlobalInvocationId|LocalInvocationIndex|WorkDim|GlobalSize|EnqueuedWorkgroupSize|GlobalOffset|GlobalLinearId|SubgroupSize|SubgroupMaxSize|NumSubgroups|NumEnqueuedSubgroups|SubgroupId|SubgroupLocalInvocationId|VertexIndex|InstanceIndex|SubgroupEqMask|SubgroupGeMask|SubgroupGtMask|SubgroupLeMask|SubgroupLtMask|SubgroupEqMaskKHR|SubgroupGeMaskKHR|SubgroupGtMaskKHR|SubgroupLeMaskKHR|SubgroupLtMaskKHR|BaseVertex|BaseInstance|DrawIndex|DeviceIndex|ViewIndex|BaryCoordNoPerspAMD|BaryCoordNoPerspCentroidAMD|BaryCoordNoPerspSampleAMD|BaryCoordSmoothAMD|BaryCoordSmoothCentroidAMD|BaryCoordSmoothSampleAMD|BaryCoordPullModelAMD|FragStencilRefEXT|ViewportMaskNV|SecondaryPositionNV|SecondaryViewportMaskNV|PositionPerViewNV|ViewportMaskPerViewNV|FullyCoveredEXT|TaskCountNV|PrimitiveCountNV|PrimitiveIndicesNV|ClipDistancePerViewNV|CullDistancePerViewNV|LayerPerViewNV|MeshViewCountNV|MeshViewIndicesNV|BaryCoordNV|BaryCoordNoPerspNV|FragSizeEXT|FragmentSizeNV|FragInvocationCountEXT|InvocationsPerPixelNV|LaunchIdNV|LaunchSizeNV|WorldRayOriginNV|WorldRayDirectionNV|ObjectRayOriginNV|ObjectRayDirectionNV|RayTminNV|RayTmaxNV|InstanceCustomIndexNV|ObjectToWorldNV|WorldToObjectNV|HitTNV|HitKindNV|IncomingRayFlagsNV|WarpsPerSMNV|SMCountNV|WarpIDNV|SMIDNV)\\b",
"name": "keyword.spirv"
},
"ValueEnum_Scope": {
"match": "\\b(CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|QueueFamilyKHR)\\b",
"name": "keyword.spirv"
},
"ValueEnum_GroupOperation": {
"match": "\\b(Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV)\\b",
"name": "keyword.spirv"
},
"ValueEnum_KernelEnqueueFlags": {
"match": "\\b(NoWait|WaitKernel|WaitWorkGroup)\\b",
"name": "keyword.spirv"
},
"ValueEnum_Capability": {
"match": "\\b(Matrix|Shader|Geometry|Tessellation|Addresses|Linkage|Kernel|Vector16|Float16Buffer|Float16|Float64|Int64|Int64Atomics|ImageBasic|ImageReadWrite|ImageMipmap|Pipes|Groups|DeviceEnqueue|LiteralSampler|AtomicStorage|Int16|TessellationPointSize|GeometryPointSize|ImageGatherExtended|StorageImageMultisample|UniformBufferArrayDynamicIndexing|SampledImageArrayDynamicIndexing|StorageBufferArrayDynamicIndexing|StorageImageArrayDynamicIndexing|ClipDistance|CullDistance|ImageCubeArray|SampleRateShading|ImageRect|SampledRect|GenericPointer|Int8|InputAttachment|SparseResidency|MinLod|Sampled1D|Image1D|SampledCubeArray|SampledBuffer|ImageBuffer|ImageMSArray|StorageImageExtendedFormats|ImageQuery|DerivativeControl|InterpolationFunction|TransformFeedback|GeometryStreams|StorageImageReadWithoutFormat|StorageImageWriteWithoutFormat|MultiViewport|SubgroupDispatch|NamedBarrier|PipeStorage|GroupNonUniform|GroupNonUniformVote|GroupNonUniformArithmetic|GroupNonUniformBallot|GroupNonUniformShuffle|GroupNonUniformShuffleRelative|GroupNonUniformClustered|GroupNonUniformQuad|ShaderLayer|ShaderViewportIndex|SubgroupBallotKHR|DrawParameters|SubgroupVoteKHR|StorageBuffer16BitAccess|StorageUniformBufferBlock16|UniformAndStorageBuffer16BitAccess|StorageUniform16|StoragePushConstant16|StorageInputOutput16|DeviceGroup|MultiView|VariablePointersStorageBuffer|VariablePointers|AtomicStorageOps|SampleMaskPostDepthCoverage|StorageBuffer8BitAccess|UniformAndStorageBuffer8BitAccess|StoragePushConstant8|DenormPreserve|DenormFlushToZero|SignedZeroInfNanPreserve|RoundingModeRTE|RoundingModeRTZ|Float16ImageAMD|ImageGatherBiasLodAMD|FragmentMaskAMD|StencilExportEXT|ImageReadWriteLodAMD|ShaderClockKHR|SampleMaskOverrideCoverageNV|GeometryShaderPassthroughNV|ShaderViewportIndexLayerEXT|ShaderViewportIndexLayerNV|ShaderViewportMaskNV|ShaderStereoViewNV|PerViewAttributesNV|FragmentFullyCoveredEXT|MeshShadingNV|ImageFootprintNV|FragmentBarycentricNV|ComputeDerivativeGroupQuadsNV|FragmentDensityEXT|ShadingRateNV|GroupNonUniformPartitionedNV|ShaderNonUniform|ShaderNonUniformEXT|RuntimeDescriptorArray|RuntimeDescriptorArrayEXT|InputAttachmentArrayDynamicIndexing|InputAttachmentArrayDynamicIndexingEXT|UniformTexelBufferArrayDynamicIndexing|UniformTexelBufferArrayDynamicIndexingEXT|StorageTexelBufferArrayDynamicIndexing|StorageTexelBufferArrayDynamicIndexingEXT|UniformBufferArrayNonUniformIndexing|UniformBufferArrayNonUniformIndexingEXT|SampledImageArrayNonUniformIndexing|SampledImageArrayNonUniformIndexingEXT|StorageBufferArrayNonUniformIndexing|StorageBufferArrayNonUniformIndexingEXT|StorageImageArrayNonUniformIndexing|StorageImageArrayNonUniformIndexingEXT|InputAttachmentArrayNonUniformIndexing|InputAttachmentArrayNonUniformIndexingEXT|UniformTexelBufferArrayNonUniformIndexing|UniformTexelBufferArrayNonUniformIndexingEXT|StorageTexelBufferArrayNonUniformIndexing|StorageTexelBufferArrayNonUniformIndexingEXT|RayTracingNV|VulkanMemoryModel|VulkanMemoryModelKHR|VulkanMemoryModelDeviceScope|VulkanMemoryModelDeviceScopeKHR|PhysicalStorageBufferAddresses|PhysicalStorageBufferAddressesEXT|ComputeDerivativeGroupLinearNV|CooperativeMatrixNV|FragmentShaderSampleInterlockEXT|FragmentShaderShadingRateInterlockEXT|ShaderSMBuiltinsNV|FragmentShaderPixelInterlockEXT|DemoteToHelperInvocationEXT|SubgroupShuffleINTEL|SubgroupBufferBlockIOINTEL|SubgroupImageBlockIOINTEL|SubgroupImageMediaBlockIOINTEL|IntegerFunctions2INTEL|SubgroupAvcMotionEstimationINTEL|SubgroupAvcMotionEstimationIntraINTEL|SubgroupAvcMotionEstimationChromaINTEL)\\b",
"name": "keyword.spirv"
},
"opcode": {
"match": "(Op[a-zA-Z]+)",
"name": "entity.name.function.spirv"
},
"identifier": {
"match": "%[a-zA-Z0-9_]+",
"name": "variable.spirv"
},
"number": {
"match": "\\b[0-9]+.?[0-9]*\\b",
"name": "constant.numeric.spirv"
},
"comment": {
"match": ";[^\n]*",
"name": "comment.line.spirv"
},
"operator": {
"match": "=",
"name": "keyword.operator.spirv"
},
"string": {
"begin": "\"",
"beginCaptures": {
"0": {
"name": "punctuation.definition.string.begin.spirv"
}
},
"end": "\"",
"endCaptures": {
"0": {
"name": "punctuation.definition.string.end.spirv"
}
},
"name": "string.quoted.double.spirv",
"patterns": [ { "include": "#string_escaped_char" } ]
},
"string_escaped_char": {
"patterns": [
{
"match": "\\\\([0-7]{3}|[abfnrtv\\\\'\"]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})",
"name": "constant.character.escape.spirv"
}, {
"match": "\\\\[^0-7xuUabfnrtv\\'\"]",
"name": "invalid.illegal.unknown-escape.spirv"
}
]
}
}
}

View File

@ -0,0 +1,67 @@
{
"scopeName": "source.spirv",
"name": "SPIR-V",
"comment": "Generated by {{GenerateArguments}}. Do not modify this file directly.",
"patterns": [
{{range $o := .OperandKinds}}{{if len $o.Enumerants}} { "include": "#{{$o.Category}}_{{$o.Kind}}" },
{{end}}{{end}} { "include": "#opcode" },
{ "include": "#identifier" },
{ "include": "#number" },
{ "include": "#string" },
{ "include": "#comment" },
{ "include": "#operator" }
],
"repository": { {{range $o := .OperandKinds}}{{if len $o.Enumerants}}
"{{$o.Category}}_{{$o.Kind}}": {
"match": "\\b({{OperandKindsMatch $o}})\\b",
"name": "keyword.spirv"
},{{end}}{{end}}
"opcode": {
"match": "(Op[a-zA-Z]+)",
"name": "entity.name.function.spirv"
},
"identifier": {
"match": "%[a-zA-Z0-9_]+",
"name": "variable.spirv"
},
"number": {
"match": "\\b[0-9]+.?[0-9]*\\b",
"name": "constant.numeric.spirv"
},
"comment": {
"match": ";[^\n]*",
"name": "comment.line.spirv"
},
"operator": {
"match": "=",
"name": "keyword.operator.spirv"
},
"string": {
"begin": "\"",
"beginCaptures": {
"0": {
"name": "punctuation.definition.string.begin.spirv"
}
},
"end": "\"",
"endCaptures": {
"0": {
"name": "punctuation.definition.string.end.spirv"
}
},
"name": "string.quoted.double.spirv",
"patterns": [ { "include": "#string_escaped_char" } ]
},
"string_escaped_char": {
"patterns": [
{
"match": "\\\\([0-7]{3}|[abfnrtv\\\\'\"]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})",
"name": "constant.character.escape.spirv"
}, {
"match": "\\\\[^0-7xuUabfnrtv\\'\"]",
"name": "invalid.illegal.unknown-escape.spirv"
}
]
}
}
}

View File

@ -0,0 +1,75 @@
// Copyright (C) 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package grammar holds the JSON type definitions for the SPIR-V grammar schema.
//
// See https://www.khronos.org/registry/spir-v/specs/unified1/MachineReadableGrammar.html
// for more information.
package grammar
// Root is the top-level structure of the JSON grammar.
type Root struct {
MagicNumber string `json:"magic_number"`
MajorVersion int `json:"major_version"`
MinorVersion int `json:"minor_version"`
Revision int `json:"revision"`
Instructions []Instruction `json:"instructions"`
OperandKinds []OperandKind `json:"operand_kinds"`
}
// Instruction holds information about a specific SPIR-V instruction.
type Instruction struct {
Opname string `json:"opname"`
Class string `json:"class"`
Opcode int `json:"opcode"`
Operands []Operand `json:"operands"`
}
// Operand contains information about a logical operand for an instruction.
type Operand struct {
Kind string `json:"kind"`
Name string `json:"name"`
Quantifier Quantifier `json:"quantifier"`
}
// OperandKind contains information about a specific operand kind.
type OperandKind struct {
Category string `json:"category"`
Kind string `json:"kind"`
Enumerants []Enumerant `json:"enumerants"`
Bases []string `json:"bases"`
}
// Enumerant contains information about an enumerant in an enum.
type Enumerant struct {
Enumerant string `json:"enumerant"`
Value interface{} `json:"value"`
Capabilities []string `json:"capabilities"`
Parameters []Parameter `json:"parameters"`
Version string `json:"version"`
}
// Parameter contains information about a logical parameter for an enumerant.
type Parameter struct {
Kind string `json:"kind"`
Name string `json:"name"`
}
type Quantifier string
const (
Once Quantifier = ""
ZeroOrOnce Quantifier = "?"
ZeroOrMany Quantifier = "*"
)

View File

@ -0,0 +1,167 @@
// Copyright (C) 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// gen-grammar generates the spirv.json grammar file from the official SPIR-V
// grammar JSON file.
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"runtime"
"strings"
"text/template"
"github.com/pkg/errors"
"../grammar"
)
const (
spirvGrammarURL = "https://raw.githubusercontent.com/KhronosGroup/SPIRV-Headers/master/include/spirv/unified1/spirv.core.grammar.json"
spirvGrammarName = "spirv.core.grammar.json"
)
var (
templatePath = flag.String("template", "", "Path to input template file (required)")
outputPath = flag.String("out", "", "Path to output generated file (required)")
cachePath = flag.String("cache", "", "Cache directory for downloaded files (optional)")
thisDir = func() string {
_, file, _, _ := runtime.Caller(1)
return filepath.Dir(file)
}()
)
func main() {
flag.Parse()
if *templatePath == "" || *outputPath == "" {
flag.Usage()
os.Exit(1)
}
if err := run(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func run() error {
tf, err := ioutil.ReadFile(*templatePath)
if err != nil {
return errors.Wrap(err, "Could not open template file")
}
t, err := template.New("tmpl").
Funcs(template.FuncMap{
"GenerateArguments": func() string {
relPath := func(path string) string {
rel, err := filepath.Rel(thisDir, path)
if err != nil {
return path
}
return rel
}
args := []string{
"--template=" + relPath(*templatePath),
"--out=" + relPath(*outputPath),
}
return "gen-grammar.go " + strings.Join(args, " ")
},
"OperandKindsMatch": func(k grammar.OperandKind) string {
sb := strings.Builder{}
for i, e := range k.Enumerants {
if i > 0 {
sb.WriteString("|")
}
sb.WriteString(e.Enumerant)
}
return sb.String()
},
}).Parse(string(tf))
if err != nil {
return errors.Wrap(err, "Failed to parse template")
}
file, err := getOrDownload(spirvGrammarName, spirvGrammarURL)
if err != nil {
return errors.Wrap(err, "Failed to load grammar file")
}
g := grammar.Root{}
if err := json.NewDecoder(bytes.NewReader(file)).Decode(&g); err != nil {
return errors.Wrap(err, "Failed to parse grammar file")
}
buf := bytes.Buffer{}
if err := t.Execute(&buf, g); err != nil {
return errors.Wrap(err, "Failed to execute template")
}
out := buf.String()
out = strings.ReplaceAll(out, "•", "")
if err := ioutil.WriteFile(*outputPath, []byte(out), 0777); err != nil {
return errors.Wrap(err, "Failed to write output file")
}
return nil
}
// getOrDownload loads the specific file from the cache, or downloads the file
// from the given url.
func getOrDownload(name, url string) ([]byte, error) {
if *cachePath != "" {
if err := os.MkdirAll(*cachePath, 0777); err == nil {
path := filepath.Join(*cachePath, name)
if isFile(path) {
return ioutil.ReadFile(path)
}
}
}
resp, err := http.Get(url)
if err != nil {
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if *cachePath != "" {
ioutil.WriteFile(filepath.Join(*cachePath, name), data, 0777)
}
return data, nil
}
// isFile returns true if path is a file.
func isFile(path string) bool {
s, err := os.Stat(path)
if err != nil {
return false
}
return !s.IsDir()
}
// isDir returns true if path is a directory.
func isDir(path string) bool {
s, err := os.Stat(path)
if err != nil {
return false
}
return s.IsDir()
}