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"
"""
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):
print('syn keyword spvasmStatement', name)
def EmitAsEnumerant(name):
print('syn keyword spvasmConstant', name)
def main():
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()
print(PREAMBLE)
core = json.loads(open(args.spirv_core_grammar).read())
print('\n" Core instructions')
for inst in core["instructions"]:
EmitAsStatement(inst['opname'])
aliases = inst.get('aliases', [])
for alias in aliases:
EmitAsStatement(alias)
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'])
aliases = e.get('aliases', [])
for a in aliases:
EmitAsEnumerant(a)
if args.extinst_glsl_grammar is not None:
print('\n" GLSL.std.450 extended instructions')
glsl = json.loads(open(args.extinst_glsl_grammar).read())
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 != "":
EmitAsEnumerant(stripped[2:])
print(POSTAMBLE)
if __name__ == '__main__':
main()