mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-30 23:10:05 +00:00
f8cc397573
Generate a vim syntax file for SPIR-V assembly. Copy the resulting spvasm.vim into your $HOME/.vim/syntax directory to get syntax highlighting in Vim. Also, suggest that the grammar file include information about what opcodes can be used in OpSpecConstantOp.
193 lines
6.4 KiB
Python
Executable File
193 lines
6.4 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Copyright (c) 2016 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.
|
|
"""Generates Vim syntax rules for SPIR-V assembly (.spvasm) files"""
|
|
|
|
from __future__ import print_function
|
|
|
|
import json
|
|
|
|
PREAMBLE="""" Vim syntax file
|
|
" Language: spvasm
|
|
" Generated by SPIRV-Tools
|
|
|
|
if version < 600
|
|
syntax clear
|
|
elseif exists("b:current_syntax")
|
|
finish
|
|
endif
|
|
|
|
syn case match
|
|
"""
|
|
|
|
POSTAMBLE="""
|
|
|
|
syntax keyword spvasmTodo TODO FIXME contained
|
|
|
|
syn match spvasmIdNumber /%\d\+\>/
|
|
|
|
" The assembler treats the leading minus sign as part of the number token.
|
|
" This applies to integers, and to floats below.
|
|
syn match spvasmNumber /-\?\<\d\+\>/
|
|
|
|
" Floating point literals.
|
|
" In general, C++ requires at least digit in the mantissa, and the
|
|
" floating point is optional. This applies to both the regular decimal float
|
|
" case and the hex float case.
|
|
|
|
" First case: digits before the optional decimal, no trailing digits.
|
|
syn match spvasmFloat /-\?\d\+\.\?\(e[+-]\d\+\)\?/
|
|
" Second case: optional digits before decimal, trailing digits
|
|
syn match spvasmFloat /-\?\d*\.\d\+\(e[+-]\d\+\)\?/
|
|
|
|
" First case: hex digits before the optional decimal, no trailing hex digits.
|
|
syn match spvasmFloat /-\?0[xX]\\x\+\.\?p[-+]\d\+/
|
|
" Second case: optional hex digits before decimal, trailing hex digits
|
|
syn match spvasmFloat /-\?0[xX]\\x*\.\\x\+p[-+]\d\+/
|
|
|
|
syn match spvasmComment /;.*$/ contains=spvasmTodo
|
|
syn region spvasmString start=/"/ skip=/\\\\"/ end=/"/
|
|
syn match spvasmId /%[a-zA-Z_][a-zA-Z_0-9]*/
|
|
|
|
" Highlight unknown constants and statements as errors
|
|
syn match spvasmError /[a-zA-Z][a-zA-Z_0-9]*/
|
|
|
|
|
|
if version >= 508 || !exists("did_c_syn_inits")
|
|
if version < 508
|
|
let did_c_syn_inits = 1
|
|
command -nargs=+ HiLink hi link <args>
|
|
else
|
|
command -nargs=+ HiLink hi def link <args>
|
|
endif
|
|
|
|
HiLink spvasmStatement Statement
|
|
HiLink spvasmNumber Number
|
|
HiLink spvasmComment Comment
|
|
HiLink spvasmString String
|
|
HiLink spvasmFloat Float
|
|
HiLink spvasmConstant Constant
|
|
HiLink spvasmIdNumber Identifier
|
|
HiLink spvasmId Identifier
|
|
HiLink spvasmTodo Todo
|
|
|
|
delcommand HiLink
|
|
endif
|
|
|
|
let b:current_syntax = "spvasm"
|
|
"""
|
|
|
|
# This list is taken from the description of OpSpecConstantOp in SPIR-V 1.1.
|
|
# TODO(dneto): Propose that this information be embedded in the grammar file.
|
|
SPEC_CONSTANT_OP_OPCODES = """
|
|
OpSConvert, OpFConvert
|
|
OpSNegate, OpNot
|
|
OpIAdd, OpISub
|
|
OpIMul, OpUDiv, OpSDiv, OpUMod, OpSRem, OpSMod
|
|
OpShiftRightLogical, OpShiftRightArithmetic, OpShiftLeftLogical
|
|
OpBitwiseOr, OpBitwiseXor, OpBitwiseAnd
|
|
OpVectorShuffle, OpCompositeExtract, OpCompositeInsert
|
|
OpLogicalOr, OpLogicalAnd, OpLogicalNot,
|
|
OpLogicalEqual, OpLogicalNotEqual
|
|
OpSelect
|
|
OpIEqual, OpINotEqual
|
|
OpULessThan, OpSLessThan
|
|
OpUGreaterThan, OpSGreaterThan
|
|
OpULessThanEqual, OpSLessThanEqual
|
|
OpUGreaterThanEqual, OpSGreaterThanEqual
|
|
|
|
OpQuantizeToF16
|
|
|
|
OpConvertFToS, OpConvertSToF
|
|
OpConvertFToU, OpConvertUToF
|
|
OpUConvert
|
|
OpConvertPtrToU, OpConvertUToPtr
|
|
OpGenericCastToPtr, OpPtrCastToGeneric
|
|
OpBitcast
|
|
OpFNegate
|
|
OpFAdd, OpFSub
|
|
OpFMul, OpFDiv
|
|
OpFRem, OpFMod
|
|
OpAccessChain, OpInBoundsAccessChain
|
|
OpPtrAccessChain, OpInBoundsPtrAccessChain"""
|
|
|
|
|
|
def EmitAsStatement(name):
|
|
"""Emits the given name as a statement token"""
|
|
print('syn keyword spvasmStatement', name)
|
|
|
|
|
|
def EmitAsEnumerant(name):
|
|
"""Emits the given name as an named operand token"""
|
|
print('syn keyword spvasmConstant', name)
|
|
|
|
|
|
def main():
|
|
"""Parses arguments, then generates the Vim syntax rules for SPIR-V assembly
|
|
on stdout."""
|
|
import argparse
|
|
parser = argparse.ArgumentParser(description='Generate SPIR-V info tables')
|
|
parser.add_argument('--spirv-core-grammar', metavar='<path>',
|
|
type=str, required=True,
|
|
help='input JSON grammar file for core SPIR-V '
|
|
'instructions')
|
|
parser.add_argument('--extinst-glsl-grammar', metavar='<path>',
|
|
type=str, required=False, default=None,
|
|
help='input JSON grammar file for GLSL extended '
|
|
'instruction set')
|
|
parser.add_argument('--extinst-opencl-grammar', metavar='<path>',
|
|
type=str, required=False, default=None,
|
|
help='input JSON grammar file for OpenGL extended '
|
|
'instruction set')
|
|
args = parser.parse_args()
|
|
|
|
# Generate the syntax rules.
|
|
print(PREAMBLE)
|
|
|
|
core = json.loads(open(args.spirv_core_grammar).read())
|
|
print('\n" Core instructions')
|
|
for inst in core["instructions"]:
|
|
EmitAsStatement(inst['opname'])
|
|
print('\n" Core operand enums')
|
|
for operand_kind in core["operand_kinds"]:
|
|
if 'enumerants' in operand_kind:
|
|
for e in operand_kind['enumerants']:
|
|
EmitAsEnumerant(e['enumerant'])
|
|
|
|
if args.extinst_glsl_grammar is not None:
|
|
print('\n" GLSL.std.450 extended instructions')
|
|
glsl = json.loads(open(args.extinst_glsl_grammar).read())
|
|
# These opcodes are really enumerant operands for the OpExtInst
|
|
# instruction.
|
|
for inst in glsl["instructions"]:
|
|
EmitAsEnumerant(inst['opname'])
|
|
|
|
if args.extinst_opencl_grammar is not None:
|
|
print('\n" OpenCL.std extended instructions')
|
|
opencl = json.loads(open(args.extinst_opencl_grammar).read())
|
|
for inst in opencl["instructions"]:
|
|
EmitAsEnumerant(inst['opname'])
|
|
|
|
print('\n" OpSpecConstantOp opcodes')
|
|
for word in SPEC_CONSTANT_OP_OPCODES.split(' '):
|
|
stripped = word.strip('\n,')
|
|
if stripped != "":
|
|
# Treat as an enumerant, but without the leading "Op"
|
|
EmitAsEnumerant(stripped[2:])
|
|
print(POSTAMBLE)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|