123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- #!/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')
- parser.add_argument('--extinst-debuginfo-grammar', metavar='<path>',
- type=str, required=False, default=None,
- help='input JSON grammar file for DebugInfo 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'])
- if args.extinst_debuginfo_grammar is not None:
- print('\n" DebugInfo extended instructions')
- debuginfo = json.loads(open(args.extinst_debuginfo_grammar).read())
- for inst in debuginfo["instructions"]:
- EmitAsEnumerant(inst['opname'])
- print('\n" DebugInfo operand enums')
- for operand_kind in debuginfo["operand_kinds"]:
- if 'enumerants' in operand_kind:
- for e in operand_kind['enumerants']:
- EmitAsEnumerant(e['enumerant'])
- 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()
|