mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-23 04:00:05 +00:00
193 lines
6.4 KiB
Python
193 lines
6.4 KiB
Python
|
#!/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()
|